glam-0.30.1/.cargo_vcs_info.json0000644000000001360000000000100120350ustar { "git": { "sha1": "aa8447d4265cd60440dcc09500622b14595fa2ec" }, "path_in_vcs": "" }glam-0.30.1/.gitattributes000064400000000000000000000000411046102023000135130ustar 00000000000000*.rs.tera linguist-language=Rust glam-0.30.1/.github/ISSUE_TEMPLATE/bug_report.md000064400000000000000000000010201046102023000170330ustar 00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: bug assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Can you provide some code that demonstrate the bug **Expected behavior** A clear and concise description of what you expected to happen. **System information (please complete the following information):** - OS: [e.g. Linux] - Architecture [e.g. x86_64] **Additional context** Add any other context about the problem here. glam-0.30.1/.github/ISSUE_TEMPLATE/config.yml000064400000000000000000000002601046102023000163360ustar 00000000000000blank_issues_enabled: false contact_links: - name: Ask a question url: https://github.com/bitshifter/glam-rs/discussions about: Please ask and answer questions here. glam-0.30.1/.github/ISSUE_TEMPLATE/feature_request.md000064400000000000000000000010521046102023000200730ustar 00000000000000--- name: Feature request about: Propose a new feature title: '' labels: enhancement assignees: '' --- **What problem does this solve or what need does it fill?** A clear and concise description of what the problem is. **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** What is your use case for this feature? How do you intend to use it? glam-0.30.1/.github/pull_request_template.md000064400000000000000000000017611046102023000171330ustar 00000000000000# Objective - Describe the objective or issue this PR addresses. - If you're fixing a specific issue, say "Fixes #X". ## Solution - Describe the solution used to achieve the objective above. ## Code generation - Most code in glam is generated by an offline tool. - Are you modify generated code? - Have you modified the templates and run the code generator? See https://github.com/bitshifter/glam-rs/blob/main/codegen/README.md for details. ## Testing and linting - Your PR should include tests for any bug fixes or new features. - `cargo test` and `cargo clippy` must pass. You can run most of glam's tests locally by running the `build_and_test_features.sh` script. ## Breaking changes *This section is optional. If there are no breaking changes, you can delete this section.* - If this PR is a breaking change describe how a user might need to migrate their code. - Simply adding new functionality is not a breaking change. - Fixing behavior that was definitely a bug is not a breaking change. glam-0.30.1/.github/workflows/cargo-deny.yml000064400000000000000000000002671046102023000170020ustar 00000000000000name: cargo-deny on: [push, pull_request] jobs: cargo-deny: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: EmbarkStudios/cargo-deny-action@v1 glam-0.30.1/.github/workflows/ci.yml000064400000000000000000000060771046102023000153520ustar 00000000000000name: CI on: [push, pull_request] jobs: lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: rustup update --no-self-update stable - run: rustup default stable # make sure all code has been formatted with rustfmt and linted with clippy - name: rustfmt run: cargo fmt -- --check --color always # run clippy to verify we have no warnings - run: cargo fetch - name: cargo clippy run: cargo clippy --workspace --all-targets --all-features -- -D warnings # check that codegen output matches committed source files - 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/pointer_width_32 test: name: Test strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] toolchain: [stable, beta, nightly] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - run: rustup update --no-self-update ${{ matrix.toolchain }} - run: rustup default ${{ matrix.toolchain }} - run: ./build_and_test_features.sh shell: bash check-msrv: name: Check MSRV strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] toolchain: [1.68.2] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - run: rustup update --no-self-update ${{ matrix.toolchain }} - run: rustup default ${{ matrix.toolchain }} - run: ./build_all_msrv.sh shell: bash test-core-simd: name: Test portable simd strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] toolchain: [nightly] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - run: rustup update --no-self-update ${{ matrix.toolchain }} - run: rustup default ${{ matrix.toolchain }} - run: cargo test --features core-simd shell: bash test-wasm: name: Test wasm strategy: matrix: toolchain: [stable] os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Install run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - run: ./build_and_test_wasm32_firefox.sh - run: ./build_and_test_wasm32_chrome.sh # macos-latest uses aarch64 so using cross shouldn't be necessary anymore # test-arm: # name: Test Arm # runs-on: ubuntu-latest # strategy: # fail-fast: false # matrix: # target: # - aarch64-unknown-linux-gnu # - arm-unknown-linux-gnueabi # steps: # - uses: actions/checkout@v4 # - run: rustup update --no-self-update stable # - run: rustup default stable # - run: rustup target add --toolchain stable ${{matrix.target}} # - uses: taiki-e/install-action@cross # - run: cross test --target ${{matrix.target}} glam-0.30.1/.github/workflows/coverage.yml000064400000000000000000000010721046102023000165400ustar 00000000000000name: coverage on: [push] jobs: coverage: container: image: xd009642/tarpaulin:develop-nightly options: --security-opt seccomp=unconfined runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Update nightly run: rustup update nightly - name: Generate code coverage run: cargo +nightly tarpaulin --timeout 120 --out lcov --output-dir ./coverage - name: Upload to coveralls.io uses: coverallsapp/github-action@master with: github-token: ${{ secrets.GITHUB_TOKEN }} glam-0.30.1/.gitignore000064400000000000000000000001371046102023000126160ustar 00000000000000.vscode **/target #*.json *.swp **/*.rs.bk Cargo.lock Session.vim .cargo-ok cargo-timing*.html glam-0.30.1/.tarpaulin.toml000064400000000000000000000021471046102023000136030ustar 00000000000000[sse2_math] features = "approx bytemuck mint rand rkyv serde debug-glam-assert" exclude-files = [ "codegen/*", "swizzlegen/*", "src/neon.rs", "src/bool/neon/*", "src/f32/neon/*", "src/swizzles/neon/*", "src/wasm32.rs", "src/bool/wasm32/*", "src/f32/wasm32/*", "src/swizzles/wasm32/*", "benches/*", "tests/support.rs" ] [scalar_math] features = "scalar-math approx bytemuck mint rand rkyv serde debug-glam-assert" exclude-files = [ "codegen/*", "swizzlegen/*", "src/neon.rs", "src/bool/neon/*", "src/f32/neon/*", "src/swizzles/neon/*", "src/wasm32.rs", "src/bool/wasm32/*", "src/f32/wasm32/*", "src/swizzles/wasm32/*", "benches/*", "tests/support.rs" ] [core_simd] features = "core-simd approx bytemuck mint rand rkyv serde debug-glam-assert" exclude-files = [ "codegen/*", "swizzlegen/*", "src/neon.rs", "src/bool/neon/*", "src/f32/neon/*", "src/swizzles/neon/*", "src/wasm32.rs", "src/bool/wasm32/*", "src/f32/wasm32/*", "src/swizzles/wasm32/*", "benches/*", "tests/support.rs" ] glam-0.30.1/ARCHITECTURE.md000064400000000000000000000074311046102023000130360ustar 00000000000000# Architecture This document describes the high-level architecture of `glam`. While `glam` is not a large library there are some complexities to its implementation. The rational and explanation of these follows. ## Design goals There overarching design goals of glam are: * Good out of the box performance using SIMD when available * Has a simple public interface * Is fast to compile * Follow Rust [standard library] conventions and [API guidelines] where possible * High quality [rustdoc] generated document [standard library]: https://doc.rust-lang.org/std/index.html [API guidelines]: https://rust-lang.github.io/api-guidelines [rustdoc]: https://doc.rust-lang.org/rustdoc/index.html ### SIMD One of the core premises of `glam` was that using SSE2 instructions on `x86` and `x86_64` architectures gave better performance than using Rust's built in `f32` type. For more on this finding see [Optimising path tracing with SIMD]. I also wanted to have a `f32` fallback when SIMD was not available. [Optimising path tracing with SIMD]: https://bitshifter.github.io/2018/06/04/simd-path-tracing/#converting-vec3-to-sse2. ### No generics Because internally storage could be a SIMD vector intrinsic like `__m128` on `x86` or say an array of `f32` if SSE2 was not available, a simple generic parameter like `Vec4` could not be used. The `T` would specify the public facing type, but not storage. Perhaps this could be achieved with a second generic parameter for storage, e.g. `Vec4` or `Vec4` but I felt that such a design would introduce a lot of complexity that end users would ultimately be burdened with, so it's not something that was pursued. Generics can also increase compile time and code size which is something glam wants to avoid. ### No traits `glam` also mostly avoids using traits in the public interface. Primarily because there wasn't a good reason to. A `Vec3` is not an interface, it is a concrete type. The secondary reason is traits fragment documentation. If the functionality of a `Vec3` is implemented across a number of different traits then the documentation of all of the `Vec3` methods will be on the individual traits, not the `Vec3` itself. This makes it harder for users to find what methods a struct actually implements as the documentation is not in one place. Conversely `glam` does use traits for swizzle methods so that the documentation for these methods is on the trait and not the `Vec2`, `Vec3`, `Vec4` and so on structs. There are many swizzle methods which would clutter the documentation, making them a trait means they won't pollute documentation. ### Support common primitives Initially `glam` only supported `f32` which kept the internal implementation relatively simple. However users also wanted support for other primitives types like `f64`, `i32` and `u32`. Because `glam` avoids using `generics` adding support for other primitive types without a lot of code duplication required some additional complexity in implementation. ## High level structure `glam` supports a number of permutations of vector, quaternion and matrix types for `f32`, `f64`, `i32` and `u32` primitives, with SSE2 or wasm32 for some `f32` types and scalar fallbacks if SIMD is not available. ### Component access via Deref The `Deref` trait is used to provide direct access to SIMD vector components like `.x`, `.y` and so on. The `Deref` implementation will return `XYZ` structure on which the vector components are accessible. Unfortunately if users dereference the public types they will see confusing errors messages about `XYZ` types but this on balance seemed preferable to needing to setter and getting methods to read and write component values. ## Code generation See the [codegen README] for information on `glam`'s code generation process. [codegen README]: codegen/README.md glam-0.30.1/ATTRIBUTION.md000064400000000000000000000072061046102023000127600ustar 00000000000000# Attribution `glam` contains code ported from the following C++ libraries. ## [DirectXMath] [DirectXMath]: https://docs.microsoft.com/en-us/windows/win32/dxmath/directxmath-portal [The MIT License (MIT)](https://github.com/microsoft/DirectXMath/blob/master/LICENSE) Copyright (c) 2011-2020 Microsoft Corp Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## [Realtime Math] [Realtime Math]: https://github.com/nfrechette/rtm [MIT License](https://github.com/nfrechette/rtm/blob/develop/LICENSE) Copyright (c) 2018 Nicholas Frechette Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## [GLM] [GLM]: https://glm.g-truc.net [The MIT License](https://github.com/g-truc/glm/blob/master/copying.txt) Copyright (c) 2005 - G-Truc Creation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. glam-0.30.1/CHANGELOG.md000064400000000000000000001221551046102023000124440ustar 00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog], and this project adheres to [Semantic Versioning]. ## [0.30.1] - 2025-03-20 ## Added * Added `usize` vector types, `USizeVec2`, `USizeVec3` and `USizeVec4`. * Added `min_position` and `max_position` methods for vector types, which return the index of the min or max element in the vector. * Added `rotate_towards` method to 3D vector types. ## Changed * Removed the small angle check from 2D vector `rotate_towards` implementations as it was unnecessary and would not preserve the length of the input. ## [0.30.0] - 2025-02-18 ### Breaking changes * The `up` and `dir` vectors passed to affine and matrix `look_to_lh` and `look_to_rh` methods must now be normalized. This was changed to be consistent with other methods. * Updated the optional `rand` dependency to `0.9` * Updated the optional `rkyv` dependency to `0.8` ### Added * Implemented `rand` `Uniform` distribution trait for all vector types. * Added "swizzle assignment" support to vector swizzles, in the form of `v.with_zx(ivec2(1, 2))` which will return a copy of `v` where the `z` and `x` components are set to 1 and 2 respectively. * Added `Mat3` and `Quat` `look_at_lh` and `look_at_rh` methods. * Added `Quat` `look_to_lh` and `look_to_rh` methods. * Added 3D vector `slerp` method that performs a spherical linear interpolation between a source and a target 3D vector. * Added `manhattan_distance`, `checked_manhattan_distance` and `chebyshev_distance` methods to integer vector types which calculates the Manhattan Distance and the Chebyshev Distance between two vectors. * Added 4x4 matrix `from_mat3_translation` method to have parity with the 3D affine type. ### Fixed * `Quat::rotate_towards()` now returns the target `Quat` if the angle is small. Previously `self` was returned which could skip the rotation entirely. ## [0.29.2] - 2024-11-05 ### Fixed * Fix regression in vector `write_to_slice` methods where the destination had to be the same size as the input, but it should support writing to a slice that is the same size or larger than the input. ## [0.29.1] - 2024-10-30 ### Added * Added `i8` and `u8` vector types, `I8Vec2`, `I8Vec3`, `I8Vec4`, `U8Vec2`, `U8Vec3` and `U8Vec4`. * Added `Mat4::project_point3a(Vec3A)` method transforming points by perspective projections. ### Changed * Removed normalized assertions from quaternion multiplies as sometimes this is valid. * Include `Debug` and `Display` implementations on `spirv` targets. * Optimized vector `from_slice` and `write_to_slice` methods. * Improved `serde` error messages. ## [0.29.0] - 2024-08-20 ### Breaking changes * `EulerRot` has been reimplemented and now has support for 24 different rotation order enum values. ### Fixed * Reduced the dot threshold at which quaternion slerp uses lerp to improve accuracy. ### Added * Added 3x3 matrix `from_mat4_minor()` and 2x2 matrix `from_mat3_minor()` methods. * Added `bvec2`, `bvec3`, `bvec3a`, `bvec4` and `bvec4a` vector mask creation functions. * Added all 24 possible intrinsic and extrinsic Euler angle rotation combinations to `EulerRot` enum. * Added `is_finite_mask` method to vector types which returns a vector mask. * Added `reflect` and `refract` methods to vector types. * Added `to_euler` methods to matrix types which extracts Euler angles from a rotation matrix for a given `EulerRot`. * Added generic `map` method to vector types which applies a functor to all vector elements. * Vector arithmetic ops are now implemented on references. ### Changed * Vector and quaternion lerp now uses a precise lerp algorithm. ## [0.28.0] - 2024-06-10 ### Breaking changes * Removed derives from `glam::deref` types used by `Deref` on SIMD vector types. These unintentionally added support for traits like `PartialOrd` to SIMD vector types. This may break existing code that was depending on this. Please use `cmple().all()` etc. instead of `PartialOrd` methods. * Removed `impl From for Vec3A` as this violated the `From` trait contract that conversions should be lossless. Please use the explicit `Vec3A::from_vec4` method instead. * Renamed 2D vector `angle_between` to `angle_to` to differentiate from the 3D `angle_between` which has different semantics to the 2D version. ### Added * Added aarch64 neon support. * Added `rotate_towards` methods for 2D vectors and quaternions. * Added `Vec3A::from_vec4` method which can perform a no-op conversion when SIMD is used. This replaces the `impl From for Vec3A` implementation. ## [0.27.0] - 2024-03-23 ### Breaking changes * Changed implementation of vector `fract` method to match the Rust implementation instead of the GLSL implementation, that is `self - self.trunc()` instead of `self - self.floor()`. ### Added * Added vector `fract_gl` which uses the GLSL specification of `fract`, `self - self.floor()`. ## [0.26.0] - 2024-03-18 ### Breaking changes * Minimum Supported Rust Version bumped to 1.68.2 for `impl From for {f32,f64}` support. ### Fixed * Respect precision format specifier in Display implementations. Previously it was ignored. * Corrected precision documentation for vector `is_normalized` methods and changed the internal check to use `2e-4` to better match the documented precision value of `1e-4`. ### Added * Added `with_x`, `with_y`, etc. to vector types which returns a copy of the vector with the new component value. * Added `midpoint` method to vector types that returns the point between two points. * Added `move_towards` for float vector types. * Added saturating add and sub methods for signed and unsigned integer vector types. * Added element wise sum and product methods for vector types. * Added element wise absolute values method for matrix types. * Added `from_array` method for boolean vector types. * Added `normalize_or` method to vector types that returns the specified value if normalization failed. * Added `From` support for all vector types. * Added `Div` and `DivAssign` by scalar implementations to matrix types. ## [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 * When the `scalar-math` feature is enabled the vector mask type for `Vec3A` was changed from `BVec3` to `BVec3A`. ### Added * Added `copysign` method to signed vector types. ## [0.22.0] - 2022-10-24 ### Breaking changes * Added `u32` implementation of `BVec3A` and `BVec4` when SIMD is not available. These are used instead of aliasing to the `bool` implementations. * Removed `Add`, `Sub`, and scalar `Mul` implementations from affine types as they didn't make sense on these types. * Removed deprecated `const_*` macros. These have been replaced by `const fn` methods. ### Fixed * Fixed `neg` and `signum` to consistently handle negative zero across multiple platforms. * Removed `register_attr` feature usage for SPIR-V targets. ### Added * Added missing `Serialize`, `Deserialize` and `PartialEq` implementations. * Added `Sum` and `Product` implementations for all vector, matrix and quaternion types. * Added 4x4 matrix methods `look_to_lh` and `look_to_rh`. These were previously private. * Added `dot_into_vec` methods to vector which returns the result of the dot product splatted to all vector lanes. * Added `is_negative_bitmask` to vector types which returns a `u32` of bits for each negative vector lane. * Added `splat` method and `TRUE` and `FALSE` constants to all `BVec` types. * Added `from_mat3a` methods to `Affine2`, `Mat2`, `Mat4` and `Quat` types. ### Changed * Disable `serde` default features. * Made `to_cols_array`, `to_cols_array_2d`, and `from_diagonal` methods `const fn`. ## [0.21.3] - 2022-08-02 ### Fixed * Fixed `glam_assert` being too restrictive in matrix transform point and transform vector methods. ### Added * Added experimental `core-simd` feature which enables SIMD support via the unstable `core::simd` module. ### Changed * Derive from `PartialEq` and `Eq` instead of providing a trait implementation for all non SIMD types. ## [0.21.2] - 2022-06-25 ### Fixed * Restore missing `$crate::` prefix in deprecated `const_*` macros. * Fixed some performance regressions in affine and matrix determinant and inverses due to lack of inlining. * Fixed some performance regressions in the SSE2 `Vec3A` to `Vec3` from conversion. ### Added * Implemented `BitXor` and `BitXorAssign` traits for `bool` vectors. ## [0.21.1] - 2022-06-22 ### Fixed * Fix compilation when FMA support is enabled. ## [0.21.0] - 2022-06-22 ### Breaking changes * Minimum Supported Version of Rust bumped to 1.58.1 to allow `const` pointer dereferences in constant evaluation. * The `abs_diff_eq` method on `Mat2` and `DMat2` now takes `other` by value instead of reference. This is consistent with the other matrix types. * The `AsMut` and `Deref` trait implementations on `Quat` and `DQuat` was removed. Quaternion fields are now public. * The `AsRef` trait implementations were removed from `BVec2`, `BVec3`, `BVec3A`, `BVec4` and `BVec4A`. ### Added * `NEG_ONE` constant was added to all signed vector types. * `NEG_X`, `NEG_Y`, `NEG_Z` and `NEG_W` negative axis vectors were added to signed vector types. * The `rotate` and `from_angle` methods were added to `Vec2` and `DVec2`. `from_angle` returns a 2D vector containing `[angle.cos(), angle.sin()]` that can be used to `rotate` another 2D vector. * The `from_array` `const` function was added to all vector types. ### Changed * Source code is now largely generated. This removes most usage of macros internally to improve readability. There should be no change in API or behavior other than what is documented here. * Many methods have been made `const fn`: * `new`, `splat`, `from_slice`, `to_array` and `extend` on vector types * `from_cols`, `from_cols_array`, `from_cols_array_2d`, `from_cols_slice` on matrix types * `from_xyzw` and `from_array` on quaternion types * `from_cols` on affine types * The `const` new macros where deprecated. ### Removed * Deleted deprecated `TransformRT` and `TransformSRT` types. ## [0.20.5] - 2022-04-12 ### Fixed * Fixed a bug in the scalar implementation of 4D vector `max_element` method where the `w` element check was incorrect. ## [0.20.4] - 2022-04-11 ### Fixed * Fixed a bug with quaternion `slerp` with a rotation of tau. ## [0.20.3] - 2022-03-28 ### Added * Added `to_array()` to `Quat` and `DQuat`. * Added `mul_add` method to all vector types - note that this will be slower without hardware support enabled. * Added the `fast-math` flag which will sacrifice some float determinism for speed. ### Fixed * Fixed a bug in the `sse2` and `wasm32` implementations of `Mat4::determinant()`. ## [0.20.2] - 2021-12-20 ### Fixed * Fixed SPIR-V build which was broken due to a typo. ## [0.20.1] - 2021-11-23 ### Added * Added the `from_rotation_arc_2d()` method to `Quat` and `DQuat` which will return a rotation between two 2D vectors around the z axis. * Added impl of `Neg` operator for matrix types. * Added `cuda` feature which forces `glam` types to match cuda's alignment requirements. ### Changed * The `Quat` and `DQuat` methods `from_rotation_arc()` and `from_rotation_arc_colinear()` are now available in `no_std`. * The `Vec3` and `DVec3` methods `any_orthogonal_vector()`, `any_orthonormal_vector()` and `any_orthonormal_pair()` are now available in `no_std`. * Added `repr(C)` attribute to affine types. ### Removed * Removed deprecated `as_f32()`, `as_f64()`, `as_i32()` and `as_u32()` methods. ## [0.20.0] - 2021-11-01 ### Breaking changes * Minimum Supported Version of Rust bumped to 1.52.1 for an update to the `mint` crate. ### Added * Added implementations for new `IntoMint` trait from the `mint` crate. * Added `mint` conversions for `Mat3A`. * Added `as_vec3a` cast methods to vector types. ## [0.19.0] - 2021-10-05 ### Breaking changes * Removed truncating vector `From` implementations. Use `.truncate()` or swizzle methods instead. ### Added * Added `Not`, `Shl`, `Shr`, `BitAnd`, `BitOr` and `BitXor` implementations for all `IVec` and `UVec` vector types. * Added `NAN` constant for all types. * Documented `glam`'s [architecture](ARCHITECTURE.md). ### Changed * `Sum` and `Product` traits are now implemented in `no_std` builds. ## [0.18.0] - 2021-08-26 ### Breaking changes * Minimum Supported Version of Rust bumped to 1.51.0 for `wasm-bindgen-test` and `rustdoc` `alias` support. ### Added * Added `wasm32` SIMD intrinsics support. * Added optional support for the `rkyv` serialization crate. * Added `Rem` and `RemAssign` implementations for all vector types. * Added quaternion `xyz()` method for returning the vector part of the quaternion. * Added `From((Scalar, Vector3))` for 4D vector types. ### Changed * Deprecated `as_f32()`, `as_f64()`, `as_i32()` and `as_u32()` methods in favor of more specific methods such as `as_vec2()`, `as_dvec2()`, `as_ivec2()` and `as_uvec2()` and so on. ## [0.17.3] - 2021-07-18 ### Fixed * Fix alignment unit tests on non x86 platforms. ## [0.17.2] - 2021-07-15 ### Fixed * Fix alignment unit tests on i686 and S390x. ## [0.17.1] - 2021-06-29 ### Added * Added `serde` support for `Affine2`, `DAffine2`, `Affine3A` and `DAffine3`. ## [0.17.0] - 2021-06-26 ### Breaking changes * The addition of `Add` and `Sub` implementations of scalar values for vector types may create ambiguities with existing calls to `add` and `sub`. * Removed `From` implementation for `Mat2` and `From` for `DMat2`. These have been replaced by `Mat2::from_mat3()` and `DMat2::from_mat3()`. * Removed `From` implementation for `Mat3` and `From` for `DMat3`. These have been replaced by `Mat3::from_mat4()` and `DMat3::from_mat4()`. * Removed deprecated `from_slice_unaligned()`, `write_to_slice_unaligned()`, `from_rotation_mat4` and `from_rotation_ypr()` methods. ### Added * Added `col_mut()` method which returns a mutable reference to a matrix column to all matrix types. * Added `AddAssign`, `MulAssign` and `SubAssign` implementations for all matrix types. * Added `Add` and `Sub` implementations of scalar values for vector types. * Added more `glam_assert!` checks and documented methods where they are used. * Added vector projection and rejection methods `project_onto()`, `project_onto_normalized()`, `reject_from()` and `reject_from_normalized()`. * Added `Mat2::from_mat3()`, `DMat2::from_mat3()`, `Mat3::from_mat4()`, `DMat3::from_mat4()` which create a smaller matrix from a larger one, discarding a final row and column of the input matrix. * Added `Mat3::from_mat2()`, `DMat3::from_mat2()`, `Mat4::from_mat3()` and `DMat4::from_mat3()` which create an affine transform from a smaller linear transform matrix. ### Changed * Don't support `AsRef` and `AsMut` on SPIR-V targets. Also removed SPIR-V support for some methods that used `as_ref()`, including `hash()`. Not a breaking change as these methods would not have worked anyway. ### Fixed * Fixed compile time alignment checks failing on i686 targets. ## [0.16.0] - 2021-06-06 ### Breaking changes * `sprirv-std` dependency was removed, rust-gpu depends on glam internally again for now. * Added `must_use` attribute to all `inverse()`, `normalize()`, `try_normalize()`, `transpose()` and `conjugate()` methods. ### Added * Added `fract()` method to float vector types which return a vector containing `self - self.floor()`. * Added optional support for the `approx` crate. Note that all glam types implement their own `abs_diff_eq()` method without requiring the `approx` dependency. ## [0.15.2] - 2021-05-20 ### Added * Added `from_cols()` methods to affine types. * Added methods for reading and writing affine types from and to arrays and slices, including `from_cols_array()`, `to_cols_array()`, `from_cols_array_2d()`, `to_cols_array_2d()`, `from_cols_slice()` and `write_cols_to_slice()`. * Added `core::fmt::Display` trait implementations for affine types. * Added `core::ops::Add`, `core::ops::Mul` scalar and `core::ops::Sub` trait implementations for affine types. * Added `from_array()` methods to quaternion types. ### Changed * Renamed vector and quaternion `from_slice_unaligned()` and `write_to_slice_unaligned()` methods to `from_slice()` and `write_to_slice()`. * Removed usage of `_mm_rcp_ps` from SSE2 implementation of `Quat::slerp` as this instruction is not deterministic between Intel and AMD chips. ## [0.15.1] - 2021-05-14 ### Changed * Disable `const_assert_eq!` size and alignment checks for SPIR-V targets. ## [0.15.0] - 2021-05-14 ### Breaking changes * Removed `PartialOrd` and `Ord` trait implementations for all `glam` types. * 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 realizing, including from `Vec4`, `(x, y, z, w)` and `[f32; 4]`. ### Added * Added `EulerRot` enum for specifying Euler rotation order and `Quat::from_euler()`, `Mat3::from_euler()` and `Mat4::from_euler()` which support specifying a rotation order and angles of rotation. * Added `Quat::to_euler()` method for extracting Euler angles. * Added `Quat::from_vec4()` which is an explicit method for creating a quaternion from a 4D vector. The method does not normalize the resulting quaternion. * Added `Mat3A` type which uses `Vec3A` columns. It is 16 byte aligned and contains internal padding but it generally faster than `Mat3` for most operations if SIMD is available. * Added 3D affine transform types `Affine3A` and `DAffine3`. These are more efficient than using `Mat4` and `DMat4` respectively when working with 3D affine transforms. * Added 2D affine transform types `Affine2` and `DAffine2`. These are more efficient than using `Mat3` and `DMat3` respectively when working with 2D affine transforms. * Added `Quat::from_affine3()` to create a quaternion from an affine transform rotation. * Added explicit `to_array()` method to vector types to better match the matrix methods. ### Changed * Deprecated `Quat::from_rotation_ypr()`, `Mat3::from_rotation_ypr()` and `Mat4::from_rotation_ypr()` in favor of new `from_euler()` methods. * Deprecated `Quat::from_rotation_mat3()` and `Quat::from_rotation_mat4()` in favor of new `from_mat3` and `from_mat4` methods. * Deprecated `TransformSRT` and `TransformRT` which are under the `transform-types` feature. These will be moved to a separate experimental crate. * Updated `spirv-std` dependency version to `0.4.0-alpha7`. ## [0.14.0] - 2021-04-09 ### Breaking changes * Minimum Supported Version of Rust bumped to 1.45.0 for the `spirv-std` dependency. ### Added * Added `AXES[]` constants to all vector types. These are arrays containing the unit vector for each axis. * Added quaternion `from_scaled_axis` and `to_scaled_axis` methods. ### Changed * Updated dependency versions of `bytemuck` to `1.5`, `rand` to `0.8`, `rand_xoshiro` to `0.6` and `spirv-std` to `0.4.0-alpha4`. ## [0.13.1] - 2021-03-24 ### Added * Added vector `clamp()` functions. * Added matrix column and row accessor methods, `col()` and `row()`. * Added SPIR-V module and dependency on `spirv-std` for the SPIR-V target. * Added matrix truncation from 4x4 to 3x3 and 3x3 to 2x2 via `From` impls. ### Changed * Documentation corrections and improvements. ## [0.13.0] - 2021-03-04 ### Breaking Changes * The behavior of the 4x4 matrix method `transform_point3()` was changed to not perform the perspective divide. This is an optimization for use with affine transforms where perspective correction is not required. The `project_point3()` method was added for transforming points by perspective projections. * The 3x3 matrix `from_scale()` method was changed to create a affine transform containing a 2-dimensional non-uniform scale to be consistent with the 4x4 matrix version. The `from_diagonal()` method can be used to create a 3x3 scale matrix. * The 3x3 matrix methods `transform_point2_as_vec3a`, `transform_vector2_as_vec3a` and `mul_vec3_as_vec3a` were unintentionally `pub` and are no longer publicly accessible. ### Added * Added `Vec2::X`, `Vec4::W` etc constants as a shorter versions of `unit_x()` and friends. * Added `ONE` constants for vectors. * Added `IDENTITY` constants for `Mat2`, `Mat3`, `Mat4` and `Quat`. * Added `ZERO` constant for vectors and matrices. * Added `clamp_length()`, `clamp_length_max()`, and `clamp_length_min` methods for `f32` and `f64` vector types. * Added `try_normalize()` and `normalize_or_zero()` for all real vector types. * Added `from_diagonal()` methods to all matrix types for creating diagonal matrices from a vector. * Added `angle_between()`, `from_rotation_arc()` and `from_rotation_arc_colinear()` to quaternion types. * Added quaternion `inverse()` which assumes the quaternion is already normalized and returns the conjugate. * Added `from_translation()` and `from_angle()` methods to 3x3 matrix types. * Added `project_point3()` method to 4x4 matrix types. This method is for transforming 3D vectors by perspective projection transforms. * Added `Eq` and `Hash` impls for integer vector types. ### Changed * Deprecated `::unit_x/y/z()`, `::zero()`, `::one()`, `::identity()` functions in favor of constants. ## [0.12.0] - 2021-01-15 ### Breaking Changes * `Vec2Mask`, `Vec3Mask` and `Vec4Mask` have been replaced by `BVec2`, `BVec3`, `BVec3A`, `BVec4` and `BVec4A`. These types are used by some vector methods and are not typically referenced directly. ### Added * Added `f64` primitive type support * vectors: `DVec2`, `DVec3` and `DVec4` * square matrices: `DMat2`, `DMat3` and `DMat4` * a quaternion type: `DQuat` * Added `i32` primitive type support * vectors: `IVec2`, `IVec3` and `IVec4` * Added `u32` primitive type support * vectors: `UVec2`, `UVec3` and `UVec4` * Added `bool` primitive type support * vectors: `BVec2`, `BVec3` and `BVec4` ### Removed * `build.rs` has been removed. ## [0.11.3] - 2020-12-29 ### Changed * Made `Vec3` `repr(simd)` for `spirv` targets. ### Added * Added `From<(Vec2, f32)>` for `Vec3` and `From<(Vec3, f32)` for `Vec4`. ## [0.11.2] - 2020-12-04 ### Changed * Compilation fixes for Rust 1.36.0. ## [0.11.1] - 2020-12-03 ### Added * Added support for the [Rust GPU](https://github.com/EmbarkStudios/rust-gpu) SPIR-V target architecture. ## [0.11.0] - 2020-11-26 ### Added * Added `is_finite` method to all types which returns `true` if, and only if, all contained elements are finite. * Added `exp` and `powf` methods for all vector types. ### Changed * The `is_nan` method now returns a `bool` to match the new `is_finite` method and to be consistent with the same methods on the `f32` and `f64` primitive types. * Renamed `is_nan` which returns a vector mask to `is_nan_mask`. * Don't use the `cfg` definitions added by `build.rs` for defining structs as `rust-analyzer` is not aware of them. ### Removed * Removed deprecated accessor methods. ## [0.10.2] - 2020-11-17 ### Changed * Deprecated element accessor members `.x()`, `.x_mut()`, `.set_x()`, etc. on vector and quaternion types. * Deprecated column accessor members `.x_axis()`, `.x_axis_mut()`, `.set_x_axis()`, etc. on matrix types. ## [0.10.1] - 2020-11-15 ### Added * Added the `Vec2::perp` method which returns a `Vec2` perpendicular to `self`. ### Changed * `Vec2` and `Vec3` types were changed to use public named fields for `.x`, `.y`, and `.z` instead of accessors. * `Quat`, `Vec3A` and `Vec4` implement `Deref` and `DerefMut` for the new `XYZ` and `XYZW` structs to emulate public named field access. * `Mat3` and `Mat4` had their axis members made public instead of needing accessors. * `Mat2` implements `Deref` and `DerefMut` for the new `XYAxes` struct to emulate public named field access. ### Removed * Removed deprecated `length_reciprocal` and `sign` methods. ### Fixed * Adding `glam` as a `no_std` dependency should now work as expected. ## [0.10.0] - 2020-10-31 ### Breaking Changes * Changed the return type of `Vec4::truncate` from `Vec3A` to `Vec3`. ### Added * Added `From` implementations to truncate to narrower vector types, e.g. `Vec4` to `Vec3A`, `Vec3` and `Vec2` and from `Vec3A` and `Vec3` to `Vec2`. * Added swizzles for `Vec4`, `Vec3A`, `Vec3` and `Vec2`. These can be used to reorder elements in the same type and also to create larger or smaller vectors from the given vectors elements. * Added `Quat` operators `Add`, `Sub`, `Mul` and `Div` and `AsMut<[f32; 9]>` trait implementations to `Mat3`. * Added optional `bytemuck` support primarily for casting types to `&[u8]`. * Added support for compiling with `no_std` by disabling the default `std` feature and adding the `libm` feature. * Added `distance` and `distance_squared` methods to `Vec2`, `Vec3`, `Vec3A` and `Vec4`. ## [0.9.5] - 2020-10-10 ### Added * `glam` uses SSE2 for some types which prevents constructor functions can not be made `const fn`. To work around this limitation the following macro functions have been added to support creating `const` values of `glam` types: `const_mat2`, `const_mat3`, `const_mat4`, `const_quat`, `const_vec2`, `const_vec3`, `const_vec3a` and `const_vec4`. * Added `is_nan` methods to `Vec2`, `Vec3`, `Vec3A` and `Vec4` which return a mask. ## Changed * Renamed the vector `reciprocal` and `length_reciprocal` methods to `recip` and `length_recip` to match the Rust standard library naming. The old methods have been deprecated. * Renamed the vector `sign` methods to `signum` match the Rust standard library naming. The new methods now check for `NAN`. The old methods have been deprecated. * Added SSE2 optimized implementations of `Mat4::determinant` and `Mat4::inverse`. ### Removed * Removed deprecated function `Mat4::perspective_glu_rh`. ## [0.9.4] - 2020-08-31 ### Fixed * Fixed `Mat4::transform_point3` to account for homogeneous w coordinate. Previously this would have been incorrect when the resulting homogeneous coordinate was not 1.0, e.g. when transforming by a perspective projection. * Fixed `Mat3::transform_point2` to account for homogeneous z coordinate. ## [0.9.3] - 2020-08-11 ### Added * Added `Mat4::perspective_rh`. ## [0.9.2] - 2020-07-09 ### Added * Added `Mat3::mul_vec3a` and `Quat::mul_vec3a`. ### Changed * Changed `Quat::mul_vec3` to accept and return `Vec3` instead of `Vec3A`. ## [0.9.1] - 2020-07-01 ### Added * Added `Mat3 * Vec3A` implementation. * Added `Vec3A` benches. ### Changed * Some documentation improvements around the new `Vec3A` type. ## [0.9.0] - 2020-06-28 ### Added * `Vec3` has been split into scalar `Vec3` and 16 byte aligned `Vec3A` types. Only the `Vec3A` type currently uses SIMD optimizations. * `Vec3Mask` has been split into scalar `Vec3Mask` and 16 byte aligned `Vec3AMask` types. * Added `mut` column accessors to all matrix types, e.g. `Mat2::x_axis_mut()`. * Added `From` trait implementations for `Vec3AMask` and `Vec4Mask` to `__m128`. ### Changed * The `Mat3` type is using the scalar `Vec3` type for storage. * Simplified `Debug` trait output for `Quat`, `Vec4` and `Vec3A`. ## Removed * Removed the `packed-vec3` feature flag as it is now redundant. ## [0.8.7] - 2020-04-28 ### Added * Added `Quat::slerp` - note that this uses a `sin` approximation. * Added `angle_between` method for `Vec2` and `Vec3`. * Implemented `Debug`, `Display`, `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Hash`, and `AsRef` traits for `Vec2Mask`, `Vec3Mask` and `Vec4Mask`. * Added conversion functions from `Vec2Mask`, `Vec3Mask` and `Vec4Mask` to an array of `[u32]`. * Added `build.rs` to simplify conditional feature compilation. ### Changed * Increased test coverage. ### Removed * Removed `cfg-if` dependency. ## [0.8.6] - 2020-02-18 ### Added * Added the `packed-vec3` feature flag to disable using SIMD types for `Vec3` and `Mat3` types. This avoids wasting some space due to 16 byte alignment at the cost of some performance. * Added `x_mut`, `y_mut`, `z_mut`, `w_mut` where appropriate to `Vec2`, `Vec3` and `Vec4`. * Added implementation of `core::ops::Index` and `core::ops::IndexMut` for `Vec2`, `Vec3` and `Vec4`. ### Changed * Merged SSE2 and scalar `Vec3` and `Vec4` implementations into single files using the `cfg-if` crate. ## [0.8.5] - 2020-01-02 ### Added * Added projection functions `Mat4::perspective_lh`, `Mat4::perspective_infinite_lh`, `Mat4::perspective_infinite_reverse_lh`, `Mat4::orthgraphic_lh` and `Mat4::orthographic_rh`. * Added `round`, `ceil` and `floor` methods to `Vec2`, `Vec3` and `Vec4`. ## [0.8.4] - 2019-12-17 ### Added * Added `Mat4::to_scale_rotation_translation` for extracting scale, rotation and translation from a 4x4 homogeneous transformation matrix. * Added `cargo-deny` GitHub Action. ### Changed * Renamed `Quat::new` to `Quat::from_xyzw`. ## [0.8.3] - 2019-11-27 ### Added * Added `Mat4::orthographic_rh_gl`. ### Changed * Renamed `Mat4::perspective_glu_rh` to `Mat4::perspective_rh_gl`. * SSE2 optimizations for `Mat2::determinant`, `Mat2::inverse`, `Mat2::transpose`, `Mat3::transpose`, `Quat::conjugate`, `Quat::lerp`, `Quat::mul_vec3`, `Quat::mul_quat` and `Quat::from_rotation_ypr`. * Disabled optimizations to `Mat4::transform_point3` and `Mat4::transform_vector3` as they are probably incorrect and need investigating. * Added missing `#[repr(C)]` to `Mat2`, `Mat3` and `Mat4`. * Benchmarks now store output of functions to better estimate the cost of a function call. ### Removed * Removed deprecated functions `Mat2::new`, `Mat3::new` and `Mat4::new`. ## [0.8.2] - 2019-11-06 ### Changed * `glam_assert!` is no longer enabled by default in debug builds, it can be enabled in any configuration using the `glam-assert` feature or in debug builds only using the `debug-glam-assert` feature. ### Removed * `glam_assert!`'s checking `lerp` is bounded between 0.0 and 1.0 and that matrix scales are non-zero have been removed. ## [0.8.1] - 2019-11-03 ### Added * Added `Display` trait implementations for `Mat2`, `Mat3` and `Mat4`. ### Changed * Disabled `glam`'s SSE2 `sin_cos` implementation - it became less precise for large angle values. * Reduced the default epsilon used by the `is_normalized!` macro from `std::f32::EPSILON` to `1e-6`. ## [0.8.0] - 2019-10-14 ### Removed * Removed the `approx` crate dependency. Each `glam` type has an `abs_diff_eq` method added which is used by unit tests for approximate floating point comparisons. * Removed the `Angle` type. All angles are now `f32` and are expected to be in radians. * Removed the deprecated `Vec2b`, `Vec3b` and `Vec4b` types and the `mask` methods on `Vec2Mask`, `Vec3Mask` and `Vec4Mask`. ### Changed * The `rand` crate dependency has been removed from default features. This was required for benchmarking but a simple random number generator has been added to the benches `support` module instead. * The `From` trait implementation converting between 1D and 2D `f32` arrays and matrix types have been removed. It was ambiguous how array data would map to matrix columns so these have been replaced with explicit methods `from_cols_array` and `from_cols_array_2d`. * Matrix `new` methods have been renamed to `from_cols` to be consistent with the other methods that create matrices from data. * Renamed `Mat4::perspective_glu` to `Mat4::perspective_glu_rh`. ## [0.7.2] - 2019-09-22 ### Fixed * Fixed incorrect projection matrix methods `Mat4::look_at_lh` and `Mat4::look_at_rh`. ### Added * Added support for building infinite projection matrices, including both standard and reverse depth `Mat4::perspective_infinite_rh` and `Mat4::perspective_infinite_rh`. * Added `Vec2Mask::new`, `Vec3Mask::new` and `Vec4Mask::new` methods. * Implemented `std::ops` `BitAnd`, `BitAndAssign`, `BitOr`, `BitOrAssign` and `Not` traits for `Vec2Mask`, `Vec3Mask` and `Vec4Mask`. * Added method documentation for `Vec4` and `Vec4Mask` types. * Added missing `serde` implementations for `Mat2`, `Mat3` and `Mat4`. * Updated `rand` and `criterion` versions. ## [0.7.1] - 2019-07-08 ### Fixed * The SSE2 implementation of `Vec4` `dot` was missing a shuffle, meaning the `dot`, `length`, `length_squared`, `length_reciprocal` and `normalize` methods were sometimes incorrect. ### Added * Added the `glam_assert` macro which behaves like Rust's `debug_assert` but can be enabled separately to `debug_assert`. This is used to perform asserts on correctness. * Added `is_normalized` method to `Vec2`, `Vec3` and `Vec4`. ### Changed * Replaced usage of `std::mem::uninitialized` with `std::mem::MaybeUninit`. This change requires stable Rust 1.36. * Renamed `Vec2b` to `Vec2Mask`, `Vec3b` to `Vec3Mask` and `Vec4b` to `Vec4Mask`. Old names are aliased to the new name and deprecated. * Deprecate `VecNMask` `mask` method, use new `bitmask` method instead * Made fallback version of `VecNMask` types the same size and alignment as the SIMD versions. * Added `Default` support to `VecNMask` types, will add more common traits in the future. * Added `#[inline]` to `mat2`, `mat3` and `mat4` functions. ## [0.7.0] - 2019-06-28 ### Added * Added `Mat2` into `[f32; 4]`, `Mat3` into `[f32; 9]` and `Mat4` into `[f32; 16]`. ### Removed * Removed `impl Mul<&Vec2> for Mat2` and `impl Mul<&Vec3> for Vec3` as these don't exist for any other types. ## [0.6.1] - 2019-06-22 ### Changed * `Mat2` now uses a `Vec4` internally which gives it some performance improvements when SSE2 is available. ## 0.6.0 - 2019-06-13 ### Changed * Switched from row vectors to column vectors * Vectors are now on the right of multiplications with matrices and quaternions. [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.30.1...HEAD [0.30.1]: https://github.com/bitshifter/glam-rs/compare/0.30.0...0.30.1 [0.30.0]: https://github.com/bitshifter/glam-rs/compare/0.29.2...0.30.0 [0.29.2]: https://github.com/bitshifter/glam-rs/compare/0.29.1...0.29.2 [0.29.1]: https://github.com/bitshifter/glam-rs/compare/0.29.0...0.29.1 [0.29.0]: https://github.com/bitshifter/glam-rs/compare/0.28.0...0.29.0 [0.28.0]: https://github.com/bitshifter/glam-rs/compare/0.27.0...0.28.0 [0.27.0]: https://github.com/bitshifter/glam-rs/compare/0.26.0...0.27.0 [0.26.0]: https://github.com/bitshifter/glam-rs/compare/0.25.0...0.26.0 [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 [0.21.2]: https://github.com/bitshifter/glam-rs/compare/0.21.1...0.21.2 [0.21.1]: https://github.com/bitshifter/glam-rs/compare/0.21.0...0.21.1 [0.21.0]: https://github.com/bitshifter/glam-rs/compare/0.20.5...0.21.0 [0.20.5]: https://github.com/bitshifter/glam-rs/compare/0.20.4...0.20.5 [0.20.4]: https://github.com/bitshifter/glam-rs/compare/0.20.3...0.20.4 [0.20.3]: https://github.com/bitshifter/glam-rs/compare/0.20.2...0.20.3 [0.20.2]: https://github.com/bitshifter/glam-rs/compare/0.20.1...0.20.2 [0.20.1]: https://github.com/bitshifter/glam-rs/compare/0.20.0...0.20.1 [0.20.0]: https://github.com/bitshifter/glam-rs/compare/0.19.0...0.20.0 [0.19.0]: https://github.com/bitshifter/glam-rs/compare/0.18.0...0.19.0 [0.18.0]: https://github.com/bitshifter/glam-rs/compare/0.17.3...0.18.0 [0.17.3]: https://github.com/bitshifter/glam-rs/compare/0.17.2...0.17.3 [0.17.2]: https://github.com/bitshifter/glam-rs/compare/0.17.1...0.17.2 [0.17.1]: https://github.com/bitshifter/glam-rs/compare/0.17.0...0.17.1 [0.17.0]: https://github.com/bitshifter/glam-rs/compare/0.16.0...0.17.0 [0.16.0]: https://github.com/bitshifter/glam-rs/compare/0.15.2...0.16.0 [0.15.2]: https://github.com/bitshifter/glam-rs/compare/0.15.1...0.15.2 [0.15.1]: https://github.com/bitshifter/glam-rs/compare/0.15.0...0.15.1 [0.15.0]: https://github.com/bitshifter/glam-rs/compare/0.14.0...0.15.0 [0.14.0]: https://github.com/bitshifter/glam-rs/compare/0.13.1...0.14.0 [0.13.1]: https://github.com/bitshifter/glam-rs/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/bitshifter/glam-rs/compare/0.12.0...0.13.0 [0.12.0]: https://github.com/bitshifter/glam-rs/compare/0.11.3...0.12.0 [0.11.3]: https://github.com/bitshifter/glam-rs/compare/0.11.2...0.11.3 [0.11.2]: https://github.com/bitshifter/glam-rs/compare/0.11.1...0.11.2 [0.11.1]: https://github.com/bitshifter/glam-rs/compare/0.11.0...0.11.1 [0.11.0]: https://github.com/bitshifter/glam-rs/compare/0.10.2...0.11.0 [0.10.2]: https://github.com/bitshifter/glam-rs/compare/0.10.1...0.10.2 [0.10.1]: https://github.com/bitshifter/glam-rs/compare/0.10.0...0.10.1 [0.10.0]: https://github.com/bitshifter/glam-rs/compare/0.9.5...0.10.0 [0.9.5]: https://github.com/bitshifter/glam-rs/compare/0.9.4...0.9.5 [0.9.4]: https://github.com/bitshifter/glam-rs/compare/0.9.3...0.9.4 [0.9.3]: https://github.com/bitshifter/glam-rs/compare/0.9.2...0.9.3 [0.9.2]: https://github.com/bitshifter/glam-rs/compare/0.9.1...0.9.2 [0.9.1]: https://github.com/bitshifter/glam-rs/compare/0.9.0...0.9.1 [0.9.0]: https://github.com/bitshifter/glam-rs/compare/0.8.7...0.9.0 [0.8.7]: https://github.com/bitshifter/glam-rs/compare/0.8.6...0.8.7 [0.8.6]: https://github.com/bitshifter/glam-rs/compare/0.8.5...0.8.6 [0.8.5]: https://github.com/bitshifter/glam-rs/compare/0.8.4...0.8.5 [0.8.4]: https://github.com/bitshifter/glam-rs/compare/0.8.3...0.8.4 [0.8.3]: https://github.com/bitshifter/glam-rs/compare/0.8.2...0.8.3 [0.8.2]: https://github.com/bitshifter/glam-rs/compare/0.8.1...0.8.2 [0.8.1]: https://github.com/bitshifter/glam-rs/compare/0.8.0...0.8.1 [0.8.0]: https://github.com/bitshifter/glam-rs/compare/0.7.2...0.8.0 [0.7.2]: https://github.com/bitshifter/glam-rs/compare/0.7.1...0.7.2 [0.7.1]: https://github.com/bitshifter/glam-rs/compare/0.7.0...0.7.1 [0.7.0]: https://github.com/bitshifter/glam-rs/compare/0.6.1...0.7.0 [0.6.1]: https://github.com/bitshifter/glam-rs/compare/0.6.0...0.6.1 glam-0.30.1/CODE_OF_CONDUCT.md000064400000000000000000000121221046102023000134220ustar 00000000000000# Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at . All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. glam-0.30.1/CONTRIBUTING.md000064400000000000000000000043721046102023000130640ustar 00000000000000# Contributing to glam Thanks for contributing to `glam`! These guidelines will try to make the process painless and efficient. The short guide to contributing is [start a discussion] on GitHub. Pull requests are welcome for bug fixes, documentation improvements and optimizations. For anything else it would be best to discuss it first. ## Questions If you have a question about the usage of this library please [ask a question] with GitHub Discussions. That's the easiest way to get support right now. ## Bugs If you find a bug please [open an issue] on GitHub or submit a pull request. A unit test for any bug that slipped through existing coverage would also be greatly appreciated. ## New functions and methods If `glam` is missing functionality on existing types, [suggest a new feature] with GitHub Discussions describing what feature you would like added and ideally what your use case is for it just so I have a better understanding of the feature. I'd like to keep `glam` reasonably light functionality wise initially but commonly used functionality that is missing is very welcome. If you do submit a pull request please ensure any new functionality also has a test. ## Optimizations If you feel some functionality could be optimized please [open an issue] on GitHub or submit a pull request. Any optimization pull request should include a benchmark if there isn't one already, so I can confirm the performance improvement. ## Documentation If you feel any documentation could be added or improved please [open a GitHub issue] or submit a pull request. ## Code contributions Most of `glam`'s source code is generated. See the [codegen README] on how to modify the code templates and generate new source code. You can run some of `glam`'s test suite locally by running the `build_and_test_features.sh` script. It's worth running that before creating a PR. Also run `cargo fmt` and `cargo clippy` on any new code. [start a discussion]: https://github.com/bitshifter/glam-rs/discussions/new [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 [codegen README]: codegen/README.md glam-0.30.1/Cargo.lock0000644000000611170000000000100100160ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anes" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" dependencies = [ "num-traits", ] [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bincode" version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ "serde", ] [[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50690fb3370fb9fe3550372746084c46f2ac8c9685c583d2be10eefd89d3d1a3" dependencies = [ "bytecheck_derive", "ptr_meta", "rancor", "simdutf8", ] [[package]] name = "bytecheck_derive" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "bytemuck" version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "shlex", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "ciborium" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", "serde", ] [[package]] name = "ciborium-io" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", "half", ] [[package]] name = "clap" version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd" dependencies = [ "anstyle", "clap_lex", ] [[package]] name = "clap_lex" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "criterion" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", "cast", "ciborium", "clap", "criterion-plot", "is-terminal", "itertools", "num-traits", "once_cell", "oorandom", "plotters", "rayon", "regex", "serde", "serde_derive", "serde_json", "tinytemplate", "walkdir", ] [[package]] name = "criterion-plot" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", "itertools", ] [[package]] name = "crossbeam-deque" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "derive_more" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "glam" version = "0.30.1" dependencies = [ "approx", "bytemuck", "criterion", "iai-callgrind", "libm", "mint", "rand", "rand_xoshiro", "rkyv", "serde", "serde_json", "wasm-bindgen-test", ] [[package]] name = "half" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", ] [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "hermit-abi" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "iai-callgrind" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22275f8051874cd2f05b2aa1e0098d5cbec34df30ff92f1a1e2686a4cefed870" dependencies = [ "bincode", "derive_more", "iai-callgrind-macros", "iai-callgrind-runner", ] [[package]] name = "iai-callgrind-macros" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8e6677dc52bd798b988e62ffd6831bf7eb46e4348cb1c74c1164954ebd0e5a1" dependencies = [ "derive_more", "proc-macro-error2", "proc-macro2", "quote", "serde", "serde_json", "syn", ] [[package]] name = "iai-callgrind-runner" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a02dd95fe4949513b45a328b5b18f527ee02e96f3428b48090aa7cf9043ab0b8" dependencies = [ "serde", ] [[package]] name = "is-terminal" version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ "hermit-abi", "libc", "windows-sys 0.52.0", ] [[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ "once_cell", "wasm-bindgen", ] [[package]] name = "libc" version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "log" version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minicov" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" dependencies = [ "cc", "walkdir", ] [[package]] name = "mint" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] name = "munge" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0091202c98cf06da46c279fdf50cccb6b1c43b4521abdf6a27b4c7e71d5d9d7" dependencies = [ "munge_macro", ] [[package]] name = "munge_macro" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "734799cf91479720b2f970c61a22850940dd91e27d4f02b1c6fc792778df2459" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "num-traits" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "plotters" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", "plotters-svg", "wasm-bindgen", "web-sys", ] [[package]] name = "plotters-backend" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "proc-macro-error-attr2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" dependencies = [ "proc-macro2", "quote", ] [[package]] name = "proc-macro-error2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", "syn", ] [[package]] name = "proc-macro2" version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "ptr_meta" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" dependencies = [ "ptr_meta_derive", ] [[package]] name = "ptr_meta_derive" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "quote" version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "rancor" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" dependencies = [ "ptr_meta", ] [[package]] name = "rand" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" dependencies = [ "rand_core", "zerocopy", ] [[package]] name = "rand_core" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" [[package]] name = "rand_xoshiro" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" dependencies = [ "rand_core", ] [[package]] name = "rayon" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", ] [[package]] name = "rayon-core" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rend" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" dependencies = [ "bytecheck", "hashbrown", "munge", "ptr_meta", "rancor", "rend", "rkyv_derive", "tinyvec", ] [[package]] name = "rkyv_derive" version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "scoped-tls" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "serde" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", "ryu", "serde", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simdutf8" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "syn" version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tinytemplate" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ "serde", "serde_json", ] [[package]] name = "tinyvec" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasm-bindgen" version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", "proc-macro2", "quote", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-bindgen-test" version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d44563646eb934577f2772656c7ad5e9c90fac78aa8013d776fcdaf24625d" dependencies = [ "js-sys", "minicov", "scoped-tls", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", ] [[package]] name = "wasm-bindgen-test-macro" version = "0.3.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54171416ce73aa0b9c377b51cc3cb542becee1cd678204812e8392e5b0e4a031" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "web-sys" version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] name = "winapi-util" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "zerocopy" version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09612fda0b63f7cb9e0af7e5916fe5a1f8cdcb066829f10f36883207628a4872" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79f81d38d7a2ed52d8f034e62c568e111df9bf8aba2f7cf19ddc5bf7bd89d520" dependencies = [ "proc-macro2", "quote", "syn", ] glam-0.30.1/Cargo.toml0000644000000110460000000000100100350ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.68.2" name = "glam" version = "0.30.1" authors = ["Cameron Hart "] build = false autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "A simple and fast 3D math library for games and graphics" readme = "README.md" keywords = [ "gamedev", "math", "matrix", "vector", "quaternion", ] categories = [ "game-engines", "no-std", ] license = "MIT OR Apache-2.0" repository = "https://github.com/bitshifter/glam-rs" [badges.maintenance] status = "actively-developed" [features] bytecheck = ["rkyv/bytecheck"] core-simd = [] cuda = [] debug-glam-assert = [] default = ["std"] fast-math = [] glam-assert = [] libm = ["dep:libm"] nostd-libm = ["dep:libm"] scalar-math = [] std = [] [lib] name = "glam" path = "src/lib.rs" bench = false [[test]] name = "affine2" path = "tests/affine2.rs" [[test]] name = "affine3" path = "tests/affine3.rs" [[test]] name = "euler" path = "tests/euler.rs" [[test]] name = "float" path = "tests/float.rs" [[test]] name = "mat2" path = "tests/mat2.rs" [[test]] name = "mat3" path = "tests/mat3.rs" [[test]] name = "mat4" path = "tests/mat4.rs" [[test]] name = "quat" path = "tests/quat.rs" [[test]] name = "support" path = "tests/support.rs" [[test]] name = "swizzles_f32" path = "tests/swizzles_f32.rs" [[test]] name = "swizzles_f64" path = "tests/swizzles_f64.rs" [[test]] name = "swizzles_i16" path = "tests/swizzles_i16.rs" [[test]] name = "swizzles_i32" path = "tests/swizzles_i32.rs" [[test]] name = "swizzles_i64" path = "tests/swizzles_i64.rs" [[test]] name = "swizzles_i8" path = "tests/swizzles_i8.rs" [[test]] name = "swizzles_u16" path = "tests/swizzles_u16.rs" [[test]] name = "swizzles_u32" path = "tests/swizzles_u32.rs" [[test]] name = "swizzles_u64" path = "tests/swizzles_u64.rs" [[test]] name = "swizzles_u8" path = "tests/swizzles_u8.rs" [[test]] name = "swizzles_usize" path = "tests/swizzles_usize.rs" [[test]] name = "vec2" path = "tests/vec2.rs" [[test]] name = "vec3" path = "tests/vec3.rs" [[test]] name = "vec4" path = "tests/vec4.rs" [[bench]] name = "affine2" path = "benches/affine2.rs" harness = false [[bench]] name = "affine3" path = "benches/affine3.rs" harness = false [[bench]] name = "iai" path = "benches/iai.rs" harness = false [[bench]] name = "mat2" path = "benches/mat2.rs" harness = false [[bench]] name = "mat3" path = "benches/mat3.rs" harness = false [[bench]] name = "mat3a" path = "benches/mat3a.rs" harness = false [[bench]] name = "mat4" path = "benches/mat4.rs" harness = false [[bench]] name = "quat" path = "benches/quat.rs" harness = false [[bench]] name = "support" path = "benches/support.rs" bench = false [[bench]] name = "vec2" path = "benches/vec2.rs" harness = false [[bench]] name = "vec3" path = "benches/vec3.rs" harness = false [[bench]] name = "vec3a" path = "benches/vec3a.rs" harness = false [[bench]] name = "vec4" path = "benches/vec4.rs" harness = false [dependencies.approx] version = "0.5" optional = true default-features = false [dependencies.bytemuck] version = "1.9" optional = true default-features = false [dependencies.libm] version = "0.2" optional = true default-features = false [dependencies.mint] version = "0.5.8" optional = true default-features = false [dependencies.rand] version = "0.9" optional = true default-features = false [dependencies.rkyv] version = "0.8" optional = true default-features = false [dependencies.serde] version = "1.0" optional = true default-features = false [dev-dependencies.rand_xoshiro] version = "0.7" [dev-dependencies.rkyv] version = "0.8" features = ["alloc"] default-features = false [dev-dependencies.serde_json] version = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.criterion] version = "0.5" features = ["html_reports"] [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies.iai-callgrind] version = "0.14" [target.'cfg(target_arch = "wasm32")'.dev-dependencies.wasm-bindgen-test] version = "0.3" [lints.rust.unexpected_cfgs] level = "warn" priority = 0 check-cfg = ['cfg(target_arch, values("spirv"))'] glam-0.30.1/Cargo.toml.orig000064400000000000000000000061611046102023000135200ustar 00000000000000[package] name = "glam" version = "0.30.1" # remember to update html_root_url edition = "2021" authors = ["Cameron Hart "] description = "A simple and fast 3D math library for games and graphics" repository = "https://github.com/bitshifter/glam-rs" readme = "README.md" license = "MIT OR Apache-2.0" keywords = ["gamedev", "math", "matrix", "vector", "quaternion"] categories = ["game-engines", "no-std"] rust-version = "1.68.2" [badges] maintenance = { status = "actively-developed" } [features] default = ["std"] # enable support for the standard library std = [] # enable additional glam checks if debug assertions are enabled debug-glam-assert = [] # always enable additional glam checks glam-assert = [] # this is primarily for testing the fallback implementation scalar-math = [] # align types to match CUDA requirements cuda = [] # Enables platform specific optimizations that might speed-up certain operations. # This will cause APIs to output different results depending on the platform used # and will likely break cross-platform determinism. # This should NOT be enabled by intermediate libraries, deferring the decision to # the end binary build instead. fast-math = [] # experimental nightly portable-simd support core-simd = [] bytecheck = ["rkyv/bytecheck"] # enables libm and prefers it over std libm = ["dep:libm"] # enables libm but will prefer std if available nostd-libm = ["dep:libm"] [dependencies] approx = { version = "0.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 } rand = { version = "0.9", optional = true, default-features = false } serde = { version = "1.0", optional = true, default-features = false } rkyv = { version = "0.8", 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.7" # "alloc" is needed to support to_bytes()/deserialize() in tests. rkyv = { version = "0.8", default-features = false, features = ["alloc"] } serde_json = "1.0" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] criterion = { version = "0.5", features = ["html_reports"] } iai-callgrind = "0.14" [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3" [lib] bench = false [[bench]] name = "mat2" harness = false [[bench]] name = "mat3" harness = false [[bench]] name = "mat3a" harness = false [[bench]] name = "affine2" harness = false [[bench]] name = "affine3" harness = false [[bench]] name = "mat4" harness = false [[bench]] name = "quat" harness = false [[bench]] name = "support" bench = false [[bench]] name = "vec2" harness = false [[bench]] name = "vec3" harness = false [[bench]] name = "vec3a" harness = false [[bench]] name = "vec4" harness = false [[bench]] name = "iai" harness = false [workspace] members = [ "codegen", "swizzlegen", "test_no_std", ] [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_arch, values("spirv"))'] } glam-0.30.1/LICENSE-APACHE000064400000000000000000000251221046102023000125530ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2020 Cameron Hart Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. glam-0.30.1/LICENSE-MIT000064400000000000000000000017771046102023000122750ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. glam-0.30.1/README.md000064400000000000000000000247311046102023000121130ustar 00000000000000# glam [![Build Status]][github-ci] [![Coverage Status]][coveralls.io] [![Latest Version]][crates.io] [![docs]][docs.rs] [![Minimum Supported Rust Version]][Rust 1.68.2] A simple and fast 3D math library for games and graphics. ## Development status `glam` is in beta stage. Base functionality has been implemented and the look and feel of the API has solidified. ## Features * `f32` types * vectors: `Vec2`, `Vec3`, `Vec3A` and `Vec4` * square matrices: `Mat2`, `Mat3`, `Mat3A` and `Mat4` * a quaternion type: `Quat` * affine transformation types: `Affine2` and `Affine3A` * `f64` types * vectors: `DVec2`, `DVec3` and `DVec4` * square matrices: `DMat2`, `DMat3` and `DMat4` * a quaternion type: `DQuat` * affine transformation types: `DAffine2` and `DAffine3` * `i8` types * vectors: `I8Vec2`, `I8Vec3` and `I8Vec4` * `u8` types * vectors: `U16Vec2`, `U16Vec3` and `U16Vec4` * `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` * `usize` types * vectors: `USizeVec2`, `USizeVec3` and `USizeVec4` * `bool` types * vectors: `BVec2`, `BVec3` and `BVec4` ### SIMD The `Vec3A`, `Vec4`, `Quat`, `Mat2`, `Mat3A`, `Mat4`, `Affine2` and `Affine3A` types use 128-bit wide SIMD vector types for storage on `x86`, `x86_64` and `wasm32` architectures. As a result, these types are all 16 byte aligned and depending on the size of the type or the type's members, they may contain internal padding. This results in some wasted space in the cases of `Vec3A`, `Mat3A`, `Affine2` and `Affine3A`. However, the use of SIMD generally results in better performance than scalar math. `glam` outperforms similar Rust libraries for common operations as tested by the [`mathbench`][mathbench] project. [mathbench]: https://github.com/bitshifter/mathbench-rs ### Enabling SIMD SIMD is supported on `x86`, `x86_64` and `wasm32` targets. * `SSE2` is enabled by default on `x86_64` targets. * To enable `SSE2` on `x86` targets add `-C target-feature=+sse2` to `RUSTCFLAGS`. * `NEON` is enabled by default on `aarch64` targets. * To enable `NEON` on `aarch64` targets add `-C target-feature=+neon` to `RUSTFLAGS`. * To enable `simd128` on `wasm32` targets add `-C target-feature=+simd128` to `RUSTFLAGS`. * Experimental [portable simd] support can be enabled with the `core-simd` feature. This requires the nightly compiler as it is still unstable in Rust. Note that SIMD on `wasm32` passes tests but has not been benchmarked, performance may or may not be better than scalar math. [portable simd]: https://doc.rust-lang.org/core/simd/index.html ### `no_std` support `no_std` support can be enabled by compiling with `--no-default-features` to disable `std` support and `--features libm` for math functions that are only defined in `std`. For example: ```toml [dependencies] glam = { version = "0.30.1", default-features = false, features = ["libm"] } ``` To support both `std` and `no_std` builds in project, you can use the following in your `Cargo.toml`: ```toml [features] default = ["std"] std = ["glam/std"] libm = ["glam/libm"] [dependencies] glam = { version = "0.30.1", default-features = false } ``` Alternatively, you can use the `nostd-libm` feature. This will always include a `libm` dependency, but allows the user to still override it with `std` if they prefer. This will allow your crate to compile with default features disabled, instead of forcing the user to enable either `std` or `libm`. ```toml [features] default = ["std"] std = ["glam/std"] libm = ["glam/libm"] [dependencies] glam = { version = "0.30.1", default-features = false, features = ["nostd-libm"] } ``` ### Optional features * [`approx`] - traits and macros for approximate float comparisons * [`bytemuck`] - for casting into slices of bytes * [`libm`] - uses `libm` math functions instead of `std` * [`nostd-libm`] - uses `libm` math functions if `std` is not available * [`mint`] - for interoperating with other 3D math libraries * [`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 * [`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 [`rand`]: https://github.com/rust-random/rand [`serde`]: https://serde.rs [`rkyv`]: https://github.com/rkyv/rkyv [`bytecheck`]: https://github.com/rkyv/bytecheck ### Feature gates * `scalar-math` - compiles with SIMD support disabled * `debug-glam-assert` - adds assertions in debug builds which check the validity of parameters passed to `glam` to help catch runtime errors * `glam-assert` - adds validation assertions to all builds * `cuda` - forces `glam` types to match expected [cuda alignment] * `fast-math` - By default, glam attempts to provide bit-for-bit identical results on all platforms. Using this feature will enable platform specific optimizations that may not be identical to other platforms. **Intermediate libraries should not use this feature and defer the decision to the final binary build**. * `core-simd` - enables SIMD support via the [portable simd] module. This is an unstable feature which requires a nightly Rust toolchain and `std` support. [cuda alignment]: https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#built-in-vector-types ### Minimum Supported Rust Version (MSRV) The minimum supported version of Rust for `glam` is `1.68.2`. ## Conventions ### Column vectors `glam` interprets vectors as column matrices (also known as "column vectors") meaning when transforming a vector with a matrix the matrix goes on the left, e.g. `v' = Mv`. DirectX uses row vectors, OpenGL uses column vectors. There are pros and cons to both. ### Column-major order Matrices are stored in column major format. Each column vector is stored in contiguous memory. ### Co-ordinate system `glam` is co-ordinate system agnostic and intends to support both right-handed and left-handed conventions. ## Design Philosophy The design of this library is guided by a desire for simplicity and good performance. * No generics and minimal traits in the public API for simplicity of usage * All dependencies are optional (e.g. `mint`, `rand` and `serde`) * Follows the [Rust API Guidelines] where possible * Aiming for 100% test [coverage] * Common functionality is benchmarked using [Criterion.rs] [Rust API Guidelines]: https://rust-lang-nursery.github.io/api-guidelines/ [coverage]: coveralls.io [Criterion.rs]: https://bheisler.github.io/criterion.rs/book/index.html ## Architecture See [ARCHITECTURE.md] for details on `glam`'s internals. [ARCHITECTURE.md]: ARCHITECTURE.md ## Inspirations There were many inspirations for the interface and internals of glam from the Rust and C++ worlds. In particular: * [How to write a maths library in 2016] inspired the initial `Vec3A` implementation * [Realtime Math] - header only C++11 with SSE and NEON SIMD intrinsic support * [DirectXMath] - header only SIMD C++ linear algebra library for use in games and graphics apps * `glam` is a play on the name of the popular C++ library [GLM] [How to write a maths library in 2016]: http://www.codersnotes.com/notes/maths-lib-2016/ [Realtime Math]: https://github.com/nfrechette/rtm [DirectXMath]: https://docs.microsoft.com/en-us/windows/desktop/dxmath/directxmath-portal [GLM]: https://glm.g-truc.net ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ## Contribution Contributions in any form (issues, pull requests, etc.) to this project must adhere to Rust's [Code of Conduct]. Unless you explicitly state otherwise, any contribution intentionally submitted 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. 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`. [Game Development in Rust Discord]: https://discord.gg/yNtPTb2 [Bevy Engine Discord]: https://discord.gg/gMUk5Ph ## Attribution `glam` contains code ported from the following C++ libraries: * [DirectXMath] - MIT License - Copyright (c) 2011-2020 Microsoft Corp * [Realtime Math] - MIT License - Copyright (c) 2018 Nicholas Frechette * [GLM] - MIT License - Copyright (c) 2005 - G-Truc Creation See [ATTRIBUTION.md] for details. [ATTRIBUTION.md]: ATTRIBUTION.md [Build Status]: https://github.com/bitshifter/glam-rs/actions/workflows/ci.yml/badge.svg [github-ci]: https://github.com/bitshifter/glam-rs/actions/workflows/ci.yml [Coverage Status]: https://coveralls.io/repos/github/bitshifter/glam-rs/badge.svg?branch=main [coveralls.io]: https://coveralls.io/github/bitshifter/glam-rs?branch=main [Latest Version]: https://img.shields.io/crates/v/glam.svg [crates.io]: https://crates.io/crates/glam/ [docs]: https://docs.rs/glam/badge.svg [docs.rs]: https://docs.rs/glam/ [Minimum Supported Rust Version]: https://img.shields.io/badge/Rust-1.68.2-blue?color=fc8d62&logo=rust [Rust 1.68.2]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1682-2023-03-28 glam-0.30.1/benches/affine2.rs000064400000000000000000000043321046102023000141160ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Affine2; use std::ops::Mul; use support::*; pub fn random_srt_affine2(rng: &mut PCG32) -> Affine2 { Affine2::from_scale_angle_translation( random_nonzero_vec2(rng), random_radians(rng), random_vec2(rng), ) } bench_unop!(affine2_inverse, "affine2 inverse", op => inverse, from => random_srt_affine2); bench_binop!( affine2_transform_point2, "affine2 transform point2", op => transform_point2, from1 => random_srt_affine2, from2 => random_vec2 ); bench_binop!( affine2_transform_vector2, "affine2 transform vector2", op => transform_vector2, from1 => random_srt_affine2, from2 => random_vec2 ); bench_binop!(affine2_mul_affine2, "affine2 mul affine2", op => mul, from => random_srt_affine2); bench_binop!(affine2_mul_mat3, "affine2 mul mat3", op => mul, from1 => random_srt_affine2, from2 => random_srt_mat3); bench_binop!(mat3_mul_affine2, "mat3 mul affine2", op => mul, from1 => random_srt_mat3, from2 => random_srt_affine2); pub fn affine2_from_srt(c: &mut Criterion) { use glam::Vec2; const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs = criterion::black_box( (0..SIZE) .map(|_| { ( random_nonzero_vec2(&mut rng), random_radians(&mut rng), random_vec2(&mut rng), ) }) .collect::>(), ); let mut outputs = vec![Affine2::default(); SIZE]; let mut i = 0; c.bench_function("affine2 from srt", |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { let data = inputs.get_unchecked(i); *outputs.get_unchecked_mut(i) = Affine2::from_scale_angle_translation(data.0, data.1, data.2); } }); }); } criterion_group!( benches, affine2_inverse, affine2_transform_point2, affine2_transform_vector2, affine2_mul_affine2, affine2_mul_mat3, mat3_mul_affine2, affine2_from_srt, ); criterion_main!(benches); glam-0.30.1/benches/affine3.rs000064400000000000000000000053411046102023000141200ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Affine3A; use std::ops::Mul; use support::*; pub fn random_srt_affine3a(rng: &mut PCG32) -> Affine3A { Affine3A::from_scale_rotation_translation( random_nonzero_vec3(rng), random_quat(rng), random_vec3(rng), ) } bench_unop!(affine3a_inverse, "affine3a inverse", op => inverse, from => random_srt_affine3a); bench_binop!( affine3a_transform_point3, "affine3a transform point3", op => transform_point3, from1 => random_srt_affine3a, from2 => random_vec3 ); bench_binop!( affine3a_transform_vector3, "affine3a transform vector3", op => transform_vector3, from1 => random_srt_affine3a, from2 => random_vec3 ); bench_binop!( affine3a_transform_point3a, "affine3a transform point3a", op => transform_point3a, from1 => random_srt_affine3a, from2 => random_vec3a ); bench_binop!( affine3a_transform_vector3a, "affine3a transform vector3a", op => transform_vector3a, from1 => random_srt_affine3a, from2 => random_vec3a ); bench_binop!( affine3a_mul_affine3a, "affine3a mul affine3a", op => mul, from => random_srt_affine3a ); bench_binop!(affine3a_mul_mat4, "affine3a mul mat4", op => mul, from1 => random_srt_affine3a, from2 => random_srt_mat4 ); bench_binop!( mat4_mul_affine3a, "mat4 mul affine3a", op => mul, from1 => random_srt_mat4, from2 => random_srt_affine3a ); pub fn affine3a_from_srt(c: &mut Criterion) { use glam::{Quat, Vec3}; const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs = criterion::black_box( (0..SIZE) .map(|_| { ( random_nonzero_vec3(&mut rng), random_quat(&mut rng), random_vec3(&mut rng), ) }) .collect::>(), ); let mut outputs = vec![Affine3A::IDENTITY; SIZE]; let mut i = 0; c.bench_function("affine3a from srt", |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { let data = inputs.get_unchecked(i); *outputs.get_unchecked_mut(i) = Affine3A::from_scale_rotation_translation(data.0, data.1, data.2); } }); }); } criterion_group!( benches, affine3a_from_srt, affine3a_inverse, affine3a_mul_affine3a, affine3a_mul_mat4, affine3a_transform_point3, affine3a_transform_point3a, affine3a_transform_vector3, affine3a_transform_vector3a, mat4_mul_affine3a, ); criterion_main!(benches); glam-0.30.1/benches/iai.rs000064400000000000000000000126251046102023000133520ustar 00000000000000#![allow(clippy::all)] use core::hint::black_box; use iai_callgrind::{library_benchmark, library_benchmark_group, main}; use glam::{BVec3A, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3A, Vec4}; #[cfg(feature = "scalar-math")] use glam::BVec4 as BVec4A; #[cfg(not(feature = "scalar-math"))] use glam::BVec4A; #[inline] fn mat2() -> Mat2 { black_box(Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0])) } #[inline] fn mat3a() -> Mat3A { black_box(Mat3A::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, ])) } #[inline] fn mat4() -> Mat4 { black_box(Mat4::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, ])) } #[inline] fn quat() -> Quat { black_box(Quat::from_xyzw(0.0, 0.0, 0.0, 1.0)) } #[inline] fn vec2() -> Vec2 { black_box(Vec2::new(1.0, 2.0)) } #[inline] fn vec3a() -> Vec3A { black_box(Vec3A::new(1.0, 2.0, 3.0)) } #[inline] fn bvec3a() -> BVec3A { black_box(BVec3A::new(true, false, true)) } #[inline] fn vec4() -> Vec4 { black_box(Vec4::new(1.0, 2.0, 3.0, 4.0)) } #[inline] fn bvec4a() -> BVec4A { black_box(BVec4A::new(true, false, true, false)) } #[library_benchmark] #[bench::args(mat2())] fn mat2_determinant(m: Mat2) -> f32 { black_box(m.determinant()) } #[library_benchmark] #[bench::args(mat2())] fn mat2_inverse(m: Mat2) -> Mat2 { black_box(m.inverse()) } #[library_benchmark] #[bench::args(mat2())] fn mat2_transpose(m: Mat2) -> Mat2 { black_box(m.transpose()) } #[library_benchmark] #[bench::args(mat2(), mat2())] fn mat2_mul_mat2(m1: Mat2, m2: Mat2) -> Mat2 { black_box(m1 * m2) } #[library_benchmark] #[bench::args(mat2(), vec2())] fn mat2_mul_vec2(m: Mat2, v: Vec2) -> Vec2 { black_box(m * v) } #[library_benchmark] #[bench::args(mat3a())] fn mat3a_determinant(m: Mat3A) -> f32 { black_box(m.determinant()) } #[library_benchmark] #[bench::args(mat3a())] fn mat3a_inverse(m: Mat3A) -> Mat3A { black_box(m.inverse()) } #[library_benchmark] #[bench::args(mat3a())] fn mat3a_transpose(m: Mat3A) -> Mat3A { black_box(m.transpose()) } #[library_benchmark] #[bench::args(mat3a(), mat3a())] fn mat3a_mul_mat3a(m1: Mat3A, m2: Mat3A) -> Mat3A { black_box(m1 * m2) } #[library_benchmark] #[bench::args(mat3a(), vec3a())] fn mat3a_mul_vec3a(m: Mat3A, v: Vec3A) -> Vec3A { black_box(m * v) } #[library_benchmark] #[bench::args(mat4())] fn mat4_determinant(m: Mat4) -> f32 { black_box(m.determinant()) } #[library_benchmark] #[bench::args(mat4())] fn mat4_inverse(m: Mat4) -> Mat4 { black_box(m.inverse()) } #[library_benchmark] #[bench::args(mat4())] fn mat4_transpose(m: Mat4) -> Mat4 { black_box(m.transpose()) } #[library_benchmark] #[bench::args(mat4(), mat4())] fn mat4_mul_mat4(m1: Mat4, m2: Mat4) -> Mat4 { black_box(m1 * m2) } #[library_benchmark] #[bench::args(mat4(), vec4())] fn mat4_mul_vec4(m: Mat4, v: Vec4) -> Vec4 { black_box(m * v) } #[library_benchmark] #[bench::args(quat(), quat())] fn quat_mul_quat(q1: Quat, q2: Quat) -> Quat { black_box(q1 * q2) } #[library_benchmark] #[bench::args(quat(), vec3a())] fn quat_mul_vec3a(q: Quat, v: Vec3A) -> Vec3A { black_box(q * v) } #[library_benchmark] #[bench::args(vec3a(), vec3a())] fn vec3a_dot(v1: Vec3A, v2: Vec3A) -> f32 { black_box(v1.dot(v2)) } #[library_benchmark] #[bench::args(vec3a(), vec3a())] fn vec3a_cross(v1: Vec3A, v2: Vec3A) -> Vec3A { black_box(v1.cross(v2)) } #[library_benchmark] #[bench::args(vec3a())] fn vec3a_length(v: Vec3A) -> f32 { black_box(v.length()) } #[library_benchmark] #[bench::args(vec3a())] fn vec3a_normalize(v: Vec3A) -> Vec3A { black_box(v.normalize()) } #[library_benchmark] #[bench::args(bvec3a(), vec3a(), vec3a())] fn vec3a_select(b: BVec3A, v1: Vec3A, v2: Vec3A) -> Vec3A { black_box(Vec3A::select(b, v1, v2)) } #[library_benchmark] #[bench::args(vec4(), vec4())] fn vec4_dot(v1: Vec4, v2: Vec4) -> f32 { black_box(v1.dot(v2)) } #[library_benchmark] #[bench::args(vec4())] fn vec4_length(v: Vec4) -> f32 { black_box(v.length()) } #[library_benchmark] #[bench::args(vec4())] fn vec4_normalize(v: Vec4) -> Vec4 { black_box(v.normalize()) } #[library_benchmark] #[bench::args(bvec4a(), vec4(), vec4())] fn vec4_select(b: BVec4A, v1: Vec4, v2: Vec4) -> Vec4 { black_box(Vec4::select(b, v1, v2)) } library_benchmark_group!( name = bench_mat2; benchmarks = mat2_determinant, mat2_inverse, mat2_mul_mat2, mat2_mul_vec2, mat2_transpose, ); library_benchmark_group!( name = bench_mat3a; benchmarks = mat3a_determinant, mat3a_inverse, mat3a_mul_mat3a, mat3a_mul_vec3a, mat3a_transpose, ); library_benchmark_group!( name = bench_mat4; benchmarks = mat4_determinant, mat4_inverse, mat4_mul_mat4, mat4_mul_vec4, mat4_transpose, ); library_benchmark_group!( name = bench_quat; benchmarks = quat_mul_quat, quat_mul_vec3a, ); library_benchmark_group!( name = bench_vec3a; benchmarks = vec3a_dot, vec3a_cross, vec3a_length, vec3a_normalize, vec3a_select, ); library_benchmark_group!( name = bench_vec4; benchmarks = vec4_dot, vec4_length, vec4_normalize, vec4_select, ); main!( library_benchmark_groups = bench_mat2, bench_mat3a, bench_mat4, bench_quat, bench_vec3a, bench_vec4 ); glam-0.30.1/benches/mat2.rs000064400000000000000000000014631046102023000134510ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use std::ops::Mul; use support::*; bench_binop!( mat2_mul_vec2, "mat2 mul vec2", op => mul, from1 => random_mat2, from2 => random_vec2 ); bench_unop!( mat2_transpose, "mat2 transpose", op => transpose, from => random_mat2 ); bench_unop!( mat2_determinant, "mat2 determinant", op => determinant, from => random_mat2 ); bench_unop!(mat2_inverse, "mat2 inverse", op => inverse, from => random_mat2); bench_binop!(mat2_mul_mat2, "mat2 mul mat2", op => mul, from => random_mat2); criterion_group!( benches, mat2_transpose, mat2_determinant, mat2_inverse, mat2_mul_vec2, mat2_mul_mat2, ); criterion_main!(benches); glam-0.30.1/benches/mat3.rs000064400000000000000000000026321046102023000134510ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Mat3; use std::ops::Mul; use support::*; bench_unop!( mat3_transpose, "mat3 transpose", op => transpose, from => random_mat3 ); bench_unop!( mat3_determinant, "mat3 determinant", op => determinant, from => random_mat3 ); bench_unop!(mat3_inverse, "mat3 inverse", op => inverse, from => random_mat3); bench_binop!(mat3_mul_mat3, "mat3 mul mat3", op => mul, from => random_mat3); bench_from_ypr!(mat3_from_ypr, "mat3 from ypr", ty => Mat3); bench_binop!( mat3_mul_vec3, "mat3 mul vec3", op => mul, from1 => random_mat3, from2 => random_vec3 ); bench_binop!( mat3_mul_vec3a, "mat3 mul vec3a", op => mul, from1 => random_mat3, from2 => random_vec3a ); bench_binop!( mat3_transform_point2, "mat3 transform point2", op => transform_point2, from1 => random_srt_mat3, from2 => random_vec2 ); bench_binop!( mat3_transform_vector2, "mat3 transform vector2", op => transform_vector2, from1 => random_srt_mat3, from2 => random_vec2 ); criterion_group!( benches, mat3_transpose, mat3_determinant, mat3_inverse, mat3_mul_vec3, mat3_mul_vec3a, mat3_mul_mat3, mat3_from_ypr, mat3_transform_vector2, mat3_transform_point2, ); criterion_main!(benches); glam-0.30.1/benches/mat3a.rs000064400000000000000000000027021046102023000136100ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Mat3A; use std::ops::Mul; use support::*; bench_unop!( mat3a_transpose, "mat3a transpose", op => transpose, from => random_mat3a ); bench_unop!( mat3a_determinant, "mat3a determinant", op => determinant, from => random_mat3a ); bench_unop!(mat3a_inverse, "mat3a inverse", op => inverse, from => random_mat3a); bench_binop!(mat3a_mul_mat3a, "mat3a mul mat3a", op => mul, from => random_mat3a); bench_from_ypr!(mat3a_from_ypr, "mat3a from ypr", ty => Mat3A); bench_binop!( mat3a_mul_vec3, "mat3a mul vec3", op => mul, from1 => random_mat3a, from2 => random_vec3 ); bench_binop!( mat3a_mul_vec3a, "mat3a mul vec3a", op => mul, from1 => random_mat3a, from2 => random_vec3a ); bench_binop!( mat3a_transform_point2, "mat3a transform point2", op => transform_point2, from1 => random_srt_mat3a, from2 => random_vec2 ); bench_binop!( mat3a_transform_vector2, "mat3a transform vector2", op => transform_vector2, from1 => random_srt_mat3a, from2 => random_vec2 ); criterion_group!( benches, mat3a_transpose, mat3a_determinant, mat3a_inverse, mat3a_mul_vec3, mat3a_mul_vec3a, mat3a_mul_mat3a, mat3a_from_ypr, mat3a_transform_vector2, mat3a_transform_point2, ); criterion_main!(benches); glam-0.30.1/benches/mat4.rs000064400000000000000000000051311046102023000134470ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Mat4; use std::ops::Mul; use support::*; bench_unop!( mat4_transpose, "mat4 transpose", op => transpose, from => random_srt_mat4 ); bench_unop!( mat4_determinant, "mat4 determinant", op => determinant, from => random_srt_mat4 ); bench_unop!( mat4_inverse, "mat4 inverse", op => inverse, from => random_srt_mat4 ); bench_binop!( mat4_mul_vec4, "mat4 mul vec4", op => mul, from1 => random_srt_mat4, from2 => random_vec4 ); bench_binop!( mat4_transform_point3, "mat4 transform point3", op => transform_point3, from1 => random_srt_mat4, from2 => random_vec3 ); bench_binop!( mat4_transform_vector3, "mat4 transform vector3", op => transform_vector3, from1 => random_srt_mat4, from2 => random_vec3 ); bench_binop!( mat4_transform_point3a, "mat4 transform point3a", op => transform_point3a, from1 => random_srt_mat4, from2 => random_vec3a ); bench_binop!( mat4_transform_vector3a, "mat4 transform vector3a", op => transform_vector3a, from1 => random_srt_mat4, from2 => random_vec3a ); bench_binop!( mat4_mul_mat4, "mat4 mul mat4", op => mul, from => random_srt_mat4 ); bench_from_ypr!( mat4_from_ypr, "mat4 from ypr", ty => Mat4 ); pub fn mat4_from_srt(c: &mut Criterion) { use glam::{Quat, Vec3}; const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs = criterion::black_box( (0..SIZE) .map(|_| { ( random_nonzero_vec3(&mut rng), random_quat(&mut rng), random_vec3(&mut rng), ) }) .collect::>(), ); let mut outputs = vec![Mat4::default(); SIZE]; let mut i = 0; c.bench_function("mat4 from srt", |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { let data = inputs.get_unchecked(i); *outputs.get_unchecked_mut(i) = Mat4::from_scale_rotation_translation(data.0, data.1, data.2); } }); }); } criterion_group!( benches, mat4_determinant, mat4_from_srt, mat4_from_ypr, mat4_inverse, mat4_mul_mat4, mat4_mul_vec4, mat4_transform_point3, mat4_transform_point3a, mat4_transform_vector3, mat4_transform_vector3a, mat4_transpose, ); criterion_main!(benches); glam-0.30.1/benches/quat.rs000064400000000000000000000023721046102023000135600ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Quat; use std::ops::Mul; use support::*; bench_unop!( quat_conjugate, "quat conjugate", op => conjugate, from => random_quat ); bench_binop!( quat_mul_vec3, "quat mul vec3", op => mul, from1 => random_quat, from2 => random_vec3 ); bench_binop!( quat_mul_vec3a, "quat mul vec3a", op => mul, from1 => random_quat, from2 => random_vec3a ); bench_binop!( quat_mul_quat, "quat mul quat", op => mul, from => random_quat ); bench_binop!( quat_dot, "quat dot", op => dot, from => random_quat ); bench_trinop!( quat_lerp, "quat lerp", op => lerp, from1 => random_quat, from2 => random_quat, from3 => random_f32 ); bench_trinop!( quat_slerp, "quat slerp", op => slerp, from1 => random_quat, from2 => random_quat, from3 => random_f32 ); bench_from_ypr!(quat_from_ypr, "quat from ypr", ty => Quat); criterion_group!( benches, quat_conjugate, quat_dot, quat_lerp, quat_slerp, quat_mul_quat, quat_mul_vec3, quat_mul_vec3a, quat_from_ypr ); criterion_main!(benches); glam-0.30.1/benches/support/macros.rs000064400000000000000000000201361046102023000156040ustar 00000000000000#[macro_export] macro_rules! bench_func { ($name: ident, $desc: expr, op => $func: ident, from => $from: expr) => { pub(crate) fn $name(c: &mut Criterion) { const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs = criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::>()); // pre-fill output vector with some random value let mut outputs = vec![$func($from(&mut rng)); SIZE]; let mut i = 0; c.bench_function($desc, |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { *outputs.get_unchecked_mut(i) = $func(*inputs.get_unchecked(i)); } }) }); criterion::black_box(outputs); } }; } #[macro_export] macro_rules! bench_unop { ($name: ident, $desc: expr, op => $unop: ident, from => $from: expr) => { pub(crate) fn $name(c: &mut Criterion) { const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs = criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::>()); // pre-fill output vector with some random value let mut outputs = vec![$from(&mut rng).$unop(); SIZE]; let mut i = 0; c.bench_function($desc, |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { *outputs.get_unchecked_mut(i) = inputs.get_unchecked(i).$unop(); } }) }); criterion::black_box(outputs); } }; } #[macro_export] macro_rules! bench_binop { ($name: ident, $desc: expr, op => $binop: ident, from1 => $from1:expr, from2 => $from2:expr) => { pub(crate) fn $name(c: &mut Criterion) { const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs1 = criterion::black_box((0..SIZE).map(|_| $from1(&mut rng)).collect::>()); let inputs2 = criterion::black_box((0..SIZE).map(|_| $from2(&mut rng)).collect::>()); // pre-fill output vector with some random value let mut outputs = vec![$from1(&mut rng).$binop($from2(&mut rng)); SIZE]; let mut i = 0; c.bench_function($desc, |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { *outputs.get_unchecked_mut(i) = inputs1.get_unchecked(i).$binop(*inputs2.get_unchecked(i)); } }) }); criterion::black_box(outputs); } }; ($name: ident, $desc: expr, op => $binop: ident, from => $from: expr) => { bench_binop!($name, $desc, op => $binop, from1 => $from, from2 => $from); }; } #[macro_export] macro_rules! bench_trinop { ($name: ident, $desc: expr, op => $trinop: ident, from1 => $from1:expr, from2 => $from2:expr, from3 => $from3:expr) => { pub(crate) fn $name(c: &mut Criterion) { const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs1 = criterion::black_box((0..SIZE).map(|_| $from1(&mut rng)).collect::>()); let inputs2 = criterion::black_box((0..SIZE).map(|_| $from2(&mut rng)).collect::>()); let inputs3 = criterion::black_box((0..SIZE).map(|_| $from3(&mut rng)).collect::>()); // pre-fill output vector with some random value let mut outputs = vec![$from1(&mut rng).$trinop($from2(&mut rng), $from3(&mut rng)); SIZE]; let mut i = 0; c.bench_function($desc, |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { *outputs.get_unchecked_mut(i) = inputs1 .get_unchecked(i) .$trinop(*inputs2.get_unchecked(i), *inputs3.get_unchecked(i)); } }) }); criterion::black_box(outputs); } }; } #[macro_export] macro_rules! bench_select { ($name:ident, $desc:expr, ty => $ty: ident, op => $op: ident, from => $from:expr) => { pub(crate) fn $name(c: &mut Criterion) { const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs1 = criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::>()); let inputs2 = criterion::black_box((0..SIZE).map(|_| $from(&mut rng)).collect::>()); let masks = vec![$from(&mut rng).$op($from(&mut rng)); SIZE]; // pre-fill output vector with some random value let mut outputs = vec![$from(&mut rng); SIZE]; let mut i = 0; c.bench_function($desc, |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { *outputs.get_unchecked_mut(i) = $ty::select( *masks.get_unchecked(i), *inputs1.get_unchecked(i), *inputs2.get_unchecked(i), ); } }) }); criterion::black_box(outputs); } }; } #[macro_export] macro_rules! bench_from_ypr { ($name: ident, $desc: expr, ty => $ty:ty) => { pub(crate) fn $name(c: &mut Criterion) { const SIZE: usize = 1 << 13; let mut rng = support::PCG32::default(); let inputs = criterion::black_box( (0..SIZE) .map(|_| { ( random_radians(&mut rng), random_radians(&mut rng), random_radians(&mut rng), ) }) .collect::>(), ); let mut outputs = vec![<$ty>::default(); SIZE]; let mut i = 0; c.bench_function($desc, |b| { b.iter(|| { i = (i + 1) & (SIZE - 1); unsafe { let data = inputs.get_unchecked(i); *outputs.get_unchecked_mut(i) = <$ty>::from_euler(glam::EulerRot::YXZ, data.0, data.1, data.2) } }) }); } }; } #[macro_export] macro_rules! euler { ($name: ident, $desc: expr, ty => $t: ty, storage => $storage: ty, zero => $zero: expr, rand => $rand: ident) => { pub(crate) fn $name(c: &mut Criterion) { const UPDATE_RATE: f32 = 1.0 / 60.0; const NUM_OBJECTS: usize = 10000; struct TestData { acc: Vec<$storage>, vel: Vec<$storage>, pos: Vec<$storage>, } let mut rng = support::PCG32::default(); let mut data = TestData { acc: vec![$rand(&mut rng); NUM_OBJECTS], vel: vec![$zero; NUM_OBJECTS], pos: vec![$zero; NUM_OBJECTS], }; let dt = <$t>::splat(UPDATE_RATE); c.bench_function($desc, |b| { b.iter(|| { for ((position, acceleration), velocity) in data.pos.iter_mut().zip(&data.acc).zip(&mut data.vel) { let local_acc: $t = (*acceleration).into(); let mut local_pos: $t = (*position).into(); let mut local_vel: $t = (*velocity).into(); local_vel += local_acc * dt; local_pos += local_vel * dt; *velocity = local_vel.into(); *position = local_pos.into(); } }) }); } }; } glam-0.30.1/benches/support.rs000064400000000000000000000062171046102023000143240ustar 00000000000000#![allow(dead_code)] use core::f32; use glam::{Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4}; pub struct PCG32 { state: u64, inc: u64, } impl Default for PCG32 { fn default() -> Self { PCG32::seed(0x853c49e6748fea9b, 0xda3e39cb94b95bdb) } } impl PCG32 { pub fn seed(initstate: u64, initseq: u64) -> Self { let mut rng = PCG32 { state: 0, inc: (initseq << 1) | 1, }; rng.next_u32(); rng.state = rng.state.wrapping_add(initstate); rng.next_u32(); rng } pub fn next_u32(&mut self) -> u32 { let oldstate = self.state; self.state = oldstate .wrapping_mul(6364136223846793005) .wrapping_add(self.inc | 1); let xorshifted = ((oldstate >> 18) ^ oldstate) >> 27; let rot = oldstate >> 59; ((xorshifted >> rot) | (xorshifted << (rot.wrapping_neg() & 31))) as u32 } pub fn next_f32(&mut self) -> f32 { (self.next_u32() & 0xffffff) as f32 / 16777216.0 } } pub fn random_vec2(rng: &mut PCG32) -> Vec2 { Vec2::new(rng.next_f32(), rng.next_f32()) } pub fn random_vec3(rng: &mut PCG32) -> Vec3 { Vec3::new(rng.next_f32(), rng.next_f32(), rng.next_f32()) } pub fn random_vec3a(rng: &mut PCG32) -> Vec3A { Vec3A::new(rng.next_f32(), rng.next_f32(), rng.next_f32()) } pub fn random_vec4(rng: &mut PCG32) -> Vec4 { Vec4::new( rng.next_f32(), rng.next_f32(), rng.next_f32(), rng.next_f32(), ) } pub fn random_nonzero_vec2(rng: &mut PCG32) -> Vec2 { loop { let v = random_vec2(rng); if v.length_squared() > 0.01 { return v; } } } pub fn random_nonzero_vec3(rng: &mut PCG32) -> Vec3 { loop { let v = random_vec3(rng); if v.length_squared() > 0.01 { return v; } } } pub fn random_f32(rng: &mut PCG32) -> f32 { rng.next_f32() } pub fn random_radians(rng: &mut PCG32) -> f32 { -f32::consts::PI + rng.next_f32() * 2.0 * f32::consts::PI } pub fn random_quat(rng: &mut PCG32) -> Quat { let yaw = random_radians(rng); let pitch = random_radians(rng); let roll = random_radians(rng); Quat::from_euler(glam::EulerRot::YXZ, yaw, pitch, roll) } pub fn random_mat2(rng: &mut PCG32) -> Mat2 { Mat2::from_cols(random_vec2(rng), random_vec2(rng)) } pub fn random_mat3(rng: &mut PCG32) -> Mat3 { Mat3::from_cols(random_vec3(rng), random_vec3(rng), random_vec3(rng)) } pub fn random_srt_mat3(rng: &mut PCG32) -> Mat3 { Mat3::from_scale_angle_translation( random_nonzero_vec2(rng), random_radians(rng), random_vec2(rng), ) } pub fn random_mat3a(rng: &mut PCG32) -> Mat3A { Mat3A::from_cols(random_vec3a(rng), random_vec3a(rng), random_vec3a(rng)) } pub fn random_srt_mat3a(rng: &mut PCG32) -> Mat3A { Mat3A::from_scale_angle_translation( random_nonzero_vec2(rng), random_radians(rng), random_vec2(rng), ) } pub fn random_srt_mat4(rng: &mut PCG32) -> Mat4 { Mat4::from_scale_rotation_translation( random_nonzero_vec3(rng), random_quat(rng), random_vec3(rng), ) } glam-0.30.1/benches/vec2.rs000064400000000000000000000014501046102023000134410ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Vec2; use std::ops::Mul; use support::*; euler!( vec2_euler, "vec2 euler", ty => Vec2, storage => Vec2, zero => Vec2::ZERO, rand => random_vec2); bench_binop!( vec2_mul_vec2, "vec2 mul vec2", op => mul, from1 => random_vec2, from2 => random_vec2 ); bench_binop!( vec2_angle_to, "vec2 angle_to", op => angle_to, from1 => random_vec2, from2 => random_vec2 ); bench_select!( vec2_select, "vec2 select", ty => Vec2, op => cmple, from => random_vec2 ); criterion_group!( benches, vec2_mul_vec2, vec2_euler, vec2_select, vec2_angle_to ); criterion_main!(benches); glam-0.30.1/benches/vec3.rs000064400000000000000000000077051046102023000134530ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Vec3; use std::ops::Mul; use support::*; bench_binop!( vec3_mul_vec3, "vec3 mul vec3", op => mul, from1 => random_vec3, from2 => random_vec3 ); #[inline] fn vec3_to_rgb_op(v: Vec3) -> u32 { let (red, green, blue) = (v.min(Vec3::ONE).max(Vec3::ZERO) * 255.0).into(); ((red as u32) << 16) | ((green as u32) << 8) | (blue as u32) } #[inline] fn vec3_fields(v: Vec3) -> [f32; 3] { [v.x, v.y, v.z] } #[inline] fn vec3_into_array(v: Vec3) -> [f32; 3] { v.into() } #[inline] fn vec3_into_tuple(v: Vec3) -> (f32, f32, f32) { v.into() } bench_func!( vec3_to_rgb, "vec3 to rgb", op => vec3_to_rgb_op, from => random_vec3 ); bench_func!( vec3_to_array_fields, "vec3 into array fields", op => vec3_fields, from => random_vec3 ); bench_func!( vec3_to_array_into, "vec3 into array fast", op => vec3_into_array, from => random_vec3 ); bench_func!( vec3_to_tuple_into, "vec3 into tuple fast", op => vec3_into_tuple, from => random_vec3 ); // --- #[inline] fn vec3_normalize(v: Vec3) -> Vec3 { v.normalize() } bench_func!( vec3_normalize_bench, "vec3 normalize", op => vec3_normalize, from => random_vec3 ); #[inline] fn vec3_normalize_or(v: Vec3) -> Vec3 { v.normalize_or(Vec3::X) } bench_func!( vec3_normalize_or_bench, "vec3 normalize_or", op => vec3_normalize_or, from => random_vec3 ); #[inline] fn vec3_normalize_or_zero(v: Vec3) -> Vec3 { v.normalize_or_zero() } bench_func!( vec3_normalize_or_zero_bench, "vec3 normalize_or_zero", op => vec3_normalize_or_zero, from => random_vec3 ); // --- #[inline(always)] fn vec3_any_orthogonal_vector(v: Vec3) -> Vec3 { v.any_orthogonal_vector() } bench_func!( vec3_any_orthogonal_vector_bench, "vec3 any_orthogonal_vector", op => vec3_any_orthogonal_vector, from => random_vec3 ); #[inline(always)] fn vec3_any_orthonormal_vector(v: Vec3) -> Vec3 { v.any_orthonormal_vector() } bench_func!( vec3_any_orthonormal_vector_bench, "vec3 any_orthonormal_vector", op => vec3_any_orthonormal_vector, from => random_vec3 ); #[inline(always)] fn vec3_any_orthonormal_pair(v: Vec3) -> (Vec3, Vec3) { v.any_orthonormal_pair() } bench_func!( vec3_any_orthonormal_pair_bench, "vec3 any_orthonormal_pair", op => vec3_any_orthonormal_pair, from => random_vec3 ); // --- euler!(vec3_euler, "vec3 euler", ty => Vec3, storage => Vec3, zero => Vec3::ZERO, rand => random_vec3); bench_binop!( vec3_angle_between, "vec3 angle_between", op => angle_between, from1 => random_vec3, from2 => random_vec3 ); bench_binop!( vec3_cross, "vec3 cross", op => cross, from1 => random_vec3, from2 => random_vec3 ); bench_binop!( vec3_dot, "vec3 dot", op => dot, from1 => random_vec3, from2 => random_vec3 ); bench_unop!( vec3_length, "vec3 length", op => length, from => random_vec3 ); bench_select!( vec3_select, "vec3 select", ty => Vec3, op => cmple, from => random_vec3 ); bench_trinop!( vec3_rotate_towards, "vec3 rotate_towards", op => rotate_towards, from1 => random_vec3, from2 => random_vec3, from3 => random_f32 ); bench_trinop!( vec3_slerp, "vec3 slerp", op => slerp, from1 => random_vec3, from2 => random_vec3, from3 => random_f32 ); criterion_group!( benches, vec3_angle_between, vec3_any_orthogonal_vector_bench, vec3_any_orthonormal_pair_bench, vec3_any_orthonormal_vector_bench, vec3_cross, vec3_dot, vec3_euler, vec3_length, vec3_mul_vec3, vec3_normalize_bench, vec3_normalize_or_bench, vec3_normalize_or_zero_bench, vec3_select, vec3_to_array_fields, vec3_to_array_into, vec3_to_rgb, vec3_to_tuple_into, vec3_slerp, vec3_rotate_towards, ); criterion_main!(benches); glam-0.30.1/benches/vec3a.rs000064400000000000000000000062261046102023000136110ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::{Vec3, Vec3A}; use std::ops::Mul; use support::*; bench_binop!( vec3a_mul_vec3a, "vec3a mul vec3a", op => mul, from1 => random_vec3a, from2 => random_vec3a ); #[inline] fn vec3a_to_rgb_op(v: Vec3A) -> u32 { let (red, green, blue) = (v.min(Vec3A::ONE).max(Vec3A::ZERO) * 255.0).into(); ((red as u32) << 16) | ((green as u32) << 8) | (blue as u32) } #[inline] fn vec3a_deref(v: Vec3A) -> [f32; 3] { [v.x, v.y, v.z] } #[inline] fn vec3a_into_array(v: Vec3A) -> [f32; 3] { v.into() } #[inline] fn vec3a_into_tuple(v: Vec3A) -> (f32, f32, f32) { v.into() } #[inline] fn vec3a_into_vec3(v: Vec3A) -> Vec3 { v.into() } bench_func!( vec3a_to_vec3, "vec3a into vec3", op => vec3a_into_vec3, from => random_vec3a ); bench_func!( vec3a_to_rgb, "vec3a to rgb", op => vec3a_to_rgb_op, from => random_vec3a ); bench_func!( vec3a_to_array_deref, "vec3a into array deref", op => vec3a_deref, from => random_vec3a ); bench_func!( vec3a_to_array_into, "vec3a into array fast", op => vec3a_into_array, from => random_vec3a ); bench_func!( vec3a_to_tuple_into, "vec3a into tuple fast", op => vec3a_into_tuple, from => random_vec3a ); euler!(vec3a_euler, "vec3a euler", ty => Vec3A, storage => Vec3A, zero => Vec3A::ZERO, rand => random_vec3a); #[inline] fn vec3a_normalize(v: Vec3A) -> Vec3A { v.normalize() } bench_func!( vec3a_normalize_bench, "vec3a normalize", op => vec3a_normalize, from => random_vec3a ); #[inline] fn vec3a_normalize_or(v: Vec3A) -> Vec3A { v.normalize_or(Vec3A::X) } bench_func!( vec3a_normalize_or_bench, "vec3a normalize_or", op => vec3a_normalize_or, from => random_vec3a ); #[inline] fn vec3a_normalize_or_zero(v: Vec3A) -> Vec3A { v.normalize_or_zero() } bench_func!( vec3a_normalize_or_zero_bench, "vec3a normalize_or_zero", op => vec3a_normalize_or_zero, from => random_vec3a ); bench_binop!( vec3a_angle_between, "vec3a angle_between", op => angle_between, from1 => random_vec3a, from2 => random_vec3a ); bench_binop!( vec3a_cross, "vec3a cross", op => cross, from1 => random_vec3a, from2 => random_vec3a ); bench_binop!( vec3a_dot, "vec3a dot", op => dot, from1 => random_vec3a, from2 => random_vec3a ); bench_unop!( vec3a_length, "vec3a length", op => length, from => random_vec3a ); bench_select!( vec3a_select, "vec3a select", ty => Vec3A, op => cmple, from => random_vec3a ); bench_trinop!( vec3a_slerp, "vec3a slerp", op => slerp, from1 => random_vec3a, from2 => random_vec3a, from3 => random_f32 ); criterion_group!( benches, vec3a_normalize_bench, vec3a_normalize_or_bench, vec3a_normalize_or_zero_bench, vec3a_angle_between, vec3a_cross, vec3a_dot, vec3a_length, vec3a_euler, vec3a_mul_vec3a, vec3a_select, vec3a_to_array_deref, vec3a_to_array_into, vec3a_to_rgb, vec3a_to_tuple_into, vec3a_to_vec3, vec3a_slerp, ); criterion_main!(benches); glam-0.30.1/benches/vec4.rs000064400000000000000000000007761046102023000134550ustar 00000000000000#[path = "support/macros.rs"] #[macro_use] mod macros; mod support; use criterion::{criterion_group, criterion_main, Criterion}; use glam::Vec4; use std::ops::Mul; use support::random_vec4; bench_binop!( vec4_mul_vec4, "vec4 mul vec4", op => mul, from1 => random_vec4, from2 => random_vec4 ); bench_select!( vec4_select, "vec4 select", ty => Vec4, op => cmple, from => random_vec4 ); criterion_group!(benches, vec4_mul_vec4, vec4_select); criterion_main!(benches); glam-0.30.1/build_all_msrv.sh000075500000000000000000000004771046102023000141720ustar 00000000000000#!/bin/sh set -e CARGO='rustup run 1.68.2 cargo' $CARGO check --features "bytemuck mint rand serde debug-glam-assert" && \ $CARGO check --features "scalar-math bytemuck mint rand serde debug-glam-assert" && \ $CARGO check --no-default-features --features "libm scalar-math bytemuck mint rand serde debug-glam-assert" glam-0.30.1/build_and_test_features.sh000075500000000000000000000012411046102023000160400ustar 00000000000000#!/bin/bash set -ex # Supported dependencies DEPENDENCIES="approx bytemuck mint rand rkyv serde debug-glam-assert" # Set of features to build & test. FEATURE_SETS=( # std "std" "std $DEPENDENCIES" "std $DEPENDENCIES bytecheck" "std scalar-math $DEPENDENCIES" "std cuda" "std scalar-math cuda" "std libm" "std scalar-math libm" # no_std "libm" "libm scalar-math $DEPENDENCIES" ) rustc --version for features in "${FEATURE_SETS[@]}" do : cargo build --tests --no-default-features --features="$features" cargo test --no-default-features --features="$features" done RUSTFLAGS='-C target-feature=+fma' cargo check cargo check -p glam-no_std glam-0.30.1/build_and_test_wasm32_chrome.sh000075500000000000000000000001771046102023000167020ustar 00000000000000#!/bin/sh set -e RUSTFLAGS="-Ctarget-feature=+simd128" wasm-pack test --headless --chrome wasm-pack test --headless --chrome glam-0.30.1/build_and_test_wasm32_firefox.sh000075500000000000000000000002011046102023000170530ustar 00000000000000#!/bin/sh set -e RUSTFLAGS="-Ctarget-feature=+simd128" wasm-pack test --headless --firefox wasm-pack test --headless --firefox glam-0.30.1/clippy.toml000064400000000000000000000000201046102023000130120ustar 00000000000000msrv = "1.68.2" glam-0.30.1/codegen.json000064400000000000000000000664601046102023000131400ustar 00000000000000{ "version": 1, "template_root": "templates", "templates": { "affine.rs.tera": { "properties": { "dim": null, "is_align": false, "is_coresimd": false, "is_neon": false, "is_scalar": false, "is_sse2": false, "is_wasm32": false, "scalar_t": null }, "outputs": { "src/f32/affine2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/affine3a.rs": { "properties": { "dim": 3, "is_align": true, "is_scalar": true, "scalar_t": "f32" } }, "src/f64/daffine2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "f64" } }, "src/f64/daffine3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "f64" } } } }, "float.rs.tera": { "properties": { "scalar_t": null }, "outputs": { "src/f32/float.rs": { "properties": { "scalar_t": "f32" } }, "src/f64/float.rs": { "properties": { "scalar_t": "f64" } } } }, "mat.rs.tera": { "properties": { "dim": null, "is_align": false, "is_coresimd": false, "is_neon": false, "is_scalar": false, "is_sse2": false, "is_wasm32": false, "scalar_t": null }, "outputs": { "src/f32/coresimd/mat2.rs": { "properties": { "dim": 2, "is_coresimd": true, "scalar_t": "f32" } }, "src/f32/coresimd/mat3a.rs": { "properties": { "dim": 3, "is_align": true, "is_coresimd": true, "scalar_t": "f32" } }, "src/f32/coresimd/mat4.rs": { "properties": { "dim": 4, "is_coresimd": true, "scalar_t": "f32" } }, "src/f32/mat3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/neon/mat2.rs": { "properties": { "dim": 2, "is_neon": true, "scalar_t": "f32" } }, "src/f32/neon/mat3a.rs": { "properties": { "dim": 3, "is_align": true, "is_neon": true, "scalar_t": "f32" } }, "src/f32/neon/mat4.rs": { "properties": { "dim": 4, "is_neon": true, "scalar_t": "f32" } }, "src/f32/scalar/mat2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/scalar/mat3a.rs": { "properties": { "dim": 3, "is_align": true, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/scalar/mat4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/sse2/mat2.rs": { "properties": { "dim": 2, "is_sse2": true, "scalar_t": "f32" } }, "src/f32/sse2/mat3a.rs": { "properties": { "dim": 3, "is_align": true, "is_sse2": true, "scalar_t": "f32" } }, "src/f32/sse2/mat4.rs": { "properties": { "dim": 4, "is_sse2": true, "scalar_t": "f32" } }, "src/f32/wasm32/mat2.rs": { "properties": { "dim": 2, "is_wasm32": true, "scalar_t": "f32" } }, "src/f32/wasm32/mat3a.rs": { "properties": { "dim": 3, "is_align": true, "is_wasm32": true, "scalar_t": "f32" } }, "src/f32/wasm32/mat4.rs": { "properties": { "dim": 4, "is_wasm32": true, "scalar_t": "f32" } }, "src/f64/dmat2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "f64" } }, "src/f64/dmat3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "f64" } }, "src/f64/dmat4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "f64" } } } }, "quat.rs.tera": { "properties": { "is_coresimd": false, "is_neon": false, "is_scalar": false, "is_sse2": false, "is_wasm32": false, "scalar_t": null }, "outputs": { "src/f32/coresimd/quat.rs": { "properties": { "is_coresimd": true, "scalar_t": "f32" } }, "src/f32/neon/quat.rs": { "properties": { "is_neon": true, "scalar_t": "f32" } }, "src/f32/scalar/quat.rs": { "properties": { "is_scalar": true, "scalar_t": "f32" } }, "src/f32/sse2/quat.rs": { "properties": { "is_sse2": true, "scalar_t": "f32" } }, "src/f32/wasm32/quat.rs": { "properties": { "is_wasm32": true, "scalar_t": "f32" } }, "src/f64/dquat.rs": { "properties": { "is_scalar": true, "scalar_t": "f64" } } } }, "swizzle_impl.rs.tera": { "properties": { "dim": null, "is_coresimd": false, "is_neon": false, "is_scalar": false, "is_sse2": false, "is_wasm32": false, "self_t": null, "vec2_t": null, "vec3_t": null, "vec4_t": null }, "outputs": { "src/swizzles/coresimd/vec3a_impl.rs": { "properties": { "dim": 3, "is_coresimd": true, "self_t": "Vec3A", "vec2_t": "Vec2", "vec3_t": "Vec3A", "vec4_t": "Vec4" } }, "src/swizzles/coresimd/vec4_impl.rs": { "properties": { "dim": 4, "is_coresimd": true, "self_t": "Vec4", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } }, "src/swizzles/dvec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "DVec2", "vec2_t": "DVec2", "vec3_t": "DVec3", "vec4_t": "DVec4" } }, "src/swizzles/dvec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "DVec3", "vec2_t": "DVec2", "vec3_t": "DVec3", "vec4_t": "DVec4" } }, "src/swizzles/dvec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "DVec4", "vec2_t": "DVec2", "vec3_t": "DVec3", "vec4_t": "DVec4" } }, "src/swizzles/i16vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "I16Vec2", "vec2_t": "I16Vec2", "vec3_t": "I16Vec3", "vec4_t": "I16Vec4" } }, "src/swizzles/i16vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "I16Vec3", "vec2_t": "I16Vec2", "vec3_t": "I16Vec3", "vec4_t": "I16Vec4" } }, "src/swizzles/i16vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "I16Vec4", "vec2_t": "I16Vec2", "vec3_t": "I16Vec3", "vec4_t": "I16Vec4" } }, "src/swizzles/i64vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "I64Vec2", "vec2_t": "I64Vec2", "vec3_t": "I64Vec3", "vec4_t": "I64Vec4" } }, "src/swizzles/i64vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "I64Vec3", "vec2_t": "I64Vec2", "vec3_t": "I64Vec3", "vec4_t": "I64Vec4" } }, "src/swizzles/i64vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "I64Vec4", "vec2_t": "I64Vec2", "vec3_t": "I64Vec3", "vec4_t": "I64Vec4" } }, "src/swizzles/i8vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "I8Vec2", "vec2_t": "I8Vec2", "vec3_t": "I8Vec3", "vec4_t": "I8Vec4" } }, "src/swizzles/i8vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "I8Vec3", "vec2_t": "I8Vec2", "vec3_t": "I8Vec3", "vec4_t": "I8Vec4" } }, "src/swizzles/i8vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "I8Vec4", "vec2_t": "I8Vec2", "vec3_t": "I8Vec3", "vec4_t": "I8Vec4" } }, "src/swizzles/ivec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "IVec2", "vec2_t": "IVec2", "vec3_t": "IVec3", "vec4_t": "IVec4" } }, "src/swizzles/ivec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "IVec3", "vec2_t": "IVec2", "vec3_t": "IVec3", "vec4_t": "IVec4" } }, "src/swizzles/ivec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "IVec4", "vec2_t": "IVec2", "vec3_t": "IVec3", "vec4_t": "IVec4" } }, "src/swizzles/neon/vec3a_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "Vec3A", "vec2_t": "Vec2", "vec3_t": "Vec3A", "vec4_t": "Vec4" } }, "src/swizzles/neon/vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "Vec4", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } }, "src/swizzles/scalar/vec3a_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "Vec3A", "vec2_t": "Vec2", "vec3_t": "Vec3A", "vec4_t": "Vec4" } }, "src/swizzles/scalar/vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "Vec4", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } }, "src/swizzles/sse2/vec3a_impl.rs": { "properties": { "dim": 3, "is_sse2": true, "self_t": "Vec3A", "vec2_t": "Vec2", "vec3_t": "Vec3A", "vec4_t": "Vec4" } }, "src/swizzles/sse2/vec4_impl.rs": { "properties": { "dim": 4, "is_sse2": true, "self_t": "Vec4", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } }, "src/swizzles/u16vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "U16Vec2", "vec2_t": "U16Vec2", "vec3_t": "U16Vec3", "vec4_t": "U16Vec4" } }, "src/swizzles/u16vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "U16Vec3", "vec2_t": "U16Vec2", "vec3_t": "U16Vec3", "vec4_t": "U16Vec4" } }, "src/swizzles/u16vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "U16Vec4", "vec2_t": "U16Vec2", "vec3_t": "U16Vec3", "vec4_t": "U16Vec4" } }, "src/swizzles/u64vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "U64Vec2", "vec2_t": "U64Vec2", "vec3_t": "U64Vec3", "vec4_t": "U64Vec4" } }, "src/swizzles/u64vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "U64Vec3", "vec2_t": "U64Vec2", "vec3_t": "U64Vec3", "vec4_t": "U64Vec4" } }, "src/swizzles/u64vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "U64Vec4", "vec2_t": "U64Vec2", "vec3_t": "U64Vec3", "vec4_t": "U64Vec4" } }, "src/swizzles/u8vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "U8Vec2", "vec2_t": "U8Vec2", "vec3_t": "U8Vec3", "vec4_t": "U8Vec4" } }, "src/swizzles/u8vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "U8Vec3", "vec2_t": "U8Vec2", "vec3_t": "U8Vec3", "vec4_t": "U8Vec4" } }, "src/swizzles/u8vec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "U8Vec4", "vec2_t": "U8Vec2", "vec3_t": "U8Vec3", "vec4_t": "U8Vec4" } }, "src/swizzles/uvec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "UVec2", "vec2_t": "UVec2", "vec3_t": "UVec3", "vec4_t": "UVec4" } }, "src/swizzles/uvec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "UVec3", "vec2_t": "UVec2", "vec3_t": "UVec3", "vec4_t": "UVec4" } }, "src/swizzles/uvec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "UVec4", "vec2_t": "UVec2", "vec3_t": "UVec3", "vec4_t": "UVec4" } }, "src/swizzles/usizevec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "USizeVec2", "vec2_t": "USizeVec2", "vec3_t": "USizeVec3", "vec4_t": "USizeVec4" } }, "src/swizzles/usizevec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "USizeVec3", "vec2_t": "USizeVec2", "vec3_t": "USizeVec3", "vec4_t": "USizeVec4" } }, "src/swizzles/usizevec4_impl.rs": { "properties": { "dim": 4, "is_scalar": true, "self_t": "USizeVec4", "vec2_t": "USizeVec2", "vec3_t": "USizeVec3", "vec4_t": "USizeVec4" } }, "src/swizzles/vec2_impl.rs": { "properties": { "dim": 2, "is_scalar": true, "self_t": "Vec2", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } }, "src/swizzles/vec3_impl.rs": { "properties": { "dim": 3, "is_scalar": true, "self_t": "Vec3", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } }, "src/swizzles/wasm32/vec3a_impl.rs": { "properties": { "dim": 3, "is_wasm32": true, "self_t": "Vec3A", "vec2_t": "Vec2", "vec3_t": "Vec3A", "vec4_t": "Vec4" } }, "src/swizzles/wasm32/vec4_impl.rs": { "properties": { "dim": 4, "is_wasm32": true, "self_t": "Vec4", "vec2_t": "Vec2", "vec3_t": "Vec3", "vec4_t": "Vec4" } } } }, "swizzle_traits.rs.tera": { "properties": {}, "outputs": { "src/swizzles/vec_traits.rs": { "properties": {} } } }, "vec.rs.tera": { "properties": { "dim": null, "is_align": false, "is_coresimd": false, "is_neon": false, "is_scalar": false, "is_sse2": false, "is_wasm32": false, "scalar_t": null }, "outputs": { "src/f32/coresimd/vec3a.rs": { "properties": { "dim": 3, "is_align": true, "is_coresimd": true, "scalar_t": "f32" } }, "src/f32/coresimd/vec4.rs": { "properties": { "dim": 4, "is_align": true, "is_coresimd": true, "scalar_t": "f32" } }, "src/f32/neon/vec3a.rs": { "properties": { "dim": 3, "is_align": true, "is_neon": true, "scalar_t": "f32" } }, "src/f32/neon/vec4.rs": { "properties": { "dim": 4, "is_align": true, "is_neon": true, "scalar_t": "f32" } }, "src/f32/scalar/vec3a.rs": { "properties": { "dim": 3, "is_align": true, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/scalar/vec4.rs": { "properties": { "dim": 4, "is_align": true, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/sse2/vec3a.rs": { "properties": { "dim": 3, "is_align": true, "is_sse2": true, "scalar_t": "f32" } }, "src/f32/sse2/vec4.rs": { "properties": { "dim": 4, "is_align": true, "is_sse2": true, "scalar_t": "f32" } }, "src/f32/vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "f32" } }, "src/f32/wasm32/vec3a.rs": { "properties": { "dim": 3, "is_align": true, "is_wasm32": true, "scalar_t": "f32" } }, "src/f32/wasm32/vec4.rs": { "properties": { "dim": 4, "is_align": true, "is_wasm32": true, "scalar_t": "f32" } }, "src/f64/dvec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "f64" } }, "src/f64/dvec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "f64" } }, "src/f64/dvec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "f64" } }, "src/i16/i16vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "i16" } }, "src/i16/i16vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "i16" } }, "src/i16/i16vec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "i16" } }, "src/i32/ivec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "i32" } }, "src/i32/ivec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "i32" } }, "src/i32/ivec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "i32" } }, "src/i64/i64vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "i64" } }, "src/i64/i64vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "i64" } }, "src/i64/i64vec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "i64" } }, "src/i8/i8vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "i8" } }, "src/i8/i8vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "i8" } }, "src/i8/i8vec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "i8" } }, "src/u16/u16vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "u16" } }, "src/u16/u16vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "u16" } }, "src/u16/u16vec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "u16" } }, "src/u32/uvec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "u32" } }, "src/u32/uvec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "u32" } }, "src/u32/uvec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "u32" } }, "src/u64/u64vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "u64" } }, "src/u64/u64vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "u64" } }, "src/u64/u64vec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "u64" } }, "src/u8/u8vec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "u8" } }, "src/u8/u8vec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "u8" } }, "src/u8/u8vec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "u8" } }, "src/usize/usizevec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "usize" } }, "src/usize/usizevec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "usize" } }, "src/usize/usizevec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "usize" } } } }, "vec_mask.rs.tera": { "properties": { "dim": null, "is_coresimd": false, "is_neon": false, "is_scalar": false, "is_sse2": false, "is_wasm32": false, "scalar_t": null }, "outputs": { "src/bool/bvec2.rs": { "properties": { "dim": 2, "is_scalar": true, "scalar_t": "bool" } }, "src/bool/bvec3.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "bool" } }, "src/bool/bvec4.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "bool" } }, "src/bool/coresimd/bvec3a.rs": { "properties": { "dim": 3, "is_coresimd": true, "scalar_t": "u32" } }, "src/bool/coresimd/bvec4a.rs": { "properties": { "dim": 4, "is_coresimd": true, "scalar_t": "u32" } }, "src/bool/neon/bvec3a.rs": { "properties": { "dim": 3, "is_neon": true, "scalar_t": "u32" } }, "src/bool/neon/bvec4a.rs": { "properties": { "dim": 4, "is_neon": true, "scalar_t": "u32" } }, "src/bool/scalar/bvec3a.rs": { "properties": { "dim": 3, "is_scalar": true, "scalar_t": "u32" } }, "src/bool/scalar/bvec4a.rs": { "properties": { "dim": 4, "is_scalar": true, "scalar_t": "u32" } }, "src/bool/sse2/bvec3a.rs": { "properties": { "dim": 3, "is_sse2": true, "scalar_t": "u32" } }, "src/bool/sse2/bvec4a.rs": { "properties": { "dim": 4, "is_sse2": true, "scalar_t": "u32" } }, "src/bool/wasm32/bvec3a.rs": { "properties": { "dim": 3, "is_wasm32": true, "scalar_t": "u32" } }, "src/bool/wasm32/bvec4a.rs": { "properties": { "dim": 4, "is_wasm32": true, "scalar_t": "u32" } } } } } } glam-0.30.1/deny.toml000064400000000000000000000003701046102023000124610ustar 00000000000000[bans] multiple-versions = "deny" deny = [] skip-tree = [ # ignore criterion dev-dependency that often have duplicate dependencies internally { name = "criterion" }, ] [licenses] allow = [ "Apache-2.0", "MIT", "Unicode-3.0", ] glam-0.30.1/src/align16.rs000064400000000000000000000012001046102023000132140ustar 00000000000000#[derive(Clone, Copy, Default, PartialEq, PartialOrd)] #[repr(C, align(16))] pub(crate) struct Align16(pub T); impl Align16 { #[allow(dead_code)] pub fn as_ptr(&self) -> *const T { &self.0 } #[allow(dead_code)] pub fn as_mut_ptr(&mut self) -> *mut T { &mut self.0 } } #[test] fn test_align16() { use core::{mem, ptr}; let mut a = Align16::(1.0); assert_eq!(mem::align_of_val(&a), 16); unsafe { assert_eq!(ptr::read(a.as_ptr()).to_bits(), f32::to_bits(1.0)); ptr::write(a.as_mut_ptr(), -1.0); } assert_eq!(a.0.to_bits(), f32::to_bits(-1.0)); } glam-0.30.1/src/bool/bvec2.rs000064400000000000000000000111131046102023000137130ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; /// Creates a 2-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec2(x: bool, y: bool) -> BVec2 { BVec2::new(x, y) } /// A 2-dimensional `bool` vector mask. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(C, align(1))] pub struct BVec2 { pub x: bool, pub y: bool, } const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec2 { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool) -> Self { Self { x, y } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 2]) -> Self { Self::new(a[0], a[1]) } /// Returns a bitmask with the lowest 2 bits set from the elements of `self`. /// /// 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]] } } impl Default for BVec2 { #[inline] fn default() -> Self { Self::FALSE } } impl BitAnd for BVec2 { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self { x: self.x & rhs.x, y: self.y & rhs.y, } } } impl BitAndAssign for BVec2 { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec2 { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self { x: self.x | rhs.x, y: self.y | rhs.y, } } } impl BitOrAssign for BVec2 { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec2 { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self { x: self.x ^ rhs.x, y: self.y ^ rhs.y, } } } impl BitXorAssign for BVec2 { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec2 { type Output = Self; #[inline] fn not(self) -> Self { Self { x: !self.x, y: !self.y, } } } impl fmt::Debug for BVec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!(f, "{}({:#x}, {:#x})", stringify!(BVec2), arr[0], arr[1]) } } impl fmt::Display for BVec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}]", arr[0], arr[1]) } } impl From<[bool; 2]> for BVec2 { #[inline] fn from(a: [bool; 2]) -> Self { Self::from_array(a) } } impl From for [bool; 2] { #[inline] fn from(mask: BVec2) -> Self { mask.into_bool_array() } } impl From for [u32; 2] { #[inline] fn from(mask: BVec2) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/bvec3.rs000064400000000000000000000120241046102023000137160ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; /// Creates a 3-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec3(x: bool, y: bool, z: bool) -> BVec3 { BVec3::new(x, y, z) } /// A 3-dimensional `bool` vector mask. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(C, align(1))] pub struct BVec3 { pub x: bool, pub y: bool, pub z: bool, } const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec3 { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// 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 mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// Returns a bitmask with the lowest 3 bits set from the elements of `self`. /// /// 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], MASK[self.y as usize], MASK[self.z as usize], ] } } impl Default for BVec3 { #[inline] fn default() -> Self { Self::FALSE } } impl BitAnd for BVec3 { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self { x: self.x & rhs.x, y: self.y & rhs.y, z: self.z & rhs.z, } } } impl BitAndAssign for BVec3 { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec3 { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self { x: self.x | rhs.x, y: self.y | rhs.y, z: self.z | rhs.z, } } } impl BitOrAssign for BVec3 { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec3 { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self { x: self.x ^ rhs.x, y: self.y ^ rhs.y, z: self.z ^ rhs.z, } } } impl BitXorAssign for BVec3 { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec3 { type Output = Self; #[inline] fn not(self) -> Self { Self { x: !self.x, y: !self.y, z: !self.z, } } } impl fmt::Debug for BVec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x})", stringify!(BVec3), arr[0], arr[1], arr[2] ) } } impl fmt::Display for BVec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) } } impl From<[bool; 3]> for BVec3 { #[inline] fn from(a: [bool; 3]) -> Self { Self::from_array(a) } } impl From for [bool; 3] { #[inline] fn from(mask: BVec3) -> Self { mask.into_bool_array() } } impl From for [u32; 3] { #[inline] fn from(mask: BVec3) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/bvec4.rs000064400000000000000000000125641046102023000137300ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; /// Creates a 4-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec4(x: bool, y: bool, z: bool, w: bool) -> BVec4 { BVec4::new(x, y, z, w) } /// A 4-dimensional `bool` vector mask. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(C, align(1))] pub struct BVec4 { pub x: bool, pub y: bool, pub z: bool, pub w: bool, } const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec4 { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// 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 mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } /// Returns a bitmask with the lowest 4 bits set from the elements of `self`. /// /// 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], MASK[self.y as usize], MASK[self.z as usize], MASK[self.w as usize], ] } } impl Default for BVec4 { #[inline] fn default() -> Self { Self::FALSE } } impl BitAnd for BVec4 { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self { x: self.x & rhs.x, y: self.y & rhs.y, z: self.z & rhs.z, w: self.w & rhs.w, } } } impl BitAndAssign for BVec4 { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec4 { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self { x: self.x | rhs.x, y: self.y | rhs.y, z: self.z | rhs.z, w: self.w | rhs.w, } } } impl BitOrAssign for BVec4 { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec4 { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self { x: self.x ^ rhs.x, y: self.y ^ rhs.y, z: self.z ^ rhs.z, w: self.w ^ rhs.w, } } } impl BitXorAssign for BVec4 { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec4 { type Output = Self; #[inline] fn not(self) -> Self { Self { x: !self.x, y: !self.y, z: !self.z, w: !self.w, } } } impl fmt::Debug for BVec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!(BVec4), arr[0], arr[1], arr[2], arr[3] ) } } impl fmt::Display for BVec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) } } impl From<[bool; 4]> for BVec4 { #[inline] fn from(a: [bool; 4]) -> Self { Self::from_array(a) } } impl From for [bool; 4] { #[inline] fn from(mask: BVec4) -> Self { mask.into_bool_array() } } impl From for [u32; 4] { #[inline] fn from(mask: BVec4) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/coresimd/bvec3a.rs000064400000000000000000000122111046102023000156620ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; use core::simd::*; #[repr(C)] union UnionCast { a: [u32; 4], v: BVec3A, } /// Creates a 3-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A { BVec3A::new(x, y, z) } /// A 3-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec3A(pub(crate) mask32x4); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec3A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool, z: bool) -> Self { unsafe { UnionCast { a: [MASK[x as usize], MASK[y as usize], MASK[z as usize], 0], } .v } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// Returns a bitmask with the lowest 3 bits set from the elements of `self`. /// /// 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(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], ] } } impl Default for BVec3A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec3A {} impl core::hash::Hash for BVec3A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec3A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(self.0 & rhs.0) } } impl BitAndAssign for BVec3A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec3A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(self.0 | rhs.0) } } impl BitOrAssign for BVec3A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec3A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(self.0 ^ rhs.0) } } impl BitXorAssign for BVec3A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec3A { type Output = Self; #[inline] fn not(self) -> Self { Self(!self.0) } } impl From for mask32x4 { #[inline] fn from(t: BVec3A) -> Self { t.0 } } impl fmt::Debug for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x})", stringify!(BVec3A), arr[0], arr[1], arr[2] ) } } impl fmt::Display for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) } } impl From<[bool; 3]> for BVec3A { #[inline] fn from(a: [bool; 3]) -> Self { Self::from_array(a) } } impl From for [bool; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_bool_array() } } impl From for [u32; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/coresimd/bvec4a.rs000064400000000000000000000126701046102023000156740ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; use core::simd::*; #[repr(C)] union UnionCast { a: [u32; 4], v: BVec4A, } /// Creates a 4-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A { BVec4A::new(x, y, z, w) } /// A 4-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec4A(pub(crate) mask32x4); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec4A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self { unsafe { UnionCast { a: [ MASK[x as usize], MASK[y as usize], MASK[z as usize], MASK[w as usize], ], } .v } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } /// Returns a bitmask with the lowest 4 bits set from the elements of `self`. /// /// 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(); [ (bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0, (bitmask & 8) != 0, ] } #[inline] #[must_use] fn into_u32_array(self) -> [u32; 4] { let bitmask = self.bitmask(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], MASK[((bitmask >> 3) & 1) as usize], ] } } impl Default for BVec4A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec4A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec4A {} impl core::hash::Hash for BVec4A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec4A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(self.0 & rhs.0) } } impl BitAndAssign for BVec4A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec4A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(self.0 | rhs.0) } } impl BitOrAssign for BVec4A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec4A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(self.0 ^ rhs.0) } } impl BitXorAssign for BVec4A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec4A { type Output = Self; #[inline] fn not(self) -> Self { Self(!self.0) } } impl From for mask32x4 { #[inline] fn from(t: BVec4A) -> Self { t.0 } } impl fmt::Debug for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!(BVec4A), arr[0], arr[1], arr[2], arr[3] ) } } impl fmt::Display for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) } } impl From<[bool; 4]> for BVec4A { #[inline] fn from(a: [bool; 4]) -> Self { Self::from_array(a) } } impl From for [bool; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_bool_array() } } impl From for [u32; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/coresimd.rs000064400000000000000000000000401046102023000145140ustar 00000000000000pub mod bvec3a; pub mod bvec4a; glam-0.30.1/src/bool/neon/bvec3a.rs000064400000000000000000000141441046102023000150230ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; use core::arch::aarch64::*; #[repr(C)] union UnionCast { a: [u32; 4], v: BVec3A, } /// Creates a 3-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A { BVec3A::new(x, y, z) } /// A 3-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec3A(pub(crate) uint32x4_t); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec3A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool, z: bool) -> Self { unsafe { UnionCast { a: [MASK[x as usize], MASK[y as usize], MASK[z as usize], 0], } .v } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// Returns a bitmask with the lowest 3 bits set from the elements of `self`. /// /// 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 { let movemask = unsafe { let mma = vandq_u32(self.0, vld1q_u32([1, 2, 4, 8].as_ptr())); // [0 1 2 3] let mmb = vextq_u32(mma, mma, 2); // [2 3 0 1] let mmc = vorrq_u32(mma, mmb); // [0+2 1+3 0+2 1+3] let mmd = vextq_u32(mmc, mmc, 3); // [1+3 0+2 1+3 0+2] let mme = vorrq_u32(mmc, mmd); // [0+1+2+3 ...] vgetq_lane_u32(mme, 0) }; movemask & 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) { self.0 = match index { 0 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 0) }, 1 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 1) }, 2 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 2) }, _ => panic!("index out of bounds"), } } #[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(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], ] } } impl Default for BVec3A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec3A {} impl core::hash::Hash for BVec3A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec3A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(unsafe { vandq_u32(self.0, rhs.0) }) } } impl BitAndAssign for BVec3A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec3A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(unsafe { vorrq_u32(self.0, rhs.0) }) } } impl BitOrAssign for BVec3A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec3A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(unsafe { veorq_u32(self.0, rhs.0) }) } } impl BitXorAssign for BVec3A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec3A { type Output = Self; #[inline] fn not(self) -> Self { Self(unsafe { vmvnq_u32(self.0) }) } } impl From for uint32x4_t { #[inline] fn from(t: BVec3A) -> Self { t.0 } } impl fmt::Debug for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x})", stringify!(BVec3A), arr[0], arr[1], arr[2] ) } } impl fmt::Display for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) } } impl From<[bool; 3]> for BVec3A { #[inline] fn from(a: [bool; 3]) -> Self { Self::from_array(a) } } impl From for [bool; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_bool_array() } } impl From for [u32; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/neon/bvec4a.rs000064400000000000000000000147631046102023000150330ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; use core::arch::aarch64::*; #[repr(C)] union UnionCast { a: [u32; 4], v: BVec4A, } /// Creates a 4-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A { BVec4A::new(x, y, z, w) } /// A 4-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec4A(pub(crate) uint32x4_t); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec4A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self { unsafe { UnionCast { a: [ MASK[x as usize], MASK[y as usize], MASK[z as usize], MASK[w as usize], ], } .v } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } /// Returns a bitmask with the lowest 4 bits set from the elements of `self`. /// /// 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 { let mma = vandq_u32(self.0, vld1q_u32([1, 2, 4, 8].as_ptr())); // [0 1 2 3] let mmb = vextq_u32(mma, mma, 2); // [2 3 0 1] let mmc = vorrq_u32(mma, mmb); // [0+2 1+3 0+2 1+3] let mmd = vextq_u32(mmc, mmc, 3); // [1+3 0+2 1+3 0+2] let mme = vorrq_u32(mmc, mmd); // [0+1+2+3 ...] vgetq_lane_u32(mme, 0) } } /// 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) { self.0 = match index { 0 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 0) }, 1 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 1) }, 2 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 2) }, 3 => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, 3) }, _ => panic!("index out of bounds"), } } #[inline] #[must_use] fn into_bool_array(self) -> [bool; 4] { let bitmask = self.bitmask(); [ (bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0, (bitmask & 8) != 0, ] } #[inline] #[must_use] fn into_u32_array(self) -> [u32; 4] { let bitmask = self.bitmask(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], MASK[((bitmask >> 3) & 1) as usize], ] } } impl Default for BVec4A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec4A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec4A {} impl core::hash::Hash for BVec4A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec4A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(unsafe { vandq_u32(self.0, rhs.0) }) } } impl BitAndAssign for BVec4A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec4A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(unsafe { vorrq_u32(self.0, rhs.0) }) } } impl BitOrAssign for BVec4A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec4A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(unsafe { veorq_u32(self.0, rhs.0) }) } } impl BitXorAssign for BVec4A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec4A { type Output = Self; #[inline] fn not(self) -> Self { Self(unsafe { vmvnq_u32(self.0) }) } } impl From for uint32x4_t { #[inline] fn from(t: BVec4A) -> Self { t.0 } } impl fmt::Debug for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!(BVec4A), arr[0], arr[1], arr[2], arr[3] ) } } impl fmt::Display for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) } } impl From<[bool; 4]> for BVec4A { #[inline] fn from(a: [bool; 4]) -> Self { Self::from_array(a) } } impl From for [bool; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_bool_array() } } impl From for [u32; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/neon.rs000064400000000000000000000000401046102023000136460ustar 00000000000000pub mod bvec3a; pub mod bvec4a; glam-0.30.1/src/bool/scalar/bvec3a.rs000064400000000000000000000123561046102023000153340ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; /// Creates a 3-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A { BVec3A::new(x, y, z) } /// A 3-dimensional `u32` vector mask. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(C, align(16))] pub struct BVec3A { pub x: u32, pub y: u32, pub z: u32, } const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec3A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// 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], y: MASK[y as usize], z: MASK[z as usize], } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// Returns a bitmask with the lowest 3 bits set from the elements of `self`. /// /// 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, (self.y & 0x1) != 0, (self.z & 0x1) != 0, ] } #[inline] #[must_use] fn into_u32_array(self) -> [u32; 3] { [self.x, self.y, self.z] } } impl Default for BVec3A { #[inline] fn default() -> Self { Self::FALSE } } impl BitAnd for BVec3A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self { x: self.x & rhs.x, y: self.y & rhs.y, z: self.z & rhs.z, } } } impl BitAndAssign for BVec3A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec3A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self { x: self.x | rhs.x, y: self.y | rhs.y, z: self.z | rhs.z, } } } impl BitOrAssign for BVec3A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec3A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self { x: self.x ^ rhs.x, y: self.y ^ rhs.y, z: self.z ^ rhs.z, } } } impl BitXorAssign for BVec3A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec3A { type Output = Self; #[inline] fn not(self) -> Self { Self { x: !self.x, y: !self.y, z: !self.z, } } } impl fmt::Debug for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x})", stringify!(BVec3A), arr[0], arr[1], arr[2] ) } } impl fmt::Display for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) } } impl From<[bool; 3]> for BVec3A { #[inline] fn from(a: [bool; 3]) -> Self { Self::from_array(a) } } impl From for [bool; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_bool_array() } } impl From for [u32; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/scalar/bvec4a.rs000064400000000000000000000132021046102023000153240ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; /// Creates a 4-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A { BVec4A::new(x, y, z, w) } /// A 4-dimensional `u32` vector mask. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[repr(C, align(16))] pub struct BVec4A { pub x: u32, pub y: u32, pub z: u32, pub w: u32, } const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec4A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// 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], y: MASK[y as usize], z: MASK[z as usize], w: MASK[w as usize], } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } /// Returns a bitmask with the lowest 4 bits set from the elements of `self`. /// /// 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, (self.y & 0x1) != 0, (self.z & 0x1) != 0, (self.w & 0x1) != 0, ] } #[inline] #[must_use] fn into_u32_array(self) -> [u32; 4] { [self.x, self.y, self.z, self.w] } } impl Default for BVec4A { #[inline] fn default() -> Self { Self::FALSE } } impl BitAnd for BVec4A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self { x: self.x & rhs.x, y: self.y & rhs.y, z: self.z & rhs.z, w: self.w & rhs.w, } } } impl BitAndAssign for BVec4A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec4A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self { x: self.x | rhs.x, y: self.y | rhs.y, z: self.z | rhs.z, w: self.w | rhs.w, } } } impl BitOrAssign for BVec4A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec4A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self { x: self.x ^ rhs.x, y: self.y ^ rhs.y, z: self.z ^ rhs.z, w: self.w ^ rhs.w, } } } impl BitXorAssign for BVec4A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec4A { type Output = Self; #[inline] fn not(self) -> Self { Self { x: !self.x, y: !self.y, z: !self.z, w: !self.w, } } } impl fmt::Debug for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!(BVec4A), arr[0], arr[1], arr[2], arr[3] ) } } impl fmt::Display for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) } } impl From<[bool; 4]> for BVec4A { #[inline] fn from(a: [bool; 4]) -> Self { Self::from_array(a) } } impl From for [bool; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_bool_array() } } impl From for [u32; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/scalar.rs000064400000000000000000000000401046102023000141540ustar 00000000000000pub mod bvec3a; pub mod bvec4a; glam-0.30.1/src/bool/sse2/bvec3a.rs000064400000000000000000000132561046102023000147430ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C)] union UnionCast { a: [u32; 4], v: BVec3A, } /// Creates a 3-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A { BVec3A::new(x, y, z) } /// A 3-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec3A(pub(crate) __m128); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec3A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool, z: bool) -> Self { unsafe { UnionCast { a: [MASK[x as usize], MASK[y as usize], MASK[z as usize], 0], } .v } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// Returns a bitmask with the lowest 3 bits set from the elements of `self`. /// /// 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.0 = 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(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], ] } } impl Default for BVec3A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec3A {} impl core::hash::Hash for BVec3A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec3A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(unsafe { _mm_and_ps(self.0, rhs.0) }) } } impl BitAndAssign for BVec3A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec3A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(unsafe { _mm_or_ps(self.0, rhs.0) }) } } impl BitOrAssign for BVec3A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec3A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(unsafe { _mm_xor_ps(self.0, rhs.0) }) } } impl BitXorAssign for BVec3A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec3A { type Output = Self; #[inline] fn not(self) -> Self { Self(unsafe { _mm_andnot_ps(self.0, _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))) }) } } impl From for __m128 { #[inline] fn from(t: BVec3A) -> Self { t.0 } } impl fmt::Debug for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x})", stringify!(BVec3A), arr[0], arr[1], arr[2] ) } } impl fmt::Display for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) } } impl From<[bool; 3]> for BVec3A { #[inline] fn from(a: [bool; 3]) -> Self { Self::from_array(a) } } impl From for [bool; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_bool_array() } } impl From for [u32; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/sse2/bvec4a.rs000064400000000000000000000140161046102023000147370ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C)] union UnionCast { a: [u32; 4], v: BVec4A, } /// Creates a 4-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A { BVec4A::new(x, y, z, w) } /// A 4-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec4A(pub(crate) __m128); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec4A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new(x: bool, y: bool, z: bool, w: bool) -> Self { unsafe { UnionCast { a: [ MASK[x as usize], MASK[y as usize], MASK[z as usize], MASK[w as usize], ], } .v } } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } /// Returns a bitmask with the lowest 4 bits set from the elements of `self`. /// /// 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.0 = v.0; } #[inline] #[must_use] fn into_bool_array(self) -> [bool; 4] { let bitmask = self.bitmask(); [ (bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0, (bitmask & 8) != 0, ] } #[inline] #[must_use] fn into_u32_array(self) -> [u32; 4] { let bitmask = self.bitmask(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], MASK[((bitmask >> 3) & 1) as usize], ] } } impl Default for BVec4A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec4A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec4A {} impl core::hash::Hash for BVec4A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec4A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(unsafe { _mm_and_ps(self.0, rhs.0) }) } } impl BitAndAssign for BVec4A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec4A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(unsafe { _mm_or_ps(self.0, rhs.0) }) } } impl BitOrAssign for BVec4A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec4A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(unsafe { _mm_xor_ps(self.0, rhs.0) }) } } impl BitXorAssign for BVec4A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec4A { type Output = Self; #[inline] fn not(self) -> Self { Self(unsafe { _mm_andnot_ps(self.0, _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))) }) } } impl From for __m128 { #[inline] fn from(t: BVec4A) -> Self { t.0 } } impl fmt::Debug for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!(BVec4A), arr[0], arr[1], arr[2], arr[3] ) } } impl fmt::Display for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) } } impl From<[bool; 4]> for BVec4A { #[inline] fn from(a: [bool; 4]) -> Self { Self::from_array(a) } } impl From for [bool; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_bool_array() } } impl From for [u32; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/sse2.rs000064400000000000000000000000401046102023000135630ustar 00000000000000pub mod bvec3a; pub mod bvec4a; glam-0.30.1/src/bool/wasm32/bvec3a.rs000064400000000000000000000126211046102023000151760ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; use core::arch::wasm32::*; /// Creates a 3-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec3a(x: bool, y: bool, z: bool) -> BVec3A { BVec3A::new(x, y, z) } /// A 3-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec3A(pub(crate) v128); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec3A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// 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], MASK[y as usize], MASK[z as usize], 0, )) } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// Returns a bitmask with the lowest 3 bits set from the elements of `self`. /// /// 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.0 = 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(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], ] } } impl Default for BVec3A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec3A {} impl core::hash::Hash for BVec3A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec3A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(v128_and(self.0, rhs.0)) } } impl BitAndAssign for BVec3A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec3A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(v128_or(self.0, rhs.0)) } } impl BitOrAssign for BVec3A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec3A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(v128_xor(self.0, rhs.0)) } } impl BitXorAssign for BVec3A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec3A { type Output = Self; #[inline] fn not(self) -> Self { Self(v128_not(self.0)) } } impl From for v128 { #[inline] fn from(t: BVec3A) -> Self { t.0 } } impl fmt::Debug for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x})", stringify!(BVec3A), arr[0], arr[1], arr[2] ) } } impl fmt::Display for BVec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) } } impl From<[bool; 3]> for BVec3A { #[inline] fn from(a: [bool; 3]) -> Self { Self::from_array(a) } } impl From for [bool; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_bool_array() } } impl From for [u32; 3] { #[inline] fn from(mask: BVec3A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/wasm32/bvec4a.rs000064400000000000000000000132161046102023000152000ustar 00000000000000// Generated from vec_mask.rs.tera template. Edit the template, not the generated file. use core::fmt; use core::ops::*; use core::arch::wasm32::*; /// Creates a 4-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn bvec4a(x: bool, y: bool, z: bool, w: bool) -> BVec4A { BVec4A::new(x, y, z, w) } /// A 4-dimensional SIMD vector mask. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct BVec4A(pub(crate) v128); const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl BVec4A { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// 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], MASK[y as usize], MASK[z as usize], MASK[w as usize], )) } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new(v, v, v, v) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } /// Returns a bitmask with the lowest 4 bits set from the elements of `self`. /// /// 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.0 = v.0; } #[inline] #[must_use] fn into_bool_array(self) -> [bool; 4] { let bitmask = self.bitmask(); [ (bitmask & 1) != 0, (bitmask & 2) != 0, (bitmask & 4) != 0, (bitmask & 8) != 0, ] } #[inline] #[must_use] fn into_u32_array(self) -> [u32; 4] { let bitmask = self.bitmask(); [ MASK[(bitmask & 1) as usize], MASK[((bitmask >> 1) & 1) as usize], MASK[((bitmask >> 2) & 1) as usize], MASK[((bitmask >> 3) & 1) as usize], ] } } impl Default for BVec4A { #[inline] fn default() -> Self { Self::FALSE } } impl PartialEq for BVec4A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for BVec4A {} impl core::hash::Hash for BVec4A { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } impl BitAnd for BVec4A { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { Self(v128_and(self.0, rhs.0)) } } impl BitAndAssign for BVec4A { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for BVec4A { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { Self(v128_or(self.0, rhs.0)) } } impl BitOrAssign for BVec4A { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for BVec4A { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { Self(v128_xor(self.0, rhs.0)) } } impl BitXorAssign for BVec4A { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for BVec4A { type Output = Self; #[inline] fn not(self) -> Self { Self(v128_not(self.0)) } } impl From for v128 { #[inline] fn from(t: BVec4A) -> Self { t.0 } } impl fmt::Debug for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); write!( f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!(BVec4A), arr[0], arr[1], arr[2], arr[3] ) } } impl fmt::Display for BVec4A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) } } impl From<[bool; 4]> for BVec4A { #[inline] fn from(a: [bool; 4]) -> Self { Self::from_array(a) } } impl From for [bool; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_bool_array() } } impl From for [u32; 4] { #[inline] fn from(mask: BVec4A) -> Self { mask.into_u32_array() } } glam-0.30.1/src/bool/wasm32.rs000064400000000000000000000000401046102023000140230ustar 00000000000000pub mod bvec3a; pub mod bvec4a; glam-0.30.1/src/bool.rs000064400000000000000000000061761046102023000127270ustar 00000000000000mod bvec2; mod bvec3; mod bvec4; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] mod coresimd; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod neon; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod sse2; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod wasm32; #[cfg(any( not(any( feature = "core-simd", target_arch = "aarch64", target_feature = "sse2", target_feature = "simd128" )), feature = "scalar-math" ))] mod scalar; pub use bvec2::{bvec2, BVec2}; pub use bvec3::{bvec3, BVec3}; pub use bvec4::{bvec4, BVec4}; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] pub use neon::bvec3a::{bvec3a, BVec3A}; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] pub use neon::bvec4a::{bvec4a, BVec4A}; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] pub use sse2::bvec3a::{bvec3a, BVec3A}; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] pub use sse2::bvec4a::{bvec4a, BVec4A}; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] pub use wasm32::bvec3a::{bvec3a, BVec3A}; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] pub use wasm32::bvec4a::{bvec4a, BVec4A}; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] pub use coresimd::bvec3a::{bvec3a, BVec3A}; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] pub use coresimd::bvec4a::{bvec4a, BVec4A}; #[cfg(any( not(any( feature = "core-simd", target_arch = "aarch64", target_feature = "sse2", target_feature = "simd128" )), feature = "scalar-math" ))] pub use scalar::bvec3a::{bvec3a, BVec3A}; #[cfg(any( not(any( feature = "core-simd", target_arch = "aarch64", target_feature = "sse2", target_feature = "simd128" )), feature = "scalar-math" ))] pub use scalar::bvec4a::{bvec4a, BVec4A}; mod const_test_bvec2 { const_assert_eq!(1, core::mem::align_of::()); const_assert_eq!(2, core::mem::size_of::()); } mod const_test_bvec3 { const_assert_eq!(1, core::mem::align_of::()); const_assert_eq!(3, core::mem::size_of::()); } mod const_test_bvec4 { const_assert_eq!(1, core::mem::align_of::()); const_assert_eq!(4, core::mem::size_of::()); } #[cfg(not(feature = "scalar-math"))] mod const_test_bvec3a { const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } #[cfg(not(feature = "scalar-math"))] mod const_test_bvec4a { const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } glam-0.30.1/src/coresimd.rs000064400000000000000000000031471046102023000135740ustar 00000000000000use core::simd::{num::SimdFloat, *}; /// Calculates the vector 3 dot product and returns answer in x lane of f32x4. #[inline(always)] pub(crate) fn dot3_in_x(lhs: f32x4, rhs: f32x4) -> f32x4 { let x2_y2_z2_w2 = lhs * rhs; let y2_0_0_0 = simd_swizzle!(x2_y2_z2_w2, [1, 0, 0, 0]); let z2_0_0_0 = simd_swizzle!(x2_y2_z2_w2, [2, 0, 0, 0]); let x2y2_0_0_0 = x2_y2_z2_w2 + y2_0_0_0; x2y2_0_0_0 + z2_0_0_0 } /// Calculates the vector 4 dot product and returns answer in x lane of f32x4. #[inline(always)] pub(crate) fn dot4_in_x(lhs: f32x4, rhs: f32x4) -> f32x4 { let x2_y2_z2_w2 = lhs * rhs; let z2_w2_0_0 = simd_swizzle!(x2_y2_z2_w2, [2, 3, 0, 0]); let x2z2_y2w2_0_0 = x2_y2_z2_w2 + z2_w2_0_0; let y2w2_0_0_0 = simd_swizzle!(x2z2_y2w2_0_0, [1, 0, 0, 0]); x2z2_y2w2_0_0 + y2w2_0_0_0 } #[inline] pub(crate) fn dot3(lhs: f32x4, rhs: f32x4) -> f32 { dot3_in_x(lhs, rhs)[0] } #[inline] pub(crate) fn dot3_into_f32x4(lhs: f32x4, rhs: f32x4) -> f32x4 { let dot_in_x = dot3_in_x(lhs, rhs); simd_swizzle!(dot_in_x, [0, 0, 0, 0]) } #[inline] pub(crate) fn dot4(lhs: f32x4, rhs: f32x4) -> f32 { dot4_in_x(lhs, rhs)[0] } #[inline] pub(crate) fn dot4_into_f32x4(lhs: f32x4, rhs: f32x4) -> f32x4 { let dot_in_x = dot4_in_x(lhs, rhs); simd_swizzle!(dot_in_x, [0, 0, 0, 0]) } #[inline(always)] pub(crate) fn f32x4_bitand(a: f32x4, b: f32x4) -> f32x4 { let a = a.to_bits(); let b = b.to_bits(); f32x4::from_bits(a & b) } #[inline(always)] pub(crate) fn f32x4_bitxor(a: f32x4, b: f32x4) -> f32x4 { let a = a.to_bits(); let b = b.to_bits(); f32x4::from_bits(a ^ b) } glam-0.30.1/src/deref.rs000064400000000000000000000015111046102023000130450ustar 00000000000000#[cfg(not(feature = "scalar-math"))] #[cfg_attr(target_arch = "spirv", repr(simd))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] pub struct Vec3 { pub x: T, pub y: T, pub z: T, } #[cfg(not(feature = "scalar-math"))] #[cfg_attr(target_arch = "spirv", repr(simd))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] pub struct Vec4 { pub x: T, pub y: T, pub z: T, pub w: T, } #[cfg(not(feature = "scalar-math"))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] pub struct Cols2 { pub x_axis: V, pub y_axis: V, } #[cfg_attr(not(target_arch = "spirv"), repr(C))] pub struct Cols3 { pub x_axis: V, pub y_axis: V, pub z_axis: V, } #[cfg_attr(not(target_arch = "spirv"), repr(C))] pub struct Cols4 { pub x_axis: V, pub y_axis: V, pub z_axis: V, pub w_axis: V, } glam-0.30.1/src/euler.rs000064400000000000000000000347101046102023000131030ustar 00000000000000// Based on Ken Shoemake. 1994. Euler angle conversion. Graphics gems IV. Academic Press // Professional, Inc., USA, 222–229. use crate::{DMat3, DMat4, DQuat, DVec3, Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A, Vec3Swizzles}; /// Euler rotation sequences. /// /// The three elemental rotations may be extrinsic (rotations about the axes xyz of the original /// coordinate system, which is assumed to remain motionless), or intrinsic(rotations about the /// axes of the rotating coordinate system XYZ, solidary with the moving body, which changes its /// orientation after each elemental rotation). /// /// ``` /// # use glam::{EulerRot, Mat3}; /// # let i = core::f32::consts::FRAC_PI_2; /// # let j = core::f32::consts::FRAC_PI_4; /// # let k = core::f32::consts::FRAC_PI_8; /// let m_intrinsic = Mat3::from_rotation_x(i) * Mat3::from_rotation_y(j) * Mat3::from_rotation_z(k); /// let n_intrinsic = Mat3::from_euler(EulerRot::XYZ, i, j, k); /// assert!(m_intrinsic.abs_diff_eq(n_intrinsic, 2e-6)); /// /// let m_extrinsic = Mat3::from_rotation_z(k) * Mat3::from_rotation_y(j) * Mat3::from_rotation_x(i); /// let n_extrinsic = Mat3::from_euler(EulerRot::XYZEx, i, j, k); /// assert!(m_extrinsic.abs_diff_eq(n_extrinsic, 2e-6)); /// ``` /// #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum EulerRot { /// Intrinsic three-axis rotation ZYX ZYX, /// Intrinsic three-axis rotation ZXY ZXY, /// Intrinsic three-axis rotation YXZ YXZ, /// Intrinsic three-axis rotation YZX YZX, /// Intrinsic three-axis rotation XYZ XYZ, /// Intrinsic three-axis rotation XZY XZY, /// Intrinsic two-axis rotation ZYZ ZYZ, /// Intrinsic two-axis rotation ZXZ ZXZ, /// Intrinsic two-axis rotation YXY YXY, /// Intrinsic two-axis rotation YZY YZY, /// Intrinsic two-axis rotation XYX XYX, /// Intrinsic two-axis rotation XZX XZX, /// Extrinsic three-axis rotation ZYX ZYXEx, /// Extrinsic three-axis rotation ZXY ZXYEx, /// Extrinsic three-axis rotation YXZ YXZEx, /// Extrinsic three-axis rotation YZX YZXEx, /// Extrinsic three-axis rotation XYZ XYZEx, /// Extrinsic three-axis rotation XZY XZYEx, /// Extrinsic two-axis rotation ZYZ ZYZEx, /// Extrinsic two-axis rotation ZXZ ZXZEx, /// Extrinsic two-axis rotation YXY YXYEx, /// Extrinsic two-axis rotation YZY YZYEx, /// Extrinsic two-axis rotation XYX XYXEx, /// Extrinsic two-axis rotation XZX XZXEx, } impl Default for EulerRot { /// Default `YXZ` as yaw (y-axis), pitch (x-axis), roll (z-axis). fn default() -> Self { Self::YXZ } } pub(crate) trait ToEuler { type Scalar; fn to_euler_angles(self, order: EulerRot) -> (Self::Scalar, Self::Scalar, Self::Scalar); } pub(crate) trait FromEuler { type Scalar; fn from_euler_angles( order: EulerRot, i: Self::Scalar, j: Self::Scalar, k: Self::Scalar, ) -> Self; } #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Axis { X = 0, Y = 1, Z = 2, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Parity { Odd = 0, Even = 1, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Repeated { No = 0, Yes = 1, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum Frame { Relative = 0, Static = 1, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] struct Order { initial_axis: Axis, parity_even: bool, initial_repeated: bool, frame_static: bool, } impl Order { const fn new( initial_axis: Axis, parity: Parity, initial_repeated: Repeated, frame: Frame, ) -> Self { Self { initial_axis, parity_even: parity as u32 == Parity::Even as u32, initial_repeated: initial_repeated as u32 == Repeated::Yes as u32, frame_static: frame as u32 == Frame::Static as u32, } } const fn from_euler(euler: EulerRot) -> Self { match euler { EulerRot::XYZ => Self::new(Axis::X, Parity::Even, Repeated::No, Frame::Static), EulerRot::XYX => Self::new(Axis::X, Parity::Even, Repeated::Yes, Frame::Static), EulerRot::XZY => Self::new(Axis::X, Parity::Odd, Repeated::No, Frame::Static), EulerRot::XZX => Self::new(Axis::X, Parity::Odd, Repeated::Yes, Frame::Static), EulerRot::YZX => Self::new(Axis::Y, Parity::Even, Repeated::No, Frame::Static), EulerRot::YZY => Self::new(Axis::Y, Parity::Even, Repeated::Yes, Frame::Static), EulerRot::YXZ => Self::new(Axis::Y, Parity::Odd, Repeated::No, Frame::Static), EulerRot::YXY => Self::new(Axis::Y, Parity::Odd, Repeated::Yes, Frame::Static), EulerRot::ZXY => Self::new(Axis::Z, Parity::Even, Repeated::No, Frame::Static), EulerRot::ZXZ => Self::new(Axis::Z, Parity::Even, Repeated::Yes, Frame::Static), EulerRot::ZYX => Self::new(Axis::Z, Parity::Odd, Repeated::No, Frame::Static), EulerRot::ZYZ => Self::new(Axis::Z, Parity::Odd, Repeated::Yes, Frame::Static), EulerRot::ZYXEx => Self::new(Axis::X, Parity::Even, Repeated::No, Frame::Relative), EulerRot::XYXEx => Self::new(Axis::X, Parity::Even, Repeated::Yes, Frame::Relative), EulerRot::YZXEx => Self::new(Axis::X, Parity::Odd, Repeated::No, Frame::Relative), EulerRot::XZXEx => Self::new(Axis::X, Parity::Odd, Repeated::Yes, Frame::Relative), EulerRot::XZYEx => Self::new(Axis::Y, Parity::Even, Repeated::No, Frame::Relative), EulerRot::YZYEx => Self::new(Axis::Y, Parity::Even, Repeated::Yes, Frame::Relative), EulerRot::ZXYEx => Self::new(Axis::Y, Parity::Odd, Repeated::No, Frame::Relative), EulerRot::YXYEx => Self::new(Axis::Y, Parity::Odd, Repeated::Yes, Frame::Relative), EulerRot::YXZEx => Self::new(Axis::Z, Parity::Even, Repeated::No, Frame::Relative), EulerRot::ZXZEx => Self::new(Axis::Z, Parity::Even, Repeated::Yes, Frame::Relative), EulerRot::XYZEx => Self::new(Axis::Z, Parity::Odd, Repeated::No, Frame::Relative), EulerRot::ZYZEx => Self::new(Axis::Z, Parity::Odd, Repeated::Yes, Frame::Relative), } } const fn next_axis(i: usize) -> usize { (i + 1) % 3 } const fn prev_axis(i: usize) -> usize { if i > 0 { i - 1 } else { 2 } } const fn angle_order(self) -> (usize, usize, usize) { let i = self.initial_axis as usize; let j = if self.parity_even { Order::next_axis(i) } else { Order::prev_axis(i) }; let k = if self.parity_even { Order::prev_axis(i) } else { Order::next_axis(i) }; (i, j, k) } } macro_rules! impl_mat3_from_euler { ($scalar:ident, $mat3:ident, $vec3:ident) => { impl FromEuler for $mat3 { type Scalar = $scalar; fn from_euler_angles( euler: EulerRot, x: Self::Scalar, y: Self::Scalar, z: Self::Scalar, ) -> Self { use crate::$scalar::math; let order = Order::from_euler(euler); let (i, j, k) = order.angle_order(); let mut angles = if order.frame_static { $vec3::new(x, y, z) } else { $vec3::new(z, y, x) }; // rotation direction is reverse from original paper if order.parity_even { angles = -angles; } let (si, ci) = math::sin_cos(angles.x); let (sj, cj) = math::sin_cos(angles.y); let (sh, ch) = math::sin_cos(angles.z); let cc = ci * ch; let cs = ci * sh; let sc = si * ch; let ss = si * sh; let mut m = [[0.0; 3]; 3]; if order.initial_repeated { m[i][i] = cj; m[i][j] = sj * si; m[i][k] = sj * ci; m[j][i] = sj * sh; m[j][j] = -cj * ss + cc; m[j][k] = -cj * cs - sc; m[k][i] = -sj * ch; m[k][j] = cj * sc + cs; m[k][k] = cj * cc - ss; } else { m[i][i] = cj * ch; m[i][j] = sj * sc - cs; m[i][k] = sj * cc + ss; m[j][i] = cj * sh; m[j][j] = sj * ss + cc; m[j][k] = sj * cs - sc; m[k][i] = -sj; m[k][j] = cj * si; m[k][k] = cj * ci; } $mat3::from_cols_array_2d(&m) } } }; } macro_rules! impl_mat4_from_euler { ($scalar:ident, $mat4:ident, $mat3:ident) => { impl FromEuler for $mat4 { type Scalar = $scalar; fn from_euler_angles( euler: EulerRot, x: Self::Scalar, y: Self::Scalar, z: Self::Scalar, ) -> Self { $mat4::from_mat3($mat3::from_euler_angles(euler, x, y, z)) } } }; } macro_rules! impl_quat_from_euler { ($scalar:ident, $quat:ident, $vec3:ident) => { impl FromEuler for $quat { type Scalar = $scalar; fn from_euler_angles( euler: EulerRot, x: Self::Scalar, y: Self::Scalar, z: Self::Scalar, ) -> Self { use crate::$scalar::math; let order = Order::from_euler(euler); let (i, j, k) = order.angle_order(); let mut angles = if order.frame_static { $vec3::new(x, y, z) } else { $vec3::new(z, y, x) }; if order.parity_even { angles.y = -angles.y; } let ti = angles.x * 0.5; let tj = angles.y * 0.5; let th = angles.z * 0.5; let (si, ci) = math::sin_cos(ti); let (sj, cj) = math::sin_cos(tj); let (sh, ch) = math::sin_cos(th); let cc = ci * ch; let cs = ci * sh; let sc = si * ch; let ss = si * sh; let parity = if !order.parity_even { 1.0 } else { -1.0 }; let mut a = [0.0; 4]; if order.initial_repeated { a[i] = cj * (cs + sc); a[j] = sj * (cc + ss) * parity; a[k] = sj * (cs - sc); a[3] = cj * (cc - ss); } else { a[i] = cj * sc - sj * cs; a[j] = (cj * ss + sj * cc) * parity; a[k] = cj * cs - sj * sc; a[3] = cj * cc + sj * ss; } $quat::from_array(a) } } }; } macro_rules! impl_mat3_to_euler { ($scalar:ident, $mat3:ident, $vec3:ident) => { impl ToEuler for $mat3 { type Scalar = $scalar; fn to_euler_angles( self, euler: EulerRot, ) -> (Self::Scalar, Self::Scalar, Self::Scalar) { use crate::$scalar::math; let order = Order::from_euler(euler); let (i, j, k) = order.angle_order(); let mut ea = $vec3::ZERO; if order.initial_repeated { let sy = math::sqrt( self.col(i)[j] * self.col(i)[j] + self.col(i)[k] * self.col(i)[k], ); if (sy > 16.0 * $scalar::EPSILON) { ea.x = math::atan2(self.col(i)[j], self.col(i)[k]); ea.y = math::atan2(sy, self.col(i)[i]); ea.z = math::atan2(self.col(j)[i], -self.col(k)[i]); } else { ea.x = math::atan2(-self.col(j)[k], self.col(j)[j]); ea.y = math::atan2(sy, self.col(i)[i]); } } else { let cy = math::sqrt( self.col(i)[i] * self.col(i)[i] + self.col(j)[i] * self.col(j)[i], ); if (cy > 16.0 * $scalar::EPSILON) { ea.x = math::atan2(self.col(k)[j], self.col(k)[k]); ea.y = math::atan2(-self.col(k)[i], cy); ea.z = math::atan2(self.col(j)[i], self.col(i)[i]); } else { ea.x = math::atan2(-self.col(j)[k], self.col(j)[j]); ea.y = math::atan2(-self.col(k)[i], cy); } } // reverse rotation angle of original code if order.parity_even { ea = -ea; } if !order.frame_static { ea = ea.zyx(); } (ea.x, ea.y, ea.z) } } }; } macro_rules! impl_mat4_to_euler { ($scalar:ident, $mat4:ident, $mat3:ident) => { impl ToEuler for $mat4 { type Scalar = $scalar; fn to_euler_angles( self, order: EulerRot, ) -> (Self::Scalar, Self::Scalar, Self::Scalar) { $mat3::from_mat4(self).to_euler_angles(order) } } }; } macro_rules! impl_quat_to_euler { ($scalar:ident, $quat:ident, $mat3:ident) => { impl ToEuler for $quat { type Scalar = $scalar; fn to_euler_angles( self, order: EulerRot, ) -> (Self::Scalar, Self::Scalar, Self::Scalar) { $mat3::from_quat(self).to_euler_angles(order) } } }; } impl_mat3_to_euler!(f32, Mat3, Vec3); impl_mat3_from_euler!(f32, Mat3, Vec3); impl_mat3_to_euler!(f32, Mat3A, Vec3A); impl_mat3_from_euler!(f32, Mat3A, Vec3A); impl_mat4_from_euler!(f32, Mat4, Mat3); impl_mat4_to_euler!(f32, Mat4, Mat3); impl_quat_to_euler!(f32, Quat, Mat3); impl_quat_from_euler!(f32, Quat, Vec3); impl_mat3_to_euler!(f64, DMat3, DVec3); impl_mat3_from_euler!(f64, DMat3, DVec3); impl_mat4_to_euler!(f64, DMat4, DMat3); impl_mat4_from_euler!(f64, DMat4, DMat3); impl_quat_to_euler!(f64, DQuat, DMat3); impl_quat_from_euler!(f64, DQuat, DVec3); glam-0.30.1/src/f32/affine2.rs000064400000000000000000000313471046102023000136760ustar 00000000000000// 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, MulAssign}; /// A 2D affine transform, which can represent translation, rotation, scaling and shear. #[derive(Copy, Clone)] #[repr(C)] pub struct Affine2 { pub matrix2: Mat2, pub translation: Vec2, } impl Affine2 { /// The degenerate zero transform. /// /// This transforms any finite vector and point to zero. /// The zero transform is non-invertible. pub const ZERO: Self = Self { matrix2: Mat2::ZERO, translation: Vec2::ZERO, }; /// The identity transform. /// /// Multiplying a vector with this returns the same vector. pub const IDENTITY: Self = Self { matrix2: Mat2::IDENTITY, translation: Vec2::ZERO, }; /// All NAN:s. pub const NAN: Self = Self { matrix2: Mat2::NAN, translation: Vec2::NAN, }; /// 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), translation: z_axis, } } /// 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_array(&[m[0], m[1], m[2], m[3]]), translation: Vec2::from_array([m[4], m[5]]), } } /// 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; let z = &self.translation; [x.x, x.y, y.x, y.y, z.x, z.y] } /// Creates an affine transform from a `[[f32; 2]; 3]` /// 2D array stored in column major order. /// 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()), translation: m[2].into(), } } /// Creates a `[[f32; 2]; 3]` 2D array storing data in /// 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(), self.matrix2.y_axis.into(), self.translation.into(), ] } /// Creates an affine transform from the first 6 values in `slice`. /// /// # Panics /// /// 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]), translation: Vec2::from_slice(&slice[4..6]), } } /// Writes the columns of `self` to the first 6 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 6 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { self.matrix2.write_cols_to_slice(&mut slice[0..4]); self.translation.write_to_slice(&mut slice[4..6]); } /// 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), translation: Vec2::ZERO, } } /// 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), translation: Vec2::ZERO, } } /// Creates an affine transformation from the given 2D `translation`. #[inline] #[must_use] pub fn from_translation(translation: Vec2) -> Self { Self { matrix2: Mat2::IDENTITY, translation, } } /// 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, translation: Vec2::ZERO, } } /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a /// translation vector. /// /// 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, translation, } } /// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and /// `translation`. /// /// 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 { matrix2: Mat2::from_cols(rotation.x_axis * scale.x, rotation.y_axis * scale.y), translation, } } /// Creates an affine transform from the given 2D rotation `angle` (in radians) and /// `translation`. /// /// 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), translation, } } /// The given `Mat3` must be an affine transform, #[inline] #[must_use] pub fn from_mat3(m: Mat3) -> Self { use crate::swizzles::Vec3Swizzles; Self { matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()), translation: m.z_axis.xy(), } } /// The given [`Mat3A`] must be an affine transform, #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { use crate::swizzles::Vec3Swizzles; Self { matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()), translation: m.z_axis.xy(), } } /// 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 } /// Transforms the given 2D vector, applying shear, scale and rotation (but NOT /// translation). /// /// To also apply translation, use [`Self::transform_point2()`] instead. #[inline] pub fn transform_vector2(&self, rhs: Vec2) -> Vec2 { self.matrix2 * rhs } /// 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.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() } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two 3x4 matrices contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Return the inverse of this transform. /// /// Note that if the transform is not invertible the result will be invalid. #[inline] #[must_use] pub fn inverse(&self) -> Self { let matrix2 = self.matrix2.inverse(); // transform negative translation by the matrix inverse: let translation = -(matrix2 * self.translation); Self { matrix2, translation, } } } impl Default for Affine2 { #[inline(always)] fn default() -> Self { Self::IDENTITY } } impl Deref for Affine2 { type Target = crate::deref::Cols3; #[inline(always)] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl DerefMut for Affine2 { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl PartialEq for Affine2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.matrix2.eq(&rhs.matrix2) && self.translation.eq(&rhs.translation) } } impl core::fmt::Debug for Affine2 { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fmt.debug_struct(stringify!(Affine2)) .field("matrix2", &self.matrix2) .field("translation", &self.translation) .finish() } } impl core::fmt::Display for Affine2 { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation ) } else { write!( f, "[{}, {}, {}]", self.matrix2.x_axis, self.matrix2.y_axis, self.translation ) } } } impl<'a> core::iter::Product<&'a Self> for Affine2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| a * b) } } impl Mul for Affine2 { type Output = Affine2; #[inline] fn mul(self, rhs: Affine2) -> Self::Output { Self { matrix2: self.matrix2 * rhs.matrix2, translation: self.matrix2 * rhs.translation + self.translation, } } } impl MulAssign for Affine2 { #[inline] fn mul_assign(&mut self, rhs: Affine2) { *self = self.mul(rhs); } } impl From for Mat3 { #[inline] fn from(m: Affine2) -> Mat3 { Self::from_cols( m.matrix2.x_axis.extend(0.0), m.matrix2.y_axis.extend(0.0), m.translation.extend(1.0), ) } } impl Mul for Affine2 { type Output = Mat3; #[inline] fn mul(self, rhs: Mat3) -> Self::Output { Mat3::from(self) * rhs } } impl Mul for Mat3 { type Output = Mat3; #[inline] fn mul(self, rhs: Affine2) -> Self::Output { self * Mat3::from(rhs) } } impl From for Mat3A { #[inline] fn from(m: Affine2) -> Mat3A { Self::from_cols( Vec3A::from((m.matrix2.x_axis, 0.0)), Vec3A::from((m.matrix2.y_axis, 0.0)), Vec3A::from((m.translation, 1.0)), ) } } impl Mul for Affine2 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { Mat3A::from(self) * rhs } } impl Mul for Mat3A { type Output = Mat3A; #[inline] fn mul(self, rhs: Affine2) -> Self::Output { self * Mat3A::from(rhs) } } glam-0.30.1/src/f32/affine3a.rs000064400000000000000000000425361046102023000140420ustar 00000000000000// 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, 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 { pub matrix3: Mat3A, pub translation: Vec3A, } impl Affine3A { /// The degenerate zero transform. /// /// This transforms any finite vector and point to zero. /// The zero transform is non-invertible. pub const ZERO: Self = Self { matrix3: Mat3A::ZERO, translation: Vec3A::ZERO, }; /// The identity transform. /// /// Multiplying a vector with this returns the same vector. pub const IDENTITY: Self = Self { matrix3: Mat3A::IDENTITY, translation: Vec3A::ZERO, }; /// All NAN:s. pub const NAN: Self = Self { matrix3: Mat3A::NAN, translation: Vec3A::NAN, }; /// 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), translation: w_axis, } } /// 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_array(&[ m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], ]), translation: Vec3A::from_array([m[9], m[10], m[11]]), } } /// 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; let z = &self.matrix3.z_axis; let w = &self.translation; [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z] } /// Creates an affine transform from a `[[f32; 3]; 4]` /// 3D array stored in column major order. /// 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()), translation: m[3].into(), } } /// Creates a `[[f32; 3]; 4]` 3D array storing data in /// 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(), self.matrix3.y_axis.into(), self.matrix3.z_axis.into(), self.translation.into(), ] } /// Creates an affine transform from the first 12 values in `slice`. /// /// # Panics /// /// 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]), translation: Vec3A::from_slice(&slice[9..12]), } } /// Writes the columns of `self` to the first 12 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 12 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { self.matrix3.write_cols_to_slice(&mut slice[0..9]); self.translation.write_to_slice(&mut slice[9..12]); } /// 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), translation: Vec3A::ZERO, } } /// 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), translation: Vec3A::ZERO, } } /// 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), translation: Vec3A::ZERO, } } /// 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), translation: Vec3A::ZERO, } } /// 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), translation: Vec3A::ZERO, } } /// 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), translation: Vec3A::ZERO, } } /// Creates an affine transformation from the given 3D `translation`. #[inline] #[must_use] pub fn from_translation(translation: Vec3) -> Self { #[allow(clippy::useless_conversion)] Self { matrix3: Mat3A::IDENTITY, translation: translation.into(), } } /// 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 { matrix3: mat3.into(), translation: Vec3A::ZERO, } } /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation) /// and a translation vector. /// /// 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 { matrix3: mat3.into(), translation: translation.into(), } } /// Creates an affine transform from the given 3D `scale`, `rotation` and /// `translation`. /// /// 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)] Self { matrix3: Mat3A::from_cols( rotation.x_axis * scale.x, rotation.y_axis * scale.y, rotation.z_axis * scale.z, ), translation: translation.into(), } } /// Creates an affine transform from the given 3D `rotation` and `translation`. /// /// 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 { matrix3: Mat3A::from_quat(rotation), translation: translation.into(), } } /// 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( Vec3A::from_vec4(m.x_axis), Vec3A::from_vec4(m.y_axis), Vec3A::from_vec4(m.z_axis), ), translation: Vec3A::from_vec4(m.w_axis), } } /// Extracts `scale`, `rotation` 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.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) { use crate::f32::math; let det = self.matrix3.determinant(); glam_assert!(det != 0.0); let scale = Vec3::new( self.matrix3.x_axis.length() * math::signum(det), self.matrix3.y_axis.length(), self.matrix3.z_axis.length(), ); glam_assert!(scale.cmpne(Vec3::ZERO).all()); let inv_scale = scale.recip(); #[allow(clippy::useless_conversion)] let rotation = Quat::from_mat3(&Mat3::from_cols( (self.matrix3.x_axis * inv_scale.x).into(), (self.matrix3.y_axis * inv_scale.y).into(), (self.matrix3.z_axis * inv_scale.z).into(), )); #[allow(clippy::useless_conversion)] (scale, rotation, self.translation.into()) } /// Creates a left-handed view transform using a camera position, an up direction, and a facing /// direction. /// /// 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) } /// Creates a right-handed view transform using a camera position, an up direction, and a facing /// direction. /// /// 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(); let u = s.cross(f); Self { matrix3: Mat3A::from_cols( Vec3A::new(s.x, u.x, -f.x), Vec3A::new(s.y, u.y, -f.y), Vec3A::new(s.z, u.z, -f.z), ), translation: Vec3A::new(-eye.dot(s), -eye.dot(u), eye.dot(f)), } } /// Creates a left-handed view transform using a camera position, an up direction, and a focal /// point. /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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) } /// Creates a right-handed view transform using a camera position, an up direction, and a focal /// point. /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// 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) } /// Transforms the given 3D points, applying shear, scale, rotation and translation. #[inline] pub fn transform_point3(&self, rhs: Vec3) -> Vec3 { #[allow(clippy::useless_conversion)] ((self.matrix3.x_axis * rhs.x) + (self.matrix3.y_axis * rhs.y) + (self.matrix3.z_axis * rhs.z) + self.translation) .into() } /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT /// translation). /// /// 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) + (self.matrix3.y_axis * rhs.y) + (self.matrix3.z_axis * rhs.z)) .into() } /// 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 /// translation). /// /// To also apply translation, use [`Self::transform_point3a()`] instead. #[inline] #[must_use] pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A { self.matrix3 * rhs } /// 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.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() } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two 3x4 matrices contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Return the inverse of this transform. /// /// Note that if the transform is not invertible the result will be invalid. #[inline] #[must_use] pub fn inverse(&self) -> Self { let matrix3 = self.matrix3.inverse(); // transform negative translation by the matrix inverse: let translation = -(matrix3 * self.translation); Self { matrix3, translation, } } } impl Default for Affine3A { #[inline(always)] fn default() -> Self { Self::IDENTITY } } impl Deref for Affine3A { type Target = crate::deref::Cols4; #[inline(always)] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl DerefMut for Affine3A { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl PartialEq for Affine3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation) } } impl core::fmt::Debug for Affine3A { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fmt.debug_struct(stringify!(Affine3A)) .field("matrix3", &self.matrix3) .field("translation", &self.translation) .finish() } } impl core::fmt::Display for Affine3A { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.matrix3.x_axis, p, self.matrix3.y_axis, p, self.matrix3.z_axis, p, self.translation ) } else { write!( f, "[{}, {}, {}, {}]", self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation ) } } } impl<'a> core::iter::Product<&'a Self> for Affine3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| a * b) } } impl Mul for Affine3A { type Output = Affine3A; #[inline] fn mul(self, rhs: Affine3A) -> Self::Output { Self { matrix3: self.matrix3 * rhs.matrix3, translation: self.matrix3 * rhs.translation + self.translation, } } } impl MulAssign for Affine3A { #[inline] fn mul_assign(&mut self, rhs: Affine3A) { *self = self.mul(rhs); } } impl From for Mat4 { #[inline] fn from(m: Affine3A) -> Mat4 { Mat4::from_cols( m.matrix3.x_axis.extend(0.0), m.matrix3.y_axis.extend(0.0), m.matrix3.z_axis.extend(0.0), m.translation.extend(1.0), ) } } impl Mul for Affine3A { type Output = Mat4; #[inline] fn mul(self, rhs: Mat4) -> Self::Output { Mat4::from(self) * rhs } } impl Mul for Mat4 { type Output = Mat4; #[inline] fn mul(self, rhs: Affine3A) -> Self::Output { self * Mat4::from(rhs) } } glam-0.30.1/src/f32/coresimd/mat2.rs000064400000000000000000000404701046102023000150310ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2}; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::simd::*; /// 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); impl Mat2 { /// A 2x2 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO); /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN); #[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])) } /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order. /// 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)) } /// 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]) } } /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order. /// 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])) } /// 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]) } } /// 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) } /// 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) = 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) = 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 the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from the first 4 values in `slice`. /// /// # Panics /// /// 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]) } /// Writes the columns of `self` to the first 4 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 4 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.y_axis.x; slice[3] = self.y_axis.y; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec2 { match index { 0 => self.x_axis, 1 => self.y_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec2 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec2::new(self.x_axis.y, self.y_axis.y), _ => panic!("index out of bounds"), } } /// 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`. #[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]); let prod = abcd * dcba; let det = prod - simd_swizzle!(prod, [1, 1, 1, 1]); det[0] } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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; let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]); let prod = abcd * dcba; let sub = prod - simd_swizzle!(prod, [1, 1, 1, 1]); let det = simd_swizzle!(sub, [0, 0, 0, 0]); let tmp = SIGN / det; glam_assert!(Mat2(tmp).is_finite()); let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]); Self(dbca.mul(tmp)) } /// 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]); let axbxcydy = abcd.mul(xxyy); let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]); let result = axbxcydy.add(cydyaxbx); unsafe { *(&result as *const f32x4 as *const Vec2) } } /// 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]); let xxyy1 = simd_swizzle!(rhs.0, [2, 2, 3, 3]); let axbxcydy0 = abcd * xxyy0; let axbxcydy1 = abcd * xxyy1; let cydyaxbx0 = simd_swizzle!(axbxcydy0, [2, 3, 0, 1]); let cydyaxbx1 = simd_swizzle!(axbxcydy1, [2, 3, 0, 1]); let result0 = axbxcydy0 + cydyaxbx0; let result1 = axbxcydy1 + cydyaxbx1; 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)) } /// Divides a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { Self(self.0 / f32x4::splat(rhs)) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs()) } #[inline] pub fn as_dmat2(&self) -> DMat2 { DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2()) } } impl Default for Mat2 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat2(&rhs) } } impl AddAssign for Mat2 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat2(&rhs); } } impl Sub for Mat2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat2(&rhs) } } impl SubAssign for Mat2 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat2(&rhs); } } impl Neg for Mat2 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self(-self.0) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat2(&rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat2(&rhs); } } impl Mul for Mat2 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Self::Output { self.mul_vec2(rhs) } } impl Mul for f32 { type Output = Mat2; #[inline] fn mul(self, rhs: Mat2) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat2; #[inline] fn div(self, rhs: Mat2) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat2 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat2 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Mat2 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Mat2 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Self as *mut [f32; 4]) } } } impl core::ops::Deref for Mat2 { type Target = crate::deref::Cols2; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl core::ops::DerefMut for Mat2 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl fmt::Debug for Mat2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat2)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .finish() } } impl fmt::Display for Mat2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) } else { write!(f, "[{}, {}]", self.x_axis, self.y_axis) } } } glam-0.30.1/src/f32/coresimd/mat3a.rs000064400000000000000000000734631046102023000152030ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::simd::*; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat3A { pub x_axis: Vec3A, pub y_axis: Vec3A, pub z_axis: Vec3A, } impl Mat3A { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self { Self { x_axis: Vec3A::new(m00, m01, m02), y_axis: Vec3A::new(m10, m11, m12), z_axis: Vec3A::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order. /// 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]) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y, z_axis_z, ] } /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order. /// 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]), Vec3A::from_array(m[1]), Vec3A::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( Vec3A::from_vec4(m.x_axis), Vec3A::from_vec4(m.y_axis), Vec3A::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols( Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (0, 1) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (0, 2) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (0, 3) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (1, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (1, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (1, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (1, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (2, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (2, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (2, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (2, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (3, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), ), (3, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), ), (3, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), ), (3, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), ), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy), Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx), Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::X, Vec3A::new(0.0, cosa, sina), Vec3A::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, 0.0, -sina), Vec3A::Y, Vec3A::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, sina, 0.0), Vec3A::new(-sina, cosa, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, Vec3A::Y, Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cos, sin, 0.0), Vec3A::new(-sin, cos, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec3A::new(scale.x, 0.0, 0.0), Vec3A::new(0.0, scale.y, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: Mat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec3A { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec3A { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[inline] #[must_use] pub fn transpose(&self) -> Self { 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, [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)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = Vec3A::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec3A::new(s.x, u.x, -f.x), Vec3A::new(s.y, u.y, -f.y), Vec3A::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// Transforms a 3D vector. #[inline] #[must_use] pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } /// 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())); res = res.add(self.z_axis.mul(rhs.zzz())); res } /// Multiplies two 3x3 matrices. #[inline] #[must_use] pub fn mul_mat3(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec3A::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_dmat3(&self) -> DMat3 { DMat3::from_cols( self.x_axis.as_dvec3(), self.y_axis.as_dvec3(), self.z_axis.as_dvec3(), ) } } impl Default for Mat3A { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for Mat3A { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for Mat3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for Mat3A { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for Mat3A { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for Mat3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl Mul for f32 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat3A; #[inline] fn div(self, rhs: Mat3A) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat3A { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Mul for Mat3A { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } } impl From for Mat3A { #[inline] fn from(m: Mat3) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } impl Sum for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } impl fmt::Debug for Mat3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat3A)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for Mat3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f32/coresimd/mat4.rs000064400000000000000000001463461046102023000150440ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ coresimd::*, euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::simd::*; /// 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) } /// A 4x4 column major matrix. /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat4 { pub x_axis: Vec4, pub y_axis: Vec4, pub z_axis: Vec4, pub w_axis: Vec4, } impl Mat4 { /// A 4x4 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO); /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self { Self { x_axis: Vec4::new(m00, m01, m02, m03), y_axis: Vec4::new(m10, m11, m12, m13), z_axis: Vec4::new(m20, m21, m22, m23), w_axis: Vec4::new(m30, m31, m32, m33), } } /// 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, y_axis, z_axis, w_axis, } } /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order. /// 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], m[14], m[15], ) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array(); let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w, z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w, ] } /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order. /// 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]), Vec4::from_array(m[1]), Vec4::from_array(m[2]), Vec4::from_array(m[3]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), self.w_axis.to_array(), ] } /// 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(); Self::new( x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w, ) } #[inline] #[must_use] fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne(Vec3::ZERO).all()); let inv_scale = scale.recip(); let rotation = Quat::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self { Self::from_cols( Vec4::from((mat3.x_axis, 0.0)), Vec4::from((mat3.y_axis, 0.0)), Vec4::from((mat3.z_axis, 0.0)), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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, Vec4::Y, Vec4::Z, Vec4::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # 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 (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( Vec4::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), Vec4::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), Vec4::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), Vec4::W, ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized() ); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::X, Vec4::new(0.0, cosa, sina, 0.0), Vec4::new(0.0, -sina, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::new(cosa, 0.0, -sina, 0.0), Vec4::Y, Vec4::new(sina, 0.0, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: f32) -> Self { 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), Vec4::Z, Vec4::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec4::new(scale.x, 0.0, 0.0, 0.0), Vec4::new(0.0, scale.y, 0.0, 0.0), Vec4::new(0.0, 0.0, scale.z, 0.0), Vec4::W, ) } /// Creates a 4x4 matrix from the first 16 values in `slice`. /// /// # Panics /// /// 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], slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15], ) } /// Writes the columns of `self` to the first 16 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 16 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.x_axis.w; slice[4] = self.y_axis.x; slice[5] = self.y_axis.y; slice[6] = self.y_axis.z; slice[7] = self.y_axis.w; slice[8] = self.z_axis.x; slice[9] = self.z_axis.y; slice[10] = self.z_axis.z; slice[11] = self.z_axis.w; slice[12] = self.w_axis.x; slice[13] = self.w_axis.y; slice[14] = self.w_axis.z; slice[15] = self.w_axis.w; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec4 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, 3 => self.w_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec4 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, 3 => &mut self.w_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), _ => panic!("index out of bounds"), } } /// 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() && self.w_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() || self.w_axis.is_nan() } /// Returns the transpose of `self`. #[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, [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, [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]); let swp3a = simd_swizzle!(self.w_axis.0, [3, 3, 2, 3]); let swp2b = simd_swizzle!(self.z_axis.0, [3, 3, 2, 3]); let swp3b = simd_swizzle!(self.w_axis.0, [2, 1, 1, 0]); let swp2c = simd_swizzle!(self.z_axis.0, [2, 1, 0, 0]); let swp3c = simd_swizzle!(self.w_axis.0, [0, 0, 2, 1]); let mula = swp2a * swp3a; let mulb = swp2b * swp3b; let mulc = swp2c * swp3c; let sube = mula - mulb; let subf = simd_swizzle!(mulc, [2, 3, 2, 3]) - mulc; let subfaca = simd_swizzle!(sube, [0, 0, 1, 2]); let swpfaca = simd_swizzle!(self.y_axis.0, [1, 0, 0, 0]); let mulfaca = swpfaca * subfaca; 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, [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; let addres = subres + mulfacc; let detcof = addres * f32x4::from_array([1.0, -1.0, 1.0, -1.0]); dot4(self.x_axis.0, detcof) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[must_use] 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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [1, 1, 5, 5]); let mul00 = swp00 * swp01; let mul01 = swp02 * swp03; mul00 - mul01 }; 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, [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, [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, [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, [3, 3, 7, 7]); let vec3 = simd_swizzle!(temp3, [0, 2, 2, 2]); let mul00 = vec1 * fac0; let mul01 = vec2 * fac1; let mul02 = vec3 * fac2; let sub00 = mul00 - mul01; let add00 = sub00 + mul02; let inv0 = sign_b * add00; let mul03 = vec0 * fac0; let mul04 = vec2 * fac3; let mul05 = vec3 * fac4; let sub01 = mul03 - mul04; let add01 = sub01 + mul05; let inv1 = sign_a * add01; let mul06 = vec0 * fac1; let mul07 = vec1 * fac3; let mul08 = vec3 * fac5; let sub02 = mul06 - mul07; let add02 = sub02 + mul08; let inv2 = sign_b * add02; let mul09 = vec0 * fac2; let mul10 = vec1 * fac4; let mul11 = vec2 * fac5; let sub03 = mul09 - mul10; let add03 = sub03 + mul11; let inv3 = sign_a * add03; 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); let rcp0 = f32x4::splat(dot0.recip()); Self { x_axis: Vec4(inv0 * rcp0), y_axis: Vec4(inv1 * rcp0), z_axis: Vec4(inv2 * rcp0), w_axis: Vec4(inv3 * rcp0), } } /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec4::new(s.x, u.x, -f.x, 0.0), Vec4::new(s.y, u.y, -f.y, 0.0), Vec4::new(s.z, u.z, -f.z, 0.0), Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, f, 0.0, 0.0), Vec4::new(0.0, 0.0, b, -1.0), Vec4::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 1.0), Vec4::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, -1.0), Vec4::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 1.0, 1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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) = math::sin_cos(0.5 * fov_y_radians); let h = cos_fov / sin_fov; let w = h / aspect_ratio; Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 0.0, 1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, -1.0, -1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, 0.0, -1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, b, 0.0, 0.0), Vec4::new(0.0, 0.0, c, 0.0), Vec4::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// 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); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction. /// /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A { let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); res = res.div(res.wwww()); Vec3A::from_vec4(res) } /// Transforms the given [`Vec3A`] as 3D point. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); Vec3A::from_vec4(res) } /// Transforms the give [`Vec3A`] as 3D vector. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); Vec3A::from_vec4(res) } /// 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())); res = res.add(self.z_axis.mul(rhs.zzzz())); res = res.add(self.w_axis.mul(rhs.wwww())); res } /// Multiplies two 4x4 matrices. #[inline] #[must_use] pub fn mul_mat4(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), self.mul(rhs.w_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), self.w_axis.add(rhs.w_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), self.w_axis.sub(rhs.w_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), self.w_axis.mul(rhs), ) } /// Divides a 4x4 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec4::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), self.w_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs(), self.w_axis.abs(), ) } #[inline] pub fn as_dmat4(&self) -> DMat4 { DMat4::from_cols( self.x_axis.as_dvec4(), self.y_axis.as_dvec4(), self.z_axis.as_dvec4(), self.w_axis.as_dvec4(), ) } } impl Default for Mat4 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat4(&rhs) } } impl AddAssign for Mat4 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat4(&rhs); } } impl Sub for Mat4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat4(&rhs) } } impl SubAssign for Mat4 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat4(&rhs); } } impl Neg for Mat4 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols( self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg(), self.w_axis.neg(), ) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat4(&rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat4(&rhs); } } impl Mul for Mat4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Self::Output { self.mul_vec4(rhs) } } impl Mul for f32 { type Output = Mat4; #[inline] fn mul(self, rhs: Mat4) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat4; #[inline] fn div(self, rhs: Mat4) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat4 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) && self.w_axis.eq(&rhs.w_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 16]> for Mat4 { #[inline] fn as_ref(&self) -> &[f32; 16] { unsafe { &*(self as *const Self as *const [f32; 16]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 16]> for Mat4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 16] { unsafe { &mut *(self as *mut Self as *mut [f32; 16]) } } } impl fmt::Debug for Mat4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat4)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .field("w_axis", &self.w_axis) .finish() } } impl fmt::Display for Mat4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis ) } else { write!( f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis ) } } } glam-0.30.1/src/f32/coresimd/quat.rs000064400000000000000000001032161046102023000151360ustar 00000000000000// Generated from quat.rs.tera template. Edit the template, not the generated file. use crate::{ coresimd::*, euler::{EulerRot, FromEuler, ToEuler}, f32::math, DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4, }; use core::simd::*; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub}; /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// 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)] pub struct Quat(pub(crate) f32x4); impl Quat { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([f32::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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])) } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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)) } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: Vec4) -> Self { Self(v.0) } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// 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]) } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [f32]) { slice[0] = self.x; slice[1] = self.y; slice[2] = self.z; slice[3] = self.w; } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `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 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// 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) = 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) = 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) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// 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 { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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 the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &Mat4) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::f32::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: f32 = 0.0; const SIN_FRAC_PI_2: f32 = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( Vec3::new(s.x, u.x, -f.x), Vec3::new(s.y, u.y, -f.y), Vec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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; 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, 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 } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) { self.to_euler_angles(order) } /// `[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. #[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)) } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { Vec4::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> f32 { Vec4::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> f32 { Vec4::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4(Vec4::from(self).normalize()) } /// 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() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { Vec4::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// 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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// 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()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: f32) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[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()); const NEG_ZERO: f32x4 = f32x4::from_array([-0.0; 4]); let dot = dot4_into_f32x4(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = f32x4_bitand(dot, NEG_ZERO); self.lerp_impl(Self(f32x4_bitxor(end.0, bias)), s) } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); let scale1 = math::sin(theta * (1.0 - s)); let scale2 = math::sin(theta * s); let theta_sin = math::sin(theta); ((self * scale1) + (end * scale2)) * (1.0 / theta_sin) } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// 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()); self.mul_vec3a(rhs.into()).into() } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { let lhs = self.0; let rhs = rhs.0; const CONTROL_WZYX: f32x4 = f32x4::from_array([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: f32x4 = f32x4::from_array([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: f32x4 = f32x4::from_array([-1.0, 1.0, 1.0, -1.0]); let r_xxxx = simd_swizzle!(lhs, [0, 0, 0, 0]); let r_yyyy = simd_swizzle!(lhs, [1, 1, 1, 1]); let r_zzzz = simd_swizzle!(lhs, [2, 2, 2, 2]); let r_wwww = simd_swizzle!(lhs, [3, 3, 3, 3]); let lxrw_lyrw_lzrw_lwrw = r_wwww * rhs; let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]); let lwrx_lzrx_lyrx_lxrx = r_xxxx * l_wzyx; let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]); let lwrx_nlzrx_lyrx_nlxrx = lwrx_lzrx_lyrx_lxrx * CONTROL_WZYX; let lzry_lwry_lxry_lyry = r_yyyy * l_zwxy; let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]); let lzry_lwry_nlxry_nlyry = lzry_lwry_lxry_lyry * CONTROL_ZWXY; let lyrz_lxrz_lwrz_lzrz = r_zzzz * l_yxwz; let result0 = lxrw_lyrw_lzrw_lwrw + lwrx_nlzrx_lyrx_nlxrx; let nlyrz_lxrz_lwrz_wlzrz = lyrz_lxrz_lwrz_lzrz * CONTROL_YXWZ; let result1 = lzry_lwry_nlxry_nlyry + nlyrz_lxrz_lwrz_wlzrz; Self(result0 + result1) } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::Affine3A) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } /// 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]); let b = self.0; let b2 = dot3_into_f32x4(b, b); Vec3A( rhs.0 .mul(w.mul(w).sub(b2)) .add(b.mul(dot3_into_f32x4(rhs.0, b).mul(TWO))) .add(Vec3A(b).cross(rhs).0.mul(w.mul(TWO))), ) } #[inline] #[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) } } impl fmt::Debug for Quat { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Quat)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for Quat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add for Quat { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) + Vec4::from(rhs)) } } impl Sub for Quat { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) - Vec4::from(rhs)) } } impl Mul for Quat { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) * rhs) } } impl Div for Quat { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) / rhs) } } impl Mul for Quat { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign for Quat { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul for Quat { type Output = Vec3; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Vec3) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for Quat { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for Quat { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for Quat { #[inline] fn eq(&self, rhs: &Self) -> bool { Vec4::from(*self).eq(&Vec4::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Quat { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } impl Sum for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl Mul for Quat { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl From for Vec4 { #[inline] fn from(q: Quat) -> Self { Self(q.0) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for [f32; 4] { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for f32x4 { #[inline] fn from(q: Quat) -> Self { q.0 } } impl Deref for Quat { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Quat { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } glam-0.30.1/src/f32/coresimd/vec3a.rs000064400000000000000000001432261046102023000151720ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{coresimd::*, f32::math, BVec3, BVec3A, FloatExt, Quat, Vec2, Vec3, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; use core::simd::{cmp::SimdPartialEq, cmp::SimdPartialOrd, num::SimdFloat, *}; use std::simd::StdFloat; /// 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. /// /// 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`] /// or [`Into`] trait implementations. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct Vec3A(pub(crate) f32x4); impl Vec3A { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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])) } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: 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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 3); 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 [f32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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] #[must_use] pub 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// 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(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]); let lhszxy_rhs = lhszxy * rhs.0; let rhszxy_lhs = rhszxy * self.0; let sub = lhszxy_rhs - rhszxy_lhs; Self(simd_swizzle!(sub, [2, 0, 1, 1])) } /// 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)) } /// 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(self.0.simd_max(rhs.0)) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { let v = self.0; let v = v.simd_min(simd_swizzle!(v, [2, 2, 1, 1])); let v = v.simd_min(simd_swizzle!(v, [1, 0, 0, 0])); v[0] } /// Returns the horizontal maximum of `self`. /// /// 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])); let v = v.simd_max(simd_swizzle!(v, [1, 0, 0, 0])); v[0] } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { simd_swizzle!(self.0, Self::ZERO.0, [0, 1, 2, 4]).reduce_sum() } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { simd_swizzle!(self.0, Self::ONE.0, [0, 1, 2, 4]).reduce_product() } /// 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) -> BVec3A { BVec3A(f32x4::simd_eq(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4::simd_ne(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4::simd_ge(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4::simd_gt(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4::simd_le(self.0, rhs.0)) } /// 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) -> 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()) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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)) } /// 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.0.is_sign_negative().to_bitmask() & 0x7) as u32 } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3A { BVec3A(f32x4::is_finite(self.0)) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec3A { BVec3A(f32x4::is_nan(self.0)) } /// 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] } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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] } /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { let length = dot3_into_f32x4(self.0, self.0).sqrt(); #[allow(clippy::let_and_return)] let normalized = Self(self.0 / length); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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()) } /// 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()) } /// 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 as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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()) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f32::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); Quat::from_axis_angle(axis.into(), angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f32) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize().into(); let rotation = Quat::from_axis_angle(axis, core::f32::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for Vec3A { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(self.0 / rhs.0) } } impl Div<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 /= rhs.0; } } impl DivAssign<&Vec3A> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &Vec3A) { self.div_assign(*rhs) } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(self.0 / f32x4::splat(rhs)) } } impl Div<&f32> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { self.div(*rhs) } } impl Div<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: f32) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 /= f32x4::splat(rhs); } } impl DivAssign<&f32> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4::splat(self) / rhs.0) } } impl Div<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(self.0 * rhs.0) } } impl Mul<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 *= rhs.0; } } impl MulAssign<&Vec3A> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &Vec3A) { self.mul_assign(*rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(self.0 * f32x4::splat(rhs)) } } impl Mul<&f32> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { self.mul(*rhs) } } impl Mul<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: f32) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 *= f32x4::splat(rhs); } } impl MulAssign<&f32> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4::splat(self) * rhs.0) } } impl Mul<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(self.0 + rhs.0) } } impl Add<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; } } impl AddAssign<&Vec3A> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &Vec3A) { self.add_assign(*rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(self.0 + f32x4::splat(rhs)) } } impl Add<&f32> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { self.add(*rhs) } } impl Add<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: f32) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 += f32x4::splat(rhs); } } impl AddAssign<&f32> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4::splat(self) + rhs.0) } } impl Add<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(self.0 - rhs.0) } } impl Sub<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: Vec3A) { self.0 -= rhs.0; } } impl SubAssign<&Vec3A> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &Vec3A) { self.sub_assign(*rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(self.0 - f32x4::splat(rhs)) } } impl Sub<&f32> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { self.sub(*rhs) } } impl Sub<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: f32) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 -= f32x4::splat(rhs); } } impl SubAssign<&f32> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4::splat(self) - rhs.0) } } impl Sub<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self(self.0 % rhs.0) } } impl Rem<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; } } impl RemAssign<&Vec3A> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &Vec3A) { self.rem_assign(*rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { self.rem(*rhs) } } impl Rem<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: f32) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: f32) { self.0 %= f32x4::splat(rhs); } } impl RemAssign<&f32> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { Vec3A::splat(self).rem(rhs) } } impl Rem<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 3]> for Vec3A { #[inline] fn as_ref(&self) -> &[f32; 3] { unsafe { &*(self as *const Vec3A as *const [f32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 3]> for Vec3A { #[inline] fn as_mut(&mut self) -> &mut [f32; 3] { unsafe { &mut *(self as *mut Vec3A as *mut [f32; 3]) } } } impl Sum for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec3A { type Output = Self; #[inline] fn neg(self) -> Self { Self(-self.0) } } impl Neg for &Vec3A { type Output = Vec3A; #[inline] fn neg(self) -> Vec3A { (*self).neg() } } impl Index for Vec3A { type Output = f32; #[inline] fn index(&self, index: usize) -> &Self::Output { &self.0[index] } } impl IndexMut for Vec3A { #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.0[index] } } impl fmt::Display for Vec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for Vec3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec3A)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From for f32x4 { #[inline(always)] fn from(t: Vec3A) -> Self { t.0 } } impl From for Vec3A { #[inline(always)] fn from(t: f32x4) -> Self { Self(t) } } impl From<[f32; 3]> for Vec3A { #[inline] fn from(a: [f32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f32; 3] { #[inline] fn from(v: Vec3A) -> Self { unsafe { *(v.0.to_array().as_ptr() as *const Self) } } } impl From<(f32, f32, f32)> for Vec3A { #[inline] fn from(t: (f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f32, f32, f32) { #[inline] fn from(v: Vec3A) -> Self { unsafe { *(v.0.to_array().as_ptr() as *const Self) } } } impl From for Vec3A { #[inline] fn from(v: Vec3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for Vec3 { #[inline] fn from(v: Vec3A) -> Self { unsafe { *(v.0.to_array().as_ptr() as *const Self) } } } impl From<(Vec2, f32)> for Vec3A { #[inline] fn from((v, z): (Vec2, f32)) -> Self { Self::new(v.x, v.y, z) } } impl Deref for Vec3A { type Target = crate::deref::Vec3; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec3A { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec3A { #[inline] fn from(v: BVec3) -> Self { Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z)) } } impl From for Vec3A { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), ) } } glam-0.30.1/src/f32/coresimd/vec4.rs000064400000000000000000001310621046102023000150250ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{coresimd::*, f32::math, BVec4, BVec4A, Vec2, Vec3, Vec3A}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; use core::simd::{cmp::SimdPartialEq, cmp::SimdPartialOrd, num::SimdFloat, *}; use std::simd::StdFloat; /// 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. /// /// 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); impl Vec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); /// 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 vector pointing along the positive W axis. pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); /// 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 vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); /// 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 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. 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: 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])) } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: 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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 4); 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 [f32]) { slice[..4].copy_from_slice(&self.to_array()); } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. /// /// To truncate to [`Vec3A`] use [`Vec3A::from_vec4()`]. #[inline] #[must_use] pub fn truncate(self) -> Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: f32) -> Self { self.w = w; self } /// 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(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)) } /// 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(self.0.simd_max(rhs.0)) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { self.0.reduce_min() } /// Returns the horizontal maximum of `self`. /// /// In other words this computes `max(x, y, ..)`. #[inline] #[must_use] pub fn max_element(self) -> f32 { self.0.reduce_max() } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { self.0.reduce_sum() } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { self.0.reduce_product() } /// 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) -> BVec4A { BVec4A(f32x4::simd_eq(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4::simd_ne(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4::simd_ge(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4::simd_gt(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4::simd_le(self.0, rhs.0)) } /// 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) -> 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()) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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)) } /// 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.0.is_sign_negative().to_bitmask() as u32 } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec4A { BVec4A(f32x4::is_finite(self.0)) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec4A { BVec4A(f32x4::is_nan(self.0)) } /// 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] } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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] } /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { let length = dot4_into_f32x4(self.0, self.0).sqrt(); #[allow(clippy::let_and_return)] let normalized = Self(self.0 / length); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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()) } /// 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()) } /// 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 as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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()) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } } impl Default for Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(self.0 / rhs.0) } } impl Div<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 /= rhs.0; } } impl DivAssign<&Vec4> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &Vec4) { self.div_assign(*rhs) } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(self.0 / f32x4::splat(rhs)) } } impl Div<&f32> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { self.div(*rhs) } } impl Div<&f32> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: f32) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 /= f32x4::splat(rhs); } } impl DivAssign<&f32> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { Vec4(f32x4::splat(self) / rhs.0) } } impl Div<&Vec4> for f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(self.0 * rhs.0) } } impl Mul<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 *= rhs.0; } } impl MulAssign<&Vec4> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &Vec4) { self.mul_assign(*rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(self.0 * f32x4::splat(rhs)) } } impl Mul<&f32> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { self.mul(*rhs) } } impl Mul<&f32> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: f32) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 *= f32x4::splat(rhs); } } impl MulAssign<&f32> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { Vec4(f32x4::splat(self) * rhs.0) } } impl Mul<&Vec4> for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(self.0 + rhs.0) } } impl Add<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0; } } impl AddAssign<&Vec4> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &Vec4) { self.add_assign(*rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(self.0 + f32x4::splat(rhs)) } } impl Add<&f32> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { self.add(*rhs) } } impl Add<&f32> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: f32) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 += f32x4::splat(rhs); } } impl AddAssign<&f32> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { Vec4(f32x4::splat(self) + rhs.0) } } impl Add<&Vec4> for f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(self.0 - rhs.0) } } impl Sub<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: Vec4) { self.0 -= rhs.0; } } impl SubAssign<&Vec4> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &Vec4) { self.sub_assign(*rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(self.0 - f32x4::splat(rhs)) } } impl Sub<&f32> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { self.sub(*rhs) } } impl Sub<&f32> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: f32) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 -= f32x4::splat(rhs); } } impl SubAssign<&f32> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { Vec4(f32x4::splat(self) - rhs.0) } } impl Sub<&Vec4> for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self(self.0 % rhs.0) } } impl Rem<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; } } impl RemAssign<&Vec4> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &Vec4) { self.rem_assign(*rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { self.rem(*rhs) } } impl Rem<&f32> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: f32) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: f32) { self.0 %= f32x4::splat(rhs); } } impl RemAssign<&f32> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { Vec4::splat(self).rem(rhs) } } impl Rem<&Vec4> for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Vec4 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Vec4 as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Vec4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Vec4 as *mut [f32; 4]) } } } impl Sum for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec4 { type Output = Self; #[inline] fn neg(self) -> Self { Self(-self.0) } } impl Neg for &Vec4 { type Output = Vec4; #[inline] fn neg(self) -> Vec4 { (*self).neg() } } impl Index for Vec4 { type Output = f32; #[inline] fn index(&self, index: usize) -> &Self::Output { &self.0[index] } } impl IndexMut for Vec4 { #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.0[index] } } impl fmt::Display for Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl fmt::Debug for Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From for f32x4 { #[inline(always)] fn from(t: Vec4) -> Self { t.0 } } impl From for Vec4 { #[inline(always)] fn from(t: f32x4) -> Self { Self(t) } } impl From<[f32; 4]> for Vec4 { #[inline] fn from(a: [f32; 4]) -> Self { Self(f32x4::from_array(a)) } } impl From for [f32; 4] { #[inline] fn from(v: Vec4) -> Self { v.0.to_array() } } impl From<(f32, f32, f32, f32)> for Vec4 { #[inline] fn from(t: (f32, f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(v: Vec4) -> Self { unsafe { *(v.0.to_array().as_ptr() as *const Self) } } } impl From<(Vec3A, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3A, f32)) -> Self { v.extend(w) } } impl From<(f32, Vec3A)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3A)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec3, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3, f32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(f32, Vec3)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec2, f32, f32)> for Vec4 { #[inline] fn from((v, z, w): (Vec2, f32, f32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(Vec2, Vec2)> for Vec4 { #[inline] fn from((v, u): (Vec2, Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl Deref for Vec4 { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec4 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( f32::from(v.x), f32::from(v.y), f32::from(v.z), f32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), f32::from(bool_array[3]), ) } } glam-0.30.1/src/f32/coresimd.rs000064400000000000000000000001261046102023000141600ustar 00000000000000pub mod mat2; pub mod mat3a; pub mod mat4; pub mod quat; pub mod vec3a; pub mod vec4; glam-0.30.1/src/f32/float.rs000064400000000000000000000010411046102023000134550ustar 00000000000000// 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) } } glam-0.30.1/src/f32/mat3.rs000064400000000000000000000675751046102023000132440ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat3 { pub x_axis: Vec3, pub y_axis: Vec3, pub z_axis: Vec3, } impl Mat3 { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec3::ZERO, Vec3::ZERO, Vec3::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec3::X, Vec3::Y, Vec3::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec3::NAN, Vec3::NAN, Vec3::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self { Self { x_axis: Vec3::new(m00, m01, m02), y_axis: Vec3::new(m10, m11, m12), z_axis: Vec3::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order. /// 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]) } /// 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, self.x_axis.y, self.x_axis.z, self.y_axis.x, self.y_axis.y, self.y_axis.z, self.z_axis.x, self.z_axis.y, self.z_axis.z, ] } /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order. /// 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]), Vec3::from_array(m[1]), Vec3::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( Vec3::from_vec4(m.x_axis), Vec3::from_vec4(m.y_axis), Vec3::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()), (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()), (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()), (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()), (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()), (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()), (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()), (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()), (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()), (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()), (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()), (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()), (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()), (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()), (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()), (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( Vec3::new(1.0 - (yy + zz), xy + wz, xz - wy), Vec3::new(xy - wz, 1.0 - (xx + zz), yz + wx), Vec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( Vec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), Vec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), Vec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3::X, Vec3::new(0.0, cosa, sina), Vec3::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3::new(cosa, 0.0, -sina), Vec3::Y, Vec3::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3::new(cosa, sina, 0.0), Vec3::new(-sina, cosa, 0.0), Vec3::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, Vec3::Y, Vec3::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols(Vec3::new(cos, sin, 0.0), Vec3::new(-sin, cos, 0.0), Vec3::Z) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), Vec3::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec3::new(scale.x, 0.0, 0.0), Vec3::new(0.0, scale.y, 0.0), Vec3::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: Mat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec3 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec3 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[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), y_axis: Vec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), z_axis: Vec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), } } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f32 { self.z_axis.dot(self.x_axis.cross(self.y_axis)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = Vec3::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec3::new(s.x, u.x, -f.x), Vec3::new(s.y, u.y, -f.y), Vec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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)); res = res.add(self.z_axis.mul(rhs.z)); res } /// 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), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec3::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_dmat3(&self) -> DMat3 { DMat3::from_cols( self.x_axis.as_dvec3(), self.y_axis.as_dvec3(), self.z_axis.as_dvec3(), ) } } impl Default for Mat3 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat3 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for Mat3 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for Mat3 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for Mat3 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for Mat3 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for Mat3 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for Mat3 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for Mat3 { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Self::Output { self.mul_vec3(rhs) } } impl Mul for f32 { type Output = Mat3; #[inline] fn mul(self, rhs: Mat3) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat3 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat3 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat3; #[inline] fn div(self, rhs: Mat3) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat3 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat3 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Mul for Mat3 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { self.mul_vec3a(rhs) } } impl From for Mat3 { #[inline] fn from(m: Mat3A) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } impl Sum for Mat3 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat3 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat3 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat3 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat3 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 9]> for Mat3 { #[inline] fn as_ref(&self) -> &[f32; 9] { unsafe { &*(self as *const Self as *const [f32; 9]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 9]> for Mat3 { #[inline] fn as_mut(&mut self) -> &mut [f32; 9] { unsafe { &mut *(self as *mut Self as *mut [f32; 9]) } } } impl fmt::Debug for Mat3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat3)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for Mat3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f32/math.rs000064400000000000000000000153671046102023000133210ustar 00000000000000/// 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(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))] 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 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(all(not(feature = "libm"), feature = "std"))] 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 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) } } // Used to reduce the number of compilation errors, in the event that no other // math backend is specified. #[cfg(all( not(feature = "libm"), not(feature = "std"), not(feature = "nostd-libm") ))] mod no_backend_math { pub(crate) fn abs(_: f32) -> f32 { unimplemented!() } pub(crate) fn acos_approx(_: f32) -> f32 { unimplemented!() } pub(crate) fn atan2(_: f32, _: f32) -> f32 { unimplemented!() } pub(crate) fn sin(_: f32) -> f32 { unimplemented!() } pub(crate) fn sin_cos(_: f32) -> (f32, f32) { unimplemented!() } pub(crate) fn tan(_: f32) -> f32 { unimplemented!() } pub(crate) fn sqrt(_: f32) -> f32 { unimplemented!() } pub(crate) fn copysign(_: f32, _: f32) -> f32 { unimplemented!() } pub(crate) fn signum(_: f32) -> f32 { unimplemented!() } pub(crate) fn round(_: f32) -> f32 { unimplemented!() } pub(crate) fn trunc(_: f32) -> f32 { unimplemented!() } pub(crate) fn ceil(_: f32) -> f32 { unimplemented!() } pub(crate) fn floor(_: f32) -> f32 { unimplemented!() } pub(crate) fn exp(_: f32) -> f32 { unimplemented!() } pub(crate) fn powf(_: f32, _: f32) -> f32 { unimplemented!() } pub(crate) fn mul_add(_: f32, _: f32, _: f32) -> f32 { unimplemented!() } pub fn div_euclid(_: f32, _: f32) -> f32 { unimplemented!() } pub fn rem_euclid(_: f32, _: f32) -> f32 { unimplemented!() } } #[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))] pub(crate) use libm_math::*; #[cfg(all(not(feature = "libm"), feature = "std"))] pub(crate) use std_math::*; #[cfg(all( not(feature = "libm"), not(feature = "std"), not(feature = "nostd-libm") ))] pub(crate) use no_backend_math::*; glam-0.30.1/src/f32/neon/mat2.rs000064400000000000000000000430361046102023000141640ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2}; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::arch::aarch64::*; #[repr(C)] union UnionCast { a: [f32; 4], v: Mat2, } /// 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) float32x4_t); impl Mat2 { /// A 2x2 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO); /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self { unsafe { UnionCast { a: [m00, m01, m10, m11], } .v } } /// 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 { a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y], } .v } } /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order. /// 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]) } /// 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]) } } /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order. /// 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])) } /// 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]) } } /// 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) } /// 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) = 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) = 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 the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from the first 4 values in `slice`. /// /// # Panics /// /// 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]) } /// Writes the columns of `self` to the first 4 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 4 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.y_axis.x; slice[3] = self.y_axis.y; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec2 { match index { 0 => self.x_axis, 1 => self.y_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec2 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec2::new(self.x_axis.y, self.y_axis.y), _ => panic!("index out of bounds"), } } /// 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`. #[inline] #[must_use] pub fn transpose(&self) -> Self { Self(unsafe { vsetq_lane_f32( vgetq_lane_f32(self.0, 2), vsetq_lane_f32(vgetq_lane_f32(self.0, 1), self.0, 2), 1, ) }) } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f32 { unsafe { let abcd = self.0; let badc = vrev64q_f32(abcd); let dcba = vextq_f32(badc, badc, 2); let prod = vmulq_f32(abcd, dcba); let det = vsubq_f32(prod, vdupq_laneq_f32(prod, 1)); vgetq_lane_f32(det, 0) } } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(&self) -> Self { unsafe { const SIGN: float32x4_t = crate::neon::f32x4_from_array([1.0, -1.0, -1.0, 1.0]); let abcd = self.0; let badc = vrev64q_f32(abcd); let dcba = vextq_f32(badc, badc, 2); let prod = vmulq_f32(abcd, dcba); let sub = vsubq_f32(prod, vdupq_laneq_f32(prod, 1)); let det = vdupq_laneq_f32(sub, 0); let tmp = vdivq_f32(SIGN, det); glam_assert!(Mat2(tmp).is_finite()); //let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]); let dbca = vsetq_lane_f32( vgetq_lane_f32(abcd, 0), vsetq_lane_f32(vgetq_lane_f32(abcd, 3), abcd, 0), 3, ); Self(vmulq_f32(dbca, tmp)) } } /// Transforms a 2D vector. #[inline] #[must_use] pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 { unsafe { let abcd = self.0; let xxyy = vld1q_f32([rhs.x, rhs.x, rhs.y, rhs.y].as_ptr()); let axbxcydy = vmulq_f32(abcd, xxyy); // let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]); let cydyaxbx = vextq_f32(axbxcydy, axbxcydy, 2); let result = vaddq_f32(axbxcydy, cydyaxbx); *(&result as *const float32x4_t as *const Vec2) } } /// Multiplies two 2x2 matrices. #[inline] #[must_use] pub fn mul_mat2(&self, rhs: &Self) -> Self { unsafe { let abcd = self.0; let xxyy0 = vzip1q_f32(rhs.0, rhs.0); let xxyy1 = vzip2q_f32(rhs.0, rhs.0); let axbxcydy0 = vmulq_f32(abcd, xxyy0); let axbxcydy1 = vmulq_f32(abcd, xxyy1); let cydyaxbx0 = vextq_f32(axbxcydy0, axbxcydy0, 2); let cydyaxbx1 = vextq_f32(axbxcydy1, axbxcydy1, 2); let result0 = vaddq_f32(axbxcydy0, cydyaxbx0); let result1 = vaddq_f32(axbxcydy1, cydyaxbx1); Self(vreinterpretq_f32_u64(vsetq_lane_u64( vgetq_lane_u64(vreinterpretq_u64_f32(result1), 0), vreinterpretq_u64_f32(result0), 1, ))) } } /// Adds two 2x2 matrices. #[inline] #[must_use] pub fn add_mat2(&self, rhs: &Self) -> Self { Self(unsafe { vaddq_f32(self.0, rhs.0) }) } /// Subtracts two 2x2 matrices. #[inline] #[must_use] pub fn sub_mat2(&self, rhs: &Self) -> Self { Self(unsafe { vsubq_f32(self.0, rhs.0) }) } /// Multiplies a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn mul_scalar(&self, rhs: f32) -> Self { Self(unsafe { vmulq_f32(self.0, vld1q_dup_f32(&rhs)) }) } /// Divides a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { Self(unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs()) } #[inline] pub fn as_dmat2(&self) -> DMat2 { DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2()) } } impl Default for Mat2 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat2(&rhs) } } impl AddAssign for Mat2 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat2(&rhs); } } impl Sub for Mat2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat2(&rhs) } } impl SubAssign for Mat2 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat2(&rhs); } } impl Neg for Mat2 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self(unsafe { vnegq_f32(self.0) }) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat2(&rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat2(&rhs); } } impl Mul for Mat2 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Self::Output { self.mul_vec2(rhs) } } impl Mul for f32 { type Output = Mat2; #[inline] fn mul(self, rhs: Mat2) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat2; #[inline] fn div(self, rhs: Mat2) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat2 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat2 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Mat2 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Mat2 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Self as *mut [f32; 4]) } } } impl core::ops::Deref for Mat2 { type Target = crate::deref::Cols2; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl core::ops::DerefMut for Mat2 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl fmt::Debug for Mat2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat2)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .finish() } } impl fmt::Display for Mat2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) } else { write!(f, "[{}, {}]", self.x_axis, self.y_axis) } } } glam-0.30.1/src/f32/neon/mat3a.rs000064400000000000000000000742431046102023000143320ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::arch::aarch64::*; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat3A { pub x_axis: Vec3A, pub y_axis: Vec3A, pub z_axis: Vec3A, } impl Mat3A { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self { Self { x_axis: Vec3A::new(m00, m01, m02), y_axis: Vec3A::new(m10, m11, m12), z_axis: Vec3A::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order. /// 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]) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y, z_axis_z, ] } /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order. /// 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]), Vec3A::from_array(m[1]), Vec3A::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( Vec3A::from_vec4(m.x_axis), Vec3A::from_vec4(m.y_axis), Vec3A::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols( Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (0, 1) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (0, 2) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (0, 3) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (1, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (1, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (1, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (1, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (2, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (2, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (2, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (2, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (3, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), ), (3, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), ), (3, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), ), (3, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), ), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy), Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx), Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::X, Vec3A::new(0.0, cosa, sina), Vec3A::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, 0.0, -sina), Vec3A::Y, Vec3A::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, sina, 0.0), Vec3A::new(-sina, cosa, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, Vec3A::Y, Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cos, sin, 0.0), Vec3A::new(-sin, cos, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec3A::new(scale.x, 0.0, 0.0), Vec3A::new(0.0, scale.y, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: Mat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec3A { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec3A { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[inline] #[must_use] pub fn transpose(&self) -> Self { let x = self.x_axis.0; let y = self.y_axis.0; let z = self.z_axis.0; unsafe { let tmp0 = vreinterpretq_f32_u64(vsetq_lane_u64( vgetq_lane_u64(vreinterpretq_u64_f32(y), 0), vreinterpretq_u64_f32(x), 1, )); let tmp1 = vreinterpretq_f32_u64(vzip2q_u64( vreinterpretq_u64_f32(x), vreinterpretq_u64_f32(y), )); Mat3A::from_cols( Vec3A::from(vsetq_lane_f32(vgetq_lane_f32(z, 0), vuzp1q_f32(tmp0, z), 3)), Vec3A::from(vuzp2q_f32(tmp0, vdupq_laneq_f32(z, 1))), Vec3A::from(vsetq_lane_f32(vgetq_lane_f32(z, 2), vuzp1q_f32(tmp1, z), 2)), ) } } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f32 { self.z_axis.dot(self.x_axis.cross(self.y_axis)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = Vec3A::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec3A::new(s.x, u.x, -f.x), Vec3A::new(s.y, u.y, -f.y), Vec3A::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// Transforms a 3D vector. #[inline] #[must_use] pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } /// 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())); res = res.add(self.z_axis.mul(rhs.zzz())); res } /// Multiplies two 3x3 matrices. #[inline] #[must_use] pub fn mul_mat3(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec3A::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_dmat3(&self) -> DMat3 { DMat3::from_cols( self.x_axis.as_dvec3(), self.y_axis.as_dvec3(), self.z_axis.as_dvec3(), ) } } impl Default for Mat3A { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for Mat3A { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for Mat3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for Mat3A { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for Mat3A { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for Mat3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl Mul for f32 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat3A; #[inline] fn div(self, rhs: Mat3A) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat3A { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Mul for Mat3A { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } } impl From for Mat3A { #[inline] fn from(m: Mat3) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } impl Sum for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } impl fmt::Debug for Mat3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat3A)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for Mat3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f32/neon/mat4.rs000064400000000000000000001472031046102023000141670ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, neon::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::arch::aarch64::*; /// 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) } /// A 4x4 column major matrix. /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat4 { pub x_axis: Vec4, pub y_axis: Vec4, pub z_axis: Vec4, pub w_axis: Vec4, } impl Mat4 { /// A 4x4 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO); /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self { Self { x_axis: Vec4::new(m00, m01, m02, m03), y_axis: Vec4::new(m10, m11, m12, m13), z_axis: Vec4::new(m20, m21, m22, m23), w_axis: Vec4::new(m30, m31, m32, m33), } } /// 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, y_axis, z_axis, w_axis, } } /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order. /// 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], m[14], m[15], ) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array(); let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w, z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w, ] } /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order. /// 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]), Vec4::from_array(m[1]), Vec4::from_array(m[2]), Vec4::from_array(m[3]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), self.w_axis.to_array(), ] } /// 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(); Self::new( x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w, ) } #[inline] #[must_use] fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne(Vec3::ZERO).all()); let inv_scale = scale.recip(); let rotation = Quat::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self { Self::from_cols( Vec4::from((mat3.x_axis, 0.0)), Vec4::from((mat3.y_axis, 0.0)), Vec4::from((mat3.z_axis, 0.0)), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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, Vec4::Y, Vec4::Z, Vec4::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # 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 (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( Vec4::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), Vec4::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), Vec4::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), Vec4::W, ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized() ); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::X, Vec4::new(0.0, cosa, sina, 0.0), Vec4::new(0.0, -sina, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::new(cosa, 0.0, -sina, 0.0), Vec4::Y, Vec4::new(sina, 0.0, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: f32) -> Self { 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), Vec4::Z, Vec4::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec4::new(scale.x, 0.0, 0.0, 0.0), Vec4::new(0.0, scale.y, 0.0, 0.0), Vec4::new(0.0, 0.0, scale.z, 0.0), Vec4::W, ) } /// Creates a 4x4 matrix from the first 16 values in `slice`. /// /// # Panics /// /// 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], slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15], ) } /// Writes the columns of `self` to the first 16 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 16 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.x_axis.w; slice[4] = self.y_axis.x; slice[5] = self.y_axis.y; slice[6] = self.y_axis.z; slice[7] = self.y_axis.w; slice[8] = self.z_axis.x; slice[9] = self.z_axis.y; slice[10] = self.z_axis.z; slice[11] = self.z_axis.w; slice[12] = self.w_axis.x; slice[13] = self.w_axis.y; slice[14] = self.w_axis.z; slice[15] = self.w_axis.w; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec4 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, 3 => self.w_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec4 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, 3 => &mut self.w_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), _ => panic!("index out of bounds"), } } /// 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() && self.w_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() || self.w_axis.is_nan() } /// Returns the transpose of `self`. #[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), y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), } } /// 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(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let a2323 = m22 * m33 - m23 * m32; let a1323 = m21 * m33 - m23 * m31; let a1223 = m21 * m32 - m22 * m31; let a0323 = m20 * m33 - m23 * m30; let a0223 = m20 * m32 - m22 * m30; let a0123 = m20 * m31 - m21 * m30; m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223) - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223) + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123) - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[must_use] pub fn inverse(&self) -> Self { unsafe { // Based on https://github.com/g-truc/glm `glm_mat4_inverse` let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp2q_f32(a, b); vtrn2q_f32(r, r) }; let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, b); vtrn2q_f32(r, r) }; let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, a); vuzp1q_f32(r, b) }; let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vzip1q_f32(a, b); vzip2q_f32(r, r) }; let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, b); vtrn1q_f32(r, r) }; let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, b); vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2) }; let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) }; let fac0 = { let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0); let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0); let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac1 = { let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0); let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0); let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac2 = { let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0); let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0); let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac3 = { let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0); let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0); let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac4 = { let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0); let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0); let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac5 = { let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0); let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0); let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0; const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0; let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0); let vec0 = swizzle0266(temp0, temp0); let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0); let vec1 = swizzle0266(temp1, temp1); let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0); let vec2 = swizzle0266(temp2, temp2); let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0); let vec3 = swizzle0266(temp3, temp3); let mul00 = vmulq_f32(vec1, fac0); let mul01 = vmulq_f32(vec2, fac1); let mul02 = vmulq_f32(vec3, fac2); let sub00 = vsubq_f32(mul00, mul01); let add00 = vaddq_f32(sub00, mul02); let inv0 = vmulq_f32(SIGN_B, add00); let mul03 = vmulq_f32(vec0, fac0); let mul04 = vmulq_f32(vec2, fac3); let mul05 = vmulq_f32(vec3, fac4); let sub01 = vsubq_f32(mul03, mul04); let add01 = vaddq_f32(sub01, mul05); let inv1 = vmulq_f32(SIGN_A, add01); let mul06 = vmulq_f32(vec0, fac1); let mul07 = vmulq_f32(vec1, fac3); let mul08 = vmulq_f32(vec3, fac5); let sub02 = vsubq_f32(mul06, mul07); let add02 = vaddq_f32(sub02, mul08); let inv2 = vmulq_f32(SIGN_B, add02); let mul09 = vmulq_f32(vec0, fac2); let mul10 = vmulq_f32(vec1, fac4); let mul11 = vmulq_f32(vec2, fac5); let sub03 = vsubq_f32(mul09, mul10); let add03 = vaddq_f32(sub03, mul11); let inv3 = vmulq_f32(SIGN_A, add03); let row0 = swizzle0044(inv0, inv1); let row1 = swizzle0044(inv2, inv3); let row2 = swizzle0246(row0, row1); let dot0 = dot4(self.x_axis.0, row2); glam_assert!(dot0 != 0.0); let rcp0 = dot0.recip(); Self { x_axis: Vec4(vmulq_n_f32(inv0, rcp0)), y_axis: Vec4(vmulq_n_f32(inv1, rcp0)), z_axis: Vec4(vmulq_n_f32(inv2, rcp0)), w_axis: Vec4(vmulq_n_f32(inv3, rcp0)), } } } /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec4::new(s.x, u.x, -f.x, 0.0), Vec4::new(s.y, u.y, -f.y, 0.0), Vec4::new(s.z, u.z, -f.z, 0.0), Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, f, 0.0, 0.0), Vec4::new(0.0, 0.0, b, -1.0), Vec4::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 1.0), Vec4::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, -1.0), Vec4::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 1.0, 1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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) = math::sin_cos(0.5 * fov_y_radians); let h = cos_fov / sin_fov; let w = h / aspect_ratio; Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 0.0, 1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, -1.0, -1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, 0.0, -1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, b, 0.0, 0.0), Vec4::new(0.0, 0.0, c, 0.0), Vec4::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// 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); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction. /// /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A { let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); res = res.div(res.wwww()); Vec3A::from_vec4(res) } /// Transforms the given [`Vec3A`] as 3D point. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); Vec3A::from_vec4(res) } /// Transforms the give [`Vec3A`] as 3D vector. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); Vec3A::from_vec4(res) } /// 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())); res = res.add(self.z_axis.mul(rhs.zzzz())); res = res.add(self.w_axis.mul(rhs.wwww())); res } /// Multiplies two 4x4 matrices. #[inline] #[must_use] pub fn mul_mat4(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), self.mul(rhs.w_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), self.w_axis.add(rhs.w_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), self.w_axis.sub(rhs.w_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), self.w_axis.mul(rhs), ) } /// Divides a 4x4 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec4::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), self.w_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs(), self.w_axis.abs(), ) } #[inline] pub fn as_dmat4(&self) -> DMat4 { DMat4::from_cols( self.x_axis.as_dvec4(), self.y_axis.as_dvec4(), self.z_axis.as_dvec4(), self.w_axis.as_dvec4(), ) } } impl Default for Mat4 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat4(&rhs) } } impl AddAssign for Mat4 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat4(&rhs); } } impl Sub for Mat4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat4(&rhs) } } impl SubAssign for Mat4 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat4(&rhs); } } impl Neg for Mat4 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols( self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg(), self.w_axis.neg(), ) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat4(&rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat4(&rhs); } } impl Mul for Mat4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Self::Output { self.mul_vec4(rhs) } } impl Mul for f32 { type Output = Mat4; #[inline] fn mul(self, rhs: Mat4) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat4; #[inline] fn div(self, rhs: Mat4) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat4 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) && self.w_axis.eq(&rhs.w_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 16]> for Mat4 { #[inline] fn as_ref(&self) -> &[f32; 16] { unsafe { &*(self as *const Self as *const [f32; 16]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 16]> for Mat4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 16] { unsafe { &mut *(self as *mut Self as *mut [f32; 16]) } } } impl fmt::Debug for Mat4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat4)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .field("w_axis", &self.w_axis) .finish() } } impl fmt::Display for Mat4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis ) } else { write!( f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis ) } } } glam-0.30.1/src/f32/neon/quat.rs000064400000000000000000001047111046102023000142710ustar 00000000000000// Generated from quat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{EulerRot, FromEuler, ToEuler}, f32::math, neon::*, DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4, }; use core::arch::aarch64::*; use core::fmt; 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, } /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// 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)] pub struct Quat(pub(crate) float32x4_t); impl Quat { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([f32::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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 } } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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]) } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: Vec4) -> Self { Self(v.0) } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] #[must_use] pub fn from_slice(slice: &[f32]) -> Self { assert!(slice.len() >= 4); Self(unsafe { vld1q_f32(slice.as_ptr()) }) } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [f32]) { assert!(slice.len() >= 4); unsafe { vst1q_f32(slice.as_mut_ptr(), self.0) } } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `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 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// 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) = 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) = 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) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// 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 { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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 the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &Mat4) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::f32::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: f32 = 0.0; const SIN_FRAC_PI_2: f32 = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( Vec3::new(s.x, u.x, -f.x), Vec3::new(s.y, u.y, -f.y), Vec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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; 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, 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 } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) { self.to_euler_angles(order) } /// `[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. #[inline] #[must_use] pub fn conjugate(self) -> Self { const SIGN: float32x4_t = f32x4_from_array([-1.0, -1.0, -1.0, 1.0]); Self(unsafe { vmulq_f32(self.0, SIGN) }) } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { Vec4::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> f32 { Vec4::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> f32 { Vec4::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4(Vec4::from(self).normalize()) } /// 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() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { Vec4::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// 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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// 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()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: f32) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[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()); const NEG_ZERO: float32x4_t = f32x4_from_array([-0.0; 4]); unsafe { let dot = dot4_into_f32x4(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = vandq_u32(vreinterpretq_u32_f32(dot), vreinterpretq_u32_f32(NEG_ZERO)); self.lerp_impl( Self(vreinterpretq_f32_u32(veorq_u32( vreinterpretq_u32_f32(end.0), bias, ))), s, ) } } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); let scale1 = math::sin(theta * (1.0 - s)); let scale2 = math::sin(theta * s); let theta_sin = math::sin(theta); ((self * scale1) + (end * scale2)) * (1.0 / theta_sin) } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// 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()); self.mul_vec3a(rhs.into()).into() } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { unsafe { let lhs = self.0; let rhs = rhs.0; const CONTROL_WZYX: float32x4_t = f32x4_from_array([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: float32x4_t = f32x4_from_array([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: float32x4_t = f32x4_from_array([-1.0, 1.0, 1.0, -1.0]); let r_xxxx = vdupq_laneq_f32(lhs, 0); let r_yyyy = vdupq_laneq_f32(lhs, 1); let r_zzzz = vdupq_laneq_f32(lhs, 2); let r_wwww = vdupq_laneq_f32(lhs, 3); let lxrw_lyrw_lzrw_lwrw = vmulq_f32(r_wwww, rhs); //let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]); let l_wzyx = vrev64q_f32(rhs); let l_wzyx = vextq_f32(l_wzyx, l_wzyx, 2); let lwrx_lzrx_lyrx_lxrx = vmulq_f32(r_xxxx, l_wzyx); //let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]); let l_zwxy = vrev64q_f32(l_wzyx); let lwrx_nlzrx_lyrx_nlxrx = vmulq_f32(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX); let lzry_lwry_lxry_lyry = vmulq_f32(r_yyyy, l_zwxy); // let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]); let l_yxwz = vrev64q_f32(l_zwxy); let l_yxwz = vextq_f32(l_yxwz, l_yxwz, 2); let lzry_lwry_nlxry_nlyry = vmulq_f32(lzry_lwry_lxry_lyry, CONTROL_ZWXY); let lyrz_lxrz_lwrz_lzrz = vmulq_f32(r_zzzz, l_yxwz); let result0 = vaddq_f32(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx); let nlyrz_lxrz_lwrz_wlzrz = vmulq_f32(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ); let result1 = vaddq_f32(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz); Self(vaddq_f32(result0, result1)) } } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::Affine3A) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. #[inline] #[must_use] pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A { unsafe { let w = self.w; let b = Vec3A::from(self.0); let b2 = b.length_squared(); Vec3A(vaddq_f32( vaddq_f32( vmulq_n_f32(rhs.0, (w * w) - b2), vmulq_n_f32(b.0, rhs.dot(b) * 2.0), ), vmulq_n_f32(b.cross(rhs).0, w * 2.0), )) } } #[inline] #[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) } } impl fmt::Debug for Quat { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Quat)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for Quat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add for Quat { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) + Vec4::from(rhs)) } } impl Sub for Quat { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) - Vec4::from(rhs)) } } impl Mul for Quat { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) * rhs) } } impl Div for Quat { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) / rhs) } } impl Mul for Quat { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign for Quat { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul for Quat { type Output = Vec3; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Vec3) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for Quat { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for Quat { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for Quat { #[inline] fn eq(&self, rhs: &Self) -> bool { Vec4::from(*self).eq(&Vec4::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Quat { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } impl Sum for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl Mul for Quat { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl From for Vec4 { #[inline] fn from(q: Quat) -> Self { Self(q.0) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for [f32; 4] { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for float32x4_t { #[inline] fn from(q: Quat) -> Self { q.0 } } impl Deref for Quat { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Quat { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } glam-0.30.1/src/f32/neon/vec3a.rs000064400000000000000000001514441046102023000143250ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, neon::*, BVec3, BVec3A, FloatExt, Quat, Vec2, Vec3, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; use core::arch::aarch64::*; #[repr(C)] union UnionCast { a: [f32; 4], v: Vec3A, } /// 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. /// /// 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`] /// or [`Into`] trait implementations. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct Vec3A(pub(crate) float32x4_t); impl Vec3A { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: BVec3A, if_true: Self, if_false: Self) -> Self { Self(unsafe { vbslq_f32(mask.0, 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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 3); 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 [f32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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] #[must_use] pub 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> f32 { // this was faster than intrinsics in testing (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(unsafe { 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 { unsafe { // Implementation taken from Realtime Math let lhs = self.0; let rhs = rhs.0; // cross(a, b) = (a.yzx * b.zxy) - (a.zxy * b.yzx) let lhs_yzwx = vextq_f32(lhs, lhs, 1); let rhs_wxyz = vextq_f32(rhs, rhs, 3); let lhs_yzx = vsetq_lane_f32(vgetq_lane_f32(lhs, 0), lhs_yzwx, 2); let rhs_zxy = vsetq_lane_f32(vgetq_lane_f32(rhs, 2), rhs_wxyz, 0); // part_a = (a.yzx * b.zxy) let part_a = vmulq_f32(lhs_yzx, rhs_zxy); let lhs_wxyz = vextq_f32(lhs, lhs, 3); let rhs_yzwx = vextq_f32(rhs, rhs, 1); let lhs_zxy = vsetq_lane_f32(vgetq_lane_f32(lhs, 2), lhs_wxyz, 0); let rhs_yzx = vsetq_lane_f32(vgetq_lane_f32(rhs, 0), rhs_yzwx, 2); // result = part_a - (a.zxy * b.yzx) let result = vmlsq_f32(part_a, lhs_zxy, rhs_yzx); Self(result) } } /// 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(unsafe { vminq_f32(self.0, rhs.0) }) } /// 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(unsafe { vmaxq_f32(self.0, rhs.0) }) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { 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) -> f32 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { unsafe { vaddvq_f32(vsetq_lane_f32(0.0, self.0, 3)) } } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { unsafe { let s = vmuls_laneq_f32(vgetq_lane_f32(self.0, 0), self.0, 1); vmuls_laneq_f32(s, self.0, 2) } } /// 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) -> BVec3A { BVec3A(unsafe { vceqq_f32(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { vmvnq_u32(vceqq_f32(self.0, rhs.0)) }) } /// 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) -> BVec3A { BVec3A(unsafe { vcgeq_f32(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { vcgtq_f32(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { vcleq_f32(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { vcltq_f32(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 { vabsq_f32(self.0) }) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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 { let result = Self(unsafe { vreinterpretq_f32_u32(vorrq_u32( vandq_u32( vreinterpretq_u32_f32(self.0), vreinterpretq_u32_f32(Self::NEG_ONE.0), ), vreinterpretq_u32_f32(Self::ONE.0), )) }); let mask = self.is_nan_mask(); Self::select(mask, self, result) } /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { let mask = Self::splat(-0.0); Self(unsafe { vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(rhs.0), vreinterpretq_u32_f32(mask.0)), vandq_u32( vreinterpretq_u32_f32(self.0), vmvnq_u32(vreinterpretq_u32_f32(mask.0)), ), )) }) } /// 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 { unsafe { let nmask = vreinterpretq_u32_f32(vdupq_n_f32(-0.0)); let m = vandq_u32(vreinterpretq_u32_f32(self.0), nmask); let x = vgetq_lane_u32(m, 0) >> 31; let y = vgetq_lane_u32(m, 1) >> 31; let z = vgetq_lane_u32(m, 2) >> 31; x | y << 1 | z << 2 } } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3A { BVec3A(unsafe { vcltq_f32(vabsq_f32(self.0), Self::INFINITY.0) }) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec3A { BVec3A(unsafe { vmvnq_u32(vceqq_f32(self.0, self.0)) }) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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 { vrndnq_f32(self.0) }) } /// 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 { vrndmq_f32(self.0) }) } /// 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 { vrndpq_f32(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 { vrndq_f32(self.0) }) } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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 { vdivq_f32(Self::ONE.0, self.0) }) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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(unsafe { vfmaq_f32(b.0, self.0, a.0) }) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f32::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); Quat::from_axis_angle(axis.into(), angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f32) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize().into(); let rotation = Quat::from_axis_angle(axis, core::f32::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for Vec3A { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(unsafe { vdivq_f32(self.0, rhs.0) }) } } impl Div<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 = unsafe { vdivq_f32(self.0, rhs.0) }; } } impl DivAssign<&Vec3A> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &Vec3A) { self.div_assign(*rhs) } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }) } } impl Div<&f32> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { self.div(*rhs) } } impl Div<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: f32) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 = unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }; } } impl DivAssign<&f32> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { vdivq_f32(vld1q_dup_f32(&self), rhs.0) }) } } impl Div<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(unsafe { vmulq_f32(self.0, rhs.0) }) } } impl Mul<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 = unsafe { vmulq_f32(self.0, rhs.0) }; } } impl MulAssign<&Vec3A> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &Vec3A) { self.mul_assign(*rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(unsafe { vmulq_n_f32(self.0, rhs) }) } } impl Mul<&f32> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { self.mul(*rhs) } } impl Mul<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: f32) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 = unsafe { vmulq_n_f32(self.0, rhs) }; } } impl MulAssign<&f32> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { vmulq_n_f32(rhs.0, self) }) } } impl Mul<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(unsafe { vaddq_f32(self.0, rhs.0) }) } } impl Add<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 = unsafe { vaddq_f32(self.0, rhs.0) }; } } impl AddAssign<&Vec3A> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &Vec3A) { self.add_assign(*rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(unsafe { vaddq_f32(self.0, vld1q_dup_f32(&rhs)) }) } } impl Add<&f32> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { self.add(*rhs) } } impl Add<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: f32) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 = unsafe { vaddq_f32(self.0, vld1q_dup_f32(&rhs)) }; } } impl AddAssign<&f32> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { vaddq_f32(vld1q_dup_f32(&self), rhs.0) }) } } impl Add<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(unsafe { vsubq_f32(self.0, rhs.0) }) } } impl Sub<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: Vec3A) { self.0 = unsafe { vsubq_f32(self.0, rhs.0) }; } } impl SubAssign<&Vec3A> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &Vec3A) { self.sub_assign(*rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(unsafe { vsubq_f32(self.0, vld1q_dup_f32(&rhs)) }) } } impl Sub<&f32> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { self.sub(*rhs) } } impl Sub<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: f32) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 = unsafe { vsubq_f32(self.0, vld1q_dup_f32(&rhs)) }; } } impl SubAssign<&f32> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { vsubq_f32(vld1q_dup_f32(&self), rhs.0) }) } } impl Sub<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { unsafe { let n = vrndmq_f32(vdivq_f32(self.0, rhs.0)); Self(vsubq_f32(self.0, vmulq_f32(n, rhs.0))) } } } impl Rem<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = self.rem(rhs); } } impl RemAssign<&Vec3A> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &Vec3A) { self.rem_assign(*rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { self.rem(*rhs) } } impl Rem<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: f32) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: f32) { *self = self.rem(Self::splat(rhs)); } } impl RemAssign<&f32> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { Vec3A::splat(self).rem(rhs) } } impl Rem<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 3]> for Vec3A { #[inline] fn as_ref(&self) -> &[f32; 3] { unsafe { &*(self as *const Vec3A as *const [f32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 3]> for Vec3A { #[inline] fn as_mut(&mut self) -> &mut [f32; 3] { unsafe { &mut *(self as *mut Vec3A as *mut [f32; 3]) } } } impl Sum for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec3A { type Output = Self; #[inline] fn neg(self) -> Self { Self(unsafe { vnegq_f32(self.0) }) } } impl Neg for &Vec3A { type Output = Vec3A; #[inline] fn neg(self) -> Vec3A { (*self).neg() } } impl Index for Vec3A { type Output = f32; #[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 for Vec3A { #[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"), } } } impl fmt::Display for Vec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for Vec3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec3A)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From for float32x4_t { #[inline(always)] fn from(t: Vec3A) -> Self { t.0 } } impl From for Vec3A { #[inline(always)] fn from(t: float32x4_t) -> Self { Self(t) } } impl From<[f32; 3]> for Vec3A { #[inline] fn from(a: [f32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f32; 3] { #[inline] fn from(v: Vec3A) -> Self { use crate::align16::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(f32, f32, f32)> for Vec3A { #[inline] fn from(t: (f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f32, f32, f32) { #[inline] fn from(v: Vec3A) -> Self { use crate::align16::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From for Vec3A { #[inline] fn from(v: Vec3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for Vec3 { #[inline] fn from(v: Vec3A) -> Self { use crate::align16::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(Vec2, f32)> for Vec3A { #[inline] fn from((v, z): (Vec2, f32)) -> Self { Self::new(v.x, v.y, z) } } impl Deref for Vec3A { type Target = crate::deref::Vec3; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec3A { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec3A { #[inline] fn from(v: BVec3) -> Self { Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z)) } } impl From for Vec3A { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), ) } } glam-0.30.1/src/f32/neon/vec4.rs000064400000000000000000001365501046102023000141660ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, neon::*, BVec4, BVec4A, Vec2, Vec3, Vec3A}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; use core::arch::aarch64::*; #[repr(C)] union UnionCast { a: [f32; 4], v: Vec4, } /// 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. /// /// 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) float32x4_t); impl Vec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); /// 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 vector pointing along the positive W axis. pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); /// 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 vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); /// 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 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. 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: BVec4A, if_true: Self, if_false: Self) -> Self { Self(unsafe { vbslq_f32(mask.0, 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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 4); 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 [f32]) { assert!(slice.len() >= 4); unsafe { vst1q_f32(slice.as_mut_ptr(), self.0); } } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. /// /// To truncate to [`Vec3A`] use [`Vec3A::from_vec4()`]. #[inline] #[must_use] pub fn truncate(self) -> Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: f32) -> Self { self.w = w; self } /// 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_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(unsafe { vminq_f32(self.0, rhs.0) }) } /// 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(unsafe { vmaxq_f32(self.0, rhs.0) }) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { unsafe { vminnmvq_f32(self.0) } } /// Returns the horizontal maximum of `self`. /// /// In other words this computes `max(x, y, ..)`. #[inline] #[must_use] pub fn max_element(self) -> f32 { unsafe { vmaxnmvq_f32(self.0) } } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { unsafe { vaddvq_f32(self.0) } } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { unsafe { let s = vmuls_laneq_f32(vgetq_lane_f32(self.0, 0), self.0, 1); let s = vmuls_laneq_f32(s, self.0, 2); vmuls_laneq_f32(s, self.0, 3) } } /// 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) -> BVec4A { BVec4A(unsafe { vceqq_f32(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { vmvnq_u32(vceqq_f32(self.0, rhs.0)) }) } /// 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) -> BVec4A { BVec4A(unsafe { vcgeq_f32(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { vcgtq_f32(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { vcleq_f32(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { vcltq_f32(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 { vabsq_f32(self.0) }) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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 { let result = Self(unsafe { vreinterpretq_f32_u32(vorrq_u32( vandq_u32( vreinterpretq_u32_f32(self.0), vreinterpretq_u32_f32(Self::NEG_ONE.0), ), vreinterpretq_u32_f32(Self::ONE.0), )) }); let mask = self.is_nan_mask(); Self::select(mask, self, result) } /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { let mask = Self::splat(-0.0); Self(unsafe { vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(rhs.0), vreinterpretq_u32_f32(mask.0)), vandq_u32( vreinterpretq_u32_f32(self.0), vmvnq_u32(vreinterpretq_u32_f32(mask.0)), ), )) }) } /// 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 { unsafe { let nmask = vreinterpretq_u32_f32(vdupq_n_f32(-0.0)); let m = vandq_u32(vreinterpretq_u32_f32(self.0), nmask); let x = vgetq_lane_u32(m, 0) >> 31; let y = vgetq_lane_u32(m, 1) >> 31; let z = vgetq_lane_u32(m, 2) >> 31; let w = vgetq_lane_u32(m, 3) >> 31; x | y << 1 | z << 2 | w << 3 } } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec4A { BVec4A(unsafe { vcltq_f32(vabsq_f32(self.0), Self::INFINITY.0) }) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec4A { BVec4A(unsafe { vmvnq_u32(vceqq_f32(self.0, self.0)) }) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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 { vrndnq_f32(self.0) }) } /// 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 { vrndmq_f32(self.0) }) } /// 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 { vrndpq_f32(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 { vrndq_f32(self.0) }) } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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 { vdivq_f32(Self::ONE.0, self.0) }) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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(unsafe { vfmaq_f32(b.0, self.0, a.0) }) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } } impl Default for Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(unsafe { vdivq_f32(self.0, rhs.0) }) } } impl Div<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 = unsafe { vdivq_f32(self.0, rhs.0) }; } } impl DivAssign<&Vec4> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &Vec4) { self.div_assign(*rhs) } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }) } } impl Div<&f32> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { self.div(*rhs) } } impl Div<&f32> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: f32) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 = unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }; } } impl DivAssign<&f32> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { vdivq_f32(vld1q_dup_f32(&self), rhs.0) }) } } impl Div<&Vec4> for f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(unsafe { vmulq_f32(self.0, rhs.0) }) } } impl Mul<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 = unsafe { vmulq_f32(self.0, rhs.0) }; } } impl MulAssign<&Vec4> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &Vec4) { self.mul_assign(*rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(unsafe { vmulq_n_f32(self.0, rhs) }) } } impl Mul<&f32> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { self.mul(*rhs) } } impl Mul<&f32> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: f32) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 = unsafe { vmulq_n_f32(self.0, rhs) }; } } impl MulAssign<&f32> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { vmulq_n_f32(rhs.0, self) }) } } impl Mul<&Vec4> for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(unsafe { vaddq_f32(self.0, rhs.0) }) } } impl Add<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 = unsafe { vaddq_f32(self.0, rhs.0) }; } } impl AddAssign<&Vec4> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &Vec4) { self.add_assign(*rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(unsafe { vaddq_f32(self.0, vld1q_dup_f32(&rhs)) }) } } impl Add<&f32> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { self.add(*rhs) } } impl Add<&f32> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: f32) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 = unsafe { vaddq_f32(self.0, vld1q_dup_f32(&rhs)) }; } } impl AddAssign<&f32> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { vaddq_f32(vld1q_dup_f32(&self), rhs.0) }) } } impl Add<&Vec4> for f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(unsafe { vsubq_f32(self.0, rhs.0) }) } } impl Sub<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: Vec4) { self.0 = unsafe { vsubq_f32(self.0, rhs.0) }; } } impl SubAssign<&Vec4> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &Vec4) { self.sub_assign(*rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(unsafe { vsubq_f32(self.0, vld1q_dup_f32(&rhs)) }) } } impl Sub<&f32> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { self.sub(*rhs) } } impl Sub<&f32> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: f32) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 = unsafe { vsubq_f32(self.0, vld1q_dup_f32(&rhs)) }; } } impl SubAssign<&f32> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { vsubq_f32(vld1q_dup_f32(&self), rhs.0) }) } } impl Sub<&Vec4> for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { unsafe { let n = vrndmq_f32(vdivq_f32(self.0, rhs.0)); Self(vsubq_f32(self.0, vmulq_f32(n, rhs.0))) } } } impl Rem<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = self.rem(rhs); } } impl RemAssign<&Vec4> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &Vec4) { self.rem_assign(*rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { self.rem(*rhs) } } impl Rem<&f32> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: f32) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: f32) { *self = self.rem(Self::splat(rhs)); } } impl RemAssign<&f32> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { Vec4::splat(self).rem(rhs) } } impl Rem<&Vec4> for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Vec4 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Vec4 as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Vec4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Vec4 as *mut [f32; 4]) } } } impl Sum for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec4 { type Output = Self; #[inline] fn neg(self) -> Self { Self(unsafe { vnegq_f32(self.0) }) } } impl Neg for &Vec4 { type Output = Vec4; #[inline] fn neg(self) -> Vec4 { (*self).neg() } } impl Index for Vec4 { type Output = f32; #[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 for Vec4 { #[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"), } } } impl fmt::Display for Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl fmt::Debug for Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From for float32x4_t { #[inline(always)] fn from(t: Vec4) -> Self { t.0 } } impl From for Vec4 { #[inline(always)] fn from(t: float32x4_t) -> Self { Self(t) } } impl From<[f32; 4]> for Vec4 { #[inline] fn from(a: [f32; 4]) -> Self { Self(unsafe { vld1q_f32(a.as_ptr()) }) } } impl From for [f32; 4] { #[inline] fn from(v: Vec4) -> Self { use crate::align16::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(f32, f32, f32, f32)> for Vec4 { #[inline] fn from(t: (f32, f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(v: Vec4) -> Self { use crate::align16::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(Vec3A, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3A, f32)) -> Self { v.extend(w) } } impl From<(f32, Vec3A)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3A)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec3, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3, f32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(f32, Vec3)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec2, f32, f32)> for Vec4 { #[inline] fn from((v, z, w): (Vec2, f32, f32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(Vec2, Vec2)> for Vec4 { #[inline] fn from((v, u): (Vec2, Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl Deref for Vec4 { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec4 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( f32::from(v.x), f32::from(v.y), f32::from(v.z), f32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), f32::from(bool_array[3]), ) } } glam-0.30.1/src/f32/neon.rs000064400000000000000000000001261046102023000133120ustar 00000000000000pub mod mat2; pub mod mat3a; pub mod mat4; pub mod quat; pub mod vec3a; pub mod vec4; glam-0.30.1/src/f32/scalar/mat2.rs000064400000000000000000000370701046102023000144730ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2}; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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. #[derive(Clone, Copy)] #[cfg_attr( not(any(feature = "scalar-math", target_arch = "spirv")), repr(align(16)) )] #[cfg_attr(feature = "cuda", repr(align(8)))] #[repr(C)] pub struct Mat2 { pub x_axis: Vec2, pub y_axis: Vec2, } impl Mat2 { /// A 2x2 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO); /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN); #[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), y_axis: Vec2::new(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 { x_axis, y_axis } } /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order. /// 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]) } /// 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] } /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order. /// 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])) } /// 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()] } /// 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) } /// 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) = 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) = 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 the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from the first 4 values in `slice`. /// /// # Panics /// /// 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]) } /// Writes the columns of `self` to the first 4 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 4 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.y_axis.x; slice[3] = self.y_axis.y; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec2 { match index { 0 => self.x_axis, 1 => self.y_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec2 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec2::new(self.x_axis.y, self.y_axis.y), _ => panic!("index out of bounds"), } } /// 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`. #[inline] #[must_use] pub fn transpose(&self) -> Self { Self { x_axis: Vec2::new(self.x_axis.x, self.y_axis.x), y_axis: Vec2::new(self.x_axis.y, self.y_axis.y), } } /// 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 } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(&self) -> Self { let inv_det = { let det = self.determinant(); glam_assert!(det != 0.0); det.recip() }; Self::new( self.y_axis.y * inv_det, self.x_axis.y * -inv_det, self.y_axis.x * -inv_det, self.x_axis.x * inv_det, ) } /// Transforms a 2D vector. #[inline] #[must_use] pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 { #[allow(clippy::suspicious_operation_groupings)] Vec2::new( (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y), (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y), ) } /// 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)) } /// Divides a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec2::splat(rhs); Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs)) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs()) } #[inline] pub fn as_dmat2(&self) -> DMat2 { DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2()) } } impl Default for Mat2 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat2(&rhs) } } impl AddAssign for Mat2 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat2(&rhs); } } impl Sub for Mat2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat2(&rhs) } } impl SubAssign for Mat2 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat2(&rhs); } } impl Neg for Mat2 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg()) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat2(&rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat2(&rhs); } } impl Mul for Mat2 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Self::Output { self.mul_vec2(rhs) } } impl Mul for f32 { type Output = Mat2; #[inline] fn mul(self, rhs: Mat2) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat2; #[inline] fn div(self, rhs: Mat2) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat2 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat2 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Mat2 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Mat2 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Self as *mut [f32; 4]) } } } impl fmt::Debug for Mat2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat2)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .finish() } } impl fmt::Display for Mat2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) } else { write!(f, "[{}, {}]", self.x_axis, self.y_axis) } } } glam-0.30.1/src/f32/scalar/mat3a.rs000064400000000000000000000730631046102023000146370ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat3A { pub x_axis: Vec3A, pub y_axis: Vec3A, pub z_axis: Vec3A, } impl Mat3A { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self { Self { x_axis: Vec3A::new(m00, m01, m02), y_axis: Vec3A::new(m10, m11, m12), z_axis: Vec3A::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order. /// 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]) } /// 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, self.x_axis.y, self.x_axis.z, self.y_axis.x, self.y_axis.y, self.y_axis.z, self.z_axis.x, self.z_axis.y, self.z_axis.z, ] } /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order. /// 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]), Vec3A::from_array(m[1]), Vec3A::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( Vec3A::from_vec4(m.x_axis), Vec3A::from_vec4(m.y_axis), Vec3A::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols( Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (0, 1) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (0, 2) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (0, 3) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (1, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (1, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (1, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (1, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (2, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (2, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (2, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (2, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (3, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), ), (3, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), ), (3, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), ), (3, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), ), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy), Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx), Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::X, Vec3A::new(0.0, cosa, sina), Vec3A::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, 0.0, -sina), Vec3A::Y, Vec3A::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, sina, 0.0), Vec3A::new(-sina, cosa, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, Vec3A::Y, Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cos, sin, 0.0), Vec3A::new(-sin, cos, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec3A::new(scale.x, 0.0, 0.0), Vec3A::new(0.0, scale.y, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: Mat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec3A { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec3A { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[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), y_axis: Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), z_axis: Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), } } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f32 { self.z_axis.dot(self.x_axis.cross(self.y_axis)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = Vec3A::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec3A::new(s.x, u.x, -f.x), Vec3A::new(s.y, u.y, -f.y), Vec3A::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// Transforms a 3D vector. #[inline] #[must_use] pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } /// 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())); res = res.add(self.z_axis.mul(rhs.zzz())); res } /// Multiplies two 3x3 matrices. #[inline] #[must_use] pub fn mul_mat3(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec3A::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_dmat3(&self) -> DMat3 { DMat3::from_cols( self.x_axis.as_dvec3(), self.y_axis.as_dvec3(), self.z_axis.as_dvec3(), ) } } impl Default for Mat3A { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for Mat3A { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for Mat3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for Mat3A { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for Mat3A { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for Mat3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl Mul for f32 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat3A; #[inline] fn div(self, rhs: Mat3A) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat3A { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Mul for Mat3A { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } } impl From for Mat3A { #[inline] fn from(m: Mat3) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } impl Sum for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } impl fmt::Debug for Mat3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat3A)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for Mat3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f32/scalar/mat4.rs000064400000000000000000001350511046102023000144730ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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) } /// A 4x4 column major matrix. /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. #[derive(Clone, Copy)] #[cfg_attr( any( not(any(feature = "scalar-math", target_arch = "spirv")), feature = "cuda" ), repr(align(16)) )] #[repr(C)] pub struct Mat4 { pub x_axis: Vec4, pub y_axis: Vec4, pub z_axis: Vec4, pub w_axis: Vec4, } impl Mat4 { /// A 4x4 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO); /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self { Self { x_axis: Vec4::new(m00, m01, m02, m03), y_axis: Vec4::new(m10, m11, m12, m13), z_axis: Vec4::new(m20, m21, m22, m23), w_axis: Vec4::new(m30, m31, m32, m33), } } /// 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, y_axis, z_axis, w_axis, } } /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order. /// 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], m[14], m[15], ) } /// 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, self.x_axis.y, self.x_axis.z, self.x_axis.w, self.y_axis.x, self.y_axis.y, self.y_axis.z, self.y_axis.w, self.z_axis.x, self.z_axis.y, self.z_axis.z, self.z_axis.w, self.w_axis.x, self.w_axis.y, self.w_axis.z, self.w_axis.w, ] } /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order. /// 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]), Vec4::from_array(m[1]), Vec4::from_array(m[2]), Vec4::from_array(m[3]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), self.w_axis.to_array(), ] } /// 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, 0.0, 0.0, diagonal.w, ) } #[inline] #[must_use] fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne(Vec3::ZERO).all()); let inv_scale = scale.recip(); let rotation = Quat::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self { Self::from_cols( Vec4::from((mat3.x_axis, 0.0)), Vec4::from((mat3.y_axis, 0.0)), Vec4::from((mat3.z_axis, 0.0)), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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, Vec4::Y, Vec4::Z, Vec4::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # 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 (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( Vec4::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), Vec4::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), Vec4::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), Vec4::W, ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized() ); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::X, Vec4::new(0.0, cosa, sina, 0.0), Vec4::new(0.0, -sina, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::new(cosa, 0.0, -sina, 0.0), Vec4::Y, Vec4::new(sina, 0.0, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: f32) -> Self { 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), Vec4::Z, Vec4::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec4::new(scale.x, 0.0, 0.0, 0.0), Vec4::new(0.0, scale.y, 0.0, 0.0), Vec4::new(0.0, 0.0, scale.z, 0.0), Vec4::W, ) } /// Creates a 4x4 matrix from the first 16 values in `slice`. /// /// # Panics /// /// 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], slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15], ) } /// Writes the columns of `self` to the first 16 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 16 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.x_axis.w; slice[4] = self.y_axis.x; slice[5] = self.y_axis.y; slice[6] = self.y_axis.z; slice[7] = self.y_axis.w; slice[8] = self.z_axis.x; slice[9] = self.z_axis.y; slice[10] = self.z_axis.z; slice[11] = self.z_axis.w; slice[12] = self.w_axis.x; slice[13] = self.w_axis.y; slice[14] = self.w_axis.z; slice[15] = self.w_axis.w; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec4 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, 3 => self.w_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec4 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, 3 => &mut self.w_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), _ => panic!("index out of bounds"), } } /// 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() && self.w_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() || self.w_axis.is_nan() } /// Returns the transpose of `self`. #[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), y_axis: Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), z_axis: Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), w_axis: Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), } } /// 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(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let a2323 = m22 * m33 - m23 * m32; let a1323 = m21 * m33 - m23 * m31; let a1223 = m21 * m32 - m22 * m31; let a0323 = m20 * m33 - m23 * m30; let a0223 = m20 * m32 - m22 * m30; let a0123 = m20 * m31 - m21 * m30; m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223) - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223) + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123) - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[must_use] pub fn inverse(&self) -> Self { let (m00, m01, m02, m03) = self.x_axis.into(); let (m10, m11, m12, m13) = self.y_axis.into(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let coef00 = m22 * m33 - m32 * m23; let coef02 = m12 * m33 - m32 * m13; let coef03 = m12 * m23 - m22 * m13; let coef04 = m21 * m33 - m31 * m23; let coef06 = m11 * m33 - m31 * m13; let coef07 = m11 * m23 - m21 * m13; let coef08 = m21 * m32 - m31 * m22; let coef10 = m11 * m32 - m31 * m12; let coef11 = m11 * m22 - m21 * m12; let coef12 = m20 * m33 - m30 * m23; let coef14 = m10 * m33 - m30 * m13; let coef15 = m10 * m23 - m20 * m13; let coef16 = m20 * m32 - m30 * m22; let coef18 = m10 * m32 - m30 * m12; let coef19 = m10 * m22 - m20 * m12; let coef20 = m20 * m31 - m30 * m21; let coef22 = m10 * m31 - m30 * m11; let coef23 = m10 * m21 - m20 * m11; let fac0 = Vec4::new(coef00, coef00, coef02, coef03); let fac1 = Vec4::new(coef04, coef04, coef06, coef07); let fac2 = Vec4::new(coef08, coef08, coef10, coef11); let fac3 = Vec4::new(coef12, coef12, coef14, coef15); let fac4 = Vec4::new(coef16, coef16, coef18, coef19); let fac5 = Vec4::new(coef20, coef20, coef22, coef23); let vec0 = Vec4::new(m10, m00, m00, m00); let vec1 = Vec4::new(m11, m01, m01, m01); let vec2 = Vec4::new(m12, m02, m02, m02); let vec3 = Vec4::new(m13, m03, m03, m03); let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2)); let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4)); let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5)); let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5)); let sign_a = Vec4::new(1.0, -1.0, 1.0, -1.0); let sign_b = Vec4::new(-1.0, 1.0, -1.0, 1.0); let inverse = Self::from_cols( inv0.mul(sign_a), inv1.mul(sign_b), inv2.mul(sign_a), inv3.mul(sign_b), ); let col0 = Vec4::new( inverse.x_axis.x, inverse.y_axis.x, inverse.z_axis.x, inverse.w_axis.x, ); let dot0 = self.x_axis.mul(col0); let dot1 = dot0.x + dot0.y + dot0.z + dot0.w; glam_assert!(dot1 != 0.0); let rcp_det = dot1.recip(); inverse.mul(rcp_det) } /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec4::new(s.x, u.x, -f.x, 0.0), Vec4::new(s.y, u.y, -f.y, 0.0), Vec4::new(s.z, u.z, -f.z, 0.0), Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, f, 0.0, 0.0), Vec4::new(0.0, 0.0, b, -1.0), Vec4::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 1.0), Vec4::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, -1.0), Vec4::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 1.0, 1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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) = math::sin_cos(0.5 * fov_y_radians); let h = cos_fov / sin_fov; let w = h / aspect_ratio; Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 0.0, 1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, -1.0, -1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, 0.0, -1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, b, 0.0, 0.0), Vec4::new(0.0, 0.0, c, 0.0), Vec4::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// 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); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction. /// /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A { self.project_point3(rhs.into()).into() } /// Transforms the given [`Vec3A`] as 3D point. /// /// 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. /// /// 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)); res = res.add(self.z_axis.mul(rhs.z)); res = res.add(self.w_axis.mul(rhs.w)); res } /// Multiplies two 4x4 matrices. #[inline] #[must_use] pub fn mul_mat4(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), self.mul(rhs.w_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), self.w_axis.add(rhs.w_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), self.w_axis.sub(rhs.w_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), self.w_axis.mul(rhs), ) } /// Divides a 4x4 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec4::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), self.w_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs(), self.w_axis.abs(), ) } #[inline] pub fn as_dmat4(&self) -> DMat4 { DMat4::from_cols( self.x_axis.as_dvec4(), self.y_axis.as_dvec4(), self.z_axis.as_dvec4(), self.w_axis.as_dvec4(), ) } } impl Default for Mat4 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat4(&rhs) } } impl AddAssign for Mat4 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat4(&rhs); } } impl Sub for Mat4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat4(&rhs) } } impl SubAssign for Mat4 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat4(&rhs); } } impl Neg for Mat4 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols( self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg(), self.w_axis.neg(), ) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat4(&rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat4(&rhs); } } impl Mul for Mat4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Self::Output { self.mul_vec4(rhs) } } impl Mul for f32 { type Output = Mat4; #[inline] fn mul(self, rhs: Mat4) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat4; #[inline] fn div(self, rhs: Mat4) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat4 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) && self.w_axis.eq(&rhs.w_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 16]> for Mat4 { #[inline] fn as_ref(&self) -> &[f32; 16] { unsafe { &*(self as *const Self as *const [f32; 16]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 16]> for Mat4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 16] { unsafe { &mut *(self as *mut Self as *mut [f32; 16]) } } } impl fmt::Debug for Mat4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat4)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .field("w_axis", &self.w_axis) .finish() } } impl fmt::Display for Mat4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis ) } else { write!( f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis ) } } } glam-0.30.1/src/f32/scalar/quat.rs000064400000000000000000001000701046102023000145710ustar 00000000000000// Generated from quat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{EulerRot, FromEuler, ToEuler}, f32::math, DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub}; /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// floating point "error creep" which can occur when successive quaternion /// operations are applied. #[derive(Clone, Copy)] #[cfg_attr( not(any(feature = "scalar-math", target_arch = "spirv")), repr(align(16)) )] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct Quat { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } impl Quat { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([f32::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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 } } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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]) } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: Vec4) -> Self { Self { x: v.x, y: v.y, z: v.z, w: v.w, } } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// 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]) } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [f32]) { slice[0] = self.x; slice[1] = self.y; slice[2] = self.z; slice[3] = self.w; } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `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 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// 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) = 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) = 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) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// 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 { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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 the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &Mat4) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::f32::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: f32 = 0.0; const SIN_FRAC_PI_2: f32 = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( Vec3::new(s.x, u.x, -f.x), Vec3::new(s.y, u.y, -f.y), Vec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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; 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, 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 } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) { self.to_euler_angles(order) } /// `[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. #[inline] #[must_use] pub fn conjugate(self) -> Self { Self { x: -self.x, y: -self.y, z: -self.z, w: self.w, } } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { Vec4::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> f32 { Vec4::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> f32 { Vec4::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4(Vec4::from(self).normalize()) } /// 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() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { Vec4::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// 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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// 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()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: f32) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[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()); let dot = self.dot(end); let bias = if dot >= 0.0 { 1.0 } else { -1.0 }; self.lerp_impl(end * bias, s) } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); let scale1 = math::sin(theta * (1.0 - s)); let scale2 = math::sin(theta * s); let theta_sin = math::sin(theta); ((self * scale1) + (end * scale2)) * (1.0 / theta_sin) } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// 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()); let w = self.w; let b = Vec3::new(self.x, self.y, self.z); let b2 = b.dot(b); rhs.mul(w * w - b2) .add(b.mul(rhs.dot(b) * 2.0)) .add(b.cross(rhs).mul(w * 2.0)) } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { let (x0, y0, z0, w0) = self.into(); let (x1, y1, z1, w1) = rhs.into(); Self::from_xyzw( w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1, w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1, w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1, w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1, ) } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::Affine3A) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } /// 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] #[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) } } impl fmt::Debug for Quat { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Quat)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for Quat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add for Quat { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) + Vec4::from(rhs)) } } impl Sub for Quat { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) - Vec4::from(rhs)) } } impl Mul for Quat { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) * rhs) } } impl Div for Quat { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) / rhs) } } impl Mul for Quat { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign for Quat { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul for Quat { type Output = Vec3; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Vec3) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for Quat { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for Quat { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for Quat { #[inline] fn eq(&self, rhs: &Self) -> bool { Vec4::from(*self).eq(&Vec4::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Quat { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } impl Sum for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl Mul for Quat { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl From for Vec4 { #[inline] fn from(q: Quat) -> Self { Self::new(q.x, q.y, q.z, q.w) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(q: Quat) -> Self { (q.x, q.y, q.z, q.w) } } impl From for [f32; 4] { #[inline] fn from(q: Quat) -> Self { [q.x, q.y, q.z, q.w] } } glam-0.30.1/src/f32/scalar/vec3a.rs000064400000000000000000001507411046102023000146320ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, BVec3, BVec3A, FloatExt, Quat, Vec2, Vec3, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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. /// /// 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`] /// 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))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct Vec3A { pub x: f32, pub y: f32, pub z: f32, } impl Vec3A { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: BVec3A, 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: [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] } /// 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: &[f32]) -> Self { assert!(slice.len() >= 3); 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 [f32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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] #[must_use] pub fn from_vec4(v: Vec4) -> 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: 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// 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, 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 [`f32::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) -> f32 { 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) -> f32 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { self.x * self.y * 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) -> BVec3A { BVec3A::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) -> BVec3A { BVec3A::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) -> BVec3A { BVec3A::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) -> BVec3A { BVec3A::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) -> BVec3A { BVec3A::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) -> 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: math::abs(self.x), y: math::abs(self.y), z: math::abs(self.z), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: math::copysign(self.x, rhs.x), y: math::copysign(self.y, rhs.y), z: math::copysign(self.z, rhs.z), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) | ((self.z.is_sign_negative() as u32) << 2) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3A { BVec3A::new(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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.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()) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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: 1.0 / self.x, y: 1.0 / self.y, z: 1.0 / self.z, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f32::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); Quat::from_axis_angle(axis.into(), angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f32) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize().into(); let rotation = Quat::from_axis_angle(axis, core::f32::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for Vec3A { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for Vec3A { 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 Div<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[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 DivAssign<&Vec3A> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &Vec3A) { self.div_assign(*rhs) } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&f32> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { self.div(*rhs) } } impl Div<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: f32) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: f32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&f32> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { Vec3A { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl Mul for Vec3A { 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 Mul<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[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 MulAssign<&Vec3A> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &Vec3A) { self.mul_assign(*rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&f32> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { self.mul(*rhs) } } impl Mul<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: f32) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: f32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&f32> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { Vec3A { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl Add for Vec3A { 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 Add<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[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 AddAssign<&Vec3A> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &Vec3A) { self.add_assign(*rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&f32> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { self.add(*rhs) } } impl Add<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: f32) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: f32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&f32> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { Vec3A { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl Sub for Vec3A { 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 Sub<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: Vec3A) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&Vec3A> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &Vec3A) { self.sub_assign(*rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&f32> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { self.sub(*rhs) } } impl Sub<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: f32) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: f32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&f32> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { Vec3A { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl Rem for Vec3A { 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 Rem<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[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 RemAssign<&Vec3A> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &Vec3A) { self.rem_assign(*rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&f32> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { self.rem(*rhs) } } impl Rem<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: f32) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: f32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&f32> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { Vec3A { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 3]> for Vec3A { #[inline] fn as_ref(&self) -> &[f32; 3] { unsafe { &*(self as *const Vec3A as *const [f32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 3]> for Vec3A { #[inline] fn as_mut(&mut self) -> &mut [f32; 3] { unsafe { &mut *(self as *mut Vec3A as *mut [f32; 3]) } } } impl Sum for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec3A { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), z: self.z.neg(), } } } impl Neg for &Vec3A { type Output = Vec3A; #[inline] fn neg(self) -> Vec3A { (*self).neg() } } impl Index for Vec3A { type Output = f32; #[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 for Vec3A { #[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"), } } } impl fmt::Display for Vec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for Vec3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec3A)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[f32; 3]> for Vec3A { #[inline] fn from(a: [f32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f32; 3] { #[inline] fn from(v: Vec3A) -> Self { [v.x, v.y, v.z] } } impl From<(f32, f32, f32)> for Vec3A { #[inline] fn from(t: (f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f32, f32, f32) { #[inline] fn from(v: Vec3A) -> Self { (v.x, v.y, v.z) } } impl From for Vec3A { #[inline] fn from(v: Vec3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for Vec3 { #[inline] fn from(v: Vec3A) -> Self { Self { x: v.x, y: v.y, z: v.z, } } } impl From<(Vec2, f32)> for Vec3A { #[inline] fn from((v, z): (Vec2, f32)) -> Self { Self::new(v.x, v.y, z) } } impl From for Vec3A { #[inline] fn from(v: BVec3) -> Self { Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z)) } } impl From for Vec3A { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), ) } } glam-0.30.1/src/f32/scalar/vec4.rs000064400000000000000000001441221046102023000144660ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(feature = "scalar-math")] use crate::BVec4 as BVec4A; #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{f32::math, BVec4, Vec2, Vec3, Vec3A}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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. #[derive(Clone, Copy, PartialEq)] #[cfg_attr( any( not(any(feature = "scalar-math", target_arch = "spirv")), feature = "cuda" ), repr(align(16)) )] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct Vec4 { pub x: f32, pub y: f32, pub z: f32, pub w: f32, } impl Vec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); /// 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 vector pointing along the positive W axis. pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); /// 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 vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); /// 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 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. 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: 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, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: BVec4A, 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: [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] } /// 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: &[f32]) -> Self { assert!(slice.len() >= 4); 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 [f32]) { slice[..4].copy_from_slice(&self.to_array()); } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. /// /// To truncate to [`Vec3A`] use [`Vec3A::from_vec4()`]. #[inline] #[must_use] pub fn truncate(self) -> Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: f32) -> Self { self.w = w; self } /// 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)) } /// 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 [`f32::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) -> f32 { 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) -> f32 { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { self.x * self.y * self.z * 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) -> BVec4A { BVec4A::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) -> BVec4A { BVec4A::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) -> BVec4A { BVec4A::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) -> BVec4A { BVec4A::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) -> BVec4A { BVec4A::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) -> BVec4A { BVec4A::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: math::abs(self.x), y: math::abs(self.y), z: math::abs(self.z), w: math::abs(self.w), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: 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), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) | ((self.z.is_sign_negative() as u32) << 2) | ((self.w.is_sign_negative() as u32) << 3) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec4A { BVec4A::new( 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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec4A { BVec4A::new( self.x.is_nan(), self.y.is_nan(), self.z.is_nan(), self.w.is_nan(), ) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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: 1.0 / self.x, y: 1.0 / self.y, z: 1.0 / self.z, w: 1.0 / self.w, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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), ) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } } impl Default for Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for Vec4 { 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 Div<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[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 DivAssign<&Vec4> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &Vec4) { self.div_assign(*rhs) } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&f32> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { self.div(*rhs) } } impl Div<&f32> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: f32) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: f32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&f32> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { Vec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&Vec4> for f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl Mul for Vec4 { 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 Mul<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[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 MulAssign<&Vec4> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &Vec4) { self.mul_assign(*rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&f32> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { self.mul(*rhs) } } impl Mul<&f32> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: f32) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&f32> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { Vec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&Vec4> for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl Add for Vec4 { 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 Add<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[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 AddAssign<&Vec4> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &Vec4) { self.add_assign(*rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&f32> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { self.add(*rhs) } } impl Add<&f32> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: f32) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: f32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&f32> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { Vec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&Vec4> for f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl Sub for Vec4 { 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 Sub<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: Vec4) { 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 SubAssign<&Vec4> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &Vec4) { self.sub_assign(*rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&f32> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { self.sub(*rhs) } } impl Sub<&f32> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: f32) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&f32> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { Vec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&Vec4> for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl Rem for Vec4 { 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 Rem<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[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 RemAssign<&Vec4> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &Vec4) { self.rem_assign(*rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&f32> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { self.rem(*rhs) } } impl Rem<&f32> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: f32) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: f32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&f32> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { Vec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&Vec4> for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Vec4 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Vec4 as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Vec4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Vec4 as *mut [f32; 4]) } } } impl Sum for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec4 { 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 Neg for &Vec4 { type Output = Vec4; #[inline] fn neg(self) -> Vec4 { (*self).neg() } } impl Index for Vec4 { type Output = f32; #[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 for Vec4 { #[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"), } } } impl fmt::Display for Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl fmt::Debug for Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[f32; 4]> for Vec4 { #[inline] fn from(a: [f32; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [f32; 4] { #[inline] fn from(v: Vec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(f32, f32, f32, f32)> for Vec4 { #[inline] fn from(t: (f32, f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(v: Vec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(Vec3A, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3A, f32)) -> Self { v.extend(w) } } impl From<(f32, Vec3A)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3A)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec3, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3, f32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(f32, Vec3)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec2, f32, f32)> for Vec4 { #[inline] fn from((v, z, w): (Vec2, f32, f32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(Vec2, Vec2)> for Vec4 { #[inline] fn from((v, u): (Vec2, Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl From for Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( f32::from(v.x), f32::from(v.y), f32::from(v.z), f32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), f32::from(bool_array[3]), ) } } glam-0.30.1/src/f32/scalar.rs000064400000000000000000000001261046102023000136200ustar 00000000000000pub mod mat2; pub mod mat3a; pub mod mat4; pub mod quat; pub mod vec3a; pub mod vec4; glam-0.30.1/src/f32/sse2/mat2.rs000064400000000000000000000426211046102023000141000ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2}; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C)] union UnionCast { a: [f32; 4], v: Mat2, } /// 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); impl Mat2 { /// A 2x2 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO); /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new(m00: f32, m01: f32, m10: f32, m11: f32) -> Self { unsafe { UnionCast { a: [m00, m01, m10, m11], } .v } } /// 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 { a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y], } .v } } /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order. /// 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]) } /// 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]) } } /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order. /// 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])) } /// 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]) } } /// 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) } /// 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) = 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) = 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 the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from the first 4 values in `slice`. /// /// # Panics /// /// 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]) } /// Writes the columns of `self` to the first 4 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 4 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.y_axis.x; slice[3] = self.y_axis.y; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec2 { match index { 0 => self.x_axis, 1 => self.y_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec2 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec2::new(self.x_axis.y, self.y_axis.y), _ => panic!("index out of bounds"), } } /// 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`. #[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; let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11); let prod = _mm_mul_ps(abcd, dcba); let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01)); _mm_cvtss_f32(det) } } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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]); let abcd = self.0; let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11); let prod = _mm_mul_ps(abcd, dcba); let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01)); let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00); let tmp = _mm_div_ps(SIGN, det); glam_assert!(Mat2(tmp).is_finite()); let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11); Self(_mm_mul_ps(dbca, tmp)) } } /// Transforms a 2D vector. #[inline] #[must_use] pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 { unsafe { use crate::Align16; use core::mem::MaybeUninit; let abcd = self.0; let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x); let axbxcydy = _mm_mul_ps(abcd, xxyy); let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10); let result = _mm_add_ps(axbxcydy, cydyaxbx); let mut out: MaybeUninit> = MaybeUninit::uninit(); _mm_store_ps(out.as_mut_ptr().cast(), result); out.assume_init().0 } } /// Multiplies two 2x2 matrices. #[inline] #[must_use] pub fn mul_mat2(&self, rhs: &Self) -> Self { unsafe { let abcd = self.0; let rhs = rhs.0; let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00); let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10); let axbxcydy0 = _mm_mul_ps(abcd, xxyy0); let axbxcydy1 = _mm_mul_ps(abcd, xxyy1); let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10); let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10); let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0); let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1); Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00)) } } /// 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)) }) } /// Divides a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) }) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs()) } #[inline] pub fn as_dmat2(&self) -> DMat2 { DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2()) } } impl Default for Mat2 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat2(&rhs) } } impl AddAssign for Mat2 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat2(&rhs); } } impl Sub for Mat2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat2(&rhs) } } impl SubAssign for Mat2 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat2(&rhs); } } impl Neg for Mat2 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) }) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat2(&rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat2(&rhs); } } impl Mul for Mat2 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Self::Output { self.mul_vec2(rhs) } } impl Mul for f32 { type Output = Mat2; #[inline] fn mul(self, rhs: Mat2) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat2; #[inline] fn div(self, rhs: Mat2) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat2 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat2 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Mat2 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Mat2 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Self as *mut [f32; 4]) } } } impl core::ops::Deref for Mat2 { type Target = crate::deref::Cols2; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl core::ops::DerefMut for Mat2 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl fmt::Debug for Mat2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat2)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .finish() } } impl fmt::Display for Mat2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) } else { write!(f, "[{}, {}]", self.x_axis, self.y_axis) } } } glam-0.30.1/src/f32/sse2/mat3a.rs000064400000000000000000000737171046102023000142540ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat3A { pub x_axis: Vec3A, pub y_axis: Vec3A, pub z_axis: Vec3A, } impl Mat3A { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self { Self { x_axis: Vec3A::new(m00, m01, m02), y_axis: Vec3A::new(m10, m11, m12), z_axis: Vec3A::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order. /// 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]) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y, z_axis_z, ] } /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order. /// 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]), Vec3A::from_array(m[1]), Vec3A::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( Vec3A::from_vec4(m.x_axis), Vec3A::from_vec4(m.y_axis), Vec3A::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols( Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (0, 1) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (0, 2) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (0, 3) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (1, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (1, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (1, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (1, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (2, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (2, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (2, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (2, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (3, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), ), (3, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), ), (3, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), ), (3, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), ), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy), Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx), Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::X, Vec3A::new(0.0, cosa, sina), Vec3A::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, 0.0, -sina), Vec3A::Y, Vec3A::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, sina, 0.0), Vec3A::new(-sina, cosa, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, Vec3A::Y, Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cos, sin, 0.0), Vec3A::new(-sin, cos, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec3A::new(scale.x, 0.0, 0.0), Vec3A::new(0.0, scale.y, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: Mat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec3A { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec3A { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[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); let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10); Self { x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)), y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)), z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)), } } } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f32 { self.z_axis.dot(self.x_axis.cross(self.y_axis)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = Vec3A::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec3A::new(s.x, u.x, -f.x), Vec3A::new(s.y, u.y, -f.y), Vec3A::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// Transforms a 3D vector. #[inline] #[must_use] pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } /// 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())); res = res.add(self.z_axis.mul(rhs.zzz())); res } /// Multiplies two 3x3 matrices. #[inline] #[must_use] pub fn mul_mat3(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec3A::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_dmat3(&self) -> DMat3 { DMat3::from_cols( self.x_axis.as_dvec3(), self.y_axis.as_dvec3(), self.z_axis.as_dvec3(), ) } } impl Default for Mat3A { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for Mat3A { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for Mat3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for Mat3A { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for Mat3A { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for Mat3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl Mul for f32 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat3A; #[inline] fn div(self, rhs: Mat3A) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat3A { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Mul for Mat3A { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } } impl From for Mat3A { #[inline] fn from(m: Mat3) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } impl Sum for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } impl fmt::Debug for Mat3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat3A)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for Mat3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f32/sse2/mat4.rs000064400000000000000000001517301046102023000141040ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, sse2::*, swizzles::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; /// 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) } /// A 4x4 column major matrix. /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat4 { pub x_axis: Vec4, pub y_axis: Vec4, pub z_axis: Vec4, pub w_axis: Vec4, } impl Mat4 { /// A 4x4 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO); /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self { Self { x_axis: Vec4::new(m00, m01, m02, m03), y_axis: Vec4::new(m10, m11, m12, m13), z_axis: Vec4::new(m20, m21, m22, m23), w_axis: Vec4::new(m30, m31, m32, m33), } } /// 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, y_axis, z_axis, w_axis, } } /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order. /// 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], m[14], m[15], ) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array(); let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w, z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w, ] } /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order. /// 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]), Vec4::from_array(m[1]), Vec4::from_array(m[2]), Vec4::from_array(m[3]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), self.w_axis.to_array(), ] } /// 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(); Self::new( x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w, ) } #[inline] #[must_use] fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne(Vec3::ZERO).all()); let inv_scale = scale.recip(); let rotation = Quat::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self { Self::from_cols( Vec4::from((mat3.x_axis, 0.0)), Vec4::from((mat3.y_axis, 0.0)), Vec4::from((mat3.z_axis, 0.0)), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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, Vec4::Y, Vec4::Z, Vec4::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # 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 (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( Vec4::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), Vec4::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), Vec4::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), Vec4::W, ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized() ); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::X, Vec4::new(0.0, cosa, sina, 0.0), Vec4::new(0.0, -sina, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::new(cosa, 0.0, -sina, 0.0), Vec4::Y, Vec4::new(sina, 0.0, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: f32) -> Self { 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), Vec4::Z, Vec4::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec4::new(scale.x, 0.0, 0.0, 0.0), Vec4::new(0.0, scale.y, 0.0, 0.0), Vec4::new(0.0, 0.0, scale.z, 0.0), Vec4::W, ) } /// Creates a 4x4 matrix from the first 16 values in `slice`. /// /// # Panics /// /// 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], slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15], ) } /// Writes the columns of `self` to the first 16 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 16 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.x_axis.w; slice[4] = self.y_axis.x; slice[5] = self.y_axis.y; slice[6] = self.y_axis.z; slice[7] = self.y_axis.w; slice[8] = self.z_axis.x; slice[9] = self.z_axis.y; slice[10] = self.z_axis.z; slice[11] = self.z_axis.w; slice[12] = self.w_axis.x; slice[13] = self.w_axis.y; slice[14] = self.w_axis.z; slice[15] = self.w_axis.w; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec4 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, 3 => self.w_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec4 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, 3 => &mut self.w_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), _ => panic!("index out of bounds"), } } /// 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() && self.w_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() || self.w_axis.is_nan() } /// Returns the transpose of `self`. #[inline] #[must_use] pub fn transpose(&self) -> Self { unsafe { // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose` let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00); let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10); let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00); let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10); Self { x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)), y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)), z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)), w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)), } } } /// 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` let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10); let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11); let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11); let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10); let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10); let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00); let mula = _mm_mul_ps(swp2a, swp3a); let mulb = _mm_mul_ps(swp2b, swp3b); let mulc = _mm_mul_ps(swp2c, swp3c); let sube = _mm_sub_ps(mula, mulb); let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc); let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00); let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01); let mulfaca = _mm_mul_ps(swpfaca, subfaca); let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01); let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00); let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10); let mulfacb = _mm_mul_ps(swpfacb, subfacb); let subres = _mm_sub_ps(mulfaca, mulfacb); let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10); let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00); let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11); let mulfacc = _mm_mul_ps(swpfacc, subfacc); let addres = _mm_add_ps(subres, mulfacc); let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0)); dot4(self.x_axis.0, detcof) } } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[must_use] pub fn inverse(&self) -> Self { unsafe { // Based on https://github.com/g-truc/glm `glm_mat4_inverse` let fac0 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac1 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac2 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac3 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac4 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac5 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0); let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0); let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00); let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00); let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01); let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00); let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10); let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00); let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11); let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00); let mul00 = _mm_mul_ps(vec1, fac0); let mul01 = _mm_mul_ps(vec2, fac1); let mul02 = _mm_mul_ps(vec3, fac2); let sub00 = _mm_sub_ps(mul00, mul01); let add00 = _mm_add_ps(sub00, mul02); let inv0 = _mm_mul_ps(sign_b, add00); let mul03 = _mm_mul_ps(vec0, fac0); let mul04 = _mm_mul_ps(vec2, fac3); let mul05 = _mm_mul_ps(vec3, fac4); let sub01 = _mm_sub_ps(mul03, mul04); let add01 = _mm_add_ps(sub01, mul05); let inv1 = _mm_mul_ps(sign_a, add01); let mul06 = _mm_mul_ps(vec0, fac1); let mul07 = _mm_mul_ps(vec1, fac3); let mul08 = _mm_mul_ps(vec3, fac5); let sub02 = _mm_sub_ps(mul06, mul07); let add02 = _mm_add_ps(sub02, mul08); let inv2 = _mm_mul_ps(sign_b, add02); let mul09 = _mm_mul_ps(vec0, fac2); let mul10 = _mm_mul_ps(vec1, fac4); let mul11 = _mm_mul_ps(vec2, fac5); let sub03 = _mm_sub_ps(mul09, mul10); let add03 = _mm_add_ps(sub03, mul11); let inv3 = _mm_mul_ps(sign_a, add03); let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00); let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00); let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00); let dot0 = dot4(self.x_axis.0, row2); glam_assert!(dot0 != 0.0); let rcp0 = _mm_set1_ps(dot0.recip()); Self { x_axis: Vec4(_mm_mul_ps(inv0, rcp0)), y_axis: Vec4(_mm_mul_ps(inv1, rcp0)), z_axis: Vec4(_mm_mul_ps(inv2, rcp0)), w_axis: Vec4(_mm_mul_ps(inv3, rcp0)), } } } /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec4::new(s.x, u.x, -f.x, 0.0), Vec4::new(s.y, u.y, -f.y, 0.0), Vec4::new(s.z, u.z, -f.z, 0.0), Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, f, 0.0, 0.0), Vec4::new(0.0, 0.0, b, -1.0), Vec4::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 1.0), Vec4::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, -1.0), Vec4::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 1.0, 1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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) = math::sin_cos(0.5 * fov_y_radians); let h = cos_fov / sin_fov; let w = h / aspect_ratio; Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 0.0, 1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, -1.0, -1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, 0.0, -1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, b, 0.0, 0.0), Vec4::new(0.0, 0.0, c, 0.0), Vec4::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// 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); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction. /// /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A { let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); res = res.div(res.wwww()); Vec3A::from_vec4(res) } /// Transforms the given [`Vec3A`] as 3D point. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); Vec3A::from_vec4(res) } /// Transforms the give [`Vec3A`] as 3D vector. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); Vec3A::from_vec4(res) } /// 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())); res = res.add(self.z_axis.mul(rhs.zzzz())); res = res.add(self.w_axis.mul(rhs.wwww())); res } /// Multiplies two 4x4 matrices. #[inline] #[must_use] pub fn mul_mat4(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), self.mul(rhs.w_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), self.w_axis.add(rhs.w_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), self.w_axis.sub(rhs.w_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), self.w_axis.mul(rhs), ) } /// Divides a 4x4 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec4::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), self.w_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs(), self.w_axis.abs(), ) } #[inline] pub fn as_dmat4(&self) -> DMat4 { DMat4::from_cols( self.x_axis.as_dvec4(), self.y_axis.as_dvec4(), self.z_axis.as_dvec4(), self.w_axis.as_dvec4(), ) } } impl Default for Mat4 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat4(&rhs) } } impl AddAssign for Mat4 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat4(&rhs); } } impl Sub for Mat4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat4(&rhs) } } impl SubAssign for Mat4 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat4(&rhs); } } impl Neg for Mat4 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols( self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg(), self.w_axis.neg(), ) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat4(&rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat4(&rhs); } } impl Mul for Mat4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Self::Output { self.mul_vec4(rhs) } } impl Mul for f32 { type Output = Mat4; #[inline] fn mul(self, rhs: Mat4) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat4; #[inline] fn div(self, rhs: Mat4) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat4 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) && self.w_axis.eq(&rhs.w_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 16]> for Mat4 { #[inline] fn as_ref(&self) -> &[f32; 16] { unsafe { &*(self as *const Self as *const [f32; 16]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 16]> for Mat4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 16] { unsafe { &mut *(self as *mut Self as *mut [f32; 16]) } } } impl fmt::Debug for Mat4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat4)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .field("w_axis", &self.w_axis) .finish() } } impl fmt::Display for Mat4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis ) } else { write!( f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis ) } } } glam-0.30.1/src/f32/sse2/quat.rs000064400000000000000000001054021046102023000142040ustar 00000000000000// Generated from quat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{EulerRot, FromEuler, ToEuler}, f32::math, sse2::*, DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4, }; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; use core::fmt; 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, } /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// 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)] pub struct Quat(pub(crate) __m128); impl Quat { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([f32::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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 } } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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]) } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: Vec4) -> Self { Self(v.0) } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// 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()) }) } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [f32]) { assert!(slice.len() >= 4); unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0) } } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `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 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// 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) = 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) = 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) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// 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 { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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 the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &Mat4) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::f32::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: f32 = 0.0; const SIN_FRAC_PI_2: f32 = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( Vec3::new(s.x, u.x, -f.x), Vec3::new(s.y, u.y, -f.y), Vec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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; 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, 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 } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) { self.to_euler_angles(order) } /// `[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. #[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) }) } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { Vec4::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> f32 { Vec4::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> f32 { Vec4::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4(Vec4::from(self).normalize()) } /// 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() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { Vec4::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// 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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// 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()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: f32) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[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()); const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]); unsafe { let dot = dot4_into_m128(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = _mm_and_ps(dot, NEG_ZERO); self.lerp_impl(Self(_mm_xor_ps(end.0, bias)), s) } } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); let x = 1.0 - s; let y = s; let z = 1.0; unsafe { let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x)); let tmp = m128_sin(tmp); let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00); let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01); let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10); Self(_mm_div_ps( _mm_add_ps(_mm_mul_ps(self.0, scale1), _mm_mul_ps(end.0, scale2)), theta_sin, )) } } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// 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()); self.mul_vec3a(rhs.into()).into() } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { // Based on https://github.com/nfrechette/rtm `rtm::quat_mul` const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]); let lhs = self.0; let rhs = rhs.0; unsafe { let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00); let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01); let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10); let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11); let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs); let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11); let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx); let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01); let lwrx_nlzrx_lyrx_nlxrx = _mm_mul_ps(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX); let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy); let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11); let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY); let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz); let result0 = _mm_add_ps(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx); let nlyrz_lxrz_lwrz_wlzrz = _mm_mul_ps(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ); let result1 = _mm_add_ps(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz); Self(_mm_add_ps(result0, result1)) } } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::Affine3A) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } /// 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]); let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11); let b = self.0; let b2 = dot3_into_m128(b, b); Vec3A(_mm_add_ps( _mm_add_ps( _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)), _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)), ), _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)), )) } } #[inline] #[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) } } impl fmt::Debug for Quat { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Quat)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for Quat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add for Quat { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) + Vec4::from(rhs)) } } impl Sub for Quat { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) - Vec4::from(rhs)) } } impl Mul for Quat { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) * rhs) } } impl Div for Quat { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) / rhs) } } impl Mul for Quat { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign for Quat { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul for Quat { type Output = Vec3; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Vec3) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for Quat { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for Quat { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for Quat { #[inline] fn eq(&self, rhs: &Self) -> bool { Vec4::from(*self).eq(&Vec4::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Quat { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } impl Sum for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl Mul for Quat { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl From for Vec4 { #[inline] fn from(q: Quat) -> Self { Self(q.0) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for [f32; 4] { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for __m128 { #[inline] fn from(q: Quat) -> Self { q.0 } } impl Deref for Quat { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Quat { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } glam-0.30.1/src/f32/sse2/vec3a.rs000064400000000000000000001521571046102023000142440ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, sse2::*, BVec3, BVec3A, FloatExt, Quat, Vec2, Vec3, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C)] union UnionCast { a: [f32; 4], v: Vec3A, } /// 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. /// /// 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`] /// or [`Into`] trait implementations. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct Vec3A(pub(crate) __m128); impl Vec3A { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: BVec3A, if_true: Self, if_false: Self) -> Self { Self(unsafe { _mm_or_ps( _mm_andnot_ps(mask.0, if_false.0), _mm_and_ps(if_true.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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 3); 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 [f32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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] #[must_use] pub 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// 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 // y <- a.z*b.x - a.x*b.z // z <- a.x*b.y - a.y*b.x // We can save a shuffle by grouping it in this wacky order: // (self.zxy() * rhs - self * rhs.zxy()).zxy() let lhszxy = _mm_shuffle_ps(self.0, self.0, 0b01_01_00_10); let rhszxy = _mm_shuffle_ps(rhs.0, rhs.0, 0b01_01_00_10); let lhszxy_rhs = _mm_mul_ps(lhszxy, rhs.0); let rhszxy_lhs = _mm_mul_ps(rhszxy, self.0); let sub = _mm_sub_ps(lhszxy_rhs, rhszxy_lhs); Self(_mm_shuffle_ps(sub, sub, 0b01_01_00_10)) } } /// 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(unsafe { _mm_min_ps(self.0, rhs.0) }) } /// 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(unsafe { _mm_max_ps(self.0, rhs.0) }) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { unsafe { let v = self.0; let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b01_01_10_10)); let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } } /// Returns the horizontal maximum of `self`. /// /// In other words this computes `max(x, y, ..)`. #[inline] #[must_use] pub fn max_element(self) -> f32 { unsafe { let v = self.0; let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_10_10)); let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { unsafe { let v = self.0; let v = _mm_add_ps(v, _mm_shuffle_ps(v, Self::ZERO.0, 0b00_11_00_01)); let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { unsafe { let v = self.0; let v = _mm_mul_ps(v, _mm_shuffle_ps(v, Self::ONE.0, 0b00_11_00_01)); let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } } /// 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) -> BVec3A { BVec3A(unsafe { _mm_cmpeq_ps(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { _mm_cmpneq_ps(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { _mm_cmpge_ps(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { _mm_cmpgt_ps(self.0, rhs.0) }) } /// 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) -> BVec3A { BVec3A(unsafe { _mm_cmple_ps(self.0, rhs.0) }) } /// 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) -> 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) }) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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 { let result = Self(unsafe { _mm_or_ps(_mm_and_ps(self.0, Self::NEG_ONE.0), Self::ONE.0) }); let mask = self.is_nan_mask(); Self::select(mask, self, result) } /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { let mask = Self::splat(-0.0); Self(unsafe { _mm_or_ps(_mm_and_ps(rhs.0, mask.0), _mm_andnot_ps(mask.0, self.0)) }) } /// 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 { unsafe { (_mm_movemask_ps(self.0) as u32) & 0x7 } } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3A { BVec3A(unsafe { _mm_cmplt_ps(crate::sse2::m128_abs(self.0), Self::INFINITY.0) }) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec3A { BVec3A(unsafe { _mm_cmpunord_ps(self.0, self.0) }) } /// 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); _mm_cvtss_f32(_mm_sqrt_ps(dot)) } } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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); _mm_cvtss_f32(_mm_div_ps(Self::ONE.0, _mm_sqrt_ps(dot))) } } /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { unsafe { let length = _mm_sqrt_ps(dot3_into_m128(self.0, self.0)); #[allow(clippy::let_and_return)] let normalized = Self(_mm_div_ps(self.0, length)); glam_assert!(normalized.is_finite()); normalized } } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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) }) } /// 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) }) } /// 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 as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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) }) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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 { Self(_mm_fmadd_ps(self.0, a.0, b.0)) } #[cfg(not(target_feature = "fma"))] Self::new( 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f32::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); Quat::from_axis_angle(axis.into(), angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f32) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize().into(); let rotation = Quat::from_axis_angle(axis, core::f32::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for Vec3A { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(unsafe { _mm_div_ps(self.0, rhs.0) }) } } impl Div<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 = unsafe { _mm_div_ps(self.0, rhs.0) }; } } impl DivAssign<&Vec3A> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &Vec3A) { self.div_assign(*rhs) } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(unsafe { _mm_div_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Div<&f32> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { self.div(*rhs) } } impl Div<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: f32) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_div_ps(self.0, _mm_set1_ps(rhs)) }; } } impl DivAssign<&f32> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { _mm_div_ps(_mm_set1_ps(self), rhs.0) }) } } impl Div<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(unsafe { _mm_mul_ps(self.0, rhs.0) }) } } impl Mul<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 = unsafe { _mm_mul_ps(self.0, rhs.0) }; } } impl MulAssign<&Vec3A> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &Vec3A) { self.mul_assign(*rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Mul<&f32> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { self.mul(*rhs) } } impl Mul<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: f32) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }; } } impl MulAssign<&f32> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { _mm_mul_ps(_mm_set1_ps(self), rhs.0) }) } } impl Mul<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(unsafe { _mm_add_ps(self.0, rhs.0) }) } } impl Add<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 = unsafe { _mm_add_ps(self.0, rhs.0) }; } } impl AddAssign<&Vec3A> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &Vec3A) { self.add_assign(*rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Add<&f32> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { self.add(*rhs) } } impl Add<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: f32) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }; } } impl AddAssign<&f32> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { _mm_add_ps(_mm_set1_ps(self), rhs.0) }) } } impl Add<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(unsafe { _mm_sub_ps(self.0, rhs.0) }) } } impl Sub<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: Vec3A) { self.0 = unsafe { _mm_sub_ps(self.0, rhs.0) }; } } impl SubAssign<&Vec3A> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &Vec3A) { self.sub_assign(*rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(unsafe { _mm_sub_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Sub<&f32> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { self.sub(*rhs) } } impl Sub<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: f32) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_sub_ps(self.0, _mm_set1_ps(rhs)) }; } } impl SubAssign<&f32> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { Vec3A(unsafe { _mm_sub_ps(_mm_set1_ps(self), rhs.0) }) } } impl Sub<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { unsafe { let n = m128_floor(_mm_div_ps(self.0, rhs.0)); Self(_mm_sub_ps(self.0, _mm_mul_ps(n, rhs.0))) } } } impl Rem<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = self.rem(rhs); } } impl RemAssign<&Vec3A> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &Vec3A) { self.rem_assign(*rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { self.rem(*rhs) } } impl Rem<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: f32) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: f32) { *self = self.rem(Self::splat(rhs)); } } impl RemAssign<&f32> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { Vec3A::splat(self).rem(rhs) } } impl Rem<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 3]> for Vec3A { #[inline] fn as_ref(&self) -> &[f32; 3] { unsafe { &*(self as *const Vec3A as *const [f32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 3]> for Vec3A { #[inline] fn as_mut(&mut self) -> &mut [f32; 3] { unsafe { &mut *(self as *mut Vec3A as *mut [f32; 3]) } } } impl Sum for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec3A { type Output = Self; #[inline] fn neg(self) -> Self { Self(unsafe { _mm_xor_ps(_mm_set1_ps(-0.0), self.0) }) } } impl Neg for &Vec3A { type Output = Vec3A; #[inline] fn neg(self) -> Vec3A { (*self).neg() } } impl Index for Vec3A { type Output = f32; #[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 for Vec3A { #[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"), } } } impl fmt::Display for Vec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for Vec3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec3A)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From for __m128 { #[inline(always)] fn from(t: Vec3A) -> Self { t.0 } } impl From<__m128> for Vec3A { #[inline(always)] fn from(t: __m128) -> Self { Self(t) } } impl From<[f32; 3]> for Vec3A { #[inline] fn from(a: [f32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f32; 3] { #[inline] fn from(v: Vec3A) -> Self { use crate::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(f32, f32, f32)> for Vec3A { #[inline] fn from(t: (f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f32, f32, f32) { #[inline] fn from(v: Vec3A) -> Self { use crate::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From for Vec3A { #[inline] fn from(v: Vec3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for Vec3 { #[inline] fn from(v: Vec3A) -> Self { use crate::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(Vec2, f32)> for Vec3A { #[inline] fn from((v, z): (Vec2, f32)) -> Self { Self::new(v.x, v.y, z) } } impl Deref for Vec3A { type Target = crate::deref::Vec3; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec3A { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec3A { #[inline] fn from(v: BVec3) -> Self { Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z)) } } impl From for Vec3A { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), ) } } glam-0.30.1/src/f32/sse2/vec4.rs000064400000000000000000001377741046102023000141140ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, sse2::*, BVec4, BVec4A, Vec2, Vec3, Vec3A}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C)] union UnionCast { a: [f32; 4], v: Vec4, } /// 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. /// /// 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); impl Vec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); /// 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 vector pointing along the positive W axis. pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); /// 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 vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); /// 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 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. 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: BVec4A, if_true: Self, if_false: Self) -> Self { Self(unsafe { _mm_or_ps( _mm_andnot_ps(mask.0, if_false.0), _mm_and_ps(if_true.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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 4); 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 [f32]) { assert!(slice.len() >= 4); unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0); } } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. /// /// To truncate to [`Vec3A`] use [`Vec3A::from_vec4()`]. #[inline] #[must_use] pub fn truncate(self) -> Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: f32) -> Self { self.w = w; self } /// 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) }) } /// 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(unsafe { _mm_min_ps(self.0, rhs.0) }) } /// 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(unsafe { _mm_max_ps(self.0, rhs.0) }) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { unsafe { let v = self.0; let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b00_00_11_10)); let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } } /// Returns the horizontal maximum of `self`. /// /// In other words this computes `max(x, y, ..)`. #[inline] #[must_use] pub fn max_element(self) -> f32 { unsafe { let v = self.0; let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_11_10)); let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { unsafe { let v = self.0; let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01)); let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { unsafe { let v = self.0; let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01)); let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } } /// 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) -> BVec4A { BVec4A(unsafe { _mm_cmpeq_ps(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { _mm_cmpneq_ps(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { _mm_cmpge_ps(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { _mm_cmpgt_ps(self.0, rhs.0) }) } /// 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) -> BVec4A { BVec4A(unsafe { _mm_cmple_ps(self.0, rhs.0) }) } /// 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) -> 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) }) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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 { let result = Self(unsafe { _mm_or_ps(_mm_and_ps(self.0, Self::NEG_ONE.0), Self::ONE.0) }); let mask = self.is_nan_mask(); Self::select(mask, self, result) } /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { let mask = Self::splat(-0.0); Self(unsafe { _mm_or_ps(_mm_and_ps(rhs.0, mask.0), _mm_andnot_ps(mask.0, self.0)) }) } /// 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 { unsafe { _mm_movemask_ps(self.0) as u32 } } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec4A { BVec4A(unsafe { _mm_cmplt_ps(crate::sse2::m128_abs(self.0), Self::INFINITY.0) }) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec4A { BVec4A(unsafe { _mm_cmpunord_ps(self.0, self.0) }) } /// 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); _mm_cvtss_f32(_mm_sqrt_ps(dot)) } } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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); _mm_cvtss_f32(_mm_div_ps(Self::ONE.0, _mm_sqrt_ps(dot))) } } /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { unsafe { let length = _mm_sqrt_ps(dot4_into_m128(self.0, self.0)); #[allow(clippy::let_and_return)] let normalized = Self(_mm_div_ps(self.0, length)); glam_assert!(normalized.is_finite()); normalized } } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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) }) } /// 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) }) } /// 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 as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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) }) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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 { Self(_mm_fmadd_ps(self.0, a.0, b.0)) } #[cfg(not(target_feature = "fma"))] Self::new( 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), ) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } } impl Default for Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(unsafe { _mm_div_ps(self.0, rhs.0) }) } } impl Div<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 = unsafe { _mm_div_ps(self.0, rhs.0) }; } } impl DivAssign<&Vec4> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &Vec4) { self.div_assign(*rhs) } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(unsafe { _mm_div_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Div<&f32> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { self.div(*rhs) } } impl Div<&f32> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: f32) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_div_ps(self.0, _mm_set1_ps(rhs)) }; } } impl DivAssign<&f32> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { _mm_div_ps(_mm_set1_ps(self), rhs.0) }) } } impl Div<&Vec4> for f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(unsafe { _mm_mul_ps(self.0, rhs.0) }) } } impl Mul<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 = unsafe { _mm_mul_ps(self.0, rhs.0) }; } } impl MulAssign<&Vec4> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &Vec4) { self.mul_assign(*rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Mul<&f32> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { self.mul(*rhs) } } impl Mul<&f32> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: f32) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }; } } impl MulAssign<&f32> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { _mm_mul_ps(_mm_set1_ps(self), rhs.0) }) } } impl Mul<&Vec4> for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(unsafe { _mm_add_ps(self.0, rhs.0) }) } } impl Add<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 = unsafe { _mm_add_ps(self.0, rhs.0) }; } } impl AddAssign<&Vec4> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &Vec4) { self.add_assign(*rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Add<&f32> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { self.add(*rhs) } } impl Add<&f32> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: f32) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }; } } impl AddAssign<&f32> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { _mm_add_ps(_mm_set1_ps(self), rhs.0) }) } } impl Add<&Vec4> for f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(unsafe { _mm_sub_ps(self.0, rhs.0) }) } } impl Sub<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: Vec4) { self.0 = unsafe { _mm_sub_ps(self.0, rhs.0) }; } } impl SubAssign<&Vec4> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &Vec4) { self.sub_assign(*rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(unsafe { _mm_sub_ps(self.0, _mm_set1_ps(rhs)) }) } } impl Sub<&f32> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { self.sub(*rhs) } } impl Sub<&f32> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: f32) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 = unsafe { _mm_sub_ps(self.0, _mm_set1_ps(rhs)) }; } } impl SubAssign<&f32> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { Vec4(unsafe { _mm_sub_ps(_mm_set1_ps(self), rhs.0) }) } } impl Sub<&Vec4> for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { unsafe { let n = m128_floor(_mm_div_ps(self.0, rhs.0)); Self(_mm_sub_ps(self.0, _mm_mul_ps(n, rhs.0))) } } } impl Rem<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = self.rem(rhs); } } impl RemAssign<&Vec4> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &Vec4) { self.rem_assign(*rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { self.rem(*rhs) } } impl Rem<&f32> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: f32) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: f32) { *self = self.rem(Self::splat(rhs)); } } impl RemAssign<&f32> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { Vec4::splat(self).rem(rhs) } } impl Rem<&Vec4> for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Vec4 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Vec4 as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Vec4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Vec4 as *mut [f32; 4]) } } } impl Sum for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec4 { type Output = Self; #[inline] fn neg(self) -> Self { Self(unsafe { _mm_xor_ps(_mm_set1_ps(-0.0), self.0) }) } } impl Neg for &Vec4 { type Output = Vec4; #[inline] fn neg(self) -> Vec4 { (*self).neg() } } impl Index for Vec4 { type Output = f32; #[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 for Vec4 { #[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"), } } } impl fmt::Display for Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl fmt::Debug for Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From for __m128 { #[inline(always)] fn from(t: Vec4) -> Self { t.0 } } impl From<__m128> for Vec4 { #[inline(always)] fn from(t: __m128) -> Self { Self(t) } } impl From<[f32; 4]> for Vec4 { #[inline] fn from(a: [f32; 4]) -> Self { Self(unsafe { _mm_loadu_ps(a.as_ptr()) }) } } impl From for [f32; 4] { #[inline] fn from(v: Vec4) -> Self { use crate::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(f32, f32, f32, f32)> for Vec4 { #[inline] fn from(t: (f32, f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(v: Vec4) -> Self { use crate::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } } } impl From<(Vec3A, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3A, f32)) -> Self { v.extend(w) } } impl From<(f32, Vec3A)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3A)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec3, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3, f32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(f32, Vec3)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec2, f32, f32)> for Vec4 { #[inline] fn from((v, z, w): (Vec2, f32, f32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(Vec2, Vec2)> for Vec4 { #[inline] fn from((v, u): (Vec2, Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl Deref for Vec4 { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec4 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( f32::from(v.x), f32::from(v.y), f32::from(v.z), f32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), f32::from(bool_array[3]), ) } } glam-0.30.1/src/f32/sse2.rs000064400000000000000000000001261046102023000132270ustar 00000000000000pub mod mat2; pub mod mat3a; pub mod mat4; pub mod quat; pub mod vec3a; pub mod vec4; glam-0.30.1/src/f32/vec2.rs000064400000000000000000001324371046102023000132250ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, BVec2, Vec3}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn vec2(x: f32, y: f32) -> Vec2 { Vec2::new(x, y) } /// A 2-dimensional vector. #[derive(Clone, Copy, PartialEq)] #[cfg_attr(feature = "cuda", repr(align(8)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct Vec2 { pub x: f32, pub y: f32, } impl Vec2 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0); /// 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.0, -1.0); /// 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y)) } /// 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: [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] } /// 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: &[f32]) -> Self { assert!(slice.len() >= 2); 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 [f32]) { slice[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// 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)) } /// 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 [`f32::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) -> f32 { 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) -> f32 { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { self.x * 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: math::abs(self.x), y: math::abs(self.y), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: math::copysign(self.x, rhs.x), y: math::copysign(self.y, rhs.y), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec2 { BVec2::new(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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec2 { BVec2::new(self.x.is_nan(), self.y.is_nan()) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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(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: 1.0 / self.x, y: 1.0 / self.y, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( math::mul_add(self.x, a.x, b.x), math::mul_add(self.y, a.y, b.y), ) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Creates a 2D vector containing `[angle.cos(), angle.sin()]`. This can be used in /// 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) = math::sin_cos(angle); Self { x: cos, y: sin } } /// Returns the angle (in radians) of this vector in the range `[-π, +π]`. /// /// The input does not need to be a unit vector however it must be non-zero. #[inline] #[must_use] pub fn to_angle(self) -> f32 { math::atan2(self.y, self.x) } #[inline] #[must_use] #[deprecated( since = "0.27.0", note = "Use angle_to() instead, the semantics of angle_between will change in the future." )] pub fn angle_between(self, rhs: Self) -> f32 { self.angle_to(rhs) } /// Returns the angle of rotation (in radians) from `self` to `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_to(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, 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) -> f32 { (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, } } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self { let a = self.angle_to(rhs); let abs_a = math::abs(a); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(abs_a - core::f32::consts::PI, abs_a) * math::signum(a); Self::from_angle(angle).rotate(*self) } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } } impl Default for Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for Vec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&Vec2> for Vec2 { type Output = Vec2; #[inline] fn div(self, rhs: &Vec2) -> Vec2 { self.div(*rhs) } } impl Div<&Vec2> for &Vec2 { type Output = Vec2; #[inline] fn div(self, rhs: &Vec2) -> Vec2 { (*self).div(*rhs) } } impl Div for &Vec2 { type Output = Vec2; #[inline] fn div(self, rhs: Vec2) -> Vec2 { (*self).div(rhs) } } impl DivAssign for Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&Vec2> for Vec2 { #[inline] fn div_assign(&mut self, rhs: &Vec2) { self.div_assign(*rhs) } } impl Div for Vec2 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&f32> for Vec2 { type Output = Vec2; #[inline] fn div(self, rhs: &f32) -> Vec2 { self.div(*rhs) } } impl Div<&f32> for &Vec2 { type Output = Vec2; #[inline] fn div(self, rhs: &f32) -> Vec2 { (*self).div(*rhs) } } impl Div for &Vec2 { type Output = Vec2; #[inline] fn div(self, rhs: f32) -> Vec2 { (*self).div(rhs) } } impl DivAssign for Vec2 { #[inline] fn div_assign(&mut self, rhs: f32) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&f32> for Vec2 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec2; #[inline] fn div(self, rhs: Vec2) -> Vec2 { Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&Vec2> for f32 { type Output = Vec2; #[inline] fn div(self, rhs: &Vec2) -> Vec2 { self.div(*rhs) } } impl Div<&Vec2> for &f32 { type Output = Vec2; #[inline] fn div(self, rhs: &Vec2) -> Vec2 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec2; #[inline] fn div(self, rhs: Vec2) -> Vec2 { (*self).div(rhs) } } impl Mul for Vec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&Vec2> for Vec2 { type Output = Vec2; #[inline] fn mul(self, rhs: &Vec2) -> Vec2 { self.mul(*rhs) } } impl Mul<&Vec2> for &Vec2 { type Output = Vec2; #[inline] fn mul(self, rhs: &Vec2) -> Vec2 { (*self).mul(*rhs) } } impl Mul for &Vec2 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Vec2 { (*self).mul(rhs) } } impl MulAssign for Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&Vec2> for Vec2 { #[inline] fn mul_assign(&mut self, rhs: &Vec2) { self.mul_assign(*rhs) } } impl Mul for Vec2 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&f32> for Vec2 { type Output = Vec2; #[inline] fn mul(self, rhs: &f32) -> Vec2 { self.mul(*rhs) } } impl Mul<&f32> for &Vec2 { type Output = Vec2; #[inline] fn mul(self, rhs: &f32) -> Vec2 { (*self).mul(*rhs) } } impl Mul for &Vec2 { type Output = Vec2; #[inline] fn mul(self, rhs: f32) -> Vec2 { (*self).mul(rhs) } } impl MulAssign for Vec2 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&f32> for Vec2 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Vec2 { Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&Vec2> for f32 { type Output = Vec2; #[inline] fn mul(self, rhs: &Vec2) -> Vec2 { self.mul(*rhs) } } impl Mul<&Vec2> for &f32 { type Output = Vec2; #[inline] fn mul(self, rhs: &Vec2) -> Vec2 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Vec2 { (*self).mul(rhs) } } impl Add for Vec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&Vec2> for Vec2 { type Output = Vec2; #[inline] fn add(self, rhs: &Vec2) -> Vec2 { self.add(*rhs) } } impl Add<&Vec2> for &Vec2 { type Output = Vec2; #[inline] fn add(self, rhs: &Vec2) -> Vec2 { (*self).add(*rhs) } } impl Add for &Vec2 { type Output = Vec2; #[inline] fn add(self, rhs: Vec2) -> Vec2 { (*self).add(rhs) } } impl AddAssign for Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&Vec2> for Vec2 { #[inline] fn add_assign(&mut self, rhs: &Vec2) { self.add_assign(*rhs) } } impl Add for Vec2 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&f32> for Vec2 { type Output = Vec2; #[inline] fn add(self, rhs: &f32) -> Vec2 { self.add(*rhs) } } impl Add<&f32> for &Vec2 { type Output = Vec2; #[inline] fn add(self, rhs: &f32) -> Vec2 { (*self).add(*rhs) } } impl Add for &Vec2 { type Output = Vec2; #[inline] fn add(self, rhs: f32) -> Vec2 { (*self).add(rhs) } } impl AddAssign for Vec2 { #[inline] fn add_assign(&mut self, rhs: f32) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&f32> for Vec2 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec2; #[inline] fn add(self, rhs: Vec2) -> Vec2 { Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&Vec2> for f32 { type Output = Vec2; #[inline] fn add(self, rhs: &Vec2) -> Vec2 { self.add(*rhs) } } impl Add<&Vec2> for &f32 { type Output = Vec2; #[inline] fn add(self, rhs: &Vec2) -> Vec2 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec2; #[inline] fn add(self, rhs: Vec2) -> Vec2 { (*self).add(rhs) } } impl Sub for Vec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&Vec2> for Vec2 { type Output = Vec2; #[inline] fn sub(self, rhs: &Vec2) -> Vec2 { self.sub(*rhs) } } impl Sub<&Vec2> for &Vec2 { type Output = Vec2; #[inline] fn sub(self, rhs: &Vec2) -> Vec2 { (*self).sub(*rhs) } } impl Sub for &Vec2 { type Output = Vec2; #[inline] fn sub(self, rhs: Vec2) -> Vec2 { (*self).sub(rhs) } } impl SubAssign for Vec2 { #[inline] fn sub_assign(&mut self, rhs: Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&Vec2> for Vec2 { #[inline] fn sub_assign(&mut self, rhs: &Vec2) { self.sub_assign(*rhs) } } impl Sub for Vec2 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&f32> for Vec2 { type Output = Vec2; #[inline] fn sub(self, rhs: &f32) -> Vec2 { self.sub(*rhs) } } impl Sub<&f32> for &Vec2 { type Output = Vec2; #[inline] fn sub(self, rhs: &f32) -> Vec2 { (*self).sub(*rhs) } } impl Sub for &Vec2 { type Output = Vec2; #[inline] fn sub(self, rhs: f32) -> Vec2 { (*self).sub(rhs) } } impl SubAssign for Vec2 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&f32> for Vec2 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec2; #[inline] fn sub(self, rhs: Vec2) -> Vec2 { Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&Vec2> for f32 { type Output = Vec2; #[inline] fn sub(self, rhs: &Vec2) -> Vec2 { self.sub(*rhs) } } impl Sub<&Vec2> for &f32 { type Output = Vec2; #[inline] fn sub(self, rhs: &Vec2) -> Vec2 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec2; #[inline] fn sub(self, rhs: Vec2) -> Vec2 { (*self).sub(rhs) } } impl Rem for Vec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&Vec2> for Vec2 { type Output = Vec2; #[inline] fn rem(self, rhs: &Vec2) -> Vec2 { self.rem(*rhs) } } impl Rem<&Vec2> for &Vec2 { type Output = Vec2; #[inline] fn rem(self, rhs: &Vec2) -> Vec2 { (*self).rem(*rhs) } } impl Rem for &Vec2 { type Output = Vec2; #[inline] fn rem(self, rhs: Vec2) -> Vec2 { (*self).rem(rhs) } } impl RemAssign for Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&Vec2> for Vec2 { #[inline] fn rem_assign(&mut self, rhs: &Vec2) { self.rem_assign(*rhs) } } impl Rem for Vec2 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&f32> for Vec2 { type Output = Vec2; #[inline] fn rem(self, rhs: &f32) -> Vec2 { self.rem(*rhs) } } impl Rem<&f32> for &Vec2 { type Output = Vec2; #[inline] fn rem(self, rhs: &f32) -> Vec2 { (*self).rem(*rhs) } } impl Rem for &Vec2 { type Output = Vec2; #[inline] fn rem(self, rhs: f32) -> Vec2 { (*self).rem(rhs) } } impl RemAssign for Vec2 { #[inline] fn rem_assign(&mut self, rhs: f32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&f32> for Vec2 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec2; #[inline] fn rem(self, rhs: Vec2) -> Vec2 { Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&Vec2> for f32 { type Output = Vec2; #[inline] fn rem(self, rhs: &Vec2) -> Vec2 { self.rem(*rhs) } } impl Rem<&Vec2> for &f32 { type Output = Vec2; #[inline] fn rem(self, rhs: &Vec2) -> Vec2 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec2; #[inline] fn rem(self, rhs: Vec2) -> Vec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 2]> for Vec2 { #[inline] fn as_ref(&self) -> &[f32; 2] { unsafe { &*(self as *const Vec2 as *const [f32; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 2]> for Vec2 { #[inline] fn as_mut(&mut self) -> &mut [f32; 2] { unsafe { &mut *(self as *mut Vec2 as *mut [f32; 2]) } } } impl Sum for Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec2 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), } } } impl Neg for &Vec2 { type Output = Vec2; #[inline] fn neg(self) -> Vec2 { (*self).neg() } } impl Index for Vec2 { type Output = f32; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for Vec2 { #[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"), } } } impl fmt::Display for Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x, p, self.y) } else { write!(f, "[{}, {}]", self.x, self.y) } } } impl fmt::Debug for Vec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[f32; 2]> for Vec2 { #[inline] fn from(a: [f32; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [f32; 2] { #[inline] fn from(v: Vec2) -> Self { [v.x, v.y] } } impl From<(f32, f32)> for Vec2 { #[inline] fn from(t: (f32, f32)) -> Self { Self::new(t.0, t.1) } } impl From for (f32, f32) { #[inline] fn from(v: Vec2) -> Self { (v.x, v.y) } } impl From for Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(f32::from(v.x), f32::from(v.y)) } } glam-0.30.1/src/f32/vec3.rs000064400000000000000000001467301046102023000132270ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, BVec3, BVec3A, FloatExt, Quat, Vec2, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// A 3-dimensional vector. #[derive(Clone, Copy, PartialEq)] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct Vec3 { pub x: f32, pub y: f32, pub z: f32, } impl Vec3 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [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] } /// 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: &[f32]) -> Self { assert!(slice.len() >= 3); 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 [f32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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, 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: 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// 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, 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 [`f32::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) -> f32 { 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) -> f32 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { self.x * self.y * 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: math::abs(self.x), y: math::abs(self.y), z: math::abs(self.z), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: math::copysign(self.x, rhs.x), y: math::copysign(self.y, rhs.y), z: math::copysign(self.z, rhs.z), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) | ((self.z.is_sign_negative() as u32) << 2) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3 { BVec3::new(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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.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()) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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: 1.0 / self.x, y: 1.0 / self.y, z: 1.0 / self.z, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f32::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); Quat::from_axis_angle(axis, angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f32) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize(); let rotation = Quat::from_axis_angle(axis, core::f32::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for Vec3 { 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 Div<&Vec3> for Vec3 { type Output = Vec3; #[inline] fn div(self, rhs: &Vec3) -> Vec3 { self.div(*rhs) } } impl Div<&Vec3> for &Vec3 { type Output = Vec3; #[inline] fn div(self, rhs: &Vec3) -> Vec3 { (*self).div(*rhs) } } impl Div for &Vec3 { type Output = Vec3; #[inline] fn div(self, rhs: Vec3) -> Vec3 { (*self).div(rhs) } } impl DivAssign for Vec3 { #[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 DivAssign<&Vec3> for Vec3 { #[inline] fn div_assign(&mut self, rhs: &Vec3) { self.div_assign(*rhs) } } impl Div for Vec3 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&f32> for Vec3 { type Output = Vec3; #[inline] fn div(self, rhs: &f32) -> Vec3 { self.div(*rhs) } } impl Div<&f32> for &Vec3 { type Output = Vec3; #[inline] fn div(self, rhs: &f32) -> Vec3 { (*self).div(*rhs) } } impl Div for &Vec3 { type Output = Vec3; #[inline] fn div(self, rhs: f32) -> Vec3 { (*self).div(rhs) } } impl DivAssign for Vec3 { #[inline] fn div_assign(&mut self, rhs: f32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&f32> for Vec3 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec3; #[inline] fn div(self, rhs: Vec3) -> Vec3 { Vec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&Vec3> for f32 { type Output = Vec3; #[inline] fn div(self, rhs: &Vec3) -> Vec3 { self.div(*rhs) } } impl Div<&Vec3> for &f32 { type Output = Vec3; #[inline] fn div(self, rhs: &Vec3) -> Vec3 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec3; #[inline] fn div(self, rhs: Vec3) -> Vec3 { (*self).div(rhs) } } impl Mul for Vec3 { 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 Mul<&Vec3> for Vec3 { type Output = Vec3; #[inline] fn mul(self, rhs: &Vec3) -> Vec3 { self.mul(*rhs) } } impl Mul<&Vec3> for &Vec3 { type Output = Vec3; #[inline] fn mul(self, rhs: &Vec3) -> Vec3 { (*self).mul(*rhs) } } impl Mul for &Vec3 { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { (*self).mul(rhs) } } impl MulAssign for Vec3 { #[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 MulAssign<&Vec3> for Vec3 { #[inline] fn mul_assign(&mut self, rhs: &Vec3) { self.mul_assign(*rhs) } } impl Mul for Vec3 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&f32> for Vec3 { type Output = Vec3; #[inline] fn mul(self, rhs: &f32) -> Vec3 { self.mul(*rhs) } } impl Mul<&f32> for &Vec3 { type Output = Vec3; #[inline] fn mul(self, rhs: &f32) -> Vec3 { (*self).mul(*rhs) } } impl Mul for &Vec3 { type Output = Vec3; #[inline] fn mul(self, rhs: f32) -> Vec3 { (*self).mul(rhs) } } impl MulAssign for Vec3 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&f32> for Vec3 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { Vec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&Vec3> for f32 { type Output = Vec3; #[inline] fn mul(self, rhs: &Vec3) -> Vec3 { self.mul(*rhs) } } impl Mul<&Vec3> for &f32 { type Output = Vec3; #[inline] fn mul(self, rhs: &Vec3) -> Vec3 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { (*self).mul(rhs) } } impl Add for Vec3 { 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 Add<&Vec3> for Vec3 { type Output = Vec3; #[inline] fn add(self, rhs: &Vec3) -> Vec3 { self.add(*rhs) } } impl Add<&Vec3> for &Vec3 { type Output = Vec3; #[inline] fn add(self, rhs: &Vec3) -> Vec3 { (*self).add(*rhs) } } impl Add for &Vec3 { type Output = Vec3; #[inline] fn add(self, rhs: Vec3) -> Vec3 { (*self).add(rhs) } } impl AddAssign for Vec3 { #[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 AddAssign<&Vec3> for Vec3 { #[inline] fn add_assign(&mut self, rhs: &Vec3) { self.add_assign(*rhs) } } impl Add for Vec3 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&f32> for Vec3 { type Output = Vec3; #[inline] fn add(self, rhs: &f32) -> Vec3 { self.add(*rhs) } } impl Add<&f32> for &Vec3 { type Output = Vec3; #[inline] fn add(self, rhs: &f32) -> Vec3 { (*self).add(*rhs) } } impl Add for &Vec3 { type Output = Vec3; #[inline] fn add(self, rhs: f32) -> Vec3 { (*self).add(rhs) } } impl AddAssign for Vec3 { #[inline] fn add_assign(&mut self, rhs: f32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&f32> for Vec3 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec3; #[inline] fn add(self, rhs: Vec3) -> Vec3 { Vec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&Vec3> for f32 { type Output = Vec3; #[inline] fn add(self, rhs: &Vec3) -> Vec3 { self.add(*rhs) } } impl Add<&Vec3> for &f32 { type Output = Vec3; #[inline] fn add(self, rhs: &Vec3) -> Vec3 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec3; #[inline] fn add(self, rhs: Vec3) -> Vec3 { (*self).add(rhs) } } impl Sub for Vec3 { 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 Sub<&Vec3> for Vec3 { type Output = Vec3; #[inline] fn sub(self, rhs: &Vec3) -> Vec3 { self.sub(*rhs) } } impl Sub<&Vec3> for &Vec3 { type Output = Vec3; #[inline] fn sub(self, rhs: &Vec3) -> Vec3 { (*self).sub(*rhs) } } impl Sub for &Vec3 { type Output = Vec3; #[inline] fn sub(self, rhs: Vec3) -> Vec3 { (*self).sub(rhs) } } impl SubAssign for Vec3 { #[inline] fn sub_assign(&mut self, rhs: Vec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&Vec3> for Vec3 { #[inline] fn sub_assign(&mut self, rhs: &Vec3) { self.sub_assign(*rhs) } } impl Sub for Vec3 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&f32> for Vec3 { type Output = Vec3; #[inline] fn sub(self, rhs: &f32) -> Vec3 { self.sub(*rhs) } } impl Sub<&f32> for &Vec3 { type Output = Vec3; #[inline] fn sub(self, rhs: &f32) -> Vec3 { (*self).sub(*rhs) } } impl Sub for &Vec3 { type Output = Vec3; #[inline] fn sub(self, rhs: f32) -> Vec3 { (*self).sub(rhs) } } impl SubAssign for Vec3 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&f32> for Vec3 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec3; #[inline] fn sub(self, rhs: Vec3) -> Vec3 { Vec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&Vec3> for f32 { type Output = Vec3; #[inline] fn sub(self, rhs: &Vec3) -> Vec3 { self.sub(*rhs) } } impl Sub<&Vec3> for &f32 { type Output = Vec3; #[inline] fn sub(self, rhs: &Vec3) -> Vec3 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec3; #[inline] fn sub(self, rhs: Vec3) -> Vec3 { (*self).sub(rhs) } } impl Rem for Vec3 { 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 Rem<&Vec3> for Vec3 { type Output = Vec3; #[inline] fn rem(self, rhs: &Vec3) -> Vec3 { self.rem(*rhs) } } impl Rem<&Vec3> for &Vec3 { type Output = Vec3; #[inline] fn rem(self, rhs: &Vec3) -> Vec3 { (*self).rem(*rhs) } } impl Rem for &Vec3 { type Output = Vec3; #[inline] fn rem(self, rhs: Vec3) -> Vec3 { (*self).rem(rhs) } } impl RemAssign for Vec3 { #[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 RemAssign<&Vec3> for Vec3 { #[inline] fn rem_assign(&mut self, rhs: &Vec3) { self.rem_assign(*rhs) } } impl Rem for Vec3 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&f32> for Vec3 { type Output = Vec3; #[inline] fn rem(self, rhs: &f32) -> Vec3 { self.rem(*rhs) } } impl Rem<&f32> for &Vec3 { type Output = Vec3; #[inline] fn rem(self, rhs: &f32) -> Vec3 { (*self).rem(*rhs) } } impl Rem for &Vec3 { type Output = Vec3; #[inline] fn rem(self, rhs: f32) -> Vec3 { (*self).rem(rhs) } } impl RemAssign for Vec3 { #[inline] fn rem_assign(&mut self, rhs: f32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&f32> for Vec3 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec3; #[inline] fn rem(self, rhs: Vec3) -> Vec3 { Vec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&Vec3> for f32 { type Output = Vec3; #[inline] fn rem(self, rhs: &Vec3) -> Vec3 { self.rem(*rhs) } } impl Rem<&Vec3> for &f32 { type Output = Vec3; #[inline] fn rem(self, rhs: &Vec3) -> Vec3 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec3; #[inline] fn rem(self, rhs: Vec3) -> Vec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 3]> for Vec3 { #[inline] fn as_ref(&self) -> &[f32; 3] { unsafe { &*(self as *const Vec3 as *const [f32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 3]> for Vec3 { #[inline] fn as_mut(&mut self) -> &mut [f32; 3] { unsafe { &mut *(self as *mut Vec3 as *mut [f32; 3]) } } } impl Sum for Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec3 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), z: self.z.neg(), } } } impl Neg for &Vec3 { type Output = Vec3; #[inline] fn neg(self) -> Vec3 { (*self).neg() } } impl Index for Vec3 { type Output = f32; #[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 for Vec3 { #[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"), } } } impl fmt::Display for Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for Vec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[f32; 3]> for Vec3 { #[inline] fn from(a: [f32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f32; 3] { #[inline] fn from(v: Vec3) -> Self { [v.x, v.y, v.z] } } impl From<(f32, f32, f32)> for Vec3 { #[inline] fn from(t: (f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f32, f32, f32) { #[inline] fn from(v: Vec3) -> Self { (v.x, v.y, v.z) } } impl From<(Vec2, f32)> for Vec3 { #[inline] fn from((v, z): (Vec2, f32)) -> Self { Self::new(v.x, v.y, z) } } impl From for Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z)) } } impl From for Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), ) } } glam-0.30.1/src/f32/wasm32/mat2.rs000064400000000000000000000413721046102023000143420ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, swizzles::*, DMat2, Mat3, Mat3A, Vec2}; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::arch::wasm32::*; /// 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); impl Mat2 { /// A 2x2 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec2::ZERO, Vec2::ZERO); /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec2::X, Vec2::Y); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec2::NAN, Vec2::NAN); #[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)) } /// Creates a 2x2 matrix from a `[f32; 4]` array stored in column major order. /// 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]) } /// 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]) } } /// Creates a 2x2 matrix from a `[[f32; 2]; 2]` 2D array stored in column major order. /// 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])) } /// 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]) } } /// 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) } /// 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) = 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) = 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 the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3_minor(m: Mat3, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3a_minor(m: Mat3A, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from the first 4 values in `slice`. /// /// # Panics /// /// 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]) } /// Writes the columns of `self` to the first 4 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 4 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.y_axis.x; slice[3] = self.y_axis.y; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec2 { match index { 0 => self.x_axis, 1 => self.y_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec2 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec2::new(self.x_axis.y, self.y_axis.y), _ => panic!("index out of bounds"), } } /// 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`. #[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); let prod = f32x4_mul(abcd, dcba); let det = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod)); f32x4_extract_lane::<0>(det) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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; let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd); let prod = f32x4_mul(abcd, dcba); let sub = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod)); let det = i32x4_shuffle::<0, 0, 4, 4>(sub, sub); let tmp = f32x4_div(SIGN, det); glam_assert!(Mat2(tmp).is_finite()); let dbca = i32x4_shuffle::<3, 1, 6, 4>(abcd, abcd); Self(f32x4_mul(dbca, tmp)) } /// Transforms a 2D vector. #[inline] #[must_use] pub fn mul_vec2(&self, rhs: Vec2) -> Vec2 { use core::mem::MaybeUninit; let abcd = self.0; let xxyy = f32x4(rhs.x, rhs.x, rhs.y, rhs.y); let axbxcydy = f32x4_mul(abcd, xxyy); let cydyaxbx = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy, axbxcydy); let result = f32x4_add(axbxcydy, cydyaxbx); let mut out: MaybeUninit = MaybeUninit::uninit(); unsafe { v128_store(out.as_mut_ptr(), result); *(&out.assume_init() as *const v128 as *const Vec2) } } /// Multiplies two 2x2 matrices. #[inline] #[must_use] pub fn mul_mat2(&self, rhs: &Self) -> Self { let abcd = self.0; let rhs = rhs.0; let xxyy0 = i32x4_shuffle::<0, 0, 5, 5>(rhs, rhs); let xxyy1 = i32x4_shuffle::<2, 2, 7, 7>(rhs, rhs); let axbxcydy0 = f32x4_mul(abcd, xxyy0); let axbxcydy1 = f32x4_mul(abcd, xxyy1); let cydyaxbx0 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy0, axbxcydy0); let cydyaxbx1 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy1, axbxcydy1); let result0 = f32x4_add(axbxcydy0, cydyaxbx0); let result1 = f32x4_add(axbxcydy1, cydyaxbx1); Self(i32x4_shuffle::<0, 1, 4, 5>(result0, result1)) } /// 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))) } /// Divides a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { Self(f32x4_div(self.0, f32x4_splat(rhs))) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs()) } #[inline] pub fn as_dmat2(&self) -> DMat2 { DMat2::from_cols(self.x_axis.as_dvec2(), self.y_axis.as_dvec2()) } } impl Default for Mat2 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat2(&rhs) } } impl AddAssign for Mat2 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat2(&rhs); } } impl Sub for Mat2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat2(&rhs) } } impl SubAssign for Mat2 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat2(&rhs); } } impl Neg for Mat2 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self(f32x4_neg(self.0)) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat2(&rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat2(&rhs); } } impl Mul for Mat2 { type Output = Vec2; #[inline] fn mul(self, rhs: Vec2) -> Self::Output { self.mul_vec2(rhs) } } impl Mul for f32 { type Output = Mat2; #[inline] fn mul(self, rhs: Mat2) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat2 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat2 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat2; #[inline] fn div(self, rhs: Mat2) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat2 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat2 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Mat2 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Mat2 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Self as *mut [f32; 4]) } } } impl core::ops::Deref for Mat2 { type Target = crate::deref::Cols2; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl core::ops::DerefMut for Mat2 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl fmt::Debug for Mat2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat2)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .finish() } } impl fmt::Display for Mat2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) } else { write!(f, "[{}, {}]", self.x_axis, self.y_axis) } } } glam-0.30.1/src/f32/wasm32/mat3a.rs000064400000000000000000000734731046102023000145130ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, DMat3, EulerRot, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::arch::wasm32::*; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`Affine2`](crate::Affine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat3A { pub x_axis: Vec3A, pub y_axis: Vec3A, pub z_axis: Vec3A, } impl Mat3A { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec3A::ZERO, Vec3A::ZERO, Vec3A::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec3A::X, Vec3A::Y, Vec3A::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec3A::NAN, Vec3A::NAN, Vec3A::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m10: f32, m11: f32, m12: f32, m20: f32, m21: f32, m22: f32, ) -> Self { Self { x_axis: Vec3A::new(m00, m01, m02), y_axis: Vec3A::new(m10, m11, m12), z_axis: Vec3A::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f32; 9]` array stored in column major order. /// 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]) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z] = self.z_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, y_axis_x, y_axis_y, y_axis_z, z_axis_x, z_axis_y, z_axis_z, ] } /// Creates a 3x3 matrix from a `[[f32; 3]; 3]` 3D array stored in column major order. /// 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]), Vec3A::from_array(m[1]), Vec3A::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( Vec3A::from_vec4(m.x_axis), Vec3A::from_vec4(m.y_axis), Vec3A::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: Mat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols( Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (0, 1) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (0, 2) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (0, 3) => Self::from_cols( Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (1, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (1, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (1, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (1, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (2, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.w_axis.yzww()), ), (2, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.w_axis.xzww()), ), (2, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.w_axis.xyww()), ), (2, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.w_axis.xyzw()), ), (3, 0) => Self::from_cols( Vec3A::from_vec4(m.x_axis.yzww()), Vec3A::from_vec4(m.y_axis.yzww()), Vec3A::from_vec4(m.z_axis.yzww()), ), (3, 1) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xzww()), Vec3A::from_vec4(m.y_axis.xzww()), Vec3A::from_vec4(m.z_axis.xzww()), ), (3, 2) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyww()), Vec3A::from_vec4(m.y_axis.xyww()), Vec3A::from_vec4(m.z_axis.xyww()), ), (3, 3) => Self::from_cols( Vec3A::from_vec4(m.x_axis.xyzw()), Vec3A::from_vec4(m.y_axis.xyzw()), Vec3A::from_vec4(m.z_axis.xyzw()), ), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( Vec3A::new(1.0 - (yy + zz), xy + wz, xz - wy), Vec3A::new(xy - wz, 1.0 - (xx + zz), yz + wx), Vec3A::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( Vec3A::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), Vec3A::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), Vec3A::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::X, Vec3A::new(0.0, cosa, sina), Vec3A::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, 0.0, -sina), Vec3A::Y, Vec3A::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cosa, sina, 0.0), Vec3A::new(-sina, cosa, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, Vec3A::Y, Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols( Vec3A::new(cos, sin, 0.0), Vec3A::new(-sin, cos, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), Vec3A::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec3A::new(scale.x, 0.0, 0.0), Vec3A::new(0.0, scale.y, 0.0), Vec3A::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: Mat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), Vec3A::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec3A { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec3A { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec3A::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => Vec3A::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[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); Self { x_axis: Vec3A(i32x4_shuffle::<0, 2, 4, 4>(tmp0, self.z_axis.0)), y_axis: Vec3A(i32x4_shuffle::<1, 3, 5, 5>(tmp0, self.z_axis.0)), z_axis: Vec3A(i32x4_shuffle::<0, 2, 6, 6>(tmp1, self.z_axis.0)), } } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f32 { self.z_axis.dot(self.x_axis.cross(self.y_axis)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = Vec3A::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec3A::new(s.x, u.x, -f.x), Vec3A::new(s.y, u.y, -f.y), Vec3A::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// Transforms a 3D vector. #[inline] #[must_use] pub fn mul_vec3(&self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } /// 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())); res = res.add(self.z_axis.mul(rhs.zzz())); res } /// Multiplies two 3x3 matrices. #[inline] #[must_use] pub fn mul_mat3(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec3A::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_dmat3(&self) -> DMat3 { DMat3::from_cols( self.x_axis.as_dvec3(), self.y_axis.as_dvec3(), self.z_axis.as_dvec3(), ) } } impl Default for Mat3A { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for Mat3A { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for Mat3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for Mat3A { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for Mat3A { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for Mat3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl Mul for f32 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat3A { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat3A; #[inline] fn div(self, rhs: Mat3A) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat3A { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Mul for Mat3A { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } } impl From for Mat3A { #[inline] fn from(m: Mat3) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } impl Sum for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat3A { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat3A { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } impl fmt::Debug for Mat3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat3A)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for Mat3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f32/wasm32/mat4.rs000064400000000000000000001500201046102023000143330ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f32::math, swizzles::*, wasm32::*, DMat4, EulerRot, Mat3, Mat3A, Quat, Vec3, Vec3A, Vec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use core::arch::wasm32::*; /// 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) } /// A 4x4 column major matrix. /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`Affine3A`](crate::Affine3A) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. #[derive(Clone, Copy)] #[repr(C)] pub struct Mat4 { pub x_axis: Vec4, pub y_axis: Vec4, pub z_axis: Vec4, pub w_axis: Vec4, } impl Mat4 { /// A 4x4 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(Vec4::ZERO, Vec4::ZERO, Vec4::ZERO, Vec4::ZERO); /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(Vec4::X, Vec4::Y, Vec4::Z, Vec4::W); /// All NAN:s. pub const NAN: Self = Self::from_cols(Vec4::NAN, Vec4::NAN, Vec4::NAN, Vec4::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f32, m01: f32, m02: f32, m03: f32, m10: f32, m11: f32, m12: f32, m13: f32, m20: f32, m21: f32, m22: f32, m23: f32, m30: f32, m31: f32, m32: f32, m33: f32, ) -> Self { Self { x_axis: Vec4::new(m00, m01, m02, m03), y_axis: Vec4::new(m10, m11, m12, m13), z_axis: Vec4::new(m20, m21, m22, m23), w_axis: Vec4::new(m30, m31, m32, m33), } } /// 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, y_axis, z_axis, w_axis, } } /// Creates a 4x4 matrix from a `[f32; 16]` array stored in column major order. /// 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], m[14], m[15], ) } /// 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(); let [z_axis_x, z_axis_y, z_axis_z, z_axis_w] = self.z_axis.to_array(); let [w_axis_x, w_axis_y, w_axis_z, w_axis_w] = self.w_axis.to_array(); [ x_axis_x, x_axis_y, x_axis_z, x_axis_w, y_axis_x, y_axis_y, y_axis_z, y_axis_w, z_axis_x, z_axis_y, z_axis_z, z_axis_w, w_axis_x, w_axis_y, w_axis_z, w_axis_w, ] } /// Creates a 4x4 matrix from a `[[f32; 4]; 4]` 4D array stored in column major order. /// 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]), Vec4::from_array(m[1]), Vec4::from_array(m[2]), Vec4::from_array(m[3]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), self.w_axis.to_array(), ] } /// 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(); Self::new( x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, w, ) } #[inline] #[must_use] fn quat_to_axes(rotation: Quat) -> (Vec4, Vec4, Vec4) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = Vec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = Vec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = Vec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne(Vec3::ZERO).all()); let inv_scale = scale.recip(); let rotation = Quat::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `Mat4::from_translation(translation) * Mat4::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self { Self::from_cols( Vec4::from((mat3.x_axis, 0.0)), Vec4::from((mat3.y_axis, 0.0)), Vec4::from((mat3.z_axis, 0.0)), Vec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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, Vec4::Y, Vec4::Z, Vec4::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # 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 (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( Vec4::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), Vec4::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), Vec4::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), Vec4::W, ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f32, f32, f32) { glam_assert!( self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized() ); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::X, Vec4::new(0.0, cosa, sina, 0.0), Vec4::new(0.0, -sina, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: f32) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( Vec4::new(cosa, 0.0, -sina, 0.0), Vec4::Y, Vec4::new(sina, 0.0, cosa, 0.0), Vec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: f32) -> Self { 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), Vec4::Z, Vec4::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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()); Self::from_cols( Vec4::new(scale.x, 0.0, 0.0, 0.0), Vec4::new(0.0, scale.y, 0.0, 0.0), Vec4::new(0.0, 0.0, scale.z, 0.0), Vec4::W, ) } /// Creates a 4x4 matrix from the first 16 values in `slice`. /// /// # Panics /// /// 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], slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15], ) } /// Writes the columns of `self` to the first 16 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 16 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f32]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.x_axis.w; slice[4] = self.y_axis.x; slice[5] = self.y_axis.y; slice[6] = self.y_axis.z; slice[7] = self.y_axis.w; slice[8] = self.z_axis.x; slice[9] = self.z_axis.y; slice[10] = self.z_axis.z; slice[11] = self.z_axis.w; slice[12] = self.w_axis.x; slice[13] = self.w_axis.y; slice[14] = self.w_axis.z; slice[15] = self.w_axis.w; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] #[must_use] pub fn col(&self, index: usize) -> Vec4 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, 3 => self.w_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut Vec4 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, 3 => &mut self.w_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => Vec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), 2 => Vec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), 3 => Vec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), _ => panic!("index out of bounds"), } } /// 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() && self.w_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() || self.w_axis.is_nan() } /// Returns the transpose of `self`. #[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); let tmp1 = i32x4_shuffle::<2, 3, 6, 7>(self.x_axis.0, self.y_axis.0); let tmp2 = i32x4_shuffle::<0, 1, 4, 5>(self.z_axis.0, self.w_axis.0); let tmp3 = i32x4_shuffle::<2, 3, 6, 7>(self.z_axis.0, self.w_axis.0); Self { x_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp0, tmp2)), y_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp0, tmp2)), z_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp1, tmp3)), w_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp1, tmp3)), } } /// 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); let swp3a = i32x4_shuffle::<3, 3, 2, 3>(self.w_axis.0, self.w_axis.0); let swp2b = i32x4_shuffle::<3, 3, 2, 3>(self.z_axis.0, self.z_axis.0); let swp3b = i32x4_shuffle::<2, 1, 1, 0>(self.w_axis.0, self.w_axis.0); let swp2c = i32x4_shuffle::<2, 1, 0, 0>(self.z_axis.0, self.z_axis.0); let swp3c = i32x4_shuffle::<0, 0, 2, 1>(self.w_axis.0, self.w_axis.0); let mula = f32x4_mul(swp2a, swp3a); let mulb = f32x4_mul(swp2b, swp3b); let mulc = f32x4_mul(swp2c, swp3c); let sube = f32x4_sub(mula, mulb); let subf = f32x4_sub(i32x4_shuffle::<6, 7, 2, 3>(mulc, mulc), mulc); let subfaca = i32x4_shuffle::<0, 0, 1, 2>(sube, sube); let swpfaca = i32x4_shuffle::<1, 0, 0, 0>(self.y_axis.0, self.y_axis.0); let mulfaca = f32x4_mul(swpfaca, subfaca); let subtmpb = i32x4_shuffle::<1, 3, 4, 4>(sube, subf); let subfacb = i32x4_shuffle::<0, 1, 1, 3>(subtmpb, subtmpb); let swpfacb = i32x4_shuffle::<2, 2, 1, 1>(self.y_axis.0, self.y_axis.0); let mulfacb = f32x4_mul(swpfacb, subfacb); let subres = f32x4_sub(mulfaca, mulfacb); let subtmpc = i32x4_shuffle::<2, 2, 4, 5>(sube, subf); let subfacc = i32x4_shuffle::<0, 2, 3, 3>(subtmpc, subtmpc); let swpfacc = i32x4_shuffle::<3, 3, 3, 2>(self.y_axis.0, self.y_axis.0); let mulfacc = f32x4_mul(swpfacc, subfacc); let addres = f32x4_add(subres, mulfacc); let detcof = f32x4_mul(addres, f32x4(1.0, -1.0, 1.0, -1.0)); dot4(self.x_axis.0, detcof) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[must_use] pub fn inverse(&self) -> Self { // Based on https://github.com/g-truc/glm `glm_mat4_inverse` let fac0 = { let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac1 = { let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac2 = { let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac3 = { let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac4 = { let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac5 = { let swp0a = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let sign_a = f32x4(-1.0, 1.0, -1.0, 1.0); let sign_b = f32x4(1.0, -1.0, 1.0, -1.0); let temp0 = i32x4_shuffle::<0, 0, 4, 4>(self.y_axis.0, self.x_axis.0); let vec0 = i32x4_shuffle::<0, 2, 6, 6>(temp0, temp0); let temp1 = i32x4_shuffle::<1, 1, 5, 5>(self.y_axis.0, self.x_axis.0); let vec1 = i32x4_shuffle::<0, 2, 6, 6>(temp1, temp1); let temp2 = i32x4_shuffle::<2, 2, 6, 6>(self.y_axis.0, self.x_axis.0); let vec2 = i32x4_shuffle::<0, 2, 6, 6>(temp2, temp2); let temp3 = i32x4_shuffle::<3, 3, 7, 7>(self.y_axis.0, self.x_axis.0); let vec3 = i32x4_shuffle::<0, 2, 6, 6>(temp3, temp3); let mul00 = f32x4_mul(vec1, fac0); let mul01 = f32x4_mul(vec2, fac1); let mul02 = f32x4_mul(vec3, fac2); let sub00 = f32x4_sub(mul00, mul01); let add00 = f32x4_add(sub00, mul02); let inv0 = f32x4_mul(sign_b, add00); let mul03 = f32x4_mul(vec0, fac0); let mul04 = f32x4_mul(vec2, fac3); let mul05 = f32x4_mul(vec3, fac4); let sub01 = f32x4_sub(mul03, mul04); let add01 = f32x4_add(sub01, mul05); let inv1 = f32x4_mul(sign_a, add01); let mul06 = f32x4_mul(vec0, fac1); let mul07 = f32x4_mul(vec1, fac3); let mul08 = f32x4_mul(vec3, fac5); let sub02 = f32x4_sub(mul06, mul07); let add02 = f32x4_add(sub02, mul08); let inv2 = f32x4_mul(sign_b, add02); let mul09 = f32x4_mul(vec0, fac2); let mul10 = f32x4_mul(vec1, fac4); let mul11 = f32x4_mul(vec2, fac5); let sub03 = f32x4_sub(mul09, mul10); let add03 = f32x4_add(sub03, mul11); let inv3 = f32x4_mul(sign_a, add03); let row0 = i32x4_shuffle::<0, 0, 4, 4>(inv0, inv1); let row1 = i32x4_shuffle::<0, 0, 4, 4>(inv2, inv3); let row2 = i32x4_shuffle::<0, 2, 4, 6>(row0, row1); let dot0 = dot4(self.x_axis.0, row2); glam_assert!(dot0 != 0.0); let rcp0 = f32x4_splat(dot0.recip()); Self { x_axis: Vec4(f32x4_mul(inv0, rcp0)), y_axis: Vec4(f32x4_mul(inv1, rcp0)), z_axis: Vec4(f32x4_mul(inv2, rcp0)), w_axis: Vec4(f32x4_mul(inv3, rcp0)), } } /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: Vec3, dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( Vec4::new(s.x, u.x, -f.x, 0.0), Vec4::new(s.y, u.y, -f.y, 0.0), Vec4::new(s.z, u.z, -f.z, 0.0), Vec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, f, 0.0, 0.0), Vec4::new(0.0, 0.0, b, -1.0), Vec4::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 1.0), Vec4::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, r, -1.0), Vec4::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 1.0, 1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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) = math::sin_cos(0.5 * fov_y_radians); let h = cos_fov / sin_fov; let w = h / aspect_ratio; Self::from_cols( Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(0.0, h, 0.0, 0.0), Vec4::new(0.0, 0.0, 0.0, 1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, -1.0, -1.0), Vec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: f32, aspect_ratio: f32, z_near: f32, ) -> Self { glam_assert!(z_near > 0.0); 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), Vec4::new(0.0, 0.0, 0.0, -1.0), Vec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( Vec4::new(a, 0.0, 0.0, 0.0), Vec4::new(0.0, b, 0.0, 0.0), Vec4::new(0.0, 0.0, c, 0.0), Vec4::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: f32, right: f32, bottom: f32, top: f32, near: f32, far: f32, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( Vec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), Vec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), Vec4::new(0.0, 0.0, r, 0.0), Vec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// 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); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction. /// /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A { let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); res = res.div(res.wwww()); Vec3A::from_vec4(res) } /// Transforms the given [`Vec3A`] as 3D point. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); Vec3A::from_vec4(res) } /// Transforms the give [`Vec3A`] as 3D vector. /// /// 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()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); Vec3A::from_vec4(res) } /// 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())); res = res.add(self.z_axis.mul(rhs.zzzz())); res = res.add(self.w_axis.mul(rhs.wwww())); res } /// Multiplies two 4x4 matrices. #[inline] #[must_use] pub fn mul_mat4(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), self.mul(rhs.w_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), self.w_axis.add(rhs.w_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), self.w_axis.sub(rhs.w_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), self.w_axis.mul(rhs), ) } /// Divides a 4x4 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f32) -> Self { let rhs = Vec4::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), self.w_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs(), self.w_axis.abs(), ) } #[inline] pub fn as_dmat4(&self) -> DMat4 { DMat4::from_cols( self.x_axis.as_dvec4(), self.y_axis.as_dvec4(), self.z_axis.as_dvec4(), self.w_axis.as_dvec4(), ) } } impl Default for Mat4 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for Mat4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat4(&rhs) } } impl AddAssign for Mat4 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat4(&rhs); } } impl Sub for Mat4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat4(&rhs) } } impl SubAssign for Mat4 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat4(&rhs); } } impl Neg for Mat4 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols( self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg(), self.w_axis.neg(), ) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat4(&rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat4(&rhs); } } impl Mul for Mat4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Self::Output { self.mul_vec4(rhs) } } impl Mul for f32 { type Output = Mat4; #[inline] fn mul(self, rhs: Mat4) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for Mat4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for Mat4 { #[inline] fn mul_assign(&mut self, rhs: f32) { *self = self.mul_scalar(rhs); } } impl Div for f32 { type Output = Mat4; #[inline] fn div(self, rhs: Mat4) -> Self::Output { rhs.div_scalar(self) } } impl Div for Mat4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for Mat4 { #[inline] fn div_assign(&mut self, rhs: f32) { *self = self.div_scalar(rhs); } } impl Sum for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Mat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Mat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for Mat4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) && self.w_axis.eq(&rhs.w_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 16]> for Mat4 { #[inline] fn as_ref(&self) -> &[f32; 16] { unsafe { &*(self as *const Self as *const [f32; 16]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 16]> for Mat4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 16] { unsafe { &mut *(self as *mut Self as *mut [f32; 16]) } } } impl fmt::Debug for Mat4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(Mat4)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .field("w_axis", &self.w_axis) .finish() } } impl fmt::Display for Mat4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis ) } else { write!( f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis ) } } } glam-0.30.1/src/f32/wasm32/quat.rs000064400000000000000000001035351046102023000144510ustar 00000000000000// Generated from quat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{EulerRot, FromEuler, ToEuler}, f32::math, wasm32::*, DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4, }; use core::arch::wasm32::*; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, Deref, DerefMut, Div, Mul, MulAssign, Neg, Sub}; /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// 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)] pub struct Quat(pub(crate) v128); impl Quat { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([f32::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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)) } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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]) } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: Vec4) -> Self { Self(v.0) } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// 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]) } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [f32]) { slice[0] = self.x; slice[1] = self.y; slice[2] = self.z; slice[3] = self.w; } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `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 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// 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) = 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) = 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) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// 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 { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: Vec3, y_axis: Vec3, z_axis: Vec3) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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 the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &Mat4) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPS: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::f32::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPSILON: f32 = 1.0 - 2.0 * f32::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: f32 = 0.0; const SIN_FRAC_PI_2: f32 = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: Vec3, up: Vec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: Vec3, up: Vec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( Vec3::new(s.x, u.x, -f.x), Vec3::new(s.y, u.y, -f.y), Vec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: Vec3, center: Vec3, up: Vec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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; 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, 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 } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> (f32, f32, f32) { self.to_euler_angles(order) } /// `[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. #[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)) } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f32 { Vec4::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> f32 { Vec4::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> f32 { Vec4::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4(Vec4::from(self).normalize()) } /// 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() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { Vec4::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// 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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// 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()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f32) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: f32) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[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()); const NEG_ZERO: v128 = v128_from_f32x4([-0.0; 4]); let dot = dot4_into_v128(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = v128_and(dot, NEG_ZERO); self.lerp_impl(Self(v128_xor(end.0, bias)), s) } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: f32 = 1.0 - f32::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); let scale1 = math::sin(theta * (1.0 - s)); let scale2 = math::sin(theta * s); let theta_sin = math::sin(theta); ((self * scale1) + (end * scale2)) * (1.0 / theta_sin) } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// 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()); self.mul_vec3a(rhs.into()).into() } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { let lhs = self.0; let rhs = rhs.0; const CONTROL_WZYX: v128 = v128_from_f32x4([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: v128 = v128_from_f32x4([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: v128 = v128_from_f32x4([-1.0, 1.0, 1.0, -1.0]); let r_xxxx = i32x4_shuffle::<0, 0, 4, 4>(lhs, lhs); let r_yyyy = i32x4_shuffle::<1, 1, 5, 5>(lhs, lhs); let r_zzzz = i32x4_shuffle::<2, 2, 6, 6>(lhs, lhs); let r_wwww = i32x4_shuffle::<3, 3, 7, 7>(lhs, lhs); let lxrw_lyrw_lzrw_lwrw = f32x4_mul(r_wwww, rhs); let l_wzyx = i32x4_shuffle::<3, 2, 5, 4>(rhs, rhs); let lwrx_lzrx_lyrx_lxrx = f32x4_mul(r_xxxx, l_wzyx); let l_zwxy = i32x4_shuffle::<1, 0, 7, 6>(l_wzyx, l_wzyx); let lwrx_nlzrx_lyrx_nlxrx = f32x4_mul(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX); let lzry_lwry_lxry_lyry = f32x4_mul(r_yyyy, l_zwxy); let l_yxwz = i32x4_shuffle::<3, 2, 5, 4>(l_zwxy, l_zwxy); let lzry_lwry_nlxry_nlyry = f32x4_mul(lzry_lwry_lxry_lyry, CONTROL_ZWXY); let lyrz_lxrz_lwrz_lzrz = f32x4_mul(r_zzzz, l_yxwz); let result0 = f32x4_add(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx); let nlyrz_lxrz_lwrz_wlzrz = f32x4_mul(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ); let result1 = f32x4_add(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz); Self(f32x4_add(result0, result1)) } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::Affine3A) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } /// 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); let b = self.0; let b2 = dot3_into_v128(b, b); Vec3A(f32x4_add( f32x4_add( f32x4_mul(rhs.0, f32x4_sub(f32x4_mul(w, w), b2)), f32x4_mul(b, f32x4_mul(dot3_into_v128(rhs.0, b), TWO)), ), f32x4_mul(Vec3A(b).cross(rhs).into(), f32x4_mul(w, TWO)), )) } #[inline] #[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) } } impl fmt::Debug for Quat { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Quat)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for Quat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add for Quat { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) + Vec4::from(rhs)) } } impl Sub for Quat { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4(Vec4::from(self) - Vec4::from(rhs)) } } impl Mul for Quat { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) * rhs) } } impl Div for Quat { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: f32) -> Self { Self::from_vec4(Vec4::from(self) / rhs) } } impl Mul for Quat { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign for Quat { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul for Quat { type Output = Vec3; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Vec3) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for Quat { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for Quat { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for Quat { #[inline] fn eq(&self, rhs: &Self) -> bool { Vec4::from(*self).eq(&Vec4::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Quat { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Self as *const [f32; 4]) } } } impl Sum for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Quat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for Quat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl Mul for Quat { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } impl From for Vec4 { #[inline] fn from(q: Quat) -> Self { Self(q.0) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for [f32; 4] { #[inline] fn from(q: Quat) -> Self { Vec4::from(q).into() } } impl From for v128 { #[inline] fn from(q: Quat) -> Self { q.0 } } impl Deref for Quat { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Quat { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } glam-0.30.1/src/f32/wasm32/vec3a.rs000064400000000000000000001457601046102023000145060ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, wasm32::*, BVec3, BVec3A, FloatExt, Quat, Vec2, Vec3, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; use core::arch::wasm32::*; /// 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. /// /// 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`] /// or [`Into`] trait implementations. /// /// This type is 16 byte aligned. #[derive(Clone, Copy)] #[repr(transparent)] pub struct Vec3A(pub(crate) v128); impl Vec3A { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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 { Self(f32x4(v, v, v, v)) } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: 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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 3); 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 [f32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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] #[must_use] pub 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// 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(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); let lhszxy_rhs = f32x4_mul(lhszxy, rhs.0); let rhszxy_lhs = f32x4_mul(rhszxy, self.0); let sub = f32x4_sub(lhszxy_rhs, rhszxy_lhs); Self(i32x4_shuffle::<2, 0, 1, 1>(sub, sub)) } /// 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)) } /// 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(f32x4_pmax(self.0, rhs.0)) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { let v = self.0; let v = f32x4_pmin(v, i32x4_shuffle::<2, 2, 1, 1>(v, v)); let v = f32x4_pmin(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// Returns the horizontal maximum of `self`. /// /// 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)); let v = f32x4_pmax(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { let v = self.0; let v = f32x4_add(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ZERO.0)); let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { let v = self.0; let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ONE.0)); let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// 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) -> BVec3A { BVec3A(f32x4_eq(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4_ne(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4_ge(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4_gt(self.0, rhs.0)) } /// 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) -> BVec3A { BVec3A(f32x4_le(self.0, rhs.0)) } /// 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) -> 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)) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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 { let result = Self(v128_or(v128_and(self.0, Self::NEG_ONE.0), Self::ONE.0)); let mask = self.is_nan_mask(); Self::select(mask, self, result) } /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { let mask = Self::splat(-0.0); Self(v128_or( v128_and(rhs.0, mask.0), v128_andnot(self.0, mask.0), )) } /// 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 { (u32x4_bitmask(self.0) & 0x7) as u32 } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3A { BVec3A(f32x4_lt(f32x4_abs(self.0), Self::INFINITY.0)) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec3A { BVec3A(f32x4_ne(self.0, self.0)) } /// 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)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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))) } /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { let length = f32x4_sqrt(dot3_into_v128(self.0, self.0)); #[allow(clippy::let_and_return)] let normalized = Self(f32x4_div(self.0, length)); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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)) } /// 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)) } /// 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 as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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)) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f32) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f32::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); Quat::from_axis_angle(axis.into(), angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f32) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize().into(); let rotation = Quat::from_axis_angle(axis, core::f32::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for Vec3A { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec3A { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(f32x4_div(self.0, rhs.0)) } } impl Div<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 = f32x4_div(self.0, rhs.0); } } impl DivAssign<&Vec3A> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &Vec3A) { self.div_assign(*rhs) } } impl Div for Vec3A { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(f32x4_div(self.0, f32x4_splat(rhs))) } } impl Div<&f32> for Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { self.div(*rhs) } } impl Div<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: &f32) -> Vec3A { (*self).div(*rhs) } } impl Div for &Vec3A { type Output = Vec3A; #[inline] fn div(self, rhs: f32) -> Vec3A { (*self).div(rhs) } } impl DivAssign for Vec3A { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 = f32x4_div(self.0, f32x4_splat(rhs)); } } impl DivAssign<&f32> for Vec3A { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4_div(f32x4_splat(self), rhs.0)) } } impl Div<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { self.div(*rhs) } } impl Div<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: &Vec3A) -> Vec3A { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec3A; #[inline] fn div(self, rhs: Vec3A) -> Vec3A { (*self).div(rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(f32x4_mul(self.0, rhs.0)) } } impl Mul<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 = f32x4_mul(self.0, rhs.0); } } impl MulAssign<&Vec3A> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &Vec3A) { self.mul_assign(*rhs) } } impl Mul for Vec3A { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(f32x4_mul(self.0, f32x4_splat(rhs))) } } impl Mul<&f32> for Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { self.mul(*rhs) } } impl Mul<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: &f32) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &Vec3A { type Output = Vec3A; #[inline] fn mul(self, rhs: f32) -> Vec3A { (*self).mul(rhs) } } impl MulAssign for Vec3A { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 = f32x4_mul(self.0, f32x4_splat(rhs)) } } impl MulAssign<&f32> for Vec3A { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4_mul(f32x4_splat(self), rhs.0)) } } impl Mul<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { self.mul(*rhs) } } impl Mul<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: &Vec3A) -> Vec3A { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { (*self).mul(rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(f32x4_add(self.0, rhs.0)) } } impl Add<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 = f32x4_add(self.0, rhs.0); } } impl AddAssign<&Vec3A> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &Vec3A) { self.add_assign(*rhs) } } impl Add for Vec3A { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(f32x4_add(self.0, f32x4_splat(rhs))) } } impl Add<&f32> for Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { self.add(*rhs) } } impl Add<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: &f32) -> Vec3A { (*self).add(*rhs) } } impl Add for &Vec3A { type Output = Vec3A; #[inline] fn add(self, rhs: f32) -> Vec3A { (*self).add(rhs) } } impl AddAssign for Vec3A { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 = f32x4_add(self.0, f32x4_splat(rhs)); } } impl AddAssign<&f32> for Vec3A { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4_add(f32x4_splat(self), rhs.0)) } } impl Add<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { self.add(*rhs) } } impl Add<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: &Vec3A) -> Vec3A { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec3A; #[inline] fn add(self, rhs: Vec3A) -> Vec3A { (*self).add(rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(f32x4_sub(self.0, rhs.0)) } } impl Sub<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: Vec3A) { self.0 = f32x4_sub(self.0, rhs.0); } } impl SubAssign<&Vec3A> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &Vec3A) { self.sub_assign(*rhs) } } impl Sub for Vec3A { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(f32x4_sub(self.0, f32x4_splat(rhs))) } } impl Sub<&f32> for Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { self.sub(*rhs) } } impl Sub<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: &f32) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &Vec3A { type Output = Vec3A; #[inline] fn sub(self, rhs: f32) -> Vec3A { (*self).sub(rhs) } } impl SubAssign for Vec3A { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 = f32x4_sub(self.0, f32x4_splat(rhs)) } } impl SubAssign<&f32> for Vec3A { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { Vec3A(f32x4_sub(f32x4_splat(self), rhs.0)) } } impl Sub<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { self.sub(*rhs) } } impl Sub<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: &Vec3A) -> Vec3A { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec3A; #[inline] fn sub(self, rhs: Vec3A) -> Vec3A { (*self).sub(rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { let n = f32x4_floor(f32x4_div(self.0, rhs.0)); Self(f32x4_sub(self.0, f32x4_mul(n, rhs.0))) } } impl Rem<&Vec3A> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = self.rem(rhs); } } impl RemAssign<&Vec3A> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &Vec3A) { self.rem_assign(*rhs) } } impl Rem for Vec3A { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { self.rem(*rhs) } } impl Rem<&f32> for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: &f32) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &Vec3A { type Output = Vec3A; #[inline] fn rem(self, rhs: f32) -> Vec3A { (*self).rem(rhs) } } impl RemAssign for Vec3A { #[inline] fn rem_assign(&mut self, rhs: f32) { *self = self.rem(Self::splat(rhs)); } } impl RemAssign<&f32> for Vec3A { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { Vec3A::splat(self).rem(rhs) } } impl Rem<&Vec3A> for f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { self.rem(*rhs) } } impl Rem<&Vec3A> for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: &Vec3A) -> Vec3A { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec3A; #[inline] fn rem(self, rhs: Vec3A) -> Vec3A { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 3]> for Vec3A { #[inline] fn as_ref(&self) -> &[f32; 3] { unsafe { &*(self as *const Vec3A as *const [f32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 3]> for Vec3A { #[inline] fn as_mut(&mut self) -> &mut [f32; 3] { unsafe { &mut *(self as *mut Vec3A as *mut [f32; 3]) } } } impl Sum for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec3A { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec3A { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec3A { type Output = Self; #[inline] fn neg(self) -> Self { Self(f32x4_neg(self.0)) } } impl Neg for &Vec3A { type Output = Vec3A; #[inline] fn neg(self) -> Vec3A { (*self).neg() } } impl Index for Vec3A { type Output = f32; #[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 for Vec3A { #[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"), } } } impl fmt::Display for Vec3A { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for Vec3A { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec3A)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From for v128 { #[inline(always)] fn from(t: Vec3A) -> Self { t.0 } } impl From for Vec3A { #[inline(always)] fn from(t: v128) -> Self { Self(t) } } impl From<[f32; 3]> for Vec3A { #[inline] fn from(a: [f32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f32; 3] { #[inline] fn from(v: Vec3A) -> Self { unsafe { *(&v.0 as *const v128 as *const Self) } } } impl From<(f32, f32, f32)> for Vec3A { #[inline] fn from(t: (f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f32, f32, f32) { #[inline] fn from(v: Vec3A) -> Self { unsafe { *(&v.0 as *const v128 as *const Self) } } } impl From for Vec3A { #[inline] fn from(v: Vec3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for Vec3 { #[inline] fn from(v: Vec3A) -> Self { unsafe { *(&v.0 as *const v128 as *const Self) } } } impl From<(Vec2, f32)> for Vec3A { #[inline] fn from((v, z): (Vec2, f32)) -> Self { Self::new(v.x, v.y, z) } } impl Deref for Vec3A { type Target = crate::deref::Vec3; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec3A { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec3A { #[inline] fn from(v: BVec3) -> Self { Self::new(f32::from(v.x), f32::from(v.y), f32::from(v.z)) } } impl From for Vec3A { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), ) } } glam-0.30.1/src/f32/wasm32/vec4.rs000064400000000000000000001344621046102023000143430ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f32::math, wasm32::*, BVec4, BVec4A, Vec2, Vec3, Vec3A}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; use core::arch::wasm32::*; /// 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. /// /// 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); impl Vec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); /// 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 vector pointing along the positive W axis. pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); /// 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 vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); /// 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 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. 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: 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 { Self(f32x4(v, v, v, v)) } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f32) -> f32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: 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]) } } /// 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: &[f32]) -> Self { assert!(slice.len() >= 4); 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 [f32]) { slice[..4].copy_from_slice(&self.to_array()); } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. /// /// To truncate to [`Vec3A`] use [`Vec3A::from_vec4()`]. #[inline] #[must_use] pub fn truncate(self) -> Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: f32) -> Self { self.w = w; self } /// 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(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)) } /// 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(f32x4_pmax(self.0, rhs.0)) } /// Component-wise clamping of values, similar to [`f32::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) -> f32 { let v = self.0; let v = f32x4_pmin(v, i32x4_shuffle::<2, 3, 0, 0>(v, v)); let v = f32x4_pmin(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// Returns the horizontal maximum of `self`. /// /// 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)); let v = f32x4_pmax(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f32 { let v = self.0; let v = f32x4_add(v, i32x4_shuffle::<1, 0, 3, 0>(v, v)); let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f32 { let v = self.0; let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 3, 0>(v, v)); let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) } /// 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) -> BVec4A { BVec4A(f32x4_eq(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4_ne(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4_ge(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4_gt(self.0, rhs.0)) } /// 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) -> BVec4A { BVec4A(f32x4_le(self.0, rhs.0)) } /// 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) -> 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)) } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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 { let result = Self(v128_or(v128_and(self.0, Self::NEG_ONE.0), Self::ONE.0)); let mask = self.is_nan_mask(); Self::select(mask, self, result) } /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { let mask = Self::splat(-0.0); Self(v128_or( v128_and(rhs.0, mask.0), v128_andnot(self.0, mask.0), )) } /// 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 { u32x4_bitmask(self.0) as u32 } /// 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.is_finite_mask().all() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec4A { BVec4A(f32x4_lt(f32x4_abs(self.0), Self::INFINITY.0)) } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { self.is_nan_mask().any() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec4A { BVec4A(f32x4_ne(self.0, self.0)) } /// 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)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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))) } /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { let length = f32x4_sqrt(dot4_into_v128(self.0, self.0)); #[allow(clippy::let_and_return)] let normalized = Self(f32x4_div(self.0, length)); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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)) } /// 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)) } /// 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 as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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)) } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f32) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f32) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f32, max: f32) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f32) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f32) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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), ) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f32) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } } impl Default for Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl PartialEq for Vec4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self(f32x4_div(self.0, rhs.0)) } } impl Div<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: Self) { self.0 = f32x4_div(self.0, rhs.0); } } impl DivAssign<&Vec4> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &Vec4) { self.div_assign(*rhs) } } impl Div for Vec4 { type Output = Self; #[inline] fn div(self, rhs: f32) -> Self { Self(f32x4_div(self.0, f32x4_splat(rhs))) } } impl Div<&f32> for Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { self.div(*rhs) } } impl Div<&f32> for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: &f32) -> Vec4 { (*self).div(*rhs) } } impl Div for &Vec4 { type Output = Vec4; #[inline] fn div(self, rhs: f32) -> Vec4 { (*self).div(rhs) } } impl DivAssign for Vec4 { #[inline] fn div_assign(&mut self, rhs: f32) { self.0 = f32x4_div(self.0, f32x4_splat(rhs)); } } impl DivAssign<&f32> for Vec4 { #[inline] fn div_assign(&mut self, rhs: &f32) { self.div_assign(*rhs) } } impl Div for f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { Vec4(f32x4_div(f32x4_splat(self), rhs.0)) } } impl Div<&Vec4> for f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { self.div(*rhs) } } impl Div<&Vec4> for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: &Vec4) -> Vec4 { (*self).div(*rhs) } } impl Div for &f32 { type Output = Vec4; #[inline] fn div(self, rhs: Vec4) -> Vec4 { (*self).div(rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self(f32x4_mul(self.0, rhs.0)) } } impl Mul<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.0 = f32x4_mul(self.0, rhs.0); } } impl MulAssign<&Vec4> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &Vec4) { self.mul_assign(*rhs) } } impl Mul for Vec4 { type Output = Self; #[inline] fn mul(self, rhs: f32) -> Self { Self(f32x4_mul(self.0, f32x4_splat(rhs))) } } impl Mul<&f32> for Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { self.mul(*rhs) } } impl Mul<&f32> for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: &f32) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &Vec4 { type Output = Vec4; #[inline] fn mul(self, rhs: f32) -> Vec4 { (*self).mul(rhs) } } impl MulAssign for Vec4 { #[inline] fn mul_assign(&mut self, rhs: f32) { self.0 = f32x4_mul(self.0, f32x4_splat(rhs)) } } impl MulAssign<&f32> for Vec4 { #[inline] fn mul_assign(&mut self, rhs: &f32) { self.mul_assign(*rhs) } } impl Mul for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { Vec4(f32x4_mul(f32x4_splat(self), rhs.0)) } } impl Mul<&Vec4> for f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { self.mul(*rhs) } } impl Mul<&Vec4> for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: &Vec4) -> Vec4 { (*self).mul(*rhs) } } impl Mul for &f32 { type Output = Vec4; #[inline] fn mul(self, rhs: Vec4) -> Vec4 { (*self).mul(rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self(f32x4_add(self.0, rhs.0)) } } impl Add<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: Self) { self.0 = f32x4_add(self.0, rhs.0); } } impl AddAssign<&Vec4> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &Vec4) { self.add_assign(*rhs) } } impl Add for Vec4 { type Output = Self; #[inline] fn add(self, rhs: f32) -> Self { Self(f32x4_add(self.0, f32x4_splat(rhs))) } } impl Add<&f32> for Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { self.add(*rhs) } } impl Add<&f32> for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: &f32) -> Vec4 { (*self).add(*rhs) } } impl Add for &Vec4 { type Output = Vec4; #[inline] fn add(self, rhs: f32) -> Vec4 { (*self).add(rhs) } } impl AddAssign for Vec4 { #[inline] fn add_assign(&mut self, rhs: f32) { self.0 = f32x4_add(self.0, f32x4_splat(rhs)); } } impl AddAssign<&f32> for Vec4 { #[inline] fn add_assign(&mut self, rhs: &f32) { self.add_assign(*rhs) } } impl Add for f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { Vec4(f32x4_add(f32x4_splat(self), rhs.0)) } } impl Add<&Vec4> for f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { self.add(*rhs) } } impl Add<&Vec4> for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: &Vec4) -> Vec4 { (*self).add(*rhs) } } impl Add for &f32 { type Output = Vec4; #[inline] fn add(self, rhs: Vec4) -> Vec4 { (*self).add(rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self(f32x4_sub(self.0, rhs.0)) } } impl Sub<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: Vec4) { self.0 = f32x4_sub(self.0, rhs.0); } } impl SubAssign<&Vec4> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &Vec4) { self.sub_assign(*rhs) } } impl Sub for Vec4 { type Output = Self; #[inline] fn sub(self, rhs: f32) -> Self { Self(f32x4_sub(self.0, f32x4_splat(rhs))) } } impl Sub<&f32> for Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { self.sub(*rhs) } } impl Sub<&f32> for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: &f32) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &Vec4 { type Output = Vec4; #[inline] fn sub(self, rhs: f32) -> Vec4 { (*self).sub(rhs) } } impl SubAssign for Vec4 { #[inline] fn sub_assign(&mut self, rhs: f32) { self.0 = f32x4_sub(self.0, f32x4_splat(rhs)) } } impl SubAssign<&f32> for Vec4 { #[inline] fn sub_assign(&mut self, rhs: &f32) { self.sub_assign(*rhs) } } impl Sub for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { Vec4(f32x4_sub(f32x4_splat(self), rhs.0)) } } impl Sub<&Vec4> for f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { self.sub(*rhs) } } impl Sub<&Vec4> for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: &Vec4) -> Vec4 { (*self).sub(*rhs) } } impl Sub for &f32 { type Output = Vec4; #[inline] fn sub(self, rhs: Vec4) -> Vec4 { (*self).sub(rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { let n = f32x4_floor(f32x4_div(self.0, rhs.0)); Self(f32x4_sub(self.0, f32x4_mul(n, rhs.0))) } } impl Rem<&Vec4> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: Self) { *self = self.rem(rhs); } } impl RemAssign<&Vec4> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &Vec4) { self.rem_assign(*rhs) } } impl Rem for Vec4 { type Output = Self; #[inline] fn rem(self, rhs: f32) -> Self { self.rem(Self::splat(rhs)) } } impl Rem<&f32> for Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { self.rem(*rhs) } } impl Rem<&f32> for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: &f32) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &Vec4 { type Output = Vec4; #[inline] fn rem(self, rhs: f32) -> Vec4 { (*self).rem(rhs) } } impl RemAssign for Vec4 { #[inline] fn rem_assign(&mut self, rhs: f32) { *self = self.rem(Self::splat(rhs)); } } impl RemAssign<&f32> for Vec4 { #[inline] fn rem_assign(&mut self, rhs: &f32) { self.rem_assign(*rhs) } } impl Rem for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { Vec4::splat(self).rem(rhs) } } impl Rem<&Vec4> for f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { self.rem(*rhs) } } impl Rem<&Vec4> for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: &Vec4) -> Vec4 { (*self).rem(*rhs) } } impl Rem for &f32 { type Output = Vec4; #[inline] fn rem(self, rhs: Vec4) -> Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f32; 4]> for Vec4 { #[inline] fn as_ref(&self) -> &[f32; 4] { unsafe { &*(self as *const Vec4 as *const [f32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f32; 4]> for Vec4 { #[inline] fn as_mut(&mut self) -> &mut [f32; 4] { unsafe { &mut *(self as *mut Vec4 as *mut [f32; 4]) } } } impl Sum for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for Vec4 { type Output = Self; #[inline] fn neg(self) -> Self { Self(f32x4_neg(self.0)) } } impl Neg for &Vec4 { type Output = Vec4; #[inline] fn neg(self) -> Vec4 { (*self).neg() } } impl Index for Vec4 { type Output = f32; #[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 for Vec4 { #[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"), } } } impl fmt::Display for Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl fmt::Debug for Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From for v128 { #[inline(always)] fn from(t: Vec4) -> Self { t.0 } } impl From for Vec4 { #[inline(always)] fn from(t: v128) -> Self { Self(t) } } impl From<[f32; 4]> for Vec4 { #[inline] fn from(a: [f32; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [f32; 4] { #[inline] fn from(v: Vec4) -> Self { unsafe { *(&v.0 as *const v128 as *const Self) } } } impl From<(f32, f32, f32, f32)> for Vec4 { #[inline] fn from(t: (f32, f32, f32, f32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (f32, f32, f32, f32) { #[inline] fn from(v: Vec4) -> Self { unsafe { *(&v.0 as *const v128 as *const Self) } } } impl From<(Vec3A, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3A, f32)) -> Self { v.extend(w) } } impl From<(f32, Vec3A)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3A)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec3, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3, f32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(f32, Vec3)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(Vec2, f32, f32)> for Vec4 { #[inline] fn from((v, z, w): (Vec2, f32, f32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(Vec2, Vec2)> for Vec4 { #[inline] fn from((v, u): (Vec2, Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl Deref for Vec4 { type Target = crate::deref::Vec4; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for Vec4 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } impl From for Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( f32::from(v.x), f32::from(v.y), f32::from(v.z), f32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( f32::from(bool_array[0]), f32::from(bool_array[1]), f32::from(bool_array[2]), f32::from(bool_array[3]), ) } } glam-0.30.1/src/f32/wasm32.rs000064400000000000000000000001261046102023000134670ustar 00000000000000pub mod mat2; pub mod mat3a; pub mod mat4; pub mod quat; pub mod vec3a; pub mod vec4; glam-0.30.1/src/f32.rs000064400000000000000000000115011046102023000123520ustar 00000000000000mod affine2; mod affine3a; mod float; mod mat3; pub(crate) mod math; mod vec2; mod vec3; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] mod coresimd; #[cfg(any( not(any( feature = "core-simd", target_arch = "aarch64", target_feature = "sse2", target_feature = "simd128" )), feature = "scalar-math" ))] mod scalar; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod neon; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod sse2; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod wasm32; #[cfg(any( not(any( feature = "core-simd", target_arch = "aarch64", target_feature = "sse2", target_feature = "simd128" )), feature = "scalar-math" ))] use scalar::*; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] use neon::*; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] use sse2::*; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] use wasm32::*; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] use coresimd::*; pub use affine2::Affine2; pub use affine3a::Affine3A; pub use mat2::{mat2, Mat2}; pub use mat3::{mat3, Mat3}; pub use mat3a::{mat3a, Mat3A}; pub use mat4::{mat4, Mat4}; pub use quat::{quat, Quat}; pub use vec2::{vec2, Vec2}; pub use vec3::{vec3, Vec3}; pub use vec3a::{vec3a, Vec3A}; pub use vec4::{vec4, Vec4}; #[cfg(not(target_arch = "spirv"))] mod test { use super::*; #[cfg(all(not(feature = "cuda"), feature = "scalar-math"))] mod const_test_affine2 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(24, core::mem::size_of::()); } #[cfg(not(feature = "scalar-math"))] mod const_test_affine2 { const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(32, core::mem::size_of::()); } mod const_test_mat2 { #[cfg(feature = "scalar-math")] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(not(any(feature = "scalar-math", target_arch = "spirv")))] const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } mod const_test_mat3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(36, core::mem::size_of::()); } mod const_test_mat3a { const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(48, core::mem::size_of::()); } mod const_test_mat4 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(64, core::mem::size_of::()); } mod const_test_quat { #[cfg(feature = "scalar-math")] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(not(any(feature = "scalar-math", target_arch = "spirv")))] const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } mod const_test_vec2 { #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(8, core::mem::align_of::()); const_assert_eq!(8, core::mem::size_of::()); } mod const_test_vec3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(12, core::mem::size_of::()); } mod const_test_vec3a { const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } mod const_test_vec4 { #[cfg(all(feature = "scalar-math", not(feature = "cuda")))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(not(feature = "scalar-math"))] const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } } glam-0.30.1/src/f64/daffine2.rs000064400000000000000000000276511046102023000140520ustar 00000000000000// Generated from affine.rs.tera template. Edit the template, not the generated file. use crate::{DMat2, DMat3, DVec2}; use core::ops::{Deref, DerefMut, Mul, MulAssign}; /// A 2D affine transform, which can represent translation, rotation, scaling and shear. #[derive(Copy, Clone)] #[repr(C)] pub struct DAffine2 { pub matrix2: DMat2, pub translation: DVec2, } impl DAffine2 { /// The degenerate zero transform. /// /// This transforms any finite vector and point to zero. /// The zero transform is non-invertible. pub const ZERO: Self = Self { matrix2: DMat2::ZERO, translation: DVec2::ZERO, }; /// The identity transform. /// /// Multiplying a vector with this returns the same vector. pub const IDENTITY: Self = Self { matrix2: DMat2::IDENTITY, translation: DVec2::ZERO, }; /// All NAN:s. pub const NAN: Self = Self { matrix2: DMat2::NAN, translation: DVec2::NAN, }; /// 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), translation: z_axis, } } /// 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_array(&[m[0], m[1], m[2], m[3]]), translation: DVec2::from_array([m[4], m[5]]), } } /// 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; let z = &self.translation; [x.x, x.y, y.x, y.y, z.x, z.y] } /// Creates an affine transform from a `[[f64; 2]; 3]` /// 2D array stored in column major order. /// 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()), translation: m[2].into(), } } /// Creates a `[[f64; 2]; 3]` 2D array storing data in /// 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(), self.matrix2.y_axis.into(), self.translation.into(), ] } /// Creates an affine transform from the first 6 values in `slice`. /// /// # Panics /// /// 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]), translation: DVec2::from_slice(&slice[4..6]), } } /// Writes the columns of `self` to the first 6 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 6 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f64]) { self.matrix2.write_cols_to_slice(&mut slice[0..4]); self.translation.write_to_slice(&mut slice[4..6]); } /// 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), translation: DVec2::ZERO, } } /// 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), translation: DVec2::ZERO, } } /// Creates an affine transformation from the given 2D `translation`. #[inline] #[must_use] pub fn from_translation(translation: DVec2) -> Self { Self { matrix2: DMat2::IDENTITY, translation, } } /// 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, translation: DVec2::ZERO, } } /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a /// translation vector. /// /// 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, translation, } } /// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and /// `translation`. /// /// 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 { matrix2: DMat2::from_cols(rotation.x_axis * scale.x, rotation.y_axis * scale.y), translation, } } /// Creates an affine transform from the given 2D rotation `angle` (in radians) and /// `translation`. /// /// 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), translation, } } /// The given `DMat3` must be an affine transform, #[inline] #[must_use] pub fn from_mat3(m: DMat3) -> Self { use crate::swizzles::Vec3Swizzles; Self { matrix2: DMat2::from_cols(m.x_axis.xy(), m.y_axis.xy()), translation: m.z_axis.xy(), } } /// 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 } /// Transforms the given 2D vector, applying shear, scale and rotation (but NOT /// translation). /// /// To also apply translation, use [`Self::transform_point2()`] instead. #[inline] pub fn transform_vector2(&self, rhs: DVec2) -> DVec2 { self.matrix2 * rhs } /// 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.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() } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two 3x4 matrices contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Return the inverse of this transform. /// /// Note that if the transform is not invertible the result will be invalid. #[inline] #[must_use] pub fn inverse(&self) -> Self { let matrix2 = self.matrix2.inverse(); // transform negative translation by the matrix inverse: let translation = -(matrix2 * self.translation); Self { matrix2, translation, } } } impl Default for DAffine2 { #[inline(always)] fn default() -> Self { Self::IDENTITY } } impl Deref for DAffine2 { type Target = crate::deref::Cols3; #[inline(always)] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl DerefMut for DAffine2 { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl PartialEq for DAffine2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.matrix2.eq(&rhs.matrix2) && self.translation.eq(&rhs.translation) } } impl core::fmt::Debug for DAffine2 { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fmt.debug_struct(stringify!(DAffine2)) .field("matrix2", &self.matrix2) .field("translation", &self.translation) .finish() } } impl core::fmt::Display for DAffine2 { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation ) } else { write!( f, "[{}, {}, {}]", self.matrix2.x_axis, self.matrix2.y_axis, self.translation ) } } } impl<'a> core::iter::Product<&'a Self> for DAffine2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| a * b) } } impl Mul for DAffine2 { type Output = DAffine2; #[inline] fn mul(self, rhs: DAffine2) -> Self::Output { Self { matrix2: self.matrix2 * rhs.matrix2, translation: self.matrix2 * rhs.translation + self.translation, } } } impl MulAssign for DAffine2 { #[inline] fn mul_assign(&mut self, rhs: DAffine2) { *self = self.mul(rhs); } } impl From for DMat3 { #[inline] fn from(m: DAffine2) -> DMat3 { Self::from_cols( m.matrix2.x_axis.extend(0.0), m.matrix2.y_axis.extend(0.0), m.translation.extend(1.0), ) } } impl Mul for DAffine2 { type Output = DMat3; #[inline] fn mul(self, rhs: DMat3) -> Self::Output { DMat3::from(self) * rhs } } impl Mul for DMat3 { type Output = DMat3; #[inline] fn mul(self, rhs: DAffine2) -> Self::Output { self * DMat3::from(rhs) } } glam-0.30.1/src/f64/daffine3.rs000064400000000000000000000415311046102023000140440ustar 00000000000000// 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, MulAssign}; /// A 3D affine transform, which can represent translation, rotation, scaling and shear. #[derive(Copy, Clone)] #[repr(C)] pub struct DAffine3 { pub matrix3: DMat3, pub translation: DVec3, } impl DAffine3 { /// The degenerate zero transform. /// /// This transforms any finite vector and point to zero. /// The zero transform is non-invertible. pub const ZERO: Self = Self { matrix3: DMat3::ZERO, translation: DVec3::ZERO, }; /// The identity transform. /// /// Multiplying a vector with this returns the same vector. pub const IDENTITY: Self = Self { matrix3: DMat3::IDENTITY, translation: DVec3::ZERO, }; /// All NAN:s. pub const NAN: Self = Self { matrix3: DMat3::NAN, translation: DVec3::NAN, }; /// 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), translation: w_axis, } } /// 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_array(&[ m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], ]), translation: DVec3::from_array([m[9], m[10], m[11]]), } } /// 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; let z = &self.matrix3.z_axis; let w = &self.translation; [x.x, x.y, x.z, y.x, y.y, y.z, z.x, z.y, z.z, w.x, w.y, w.z] } /// Creates an affine transform from a `[[f64; 3]; 4]` /// 3D array stored in column major order. /// 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()), translation: m[3].into(), } } /// Creates a `[[f64; 3]; 4]` 3D array storing data in /// 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(), self.matrix3.y_axis.into(), self.matrix3.z_axis.into(), self.translation.into(), ] } /// Creates an affine transform from the first 12 values in `slice`. /// /// # Panics /// /// 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]), translation: DVec3::from_slice(&slice[9..12]), } } /// Writes the columns of `self` to the first 12 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 12 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f64]) { self.matrix3.write_cols_to_slice(&mut slice[0..9]); self.translation.write_to_slice(&mut slice[9..12]); } /// 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), translation: DVec3::ZERO, } } /// 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), translation: DVec3::ZERO, } } /// 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), translation: DVec3::ZERO, } } /// 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), translation: DVec3::ZERO, } } /// 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), translation: DVec3::ZERO, } } /// 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), translation: DVec3::ZERO, } } /// Creates an affine transformation from the given 3D `translation`. #[inline] #[must_use] pub fn from_translation(translation: DVec3) -> Self { #[allow(clippy::useless_conversion)] Self { matrix3: DMat3::IDENTITY, translation: translation.into(), } } /// 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 { matrix3: mat3.into(), translation: DVec3::ZERO, } } /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation) /// and a translation vector. /// /// 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 { matrix3: mat3.into(), translation: translation.into(), } } /// Creates an affine transform from the given 3D `scale`, `rotation` and /// `translation`. /// /// 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, translation: DVec3, ) -> Self { let rotation = DMat3::from_quat(rotation); #[allow(clippy::useless_conversion)] Self { matrix3: DMat3::from_cols( rotation.x_axis * scale.x, rotation.y_axis * scale.y, rotation.z_axis * scale.z, ), translation: translation.into(), } } /// Creates an affine transform from the given 3D `rotation` and `translation`. /// /// 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 { matrix3: DMat3::from_quat(rotation), translation: translation.into(), } } /// 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( DVec3::from_vec4(m.x_axis), DVec3::from_vec4(m.y_axis), DVec3::from_vec4(m.z_axis), ), translation: DVec3::from_vec4(m.w_axis), } } /// Extracts `scale`, `rotation` 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.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) { use crate::f64::math; let det = self.matrix3.determinant(); glam_assert!(det != 0.0); let scale = DVec3::new( self.matrix3.x_axis.length() * math::signum(det), self.matrix3.y_axis.length(), self.matrix3.z_axis.length(), ); glam_assert!(scale.cmpne(DVec3::ZERO).all()); let inv_scale = scale.recip(); #[allow(clippy::useless_conversion)] let rotation = DQuat::from_mat3(&DMat3::from_cols( (self.matrix3.x_axis * inv_scale.x).into(), (self.matrix3.y_axis * inv_scale.y).into(), (self.matrix3.z_axis * inv_scale.z).into(), )); #[allow(clippy::useless_conversion)] (scale, rotation, self.translation.into()) } /// Creates a left-handed view transform using a camera position, an up direction, and a facing /// direction. /// /// 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) } /// Creates a right-handed view transform using a camera position, an up direction, and a facing /// direction. /// /// 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(); let u = s.cross(f); Self { matrix3: DMat3::from_cols( DVec3::new(s.x, u.x, -f.x), DVec3::new(s.y, u.y, -f.y), DVec3::new(s.z, u.z, -f.z), ), translation: DVec3::new(-eye.dot(s), -eye.dot(u), eye.dot(f)), } } /// Creates a left-handed view transform using a camera position, an up direction, and a focal /// point. /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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) } /// Creates a right-handed view transform using a camera position, an up direction, and a focal /// point. /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// 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) } /// Transforms the given 3D points, applying shear, scale, rotation and translation. #[inline] pub fn transform_point3(&self, rhs: DVec3) -> DVec3 { #[allow(clippy::useless_conversion)] ((self.matrix3.x_axis * rhs.x) + (self.matrix3.y_axis * rhs.y) + (self.matrix3.z_axis * rhs.z) + self.translation) .into() } /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT /// translation). /// /// 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) + (self.matrix3.y_axis * rhs.y) + (self.matrix3.z_axis * rhs.z)) .into() } /// 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.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() } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two 3x4 matrices contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Return the inverse of this transform. /// /// Note that if the transform is not invertible the result will be invalid. #[inline] #[must_use] pub fn inverse(&self) -> Self { let matrix3 = self.matrix3.inverse(); // transform negative translation by the matrix inverse: let translation = -(matrix3 * self.translation); Self { matrix3, translation, } } } impl Default for DAffine3 { #[inline(always)] fn default() -> Self { Self::IDENTITY } } impl Deref for DAffine3 { type Target = crate::deref::Cols4; #[inline(always)] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl DerefMut for DAffine3 { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl PartialEq for DAffine3 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.matrix3.eq(&rhs.matrix3) && self.translation.eq(&rhs.translation) } } impl core::fmt::Debug for DAffine3 { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fmt.debug_struct(stringify!(DAffine3)) .field("matrix3", &self.matrix3) .field("translation", &self.translation) .finish() } } impl core::fmt::Display for DAffine3 { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.matrix3.x_axis, p, self.matrix3.y_axis, p, self.matrix3.z_axis, p, self.translation ) } else { write!( f, "[{}, {}, {}, {}]", self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation ) } } } impl<'a> core::iter::Product<&'a Self> for DAffine3 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| a * b) } } impl Mul for DAffine3 { type Output = DAffine3; #[inline] fn mul(self, rhs: DAffine3) -> Self::Output { Self { matrix3: self.matrix3 * rhs.matrix3, translation: self.matrix3 * rhs.translation + self.translation, } } } impl MulAssign for DAffine3 { #[inline] fn mul_assign(&mut self, rhs: DAffine3) { *self = self.mul(rhs); } } impl From for DMat4 { #[inline] fn from(m: DAffine3) -> DMat4 { DMat4::from_cols( m.matrix3.x_axis.extend(0.0), m.matrix3.y_axis.extend(0.0), m.matrix3.z_axis.extend(0.0), m.translation.extend(1.0), ) } } impl Mul for DAffine3 { type Output = DMat4; #[inline] fn mul(self, rhs: DMat4) -> Self::Output { DMat4::from(self) * rhs } } impl Mul for DMat4 { type Output = DMat4; #[inline] fn mul(self, rhs: DAffine3) -> Self::Output { self * DMat4::from(rhs) } } glam-0.30.1/src/f64/dmat2.rs000064400000000000000000000345171046102023000134020ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{f64::math, swizzles::*, DMat3, DVec2, Mat2}; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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) } /// A 2x2 column major matrix. #[derive(Clone, Copy)] #[cfg_attr(feature = "cuda", repr(align(16)))] #[repr(C)] pub struct DMat2 { pub x_axis: DVec2, pub y_axis: DVec2, } impl DMat2 { /// A 2x2 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(DVec2::ZERO, DVec2::ZERO); /// A 2x2 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(DVec2::X, DVec2::Y); /// All NAN:s. pub const NAN: Self = Self::from_cols(DVec2::NAN, DVec2::NAN); #[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), y_axis: DVec2::new(m10, m11), } } /// 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 } } /// Creates a 2x2 matrix from a `[f64; 4]` array stored in column major order. /// 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]) } /// 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] } /// Creates a 2x2 matrix from a `[[f64; 2]; 2]` 2D array stored in column major order. /// 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])) } /// 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()] } /// 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) } /// 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) = 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) = 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()) } /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3_minor(m: DMat3, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } /// Creates a 2x2 matrix from the first 4 values in `slice`. /// /// # Panics /// /// 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]) } /// Writes the columns of `self` to the first 4 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 4 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f64]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.y_axis.x; slice[3] = self.y_axis.y; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] #[must_use] pub fn col(&self, index: usize) -> DVec2 { match index { 0 => self.x_axis, 1 => self.y_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 1. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut DVec2 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => DVec2::new(self.x_axis.y, self.y_axis.y), _ => panic!("index out of bounds"), } } /// 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`. #[inline] #[must_use] pub fn transpose(&self) -> Self { Self { x_axis: DVec2::new(self.x_axis.x, self.y_axis.x), y_axis: DVec2::new(self.x_axis.y, self.y_axis.y), } } /// 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 } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(&self) -> Self { let inv_det = { let det = self.determinant(); glam_assert!(det != 0.0); det.recip() }; Self::new( self.y_axis.y * inv_det, self.x_axis.y * -inv_det, self.y_axis.x * -inv_det, self.x_axis.x * inv_det, ) } /// Transforms a 2D vector. #[inline] #[must_use] pub fn mul_vec2(&self, rhs: DVec2) -> DVec2 { #[allow(clippy::suspicious_operation_groupings)] DVec2::new( (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y), (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y), ) } /// 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)) } /// Divides a 2x2 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f64) -> Self { let rhs = DVec2::splat(rhs); Self::from_cols(self.x_axis.div(rhs), self.y_axis.div(rhs)) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs()) } #[inline] pub fn as_mat2(&self) -> Mat2 { Mat2::from_cols(self.x_axis.as_vec2(), self.y_axis.as_vec2()) } } impl Default for DMat2 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for DMat2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat2(&rhs) } } impl AddAssign for DMat2 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat2(&rhs); } } impl Sub for DMat2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat2(&rhs) } } impl SubAssign for DMat2 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat2(&rhs); } } impl Neg for DMat2 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg()) } } impl Mul for DMat2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat2(&rhs) } } impl MulAssign for DMat2 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat2(&rhs); } } impl Mul for DMat2 { type Output = DVec2; #[inline] fn mul(self, rhs: DVec2) -> Self::Output { self.mul_vec2(rhs) } } impl Mul for f64 { type Output = DMat2; #[inline] fn mul(self, rhs: DMat2) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for DMat2 { type Output = Self; #[inline] fn mul(self, rhs: f64) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for DMat2 { #[inline] fn mul_assign(&mut self, rhs: f64) { *self = self.mul_scalar(rhs); } } impl Div for f64 { type Output = DMat2; #[inline] fn div(self, rhs: DMat2) -> Self::Output { rhs.div_scalar(self) } } impl Div for DMat2 { type Output = Self; #[inline] fn div(self, rhs: f64) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for DMat2 { #[inline] fn div_assign(&mut self, rhs: f64) { *self = self.div_scalar(rhs); } } impl Sum for DMat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DMat2 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DMat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for DMat2 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for DMat2 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 4]> for DMat2 { #[inline] fn as_ref(&self) -> &[f64; 4] { unsafe { &*(self as *const Self as *const [f64; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f64; 4]> for DMat2 { #[inline] fn as_mut(&mut self) -> &mut [f64; 4] { unsafe { &mut *(self as *mut Self as *mut [f64; 4]) } } } impl fmt::Debug for DMat2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(DMat2)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .finish() } } impl fmt::Display for DMat2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) } else { write!(f, "[{}, {}]", self.x_axis, self.y_axis) } } } glam-0.30.1/src/f64/dmat3.rs000064400000000000000000000670421046102023000134020ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f64::math, swizzles::*, DMat2, DMat4, DQuat, DVec2, DVec3, EulerRot, Mat3, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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) } /// A 3x3 column major matrix. /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`DAffine2`](crate::DAffine2) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. #[derive(Clone, Copy)] #[repr(C)] pub struct DMat3 { pub x_axis: DVec3, pub y_axis: DVec3, pub z_axis: DVec3, } impl DMat3 { /// A 3x3 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(DVec3::ZERO, DVec3::ZERO, DVec3::ZERO); /// A 3x3 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(DVec3::X, DVec3::Y, DVec3::Z); /// All NAN:s. pub const NAN: Self = Self::from_cols(DVec3::NAN, DVec3::NAN, DVec3::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f64, m01: f64, m02: f64, m10: f64, m11: f64, m12: f64, m20: f64, m21: f64, m22: f64, ) -> Self { Self { x_axis: DVec3::new(m00, m01, m02), y_axis: DVec3::new(m10, m11, m12), z_axis: DVec3::new(m20, m21, m22), } } /// 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, y_axis, z_axis, } } /// Creates a 3x3 matrix from a `[f64; 9]` array stored in column major order. /// 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]) } /// 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, self.x_axis.y, self.x_axis.z, self.y_axis.x, self.y_axis.y, self.y_axis.z, self.z_axis.x, self.z_axis.y, self.z_axis.z, ] } /// Creates a 3x3 matrix from a `[[f64; 3]; 3]` 3D array stored in column major order. /// 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]), DVec3::from_array(m[1]), DVec3::from_array(m[2]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), ] } /// 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, ) } /// 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( DVec3::from_vec4(m.x_axis), DVec3::from_vec4(m.y_axis), DVec3::from_vec4(m.z_axis), ) } /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: DMat4, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()), (0, 1) => Self::from_cols(m.y_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()), (0, 2) => Self::from_cols(m.y_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()), (0, 3) => Self::from_cols(m.y_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()), (1, 0) => Self::from_cols(m.x_axis.yzw(), m.z_axis.yzw(), m.w_axis.yzw()), (1, 1) => Self::from_cols(m.x_axis.xzw(), m.z_axis.xzw(), m.w_axis.xzw()), (1, 2) => Self::from_cols(m.x_axis.xyw(), m.z_axis.xyw(), m.w_axis.xyw()), (1, 3) => Self::from_cols(m.x_axis.xyz(), m.z_axis.xyz(), m.w_axis.xyz()), (2, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.w_axis.yzw()), (2, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.w_axis.xzw()), (2, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.w_axis.xyw()), (2, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.w_axis.xyz()), (3, 0) => Self::from_cols(m.x_axis.yzw(), m.y_axis.yzw(), m.z_axis.yzw()), (3, 1) => Self::from_cols(m.x_axis.xzw(), m.y_axis.xzw(), m.z_axis.xzw()), (3, 2) => Self::from_cols(m.x_axis.xyw(), m.y_axis.xyw(), m.z_axis.xyw()), (3, 3) => Self::from_cols(m.x_axis.xyz(), m.y_axis.xyz(), m.z_axis.xyz()), _ => panic!("index out of bounds"), } } /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// 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()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( DVec3::new(1.0 - (yy + zz), xy + wz, xz - wy), DVec3::new(xy - wz, 1.0 - (xx + zz), yz + wx), DVec3::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # 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 (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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( DVec3::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), DVec3::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), DVec3::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) { glam_assert!( self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized() ); self.to_euler_angles(order) } /// 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) = math::sin_cos(angle); Self::from_cols( DVec3::X, DVec3::new(0.0, cosa, sina), DVec3::new(0.0, -sina, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( DVec3::new(cosa, 0.0, -sina), DVec3::Y, DVec3::new(sina, 0.0, cosa), ) } /// 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) = math::sin_cos(angle); Self::from_cols( DVec3::new(cosa, sina, 0.0), DVec3::new(-sina, cosa, 0.0), DVec3::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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, DVec3::Y, DVec3::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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) = math::sin_cos(angle); Self::from_cols( DVec3::new(cos, sin, 0.0), DVec3::new(-sin, cos, 0.0), DVec3::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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) = 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), DVec3::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// 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()); Self::from_cols( DVec3::new(scale.x, 0.0, 0.0), DVec3::new(0.0, scale.y, 0.0), DVec3::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: DMat2) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), DVec3::Z) } /// Creates a 3x3 matrix from the first 9 values in `slice`. /// /// # Panics /// /// 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], slice[8], ) } /// Writes the columns of `self` to the first 9 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 9 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f64]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.y_axis.x; slice[4] = self.y_axis.y; slice[5] = self.y_axis.z; slice[6] = self.z_axis.x; slice[7] = self.z_axis.y; slice[8] = self.z_axis.z; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] #[must_use] pub fn col(&self, index: usize) -> DVec3 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 2. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut DVec3 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), 2 => DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), _ => panic!("index out of bounds"), } } /// 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`. #[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), y_axis: DVec3::new(self.x_axis.y, self.y_axis.y, self.z_axis.y), z_axis: DVec3::new(self.x_axis.z, self.y_axis.z, self.z_axis.z), } } /// Returns the determinant of `self`. #[inline] #[must_use] pub fn determinant(&self) -> f64 { self.z_axis.dot(self.x_axis.cross(self.y_axis)) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[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); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = DVec3::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() } /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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 } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( DVec3::new(s.x, u.x, -f.x), DVec3::new(s.y, u.y, -f.y), DVec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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)); res = res.add(self.z_axis.mul(rhs.z)); res } /// Multiplies two 3x3 matrices. #[inline] #[must_use] pub fn mul_mat3(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), ) } /// Divides a 3x3 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f64) -> Self { let rhs = DVec3::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols(self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs()) } #[inline] pub fn as_mat3(&self) -> Mat3 { Mat3::from_cols( self.x_axis.as_vec3(), self.y_axis.as_vec3(), self.z_axis.as_vec3(), ) } } impl Default for DMat3 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for DMat3 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat3(&rhs) } } impl AddAssign for DMat3 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat3(&rhs); } } impl Sub for DMat3 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat3(&rhs) } } impl SubAssign for DMat3 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat3(&rhs); } } impl Neg for DMat3 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols(self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg()) } } impl Mul for DMat3 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat3(&rhs) } } impl MulAssign for DMat3 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat3(&rhs); } } impl Mul for DMat3 { type Output = DVec3; #[inline] fn mul(self, rhs: DVec3) -> Self::Output { self.mul_vec3(rhs) } } impl Mul for f64 { type Output = DMat3; #[inline] fn mul(self, rhs: DMat3) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for DMat3 { type Output = Self; #[inline] fn mul(self, rhs: f64) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for DMat3 { #[inline] fn mul_assign(&mut self, rhs: f64) { *self = self.mul_scalar(rhs); } } impl Div for f64 { type Output = DMat3; #[inline] fn div(self, rhs: DMat3) -> Self::Output { rhs.div_scalar(self) } } impl Div for DMat3 { type Output = Self; #[inline] fn div(self, rhs: f64) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for DMat3 { #[inline] fn div_assign(&mut self, rhs: f64) { *self = self.div_scalar(rhs); } } impl Sum for DMat3 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DMat3 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DMat3 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for DMat3 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for DMat3 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 9]> for DMat3 { #[inline] fn as_ref(&self) -> &[f64; 9] { unsafe { &*(self as *const Self as *const [f64; 9]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f64; 9]> for DMat3 { #[inline] fn as_mut(&mut self) -> &mut [f64; 9] { unsafe { &mut *(self as *mut Self as *mut [f64; 9]) } } } impl fmt::Debug for DMat3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(DMat3)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .finish() } } impl fmt::Display for DMat3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis ) } else { write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) } } } glam-0.30.1/src/f64/dmat4.rs000064400000000000000000001321341046102023000133760ustar 00000000000000// Generated from mat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{FromEuler, ToEuler}, f64::math, swizzles::*, DMat3, DQuat, DVec3, DVec4, EulerRot, Mat4, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; /// 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) } /// A 4x4 column major matrix. /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`DAffine3`](crate::DAffine3) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. #[derive(Clone, Copy)] #[cfg_attr(feature = "cuda", repr(align(16)))] #[repr(C)] pub struct DMat4 { pub x_axis: DVec4, pub y_axis: DVec4, pub z_axis: DVec4, pub w_axis: DVec4, } impl DMat4 { /// A 4x4 matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols(DVec4::ZERO, DVec4::ZERO, DVec4::ZERO, DVec4::ZERO); /// A 4x4 identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols(DVec4::X, DVec4::Y, DVec4::Z, DVec4::W); /// All NAN:s. pub const NAN: Self = Self::from_cols(DVec4::NAN, DVec4::NAN, DVec4::NAN, DVec4::NAN); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( m00: f64, m01: f64, m02: f64, m03: f64, m10: f64, m11: f64, m12: f64, m13: f64, m20: f64, m21: f64, m22: f64, m23: f64, m30: f64, m31: f64, m32: f64, m33: f64, ) -> Self { Self { x_axis: DVec4::new(m00, m01, m02, m03), y_axis: DVec4::new(m10, m11, m12, m13), z_axis: DVec4::new(m20, m21, m22, m23), w_axis: DVec4::new(m30, m31, m32, m33), } } /// 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, y_axis, z_axis, w_axis, } } /// Creates a 4x4 matrix from a `[f64; 16]` array stored in column major order. /// 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], m[14], m[15], ) } /// 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, self.x_axis.y, self.x_axis.z, self.x_axis.w, self.y_axis.x, self.y_axis.y, self.y_axis.z, self.y_axis.w, self.z_axis.x, self.z_axis.y, self.z_axis.z, self.z_axis.w, self.w_axis.x, self.w_axis.y, self.w_axis.z, self.w_axis.w, ] } /// Creates a 4x4 matrix from a `[[f64; 4]; 4]` 4D array stored in column major order. /// 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]), DVec4::from_array(m[1]), DVec4::from_array(m[2]), DVec4::from_array(m[3]), ) } /// 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(), self.y_axis.to_array(), self.z_axis.to_array(), self.w_axis.to_array(), ] } /// 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, 0.0, 0.0, diagonal.w, ) } #[inline] #[must_use] fn quat_to_axes(rotation: DQuat) -> (DVec4, DVec4, DVec4) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = DVec4::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = DVec4::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = DVec4::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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, translation: DVec3, ) -> Self { let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation); Self::from_cols( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), DVec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne(DVec3::ZERO).all()); let inv_scale = scale.recip(); let rotation = DQuat::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), DVec4::from((m.y_axis, 0.0)), DVec4::from((m.z_axis, 0.0)), DVec4::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `DMat4::from_translation(translation) * DMat4::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: DMat3, translation: DVec3) -> Self { Self::from_cols( DVec4::from((mat3.x_axis, 0.0)), DVec4::from((mat3.y_axis, 0.0)), DVec4::from((mat3.z_axis, 0.0)), DVec4::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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, DVec4::Y, DVec4::Z, DVec4::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # 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 (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( DVec4::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), DVec4::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), DVec4::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), DVec4::W, ) } /// 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 { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> (f64, f64, f64) { glam_assert!( self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized() ); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: f64) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( DVec4::X, DVec4::new(0.0, cosa, sina, 0.0), DVec4::new(0.0, -sina, cosa, 0.0), DVec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: f64) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( DVec4::new(cosa, 0.0, -sina, 0.0), DVec4::Y, DVec4::new(sina, 0.0, cosa, 0.0), DVec4::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: f64) -> Self { 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), DVec4::Z, DVec4::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// 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()); Self::from_cols( DVec4::new(scale.x, 0.0, 0.0, 0.0), DVec4::new(0.0, scale.y, 0.0, 0.0), DVec4::new(0.0, 0.0, scale.z, 0.0), DVec4::W, ) } /// Creates a 4x4 matrix from the first 16 values in `slice`. /// /// # Panics /// /// 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], slice[8], slice[9], slice[10], slice[11], slice[12], slice[13], slice[14], slice[15], ) } /// Writes the columns of `self` to the first 16 elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than 16 elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [f64]) { slice[0] = self.x_axis.x; slice[1] = self.x_axis.y; slice[2] = self.x_axis.z; slice[3] = self.x_axis.w; slice[4] = self.y_axis.x; slice[5] = self.y_axis.y; slice[6] = self.y_axis.z; slice[7] = self.y_axis.w; slice[8] = self.z_axis.x; slice[9] = self.z_axis.y; slice[10] = self.z_axis.z; slice[11] = self.z_axis.w; slice[12] = self.w_axis.x; slice[13] = self.w_axis.y; slice[14] = self.w_axis.z; slice[15] = self.w_axis.w; } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] #[must_use] pub fn col(&self, index: usize) -> DVec4 { match index { 0 => self.x_axis, 1 => self.y_axis, 2 => self.z_axis, 3 => self.w_axis, _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than 3. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut DVec4 { match index { 0 => &mut self.x_axis, 1 => &mut self.y_axis, 2 => &mut self.z_axis, 3 => &mut self.w_axis, _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// 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), 1 => DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), 2 => DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), 3 => DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), _ => panic!("index out of bounds"), } } /// 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() && self.w_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() || self.w_axis.is_nan() } /// Returns the transpose of `self`. #[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), y_axis: DVec4::new(self.x_axis.y, self.y_axis.y, self.z_axis.y, self.w_axis.y), z_axis: DVec4::new(self.x_axis.z, self.y_axis.z, self.z_axis.z, self.w_axis.z), w_axis: DVec4::new(self.x_axis.w, self.y_axis.w, self.z_axis.w, self.w_axis.w), } } /// 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(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let a2323 = m22 * m33 - m23 * m32; let a1323 = m21 * m33 - m23 * m31; let a1223 = m21 * m32 - m22 * m31; let a0323 = m20 * m33 - m23 * m30; let a0223 = m20 * m32 - m22 * m30; let a0123 = m20 * m31 - m21 * m30; m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223) - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223) + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123) - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123) } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. #[must_use] pub fn inverse(&self) -> Self { let (m00, m01, m02, m03) = self.x_axis.into(); let (m10, m11, m12, m13) = self.y_axis.into(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let coef00 = m22 * m33 - m32 * m23; let coef02 = m12 * m33 - m32 * m13; let coef03 = m12 * m23 - m22 * m13; let coef04 = m21 * m33 - m31 * m23; let coef06 = m11 * m33 - m31 * m13; let coef07 = m11 * m23 - m21 * m13; let coef08 = m21 * m32 - m31 * m22; let coef10 = m11 * m32 - m31 * m12; let coef11 = m11 * m22 - m21 * m12; let coef12 = m20 * m33 - m30 * m23; let coef14 = m10 * m33 - m30 * m13; let coef15 = m10 * m23 - m20 * m13; let coef16 = m20 * m32 - m30 * m22; let coef18 = m10 * m32 - m30 * m12; let coef19 = m10 * m22 - m20 * m12; let coef20 = m20 * m31 - m30 * m21; let coef22 = m10 * m31 - m30 * m11; let coef23 = m10 * m21 - m20 * m11; let fac0 = DVec4::new(coef00, coef00, coef02, coef03); let fac1 = DVec4::new(coef04, coef04, coef06, coef07); let fac2 = DVec4::new(coef08, coef08, coef10, coef11); let fac3 = DVec4::new(coef12, coef12, coef14, coef15); let fac4 = DVec4::new(coef16, coef16, coef18, coef19); let fac5 = DVec4::new(coef20, coef20, coef22, coef23); let vec0 = DVec4::new(m10, m00, m00, m00); let vec1 = DVec4::new(m11, m01, m01, m01); let vec2 = DVec4::new(m12, m02, m02, m02); let vec3 = DVec4::new(m13, m03, m03, m03); let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2)); let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4)); let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5)); let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5)); let sign_a = DVec4::new(1.0, -1.0, 1.0, -1.0); let sign_b = DVec4::new(-1.0, 1.0, -1.0, 1.0); let inverse = Self::from_cols( inv0.mul(sign_a), inv1.mul(sign_b), inv2.mul(sign_a), inv3.mul(sign_b), ); let col0 = DVec4::new( inverse.x_axis.x, inverse.y_axis.x, inverse.z_axis.x, inverse.w_axis.x, ); let dot0 = self.x_axis.mul(col0); let dot1 = dot0.x + dot0.y + dot0.z + dot0.w; glam_assert!(dot1 != 0.0); let rcp_det = dot1.recip(); inverse.mul(rcp_det) } /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: DVec3, dir: DVec3, up: DVec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( DVec4::new(s.x, u.x, -f.x, 0.0), DVec4::new(s.y, u.y, -f.y, 0.0), DVec4::new(s.z, u.z, -f.z, 0.0), DVec4::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, z_far: f64, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( DVec4::new(a, 0.0, 0.0, 0.0), DVec4::new(0.0, f, 0.0, 0.0), DVec4::new(0.0, 0.0, b, -1.0), DVec4::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( DVec4::new(w, 0.0, 0.0, 0.0), DVec4::new(0.0, h, 0.0, 0.0), DVec4::new(0.0, 0.0, r, 1.0), DVec4::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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) = 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); Self::from_cols( DVec4::new(w, 0.0, 0.0, 0.0), DVec4::new(0.0, h, 0.0, 0.0), DVec4::new(0.0, 0.0, r, -1.0), DVec4::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self { glam_assert!(z_near > 0.0); 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( DVec4::new(w, 0.0, 0.0, 0.0), DVec4::new(0.0, h, 0.0, 0.0), DVec4::new(0.0, 0.0, 1.0, 1.0), DVec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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) = math::sin_cos(0.5 * fov_y_radians); let h = cos_fov / sin_fov; let w = h / aspect_ratio; Self::from_cols( DVec4::new(w, 0.0, 0.0, 0.0), DVec4::new(0.0, h, 0.0, 0.0), DVec4::new(0.0, 0.0, 0.0, 1.0), DVec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: f64, aspect_ratio: f64, z_near: f64) -> Self { glam_assert!(z_near > 0.0); 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), DVec4::new(0.0, 0.0, -1.0, -1.0), DVec4::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: f64, aspect_ratio: f64, z_near: f64, ) -> Self { glam_assert!(z_near > 0.0); 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), DVec4::new(0.0, 0.0, 0.0, -1.0), DVec4::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( DVec4::new(a, 0.0, 0.0, 0.0), DVec4::new(0.0, b, 0.0, 0.0), DVec4::new(0.0, 0.0, c, 0.0), DVec4::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), DVec4::new(0.0, 0.0, r, 0.0), DVec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: f64, right: f64, bottom: f64, top: f64, near: f64, far: f64, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( DVec4::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), DVec4::new(0.0, rcp_height + rcp_height, 0.0, 0.0), DVec4::new(0.0, 0.0, r, 0.0), DVec4::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// 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); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } /// 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)); res = res.add(self.z_axis.mul(rhs.z)); res = res.add(self.w_axis.mul(rhs.w)); res } /// Multiplies two 4x4 matrices. #[inline] #[must_use] pub fn mul_mat4(&self, rhs: &Self) -> Self { Self::from_cols( self.mul(rhs.x_axis), self.mul(rhs.y_axis), self.mul(rhs.z_axis), self.mul(rhs.w_axis), ) } /// 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), self.y_axis.add(rhs.y_axis), self.z_axis.add(rhs.z_axis), self.w_axis.add(rhs.w_axis), ) } /// 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), self.y_axis.sub(rhs.y_axis), self.z_axis.sub(rhs.z_axis), self.w_axis.sub(rhs.w_axis), ) } /// 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), self.y_axis.mul(rhs), self.z_axis.mul(rhs), self.w_axis.mul(rhs), ) } /// Divides a 4x4 matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: f64) -> Self { let rhs = DVec4::splat(rhs); Self::from_cols( self.x_axis.div(rhs), self.y_axis.div(rhs), self.z_axis.div(rhs), self.w_axis.div(rhs), ) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) && self.z_axis.abs_diff_eq(rhs.z_axis, max_abs_diff) && self.w_axis.abs_diff_eq(rhs.w_axis, max_abs_diff) } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( self.x_axis.abs(), self.y_axis.abs(), self.z_axis.abs(), self.w_axis.abs(), ) } #[inline] pub fn as_mat4(&self) -> Mat4 { Mat4::from_cols( self.x_axis.as_vec4(), self.y_axis.as_vec4(), self.z_axis.as_vec4(), self.w_axis.as_vec4(), ) } } impl Default for DMat4 { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add for DMat4 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat4(&rhs) } } impl AddAssign for DMat4 { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat4(&rhs); } } impl Sub for DMat4 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat4(&rhs) } } impl SubAssign for DMat4 { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat4(&rhs); } } impl Neg for DMat4 { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::from_cols( self.x_axis.neg(), self.y_axis.neg(), self.z_axis.neg(), self.w_axis.neg(), ) } } impl Mul for DMat4 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat4(&rhs) } } impl MulAssign for DMat4 { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat4(&rhs); } } impl Mul for DMat4 { type Output = DVec4; #[inline] fn mul(self, rhs: DVec4) -> Self::Output { self.mul_vec4(rhs) } } impl Mul for f64 { type Output = DMat4; #[inline] fn mul(self, rhs: DMat4) -> Self::Output { rhs.mul_scalar(self) } } impl Mul for DMat4 { type Output = Self; #[inline] fn mul(self, rhs: f64) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign for DMat4 { #[inline] fn mul_assign(&mut self, rhs: f64) { *self = self.mul_scalar(rhs); } } impl Div for f64 { type Output = DMat4; #[inline] fn div(self, rhs: DMat4) -> Self::Output { rhs.div_scalar(self) } } impl Div for DMat4 { type Output = Self; #[inline] fn div(self, rhs: f64) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign for DMat4 { #[inline] fn div_assign(&mut self, rhs: f64) { *self = self.div_scalar(rhs); } } impl Sum for DMat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DMat4 { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DMat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for DMat4 { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for DMat4 { #[inline] fn eq(&self, rhs: &Self) -> bool { self.x_axis.eq(&rhs.x_axis) && self.y_axis.eq(&rhs.y_axis) && self.z_axis.eq(&rhs.z_axis) && self.w_axis.eq(&rhs.w_axis) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 16]> for DMat4 { #[inline] fn as_ref(&self) -> &[f64; 16] { unsafe { &*(self as *const Self as *const [f64; 16]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f64; 16]> for DMat4 { #[inline] fn as_mut(&mut self) -> &mut [f64; 16] { unsafe { &mut *(self as *mut Self as *mut [f64; 16]) } } } impl fmt::Debug for DMat4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!(DMat4)) .field("x_axis", &self.x_axis) .field("y_axis", &self.y_axis) .field("z_axis", &self.z_axis) .field("w_axis", &self.w_axis) .finish() } } impl fmt::Display for DMat4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis ) } else { write!( f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis ) } } } glam-0.30.1/src/f64/dquat.rs000064400000000000000000000762551046102023000135160ustar 00000000000000// Generated from quat.rs.tera template. Edit the template, not the generated file. use crate::{ euler::{EulerRot, FromEuler, ToEuler}, f64::math, DMat3, DMat4, DVec2, DVec3, DVec4, Quat, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, Div, Mul, MulAssign, Neg, Sub}; /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// floating point "error creep" which can occur when successive quaternion /// operations are applied. #[derive(Clone, Copy)] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct DQuat { pub x: f64, pub y: f64, pub z: f64, pub w: f64, } impl DQuat { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([f64::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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 } } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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]) } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: DVec4) -> Self { Self { x: v.x, y: v.y, z: v.z, w: v.w, } } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// 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]) } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [f64]) { slice[0] = self.x; slice[1] = self.y; slice[2] = self.z; slice[3] = self.w; } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `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 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// 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) = 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) = 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) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// 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 { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: DVec3, y_axis: DVec3, z_axis: DVec3) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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 the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &DMat4) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPS: f64 = 1.0 - 2.0 * f64::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::f64::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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()); const ONE_MINUS_EPSILON: f64 = 1.0 - 2.0 * f64::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: f64 = 0.0; const SIN_FRAC_PI_2: f64 = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: DVec3, up: DVec3) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: DVec3, up: DVec3) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( DVec3::new(s.x, u.x, -f.x), DVec3::new(s.y, u.y, -f.y), DVec3::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// 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 { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: DVec3, center: DVec3, up: DVec3) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// 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; 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, 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 } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> (f64, f64, f64) { self.to_euler_angles(order) } /// `[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. #[inline] #[must_use] pub fn conjugate(self) -> Self { Self { x: -self.x, y: -self.y, z: -self.z, w: self.w, } } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f64 { DVec4::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> f64 { DVec4::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> f64 { DVec4::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4(DVec4::from(self).normalize()) } /// 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() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { DVec4::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// 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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// 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()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f64) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: f64) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[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()); let dot = self.dot(end); let bias = if dot >= 0.0 { 1.0 } else { -1.0 }; self.lerp_impl(end * bias, s) } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: f64 = 1.0 - f64::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); let scale1 = math::sin(theta * (1.0 - s)); let scale2 = math::sin(theta * s); let theta_sin = math::sin(theta); ((self * scale1) + (end * scale2)) * (1.0 / theta_sin) } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// 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()); let w = self.w; let b = DVec3::new(self.x, self.y, self.z); let b2 = b.dot(b); rhs.mul(w * w - b2) .add(b.mul(rhs.dot(b) * 2.0)) .add(b.cross(rhs).mul(w * 2.0)) } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { let (x0, y0, z0, w0) = self.into(); let (x1, y1, z1, w1) = rhs.into(); Self::from_xyzw( w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1, w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1, w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1, w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1, ) } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::DAffine3) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } #[inline] #[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) } } impl fmt::Debug for DQuat { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(DQuat)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for DQuat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add for DQuat { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4(DVec4::from(self) + DVec4::from(rhs)) } } impl Sub for DQuat { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4(DVec4::from(self) - DVec4::from(rhs)) } } impl Mul for DQuat { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: f64) -> Self { Self::from_vec4(DVec4::from(self) * rhs) } } impl Div for DQuat { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: f64) -> Self { Self::from_vec4(DVec4::from(self) / rhs) } } impl Mul for DQuat { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign for DQuat { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul for DQuat { type Output = DVec3; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: DVec3) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for DQuat { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for DQuat { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for DQuat { #[inline] fn eq(&self, rhs: &Self) -> bool { DVec4::from(*self).eq(&DVec4::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 4]> for DQuat { #[inline] fn as_ref(&self) -> &[f64; 4] { unsafe { &*(self as *const Self as *const [f64; 4]) } } } impl Sum for DQuat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DQuat { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DQuat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for DQuat { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl From for DVec4 { #[inline] fn from(q: DQuat) -> Self { Self::new(q.x, q.y, q.z, q.w) } } impl From for (f64, f64, f64, f64) { #[inline] fn from(q: DQuat) -> Self { (q.x, q.y, q.z, q.w) } } impl From for [f64; 4] { #[inline] fn from(q: DQuat) -> Self { [q.x, q.y, q.z, q.w] } } glam-0.30.1/src/f64/dvec2.rs000064400000000000000000001337461046102023000134020ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f64::math, BVec2, DVec3, IVec2, UVec2, Vec2}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn dvec2(x: f64, y: f64) -> DVec2 { DVec2::new(x, y) } /// A 2-dimensional vector. #[derive(Clone, Copy, PartialEq)] #[cfg_attr(feature = "cuda", repr(align(16)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct DVec2 { pub x: f64, pub y: f64, } impl DVec2 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0); /// 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.0, -1.0); /// 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f64) -> f64, { Self::new(f(self.x), f(self.y)) } /// 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: [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] } /// 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: &[f64]) -> Self { assert!(slice.len() >= 2); 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 [f64]) { slice[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f64) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f64) -> Self { self.y = y; self } /// 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)) } /// 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 [`f64::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) -> f64 { 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) -> f64 { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f64 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f64 { self.x * 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: math::abs(self.x), y: math::abs(self.y), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: math::copysign(self.x, rhs.x), y: math::copysign(self.y, rhs.y), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec2 { BVec2::new(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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec2 { BVec2::new(self.x.is_nan(), self.y.is_nan()) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f64 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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(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: 1.0 / self.x, y: 1.0 / self.y, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f64) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f64) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f64, max: f64) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f64) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f64) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( math::mul_add(self.x, a.x, b.x), math::mul_add(self.y, a.y, b.y), ) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f64) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Creates a 2D vector containing `[angle.cos(), angle.sin()]`. This can be used in /// 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) = math::sin_cos(angle); Self { x: cos, y: sin } } /// Returns the angle (in radians) of this vector in the range `[-π, +π]`. /// /// The input does not need to be a unit vector however it must be non-zero. #[inline] #[must_use] pub fn to_angle(self) -> f64 { math::atan2(self.y, self.x) } #[inline] #[must_use] #[deprecated( since = "0.27.0", note = "Use angle_to() instead, the semantics of angle_between will change in the future." )] pub fn angle_between(self, rhs: Self) -> f64 { self.angle_to(rhs) } /// Returns the angle of rotation (in radians) from `self` to `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_to(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, 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) -> f64 { (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, } } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: f64) -> Self { let a = self.angle_to(rhs); let abs_a = math::abs(a); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(abs_a - core::f64::consts::PI, abs_a) * math::signum(a); Self::from_angle(angle).rotate(*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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } } impl Default for DVec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for DVec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&DVec2> for DVec2 { type Output = DVec2; #[inline] fn div(self, rhs: &DVec2) -> DVec2 { self.div(*rhs) } } impl Div<&DVec2> for &DVec2 { type Output = DVec2; #[inline] fn div(self, rhs: &DVec2) -> DVec2 { (*self).div(*rhs) } } impl Div for &DVec2 { type Output = DVec2; #[inline] fn div(self, rhs: DVec2) -> DVec2 { (*self).div(rhs) } } impl DivAssign for DVec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&DVec2> for DVec2 { #[inline] fn div_assign(&mut self, rhs: &DVec2) { self.div_assign(*rhs) } } impl Div for DVec2 { type Output = Self; #[inline] fn div(self, rhs: f64) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&f64> for DVec2 { type Output = DVec2; #[inline] fn div(self, rhs: &f64) -> DVec2 { self.div(*rhs) } } impl Div<&f64> for &DVec2 { type Output = DVec2; #[inline] fn div(self, rhs: &f64) -> DVec2 { (*self).div(*rhs) } } impl Div for &DVec2 { type Output = DVec2; #[inline] fn div(self, rhs: f64) -> DVec2 { (*self).div(rhs) } } impl DivAssign for DVec2 { #[inline] fn div_assign(&mut self, rhs: f64) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&f64> for DVec2 { #[inline] fn div_assign(&mut self, rhs: &f64) { self.div_assign(*rhs) } } impl Div for f64 { type Output = DVec2; #[inline] fn div(self, rhs: DVec2) -> DVec2 { DVec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&DVec2> for f64 { type Output = DVec2; #[inline] fn div(self, rhs: &DVec2) -> DVec2 { self.div(*rhs) } } impl Div<&DVec2> for &f64 { type Output = DVec2; #[inline] fn div(self, rhs: &DVec2) -> DVec2 { (*self).div(*rhs) } } impl Div for &f64 { type Output = DVec2; #[inline] fn div(self, rhs: DVec2) -> DVec2 { (*self).div(rhs) } } impl Mul for DVec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&DVec2> for DVec2 { type Output = DVec2; #[inline] fn mul(self, rhs: &DVec2) -> DVec2 { self.mul(*rhs) } } impl Mul<&DVec2> for &DVec2 { type Output = DVec2; #[inline] fn mul(self, rhs: &DVec2) -> DVec2 { (*self).mul(*rhs) } } impl Mul for &DVec2 { type Output = DVec2; #[inline] fn mul(self, rhs: DVec2) -> DVec2 { (*self).mul(rhs) } } impl MulAssign for DVec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&DVec2> for DVec2 { #[inline] fn mul_assign(&mut self, rhs: &DVec2) { self.mul_assign(*rhs) } } impl Mul for DVec2 { type Output = Self; #[inline] fn mul(self, rhs: f64) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&f64> for DVec2 { type Output = DVec2; #[inline] fn mul(self, rhs: &f64) -> DVec2 { self.mul(*rhs) } } impl Mul<&f64> for &DVec2 { type Output = DVec2; #[inline] fn mul(self, rhs: &f64) -> DVec2 { (*self).mul(*rhs) } } impl Mul for &DVec2 { type Output = DVec2; #[inline] fn mul(self, rhs: f64) -> DVec2 { (*self).mul(rhs) } } impl MulAssign for DVec2 { #[inline] fn mul_assign(&mut self, rhs: f64) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&f64> for DVec2 { #[inline] fn mul_assign(&mut self, rhs: &f64) { self.mul_assign(*rhs) } } impl Mul for f64 { type Output = DVec2; #[inline] fn mul(self, rhs: DVec2) -> DVec2 { DVec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&DVec2> for f64 { type Output = DVec2; #[inline] fn mul(self, rhs: &DVec2) -> DVec2 { self.mul(*rhs) } } impl Mul<&DVec2> for &f64 { type Output = DVec2; #[inline] fn mul(self, rhs: &DVec2) -> DVec2 { (*self).mul(*rhs) } } impl Mul for &f64 { type Output = DVec2; #[inline] fn mul(self, rhs: DVec2) -> DVec2 { (*self).mul(rhs) } } impl Add for DVec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&DVec2> for DVec2 { type Output = DVec2; #[inline] fn add(self, rhs: &DVec2) -> DVec2 { self.add(*rhs) } } impl Add<&DVec2> for &DVec2 { type Output = DVec2; #[inline] fn add(self, rhs: &DVec2) -> DVec2 { (*self).add(*rhs) } } impl Add for &DVec2 { type Output = DVec2; #[inline] fn add(self, rhs: DVec2) -> DVec2 { (*self).add(rhs) } } impl AddAssign for DVec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&DVec2> for DVec2 { #[inline] fn add_assign(&mut self, rhs: &DVec2) { self.add_assign(*rhs) } } impl Add for DVec2 { type Output = Self; #[inline] fn add(self, rhs: f64) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&f64> for DVec2 { type Output = DVec2; #[inline] fn add(self, rhs: &f64) -> DVec2 { self.add(*rhs) } } impl Add<&f64> for &DVec2 { type Output = DVec2; #[inline] fn add(self, rhs: &f64) -> DVec2 { (*self).add(*rhs) } } impl Add for &DVec2 { type Output = DVec2; #[inline] fn add(self, rhs: f64) -> DVec2 { (*self).add(rhs) } } impl AddAssign for DVec2 { #[inline] fn add_assign(&mut self, rhs: f64) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&f64> for DVec2 { #[inline] fn add_assign(&mut self, rhs: &f64) { self.add_assign(*rhs) } } impl Add for f64 { type Output = DVec2; #[inline] fn add(self, rhs: DVec2) -> DVec2 { DVec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&DVec2> for f64 { type Output = DVec2; #[inline] fn add(self, rhs: &DVec2) -> DVec2 { self.add(*rhs) } } impl Add<&DVec2> for &f64 { type Output = DVec2; #[inline] fn add(self, rhs: &DVec2) -> DVec2 { (*self).add(*rhs) } } impl Add for &f64 { type Output = DVec2; #[inline] fn add(self, rhs: DVec2) -> DVec2 { (*self).add(rhs) } } impl Sub for DVec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&DVec2> for DVec2 { type Output = DVec2; #[inline] fn sub(self, rhs: &DVec2) -> DVec2 { self.sub(*rhs) } } impl Sub<&DVec2> for &DVec2 { type Output = DVec2; #[inline] fn sub(self, rhs: &DVec2) -> DVec2 { (*self).sub(*rhs) } } impl Sub for &DVec2 { type Output = DVec2; #[inline] fn sub(self, rhs: DVec2) -> DVec2 { (*self).sub(rhs) } } impl SubAssign for DVec2 { #[inline] fn sub_assign(&mut self, rhs: DVec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&DVec2> for DVec2 { #[inline] fn sub_assign(&mut self, rhs: &DVec2) { self.sub_assign(*rhs) } } impl Sub for DVec2 { type Output = Self; #[inline] fn sub(self, rhs: f64) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&f64> for DVec2 { type Output = DVec2; #[inline] fn sub(self, rhs: &f64) -> DVec2 { self.sub(*rhs) } } impl Sub<&f64> for &DVec2 { type Output = DVec2; #[inline] fn sub(self, rhs: &f64) -> DVec2 { (*self).sub(*rhs) } } impl Sub for &DVec2 { type Output = DVec2; #[inline] fn sub(self, rhs: f64) -> DVec2 { (*self).sub(rhs) } } impl SubAssign for DVec2 { #[inline] fn sub_assign(&mut self, rhs: f64) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&f64> for DVec2 { #[inline] fn sub_assign(&mut self, rhs: &f64) { self.sub_assign(*rhs) } } impl Sub for f64 { type Output = DVec2; #[inline] fn sub(self, rhs: DVec2) -> DVec2 { DVec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&DVec2> for f64 { type Output = DVec2; #[inline] fn sub(self, rhs: &DVec2) -> DVec2 { self.sub(*rhs) } } impl Sub<&DVec2> for &f64 { type Output = DVec2; #[inline] fn sub(self, rhs: &DVec2) -> DVec2 { (*self).sub(*rhs) } } impl Sub for &f64 { type Output = DVec2; #[inline] fn sub(self, rhs: DVec2) -> DVec2 { (*self).sub(rhs) } } impl Rem for DVec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&DVec2> for DVec2 { type Output = DVec2; #[inline] fn rem(self, rhs: &DVec2) -> DVec2 { self.rem(*rhs) } } impl Rem<&DVec2> for &DVec2 { type Output = DVec2; #[inline] fn rem(self, rhs: &DVec2) -> DVec2 { (*self).rem(*rhs) } } impl Rem for &DVec2 { type Output = DVec2; #[inline] fn rem(self, rhs: DVec2) -> DVec2 { (*self).rem(rhs) } } impl RemAssign for DVec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&DVec2> for DVec2 { #[inline] fn rem_assign(&mut self, rhs: &DVec2) { self.rem_assign(*rhs) } } impl Rem for DVec2 { type Output = Self; #[inline] fn rem(self, rhs: f64) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&f64> for DVec2 { type Output = DVec2; #[inline] fn rem(self, rhs: &f64) -> DVec2 { self.rem(*rhs) } } impl Rem<&f64> for &DVec2 { type Output = DVec2; #[inline] fn rem(self, rhs: &f64) -> DVec2 { (*self).rem(*rhs) } } impl Rem for &DVec2 { type Output = DVec2; #[inline] fn rem(self, rhs: f64) -> DVec2 { (*self).rem(rhs) } } impl RemAssign for DVec2 { #[inline] fn rem_assign(&mut self, rhs: f64) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&f64> for DVec2 { #[inline] fn rem_assign(&mut self, rhs: &f64) { self.rem_assign(*rhs) } } impl Rem for f64 { type Output = DVec2; #[inline] fn rem(self, rhs: DVec2) -> DVec2 { DVec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&DVec2> for f64 { type Output = DVec2; #[inline] fn rem(self, rhs: &DVec2) -> DVec2 { self.rem(*rhs) } } impl Rem<&DVec2> for &f64 { type Output = DVec2; #[inline] fn rem(self, rhs: &DVec2) -> DVec2 { (*self).rem(*rhs) } } impl Rem for &f64 { type Output = DVec2; #[inline] fn rem(self, rhs: DVec2) -> DVec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 2]> for DVec2 { #[inline] fn as_ref(&self) -> &[f64; 2] { unsafe { &*(self as *const DVec2 as *const [f64; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f64; 2]> for DVec2 { #[inline] fn as_mut(&mut self) -> &mut [f64; 2] { unsafe { &mut *(self as *mut DVec2 as *mut [f64; 2]) } } } impl Sum for DVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for DVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for DVec2 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), } } } impl Neg for &DVec2 { type Output = DVec2; #[inline] fn neg(self) -> DVec2 { (*self).neg() } } impl Index for DVec2 { type Output = f64; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for DVec2 { #[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"), } } } impl fmt::Display for DVec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}]", p, self.x, p, self.y) } else { write!(f, "[{}, {}]", self.x, self.y) } } } impl fmt::Debug for DVec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(DVec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[f64; 2]> for DVec2 { #[inline] fn from(a: [f64; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [f64; 2] { #[inline] fn from(v: DVec2) -> Self { [v.x, v.y] } } impl From<(f64, f64)> for DVec2 { #[inline] fn from(t: (f64, f64)) -> Self { Self::new(t.0, t.1) } } impl From for (f64, f64) { #[inline] fn from(v: DVec2) -> Self { (v.x, v.y) } } impl From for DVec2 { #[inline] fn from(v: Vec2) -> Self { Self::new(f64::from(v.x), f64::from(v.y)) } } impl From for DVec2 { #[inline] fn from(v: IVec2) -> Self { Self::new(f64::from(v.x), f64::from(v.y)) } } impl From for DVec2 { #[inline] fn from(v: UVec2) -> Self { Self::new(f64::from(v.x), f64::from(v.y)) } } impl From for DVec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(f64::from(v.x), f64::from(v.y)) } } glam-0.30.1/src/f64/dvec3.rs000064400000000000000000001506341046102023000133760ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{f64::math, BVec3, BVec3A, DQuat, DVec2, DVec4, FloatExt, IVec3, UVec3, Vec3}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// A 3-dimensional vector. #[derive(Clone, Copy, PartialEq)] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct DVec3 { pub x: f64, pub y: f64, pub z: f64, } impl DVec3 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0); /// A unit vector pointing along the positive Z axis. pub const Z: Self = Self::new(0.0, 0.0, 1.0); /// A unit vector pointing along the negative X axis. pub const NEG_X: Self = Self::new(-1.0, 0.0, 0.0); /// A unit vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0); /// 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. pub const AXES: [Self; 3] = [Self::X, Self::Y, Self::Z]; /// 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f64) -> f64, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [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] } /// 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: &[f64]) -> Self { assert!(slice.len() >= 3); 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 [f64]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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, 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: 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> DVec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f64) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f64) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f64) -> Self { self.z = z; self } /// 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, 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 [`f64::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) -> f64 { 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) -> f64 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f64 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f64 { self.x * self.y * 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: math::abs(self.x), y: math::abs(self.y), z: math::abs(self.z), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: math::copysign(self.x, rhs.x), y: math::copysign(self.y, rhs.y), z: math::copysign(self.z, rhs.z), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) | ((self.z.is_sign_negative() as u32) << 2) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec3 { BVec3::new(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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.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()) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f64 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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: 1.0 / self.x, y: 1.0 / self.y, z: 1.0 / self.z, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f64) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f64) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f64, max: f64) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f64) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f64) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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 reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f64) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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 { math::acos_approx( self.dot(rhs) .div(math::sqrt(self.length_squared().mul(rhs.length_squared()))), ) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: f64) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::f64::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); DQuat::from_axis_angle(axis, angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: f64) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize(); let rotation = DQuat::from_axis_angle(axis, core::f64::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } } impl Default for DVec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for DVec3 { 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 Div<&DVec3> for DVec3 { type Output = DVec3; #[inline] fn div(self, rhs: &DVec3) -> DVec3 { self.div(*rhs) } } impl Div<&DVec3> for &DVec3 { type Output = DVec3; #[inline] fn div(self, rhs: &DVec3) -> DVec3 { (*self).div(*rhs) } } impl Div for &DVec3 { type Output = DVec3; #[inline] fn div(self, rhs: DVec3) -> DVec3 { (*self).div(rhs) } } impl DivAssign for DVec3 { #[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 DivAssign<&DVec3> for DVec3 { #[inline] fn div_assign(&mut self, rhs: &DVec3) { self.div_assign(*rhs) } } impl Div for DVec3 { type Output = Self; #[inline] fn div(self, rhs: f64) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&f64> for DVec3 { type Output = DVec3; #[inline] fn div(self, rhs: &f64) -> DVec3 { self.div(*rhs) } } impl Div<&f64> for &DVec3 { type Output = DVec3; #[inline] fn div(self, rhs: &f64) -> DVec3 { (*self).div(*rhs) } } impl Div for &DVec3 { type Output = DVec3; #[inline] fn div(self, rhs: f64) -> DVec3 { (*self).div(rhs) } } impl DivAssign for DVec3 { #[inline] fn div_assign(&mut self, rhs: f64) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&f64> for DVec3 { #[inline] fn div_assign(&mut self, rhs: &f64) { self.div_assign(*rhs) } } impl Div for f64 { type Output = DVec3; #[inline] fn div(self, rhs: DVec3) -> DVec3 { DVec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&DVec3> for f64 { type Output = DVec3; #[inline] fn div(self, rhs: &DVec3) -> DVec3 { self.div(*rhs) } } impl Div<&DVec3> for &f64 { type Output = DVec3; #[inline] fn div(self, rhs: &DVec3) -> DVec3 { (*self).div(*rhs) } } impl Div for &f64 { type Output = DVec3; #[inline] fn div(self, rhs: DVec3) -> DVec3 { (*self).div(rhs) } } impl Mul for DVec3 { 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 Mul<&DVec3> for DVec3 { type Output = DVec3; #[inline] fn mul(self, rhs: &DVec3) -> DVec3 { self.mul(*rhs) } } impl Mul<&DVec3> for &DVec3 { type Output = DVec3; #[inline] fn mul(self, rhs: &DVec3) -> DVec3 { (*self).mul(*rhs) } } impl Mul for &DVec3 { type Output = DVec3; #[inline] fn mul(self, rhs: DVec3) -> DVec3 { (*self).mul(rhs) } } impl MulAssign for DVec3 { #[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 MulAssign<&DVec3> for DVec3 { #[inline] fn mul_assign(&mut self, rhs: &DVec3) { self.mul_assign(*rhs) } } impl Mul for DVec3 { type Output = Self; #[inline] fn mul(self, rhs: f64) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&f64> for DVec3 { type Output = DVec3; #[inline] fn mul(self, rhs: &f64) -> DVec3 { self.mul(*rhs) } } impl Mul<&f64> for &DVec3 { type Output = DVec3; #[inline] fn mul(self, rhs: &f64) -> DVec3 { (*self).mul(*rhs) } } impl Mul for &DVec3 { type Output = DVec3; #[inline] fn mul(self, rhs: f64) -> DVec3 { (*self).mul(rhs) } } impl MulAssign for DVec3 { #[inline] fn mul_assign(&mut self, rhs: f64) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&f64> for DVec3 { #[inline] fn mul_assign(&mut self, rhs: &f64) { self.mul_assign(*rhs) } } impl Mul for f64 { type Output = DVec3; #[inline] fn mul(self, rhs: DVec3) -> DVec3 { DVec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&DVec3> for f64 { type Output = DVec3; #[inline] fn mul(self, rhs: &DVec3) -> DVec3 { self.mul(*rhs) } } impl Mul<&DVec3> for &f64 { type Output = DVec3; #[inline] fn mul(self, rhs: &DVec3) -> DVec3 { (*self).mul(*rhs) } } impl Mul for &f64 { type Output = DVec3; #[inline] fn mul(self, rhs: DVec3) -> DVec3 { (*self).mul(rhs) } } impl Add for DVec3 { 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 Add<&DVec3> for DVec3 { type Output = DVec3; #[inline] fn add(self, rhs: &DVec3) -> DVec3 { self.add(*rhs) } } impl Add<&DVec3> for &DVec3 { type Output = DVec3; #[inline] fn add(self, rhs: &DVec3) -> DVec3 { (*self).add(*rhs) } } impl Add for &DVec3 { type Output = DVec3; #[inline] fn add(self, rhs: DVec3) -> DVec3 { (*self).add(rhs) } } impl AddAssign for DVec3 { #[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 AddAssign<&DVec3> for DVec3 { #[inline] fn add_assign(&mut self, rhs: &DVec3) { self.add_assign(*rhs) } } impl Add for DVec3 { type Output = Self; #[inline] fn add(self, rhs: f64) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&f64> for DVec3 { type Output = DVec3; #[inline] fn add(self, rhs: &f64) -> DVec3 { self.add(*rhs) } } impl Add<&f64> for &DVec3 { type Output = DVec3; #[inline] fn add(self, rhs: &f64) -> DVec3 { (*self).add(*rhs) } } impl Add for &DVec3 { type Output = DVec3; #[inline] fn add(self, rhs: f64) -> DVec3 { (*self).add(rhs) } } impl AddAssign for DVec3 { #[inline] fn add_assign(&mut self, rhs: f64) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&f64> for DVec3 { #[inline] fn add_assign(&mut self, rhs: &f64) { self.add_assign(*rhs) } } impl Add for f64 { type Output = DVec3; #[inline] fn add(self, rhs: DVec3) -> DVec3 { DVec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&DVec3> for f64 { type Output = DVec3; #[inline] fn add(self, rhs: &DVec3) -> DVec3 { self.add(*rhs) } } impl Add<&DVec3> for &f64 { type Output = DVec3; #[inline] fn add(self, rhs: &DVec3) -> DVec3 { (*self).add(*rhs) } } impl Add for &f64 { type Output = DVec3; #[inline] fn add(self, rhs: DVec3) -> DVec3 { (*self).add(rhs) } } impl Sub for DVec3 { 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 Sub<&DVec3> for DVec3 { type Output = DVec3; #[inline] fn sub(self, rhs: &DVec3) -> DVec3 { self.sub(*rhs) } } impl Sub<&DVec3> for &DVec3 { type Output = DVec3; #[inline] fn sub(self, rhs: &DVec3) -> DVec3 { (*self).sub(*rhs) } } impl Sub for &DVec3 { type Output = DVec3; #[inline] fn sub(self, rhs: DVec3) -> DVec3 { (*self).sub(rhs) } } impl SubAssign for DVec3 { #[inline] fn sub_assign(&mut self, rhs: DVec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&DVec3> for DVec3 { #[inline] fn sub_assign(&mut self, rhs: &DVec3) { self.sub_assign(*rhs) } } impl Sub for DVec3 { type Output = Self; #[inline] fn sub(self, rhs: f64) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&f64> for DVec3 { type Output = DVec3; #[inline] fn sub(self, rhs: &f64) -> DVec3 { self.sub(*rhs) } } impl Sub<&f64> for &DVec3 { type Output = DVec3; #[inline] fn sub(self, rhs: &f64) -> DVec3 { (*self).sub(*rhs) } } impl Sub for &DVec3 { type Output = DVec3; #[inline] fn sub(self, rhs: f64) -> DVec3 { (*self).sub(rhs) } } impl SubAssign for DVec3 { #[inline] fn sub_assign(&mut self, rhs: f64) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&f64> for DVec3 { #[inline] fn sub_assign(&mut self, rhs: &f64) { self.sub_assign(*rhs) } } impl Sub for f64 { type Output = DVec3; #[inline] fn sub(self, rhs: DVec3) -> DVec3 { DVec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&DVec3> for f64 { type Output = DVec3; #[inline] fn sub(self, rhs: &DVec3) -> DVec3 { self.sub(*rhs) } } impl Sub<&DVec3> for &f64 { type Output = DVec3; #[inline] fn sub(self, rhs: &DVec3) -> DVec3 { (*self).sub(*rhs) } } impl Sub for &f64 { type Output = DVec3; #[inline] fn sub(self, rhs: DVec3) -> DVec3 { (*self).sub(rhs) } } impl Rem for DVec3 { 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 Rem<&DVec3> for DVec3 { type Output = DVec3; #[inline] fn rem(self, rhs: &DVec3) -> DVec3 { self.rem(*rhs) } } impl Rem<&DVec3> for &DVec3 { type Output = DVec3; #[inline] fn rem(self, rhs: &DVec3) -> DVec3 { (*self).rem(*rhs) } } impl Rem for &DVec3 { type Output = DVec3; #[inline] fn rem(self, rhs: DVec3) -> DVec3 { (*self).rem(rhs) } } impl RemAssign for DVec3 { #[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 RemAssign<&DVec3> for DVec3 { #[inline] fn rem_assign(&mut self, rhs: &DVec3) { self.rem_assign(*rhs) } } impl Rem for DVec3 { type Output = Self; #[inline] fn rem(self, rhs: f64) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&f64> for DVec3 { type Output = DVec3; #[inline] fn rem(self, rhs: &f64) -> DVec3 { self.rem(*rhs) } } impl Rem<&f64> for &DVec3 { type Output = DVec3; #[inline] fn rem(self, rhs: &f64) -> DVec3 { (*self).rem(*rhs) } } impl Rem for &DVec3 { type Output = DVec3; #[inline] fn rem(self, rhs: f64) -> DVec3 { (*self).rem(rhs) } } impl RemAssign for DVec3 { #[inline] fn rem_assign(&mut self, rhs: f64) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&f64> for DVec3 { #[inline] fn rem_assign(&mut self, rhs: &f64) { self.rem_assign(*rhs) } } impl Rem for f64 { type Output = DVec3; #[inline] fn rem(self, rhs: DVec3) -> DVec3 { DVec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&DVec3> for f64 { type Output = DVec3; #[inline] fn rem(self, rhs: &DVec3) -> DVec3 { self.rem(*rhs) } } impl Rem<&DVec3> for &f64 { type Output = DVec3; #[inline] fn rem(self, rhs: &DVec3) -> DVec3 { (*self).rem(*rhs) } } impl Rem for &f64 { type Output = DVec3; #[inline] fn rem(self, rhs: DVec3) -> DVec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 3]> for DVec3 { #[inline] fn as_ref(&self) -> &[f64; 3] { unsafe { &*(self as *const DVec3 as *const [f64; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f64; 3]> for DVec3 { #[inline] fn as_mut(&mut self) -> &mut [f64; 3] { unsafe { &mut *(self as *mut DVec3 as *mut [f64; 3]) } } } impl Sum for DVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for DVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for DVec3 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), z: self.z.neg(), } } } impl Neg for &DVec3 { type Output = DVec3; #[inline] fn neg(self) -> DVec3 { (*self).neg() } } impl Index for DVec3 { type Output = f64; #[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 for DVec3 { #[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"), } } } impl fmt::Display for DVec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) } else { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } } impl fmt::Debug for DVec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(DVec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[f64; 3]> for DVec3 { #[inline] fn from(a: [f64; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [f64; 3] { #[inline] fn from(v: DVec3) -> Self { [v.x, v.y, v.z] } } impl From<(f64, f64, f64)> for DVec3 { #[inline] fn from(t: (f64, f64, f64)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (f64, f64, f64) { #[inline] fn from(v: DVec3) -> Self { (v.x, v.y, v.z) } } impl From<(DVec2, f64)> for DVec3 { #[inline] fn from((v, z): (DVec2, f64)) -> Self { Self::new(v.x, v.y, z) } } impl From for DVec3 { #[inline] fn from(v: Vec3) -> Self { Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z)) } } impl From for DVec3 { #[inline] fn from(v: IVec3) -> Self { Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z)) } } impl From for DVec3 { #[inline] fn from(v: UVec3) -> Self { Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z)) } } impl From for DVec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(f64::from(v.x), f64::from(v.y), f64::from(v.z)) } } impl From for DVec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( f64::from(bool_array[0]), f64::from(bool_array[1]), f64::from(bool_array[2]), ) } } glam-0.30.1/src/f64/dvec4.rs000064400000000000000000001450701046102023000133750ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{f64::math, BVec4, DVec2, DVec3, IVec4, UVec4, Vec4}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// A 4-dimensional vector. #[derive(Clone, Copy, PartialEq)] #[cfg_attr(feature = "cuda", repr(align(16)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct DVec4 { pub x: f64, pub y: f64, pub z: f64, pub w: f64, } impl DVec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0.0); /// All ones. pub const ONE: Self = Self::splat(1.0); /// All negative ones. pub const NEG_ONE: Self = Self::splat(-1.0); /// 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); /// 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 vector pointing along the positive Y axis. pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0); /// 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 vector pointing along the positive W axis. pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0); /// 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 vector pointing along the negative Y axis. pub const NEG_Y: Self = Self::new(0.0, -1.0, 0.0, 0.0); /// 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 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. 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: 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, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(f64) -> f64, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: [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] } /// 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: &[f64]) -> Self { assert!(slice.len() >= 4); 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 [f64]) { slice[..4].copy_from_slice(&self.to_array()); } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. #[inline] #[must_use] pub fn truncate(self) -> DVec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: f64) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: f64) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: f64) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: f64) -> Self { self.w = w; self } /// 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)) } /// 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 [`f64::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) -> f64 { 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) -> f64 { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> f64 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> f64 { self.x * self.y * self.z * 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: math::abs(self.x), y: math::abs(self.y), z: math::abs(self.z), w: math::abs(self.w), } } /// Returns a vector with elements representing the sign of `self`. /// /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-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: 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: 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), } } /// 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_sign_negative() as u32) | ((self.y.is_sign_negative() as u32) << 1) | ((self.z.is_sign_negative() as u32) << 2) | ((self.w.is_sign_negative() as u32) << 3) } /// 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() } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> BVec4 { BVec4::new( 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() } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> BVec4 { BVec4::new( self.x.is_nan(), self.y.is_nan(), self.z.is_nan(), self.w.is_nan(), ) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> f64 { math::sqrt(self.dot(self)) } /// Computes the squared length of `self`. /// /// 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) } /// Computes `1.0 / length()`. /// /// 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 be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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: 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: 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: 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), } } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { 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( 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: 1.0 / self.x, y: 1.0 / self.y, z: 1.0 / self.z, w: 1.0 / self.w, } } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: f64) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: f64) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: f64, max: f64) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: f64) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: f64) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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( 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), ) } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: f64) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } } impl Default for DVec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for DVec4 { 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 Div<&DVec4> for DVec4 { type Output = DVec4; #[inline] fn div(self, rhs: &DVec4) -> DVec4 { self.div(*rhs) } } impl Div<&DVec4> for &DVec4 { type Output = DVec4; #[inline] fn div(self, rhs: &DVec4) -> DVec4 { (*self).div(*rhs) } } impl Div for &DVec4 { type Output = DVec4; #[inline] fn div(self, rhs: DVec4) -> DVec4 { (*self).div(rhs) } } impl DivAssign for DVec4 { #[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 DivAssign<&DVec4> for DVec4 { #[inline] fn div_assign(&mut self, rhs: &DVec4) { self.div_assign(*rhs) } } impl Div for DVec4 { type Output = Self; #[inline] fn div(self, rhs: f64) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&f64> for DVec4 { type Output = DVec4; #[inline] fn div(self, rhs: &f64) -> DVec4 { self.div(*rhs) } } impl Div<&f64> for &DVec4 { type Output = DVec4; #[inline] fn div(self, rhs: &f64) -> DVec4 { (*self).div(*rhs) } } impl Div for &DVec4 { type Output = DVec4; #[inline] fn div(self, rhs: f64) -> DVec4 { (*self).div(rhs) } } impl DivAssign for DVec4 { #[inline] fn div_assign(&mut self, rhs: f64) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&f64> for DVec4 { #[inline] fn div_assign(&mut self, rhs: &f64) { self.div_assign(*rhs) } } impl Div for f64 { type Output = DVec4; #[inline] fn div(self, rhs: DVec4) -> DVec4 { DVec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&DVec4> for f64 { type Output = DVec4; #[inline] fn div(self, rhs: &DVec4) -> DVec4 { self.div(*rhs) } } impl Div<&DVec4> for &f64 { type Output = DVec4; #[inline] fn div(self, rhs: &DVec4) -> DVec4 { (*self).div(*rhs) } } impl Div for &f64 { type Output = DVec4; #[inline] fn div(self, rhs: DVec4) -> DVec4 { (*self).div(rhs) } } impl Mul for DVec4 { 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 Mul<&DVec4> for DVec4 { type Output = DVec4; #[inline] fn mul(self, rhs: &DVec4) -> DVec4 { self.mul(*rhs) } } impl Mul<&DVec4> for &DVec4 { type Output = DVec4; #[inline] fn mul(self, rhs: &DVec4) -> DVec4 { (*self).mul(*rhs) } } impl Mul for &DVec4 { type Output = DVec4; #[inline] fn mul(self, rhs: DVec4) -> DVec4 { (*self).mul(rhs) } } impl MulAssign for DVec4 { #[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 MulAssign<&DVec4> for DVec4 { #[inline] fn mul_assign(&mut self, rhs: &DVec4) { self.mul_assign(*rhs) } } impl Mul for DVec4 { type Output = Self; #[inline] fn mul(self, rhs: f64) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&f64> for DVec4 { type Output = DVec4; #[inline] fn mul(self, rhs: &f64) -> DVec4 { self.mul(*rhs) } } impl Mul<&f64> for &DVec4 { type Output = DVec4; #[inline] fn mul(self, rhs: &f64) -> DVec4 { (*self).mul(*rhs) } } impl Mul for &DVec4 { type Output = DVec4; #[inline] fn mul(self, rhs: f64) -> DVec4 { (*self).mul(rhs) } } impl MulAssign for DVec4 { #[inline] fn mul_assign(&mut self, rhs: f64) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&f64> for DVec4 { #[inline] fn mul_assign(&mut self, rhs: &f64) { self.mul_assign(*rhs) } } impl Mul for f64 { type Output = DVec4; #[inline] fn mul(self, rhs: DVec4) -> DVec4 { DVec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&DVec4> for f64 { type Output = DVec4; #[inline] fn mul(self, rhs: &DVec4) -> DVec4 { self.mul(*rhs) } } impl Mul<&DVec4> for &f64 { type Output = DVec4; #[inline] fn mul(self, rhs: &DVec4) -> DVec4 { (*self).mul(*rhs) } } impl Mul for &f64 { type Output = DVec4; #[inline] fn mul(self, rhs: DVec4) -> DVec4 { (*self).mul(rhs) } } impl Add for DVec4 { 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 Add<&DVec4> for DVec4 { type Output = DVec4; #[inline] fn add(self, rhs: &DVec4) -> DVec4 { self.add(*rhs) } } impl Add<&DVec4> for &DVec4 { type Output = DVec4; #[inline] fn add(self, rhs: &DVec4) -> DVec4 { (*self).add(*rhs) } } impl Add for &DVec4 { type Output = DVec4; #[inline] fn add(self, rhs: DVec4) -> DVec4 { (*self).add(rhs) } } impl AddAssign for DVec4 { #[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 AddAssign<&DVec4> for DVec4 { #[inline] fn add_assign(&mut self, rhs: &DVec4) { self.add_assign(*rhs) } } impl Add for DVec4 { type Output = Self; #[inline] fn add(self, rhs: f64) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&f64> for DVec4 { type Output = DVec4; #[inline] fn add(self, rhs: &f64) -> DVec4 { self.add(*rhs) } } impl Add<&f64> for &DVec4 { type Output = DVec4; #[inline] fn add(self, rhs: &f64) -> DVec4 { (*self).add(*rhs) } } impl Add for &DVec4 { type Output = DVec4; #[inline] fn add(self, rhs: f64) -> DVec4 { (*self).add(rhs) } } impl AddAssign for DVec4 { #[inline] fn add_assign(&mut self, rhs: f64) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&f64> for DVec4 { #[inline] fn add_assign(&mut self, rhs: &f64) { self.add_assign(*rhs) } } impl Add for f64 { type Output = DVec4; #[inline] fn add(self, rhs: DVec4) -> DVec4 { DVec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&DVec4> for f64 { type Output = DVec4; #[inline] fn add(self, rhs: &DVec4) -> DVec4 { self.add(*rhs) } } impl Add<&DVec4> for &f64 { type Output = DVec4; #[inline] fn add(self, rhs: &DVec4) -> DVec4 { (*self).add(*rhs) } } impl Add for &f64 { type Output = DVec4; #[inline] fn add(self, rhs: DVec4) -> DVec4 { (*self).add(rhs) } } impl Sub for DVec4 { 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 Sub<&DVec4> for DVec4 { type Output = DVec4; #[inline] fn sub(self, rhs: &DVec4) -> DVec4 { self.sub(*rhs) } } impl Sub<&DVec4> for &DVec4 { type Output = DVec4; #[inline] fn sub(self, rhs: &DVec4) -> DVec4 { (*self).sub(*rhs) } } impl Sub for &DVec4 { type Output = DVec4; #[inline] fn sub(self, rhs: DVec4) -> DVec4 { (*self).sub(rhs) } } impl SubAssign for DVec4 { #[inline] fn sub_assign(&mut self, rhs: DVec4) { 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 SubAssign<&DVec4> for DVec4 { #[inline] fn sub_assign(&mut self, rhs: &DVec4) { self.sub_assign(*rhs) } } impl Sub for DVec4 { type Output = Self; #[inline] fn sub(self, rhs: f64) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&f64> for DVec4 { type Output = DVec4; #[inline] fn sub(self, rhs: &f64) -> DVec4 { self.sub(*rhs) } } impl Sub<&f64> for &DVec4 { type Output = DVec4; #[inline] fn sub(self, rhs: &f64) -> DVec4 { (*self).sub(*rhs) } } impl Sub for &DVec4 { type Output = DVec4; #[inline] fn sub(self, rhs: f64) -> DVec4 { (*self).sub(rhs) } } impl SubAssign for DVec4 { #[inline] fn sub_assign(&mut self, rhs: f64) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&f64> for DVec4 { #[inline] fn sub_assign(&mut self, rhs: &f64) { self.sub_assign(*rhs) } } impl Sub for f64 { type Output = DVec4; #[inline] fn sub(self, rhs: DVec4) -> DVec4 { DVec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&DVec4> for f64 { type Output = DVec4; #[inline] fn sub(self, rhs: &DVec4) -> DVec4 { self.sub(*rhs) } } impl Sub<&DVec4> for &f64 { type Output = DVec4; #[inline] fn sub(self, rhs: &DVec4) -> DVec4 { (*self).sub(*rhs) } } impl Sub for &f64 { type Output = DVec4; #[inline] fn sub(self, rhs: DVec4) -> DVec4 { (*self).sub(rhs) } } impl Rem for DVec4 { 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 Rem<&DVec4> for DVec4 { type Output = DVec4; #[inline] fn rem(self, rhs: &DVec4) -> DVec4 { self.rem(*rhs) } } impl Rem<&DVec4> for &DVec4 { type Output = DVec4; #[inline] fn rem(self, rhs: &DVec4) -> DVec4 { (*self).rem(*rhs) } } impl Rem for &DVec4 { type Output = DVec4; #[inline] fn rem(self, rhs: DVec4) -> DVec4 { (*self).rem(rhs) } } impl RemAssign for DVec4 { #[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 RemAssign<&DVec4> for DVec4 { #[inline] fn rem_assign(&mut self, rhs: &DVec4) { self.rem_assign(*rhs) } } impl Rem for DVec4 { type Output = Self; #[inline] fn rem(self, rhs: f64) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&f64> for DVec4 { type Output = DVec4; #[inline] fn rem(self, rhs: &f64) -> DVec4 { self.rem(*rhs) } } impl Rem<&f64> for &DVec4 { type Output = DVec4; #[inline] fn rem(self, rhs: &f64) -> DVec4 { (*self).rem(*rhs) } } impl Rem for &DVec4 { type Output = DVec4; #[inline] fn rem(self, rhs: f64) -> DVec4 { (*self).rem(rhs) } } impl RemAssign for DVec4 { #[inline] fn rem_assign(&mut self, rhs: f64) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&f64> for DVec4 { #[inline] fn rem_assign(&mut self, rhs: &f64) { self.rem_assign(*rhs) } } impl Rem for f64 { type Output = DVec4; #[inline] fn rem(self, rhs: DVec4) -> DVec4 { DVec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&DVec4> for f64 { type Output = DVec4; #[inline] fn rem(self, rhs: &DVec4) -> DVec4 { self.rem(*rhs) } } impl Rem<&DVec4> for &f64 { type Output = DVec4; #[inline] fn rem(self, rhs: &DVec4) -> DVec4 { (*self).rem(*rhs) } } impl Rem for &f64 { type Output = DVec4; #[inline] fn rem(self, rhs: DVec4) -> DVec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[f64; 4]> for DVec4 { #[inline] fn as_ref(&self) -> &[f64; 4] { unsafe { &*(self as *const DVec4 as *const [f64; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[f64; 4]> for DVec4 { #[inline] fn as_mut(&mut self) -> &mut [f64; 4] { unsafe { &mut *(self as *mut DVec4 as *mut [f64; 4]) } } } impl Sum for DVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for DVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for DVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for DVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for DVec4 { 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 Neg for &DVec4 { type Output = DVec4; #[inline] fn neg(self) -> DVec4 { (*self).neg() } } impl Index for DVec4 { type Output = f64; #[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 for DVec4 { #[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"), } } } impl fmt::Display for DVec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!( f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w ) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl fmt::Debug for DVec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(DVec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[f64; 4]> for DVec4 { #[inline] fn from(a: [f64; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [f64; 4] { #[inline] fn from(v: DVec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(f64, f64, f64, f64)> for DVec4 { #[inline] fn from(t: (f64, f64, f64, f64)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (f64, f64, f64, f64) { #[inline] fn from(v: DVec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(DVec3, f64)> for DVec4 { #[inline] fn from((v, w): (DVec3, f64)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(f64, DVec3)> for DVec4 { #[inline] fn from((x, v): (f64, DVec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(DVec2, f64, f64)> for DVec4 { #[inline] fn from((v, z, w): (DVec2, f64, f64)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(DVec2, DVec2)> for DVec4 { #[inline] fn from((v, u): (DVec2, DVec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl From 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 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 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), ) } } impl From for DVec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( f64::from(v.x), f64::from(v.y), f64::from(v.z), f64::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for DVec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( f64::from(bool_array[0]), f64::from(bool_array[1]), f64::from(bool_array[2]), f64::from(bool_array[3]), ) } } glam-0.30.1/src/f64/float.rs000064400000000000000000000010411046102023000134620ustar 00000000000000// 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) } } glam-0.30.1/src/f64/math.rs000064400000000000000000000135311046102023000133150ustar 00000000000000#[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))] 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 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(all(not(feature = "libm"), feature = "std"))] 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 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) } } // Used to reduce the number of compilation errors, in the event that no other // math backend is specified. #[cfg(all( not(feature = "libm"), not(feature = "std"), not(feature = "nostd-libm") ))] mod no_backend_math { pub(crate) fn abs(_: f64) -> f64 { unimplemented!() } pub(crate) fn acos_approx(_: f64) -> f64 { unimplemented!() } pub(crate) fn atan2(_: f64, _: f64) -> f64 { unimplemented!() } pub(crate) fn sin(_: f64) -> f64 { unimplemented!() } pub(crate) fn sin_cos(_: f64) -> (f64, f64) { unimplemented!() } pub(crate) fn tan(_: f64) -> f64 { unimplemented!() } pub(crate) fn sqrt(_: f64) -> f64 { unimplemented!() } pub(crate) fn copysign(_: f64, _: f64) -> f64 { unimplemented!() } pub(crate) fn signum(_: f64) -> f64 { unimplemented!() } pub(crate) fn round(_: f64) -> f64 { unimplemented!() } pub(crate) fn trunc(_: f64) -> f64 { unimplemented!() } pub(crate) fn ceil(_: f64) -> f64 { unimplemented!() } pub(crate) fn floor(_: f64) -> f64 { unimplemented!() } pub(crate) fn exp(_: f64) -> f64 { unimplemented!() } pub(crate) fn powf(_: f64, _: f64) -> f64 { unimplemented!() } pub(crate) fn mul_add(_: f64, _: f64, _: f64) -> f64 { unimplemented!() } pub fn div_euclid(_: f64, _: f64) -> f64 { unimplemented!() } pub fn rem_euclid(_: f64, _: f64) -> f64 { unimplemented!() } } #[cfg(any(feature = "libm", all(feature = "nostd-libm", not(feature = "std"))))] pub(crate) use libm_math::*; #[cfg(all(not(feature = "libm"), feature = "std"))] pub(crate) use std_math::*; #[cfg(all( not(feature = "libm"), not(feature = "std"), not(feature = "nostd-libm") ))] pub(crate) use no_backend_math::*; glam-0.30.1/src/f64.rs000064400000000000000000000057621046102023000123730ustar 00000000000000mod daffine2; mod daffine3; mod dmat2; mod dmat3; mod dmat4; mod dquat; mod dvec2; mod dvec3; mod dvec4; mod float; pub(crate) mod math; pub use daffine2::DAffine2; pub use daffine3::DAffine3; pub use dmat2::{dmat2, DMat2}; pub use dmat3::{dmat3, DMat3}; pub use dmat4::{dmat4, DMat4}; pub use dquat::{dquat, DQuat}; pub use dvec2::{dvec2, DVec2}; pub use dvec3::{dvec3, DVec3}; pub use dvec4::{dvec4, DVec4}; #[cfg(not(target_arch = "spirv"))] mod test { pub use super::*; mod const_test_daffine2 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(48, core::mem::size_of::()); } mod const_test_dmat2 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(32, core::mem::size_of::()); } mod const_test_dmat3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(72, core::mem::size_of::()); } mod const_test_dmat4 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(128, core::mem::size_of::()); } mod const_test_dquat { #[cfg(not(target_arch = "spirv"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(target_arch = "spirv")] const_assert_eq!(32, core::mem::align_of::()); const_assert_eq!(32, core::mem::size_of::()); } mod const_test_dvec2 { #[cfg(not(any(feature = "cuda", target_arch = "spirv")))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(any(feature = "cuda", target_arch = "spirv"))] const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(16, core::mem::size_of::()); } mod const_test_dvec3 { #[cfg(not(target_arch = "spirv"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(target_arch = "spirv")] const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(24, core::mem::size_of::()); } mod const_test_dvec4 { #[cfg(not(any(feature = "cuda", target_arch = "spirv")))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(any(feature = "cuda", target_arch = "spirv"))] const_assert_eq!(16, core::mem::align_of::()); const_assert_eq!(32, core::mem::size_of::()); } } glam-0.30.1/src/features/impl_approx.rs000064400000000000000000000200261046102023000161320ustar 00000000000000use crate::{ Affine2, Affine3A, DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4, }; use approx::{AbsDiffEq, RelativeEq, UlpsEq}; macro_rules! impl_approx_as_ref { ($prim:ident, $type:ty) => { impl AbsDiffEq for $type { type Epsilon = <$prim as AbsDiffEq>::Epsilon; fn default_epsilon() -> Self::Epsilon { $prim::default_epsilon() } fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { self.as_ref().abs_diff_eq(other.as_ref(), epsilon) } } impl RelativeEq for $type { fn default_max_relative() -> Self::Epsilon { $prim::default_max_relative() } fn relative_eq( &self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { self.as_ref() .relative_eq(other.as_ref(), epsilon, max_relative) } } impl UlpsEq for $type { fn default_max_ulps() -> u32 { $prim::default_max_ulps() } fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { self.as_ref().ulps_eq(other.as_ref(), epsilon, max_ulps) } } }; } macro_rules! impl_approx_xzy_axes { ($prim:ident, $type:ty) => { impl AbsDiffEq for $type { type Epsilon = <$prim as AbsDiffEq>::Epsilon; fn default_epsilon() -> Self::Epsilon { $prim::default_epsilon() } fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { AbsDiffEq::abs_diff_eq(&self.x_axis, &other.x_axis, epsilon) && AbsDiffEq::abs_diff_eq(&self.y_axis, &other.y_axis, epsilon) && AbsDiffEq::abs_diff_eq(&self.z_axis, &other.z_axis, epsilon) } } impl RelativeEq for $type { fn default_max_relative() -> Self::Epsilon { $prim::default_max_relative() } fn relative_eq( &self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { RelativeEq::relative_eq(&self.x_axis, &other.x_axis, epsilon, max_relative) && RelativeEq::relative_eq(&self.y_axis, &other.y_axis, epsilon, max_relative) && RelativeEq::relative_eq(&self.z_axis, &other.z_axis, epsilon, max_relative) } } impl UlpsEq for $type { fn default_max_ulps() -> u32 { $prim::default_max_ulps() } fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { UlpsEq::ulps_eq(&self.x_axis, &other.x_axis, epsilon, max_ulps) && UlpsEq::ulps_eq(&self.y_axis, &other.y_axis, epsilon, max_ulps) && UlpsEq::ulps_eq(&self.z_axis, &other.z_axis, epsilon, max_ulps) } } }; } macro_rules! impl_approx_xzyw_axes { ($prim:ident, $type:ty) => { impl AbsDiffEq for $type { type Epsilon = <$prim as AbsDiffEq>::Epsilon; fn default_epsilon() -> Self::Epsilon { $prim::default_epsilon() } fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { AbsDiffEq::abs_diff_eq(&self.x_axis, &other.x_axis, epsilon) && AbsDiffEq::abs_diff_eq(&self.y_axis, &other.y_axis, epsilon) && AbsDiffEq::abs_diff_eq(&self.z_axis, &other.z_axis, epsilon) && AbsDiffEq::abs_diff_eq(&self.w_axis, &other.w_axis, epsilon) } } impl RelativeEq for $type { fn default_max_relative() -> Self::Epsilon { $prim::default_max_relative() } fn relative_eq( &self, other: &Self, epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { RelativeEq::relative_eq(&self.x_axis, &other.x_axis, epsilon, max_relative) && RelativeEq::relative_eq(&self.y_axis, &other.y_axis, epsilon, max_relative) && RelativeEq::relative_eq(&self.z_axis, &other.z_axis, epsilon, max_relative) && RelativeEq::relative_eq(&self.w_axis, &other.w_axis, epsilon, max_relative) } } impl UlpsEq for $type { fn default_max_ulps() -> u32 { $prim::default_max_ulps() } fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { UlpsEq::ulps_eq(&self.x_axis, &other.x_axis, epsilon, max_ulps) && UlpsEq::ulps_eq(&self.y_axis, &other.y_axis, epsilon, max_ulps) && UlpsEq::ulps_eq(&self.z_axis, &other.z_axis, epsilon, max_ulps) && UlpsEq::ulps_eq(&self.w_axis, &other.w_axis, epsilon, max_ulps) } } }; } impl_approx_as_ref!(f32, Mat2); impl_approx_as_ref!(f32, Mat3); impl_approx_as_ref!(f32, Mat4); impl_approx_as_ref!(f32, Quat); impl_approx_as_ref!(f32, Vec2); impl_approx_as_ref!(f32, Vec3); impl_approx_as_ref!(f32, Vec4); impl_approx_as_ref!(f32, Vec3A); impl_approx_xzy_axes!(f32, Affine2); impl_approx_xzyw_axes!(f32, Affine3A); impl_approx_xzy_axes!(f32, Mat3A); impl_approx_xzy_axes!(f64, DAffine2); impl_approx_xzyw_axes!(f64, DAffine3); impl_approx_as_ref!(f64, DMat2); impl_approx_as_ref!(f64, DMat3); impl_approx_as_ref!(f64, DMat4); impl_approx_as_ref!(f64, DQuat); impl_approx_as_ref!(f64, DVec2); impl_approx_as_ref!(f64, DVec3); impl_approx_as_ref!(f64, DVec4); #[cfg(test)] mod test { use crate::*; use approx::*; macro_rules! impl_approx_test { ($prim:ident, $type:ident, $ones:expr) => { let one_eps = $ones * $type::default_epsilon(); let two_eps = one_eps + one_eps; let one_ulp = $ones * $prim::from_bits($prim::to_bits(1.0) + 1); let four_ulp = $ones * $prim::from_bits($prim::to_bits(1.0) + 16); approx::assert_abs_diff_eq!($ones, $ones); approx::assert_abs_diff_eq!($ones, $ones + one_eps); approx::assert_abs_diff_eq!($ones, $ones - one_eps); approx::assert_abs_diff_ne!($ones, $ones + two_eps); approx::assert_abs_diff_ne!($ones, $ones - two_eps); approx::assert_relative_eq!($ones, $ones); approx::assert_relative_ne!($ones, $ones - $ones); // defaults to 4 ulps and I have no idea how to pass other parameters to this macro :) approx::assert_ulps_eq!($ones, one_ulp); approx::assert_ulps_ne!($ones, four_ulp); }; ($prim:ident, $type:ident) => { impl_approx_test!($prim, $type, $type::ONE) }; } #[test] fn test_approx() { const ONESF32: [f32; 16] = [1.0; 16]; impl_approx_test!(f32, Vec2); impl_approx_test!(f32, Vec3); impl_approx_test!(f32, Vec3A); impl_approx_test!(f32, Vec4); impl_approx_test!(f32, Quat, Quat::from_slice(&ONESF32)); impl_approx_test!(f32, Mat2, Mat2::from_cols_slice(&ONESF32)); impl_approx_test!(f32, Mat3, Mat3::from_cols_slice(&ONESF32)); impl_approx_test!(f32, Mat3A, Mat3A::from_cols_slice(&ONESF32)); impl_approx_test!(f32, Mat4, Mat4::from_cols_slice(&ONESF32)); const ONESF64: [f64; 16] = [1.0; 16]; impl_approx_test!(f64, DVec2); impl_approx_test!(f64, DVec3); impl_approx_test!(f64, DVec4); impl_approx_test!(f64, DQuat, DQuat::from_slice(&ONESF64)); impl_approx_test!(f64, DMat2, DMat2::from_cols_slice(&ONESF64)); impl_approx_test!(f64, DMat3, DMat3::from_cols_slice(&ONESF64)); impl_approx_test!(f64, DMat4, DMat4::from_cols_slice(&ONESF64)); } } glam-0.30.1/src/features/impl_bytemuck.rs000064400000000000000000000143441046102023000164520ustar 00000000000000use crate::{ Affine2, Affine3A, DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, I16Vec2, I16Vec3, I16Vec4, I64Vec2, I64Vec3, I64Vec4, I8Vec2, I8Vec3, I8Vec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat3A, Mat4, Quat, U16Vec2, U16Vec3, U16Vec4, U64Vec2, U64Vec3, U64Vec4, U8Vec2, U8Vec3, U8Vec4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4, }; 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 {} unsafe impl Pod for Quat {} unsafe impl Zeroable for Quat {} unsafe impl Pod for Vec2 {} 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 {} unsafe impl Zeroable for DMat3 {} unsafe impl Pod for DMat4 {} unsafe impl Zeroable for DMat4 {} unsafe impl Pod for DQuat {} unsafe impl Zeroable for DQuat {} unsafe impl Pod for DVec2 {} unsafe impl Zeroable for DVec2 {} unsafe impl Pod for DVec3 {} unsafe impl Zeroable for DVec3 {} unsafe impl Pod for DVec4 {} unsafe impl Zeroable for DVec4 {} unsafe impl Pod for I8Vec2 {} unsafe impl Zeroable for I8Vec2 {} unsafe impl Pod for I8Vec3 {} unsafe impl Zeroable for I8Vec3 {} unsafe impl Pod for I8Vec4 {} unsafe impl Zeroable for I8Vec4 {} unsafe impl Pod for U8Vec2 {} unsafe impl Zeroable for U8Vec2 {} unsafe impl Pod for U8Vec3 {} unsafe impl Zeroable for U8Vec3 {} unsafe impl Pod for U8Vec4 {} unsafe impl Zeroable for U8Vec4 {} 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 {} unsafe impl Zeroable for IVec3 {} unsafe impl Pod for IVec4 {} unsafe impl Zeroable for IVec4 {} unsafe impl Pod for UVec2 {} unsafe impl Zeroable for UVec2 {} unsafe impl Pod for UVec3 {} unsafe impl Zeroable for UVec3 {} 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::{ Affine2, Affine3A, DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, I16Vec2, I16Vec3, I16Vec4, I64Vec2, I64Vec3, I64Vec4, I8Vec2, I8Vec3, I8Vec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat3A, Mat4, Quat, U16Vec2, U16Vec3, U16Vec4, U64Vec2, U64Vec3, U64Vec4, U8Vec2, U8Vec3, U8Vec4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4, }; use core::mem; macro_rules! test_pod_t { ($name:ident, $t:ty) => { #[test] fn $name() { let t = <$t>::default(); let b = bytemuck::bytes_of(&t); // 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)); } }; } 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_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_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_pod_t!(i8vec2, I8Vec2); test_pod_t!(i8vec3, I8Vec3); test_pod_t!(i8vec4, I8Vec4); test_pod_t!(u8vec2, U8Vec2); test_pod_t!(u8vec3, U8Vec3); test_pod_t!(u8vec4, U8Vec4); 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); } glam-0.30.1/src/features/impl_mint.rs000064400000000000000000000363471046102023000156050ustar 00000000000000use mint::IntoMint; use crate::{ DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, I16Vec2, I16Vec3, I16Vec4, I64Vec2, I64Vec3, I64Vec4, I8Vec2, I8Vec3, I8Vec4, IVec2, IVec3, IVec4, Mat2, Mat3, Mat3A, Mat4, Quat, U16Vec2, U16Vec3, U16Vec4, U64Vec2, U64Vec3, U64Vec4, U8Vec2, U8Vec3, U8Vec4, USizeVec2, USizeVec3, USizeVec4, UVec2, UVec3, UVec4, Vec2, Vec3, Vec3A, Vec4, }; macro_rules! impl_vec_types { ($t:ty, $vec2:ty, $vec3:ty, $vec4:ty) => { impl From> for $vec2 { fn from(v: mint::Point2<$t>) -> Self { Self::new(v.x, v.y) } } impl From<$vec2> for mint::Point2<$t> { fn from(v: $vec2) -> Self { Self { x: v.x, y: v.y } } } impl From> for $vec2 { fn from(v: mint::Vector2<$t>) -> Self { Self::new(v.x, v.y) } } impl From<$vec2> for mint::Vector2<$t> { fn from(v: $vec2) -> Self { Self { x: v.x, y: v.y } } } impl IntoMint for $vec2 { type MintType = mint::Vector2<$t>; } impl From> for $vec3 { fn from(v: mint::Point3<$t>) -> Self { Self::new(v.x, v.y, v.z) } } impl From<$vec3> for mint::Point3<$t> { fn from(v: $vec3) -> Self { Self { x: v.x, y: v.y, z: v.z, } } } impl From> for $vec3 { fn from(v: mint::Vector3<$t>) -> Self { Self::new(v.x, v.y, v.z) } } impl From<$vec3> for mint::Vector3<$t> { fn from(v: $vec3) -> Self { Self { x: v.x, y: v.y, z: v.z, } } } impl IntoMint for $vec3 { type MintType = mint::Vector3<$t>; } impl From> for $vec4 { fn from(v: mint::Vector4<$t>) -> Self { Self::new(v.x, v.y, v.z, v.w) } } impl From<$vec4> for mint::Vector4<$t> { fn from(v: $vec4) -> Self { Self { x: v.x, y: v.y, z: v.z, w: v.w, } } } impl IntoMint for $vec4 { type MintType = mint::Vector4<$t>; } }; } macro_rules! impl_float_types { ($t:ty, $mat2:ty, $mat3:ty, $mat4:ty, $quat:ty, $vec2:ty, $vec3:ty, $vec4:ty) => { impl_vec_types!($t, $vec2, $vec3, $vec4); impl From> for $quat { fn from(q: mint::Quaternion<$t>) -> Self { Self::from_xyzw(q.v.x, q.v.y, q.v.z, q.s) } } impl From<$quat> for mint::Quaternion<$t> { fn from(q: $quat) -> Self { Self { s: q.w, v: mint::Vector3 { x: q.x, y: q.y, z: q.z, }, } } } impl IntoMint for $quat { type MintType = mint::Quaternion<$t>; } impl From> for $mat2 { fn from(m: mint::RowMatrix2<$t>) -> Self { Self::from_cols(m.x.into(), m.y.into()).transpose() } } impl From<$mat2> for mint::RowMatrix2<$t> { fn from(m: $mat2) -> Self { let mt = m.transpose(); Self { x: mt.x_axis.into(), y: mt.y_axis.into(), } } } impl From> for $mat2 { fn from(m: mint::ColumnMatrix2<$t>) -> Self { Self::from_cols(m.x.into(), m.y.into()) } } impl From<$mat2> for mint::ColumnMatrix2<$t> { fn from(m: $mat2) -> Self { Self { x: m.x_axis.into(), y: m.y_axis.into(), } } } impl IntoMint for $mat2 { type MintType = mint::ColumnMatrix2<$t>; } impl From> for $mat3 { fn from(m: mint::RowMatrix3<$t>) -> Self { Self::from_cols(m.x.into(), m.y.into(), m.z.into()).transpose() } } impl From<$mat3> for mint::RowMatrix3<$t> { fn from(m: $mat3) -> Self { let mt = m.transpose(); Self { x: mt.x_axis.into(), y: mt.y_axis.into(), z: mt.z_axis.into(), } } } impl From> for $mat3 { fn from(m: mint::ColumnMatrix3<$t>) -> Self { Self::from_cols(m.x.into(), m.y.into(), m.z.into()) } } impl From<$mat3> for mint::ColumnMatrix3<$t> { fn from(m: $mat3) -> Self { Self { x: m.x_axis.into(), y: m.y_axis.into(), z: m.z_axis.into(), } } } impl IntoMint for $mat3 { type MintType = mint::ColumnMatrix3<$t>; } impl From> for $mat4 { fn from(m: mint::RowMatrix4<$t>) -> Self { Self::from_cols(m.x.into(), m.y.into(), m.z.into(), m.w.into()).transpose() } } impl From<$mat4> for mint::RowMatrix4<$t> { fn from(m: $mat4) -> Self { let mt = m.transpose(); Self { x: mt.x_axis.into(), y: mt.y_axis.into(), z: mt.z_axis.into(), w: mt.w_axis.into(), } } } impl From> for $mat4 { fn from(m: mint::ColumnMatrix4<$t>) -> Self { Self::from_cols(m.x.into(), m.y.into(), m.z.into(), m.w.into()) } } impl From<$mat4> for mint::ColumnMatrix4<$t> { fn from(m: $mat4) -> Self { Self { x: m.x_axis.into(), y: m.y_axis.into(), z: m.z_axis.into(), w: m.w_axis.into(), } } } impl IntoMint for $mat4 { type MintType = mint::ColumnMatrix4<$t>; } }; } impl From> for Vec3A { fn from(v: mint::Point3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for mint::Point3 { fn from(v: Vec3A) -> Self { Self { x: v.x, y: v.y, z: v.z, } } } impl From> for Vec3A { fn from(v: mint::Vector3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for mint::Vector3 { fn from(v: Vec3A) -> Self { Self { x: v.x, y: v.y, z: v.z, } } } impl IntoMint for Vec3A { type MintType = mint::Vector3; } impl From> for Mat3A { fn from(m: mint::RowMatrix3) -> Self { Self::from_cols(m.x.into(), m.y.into(), m.z.into()).transpose() } } impl From for mint::RowMatrix3 { fn from(m: Mat3A) -> Self { let mt = m.transpose(); Self { x: mt.x_axis.into(), y: mt.y_axis.into(), z: mt.z_axis.into(), } } } impl From> for Mat3A { fn from(m: mint::ColumnMatrix3) -> Self { Self::from_cols(m.x.into(), m.y.into(), m.z.into()) } } impl From for mint::ColumnMatrix3 { fn from(m: Mat3A) -> Self { Self { x: m.x_axis.into(), y: m.y_axis.into(), z: m.z_axis.into(), } } } impl IntoMint for Mat3A { type MintType = mint::ColumnMatrix3; } 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!(i8, I8Vec2, I8Vec3, I8Vec4); impl_vec_types!(u8, U8Vec2, U8Vec3, U8Vec4); 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); impl_vec_types!(usize, USizeVec2, USizeVec3, USizeVec4); #[cfg(test)] mod test { macro_rules! impl_vec_tests { ($t:ty, $vec2:ident, $vec3:ident, $vec4:ident) => { use crate::{$vec2, $vec3, $vec4}; use mint; #[test] fn test_point2() { let m = mint::Point2 { x: 1 as $t, y: 2 as $t, }; let g = $vec2::from(m); assert_eq!(g, $vec2::new(1 as $t, 2 as $t)); assert_eq!(m, g.into()); } #[test] fn test_point3() { let m = mint::Point3 { x: 1 as $t, y: 2 as $t, z: 3 as $t, }; let g = $vec3::from(m); assert_eq!(g, $vec3::new(1 as $t, 2 as $t, 3 as $t)); assert_eq!(m, g.into()); } #[test] fn test_vector2() { let m = mint::Vector2 { x: 1 as $t, y: 2 as $t, }; let g = $vec2::from(m); assert_eq!(g, $vec2::new(1 as $t, 2 as $t)); assert_eq!(m, g.into()); } #[test] fn test_vector3() { let m = mint::Vector3 { x: 1 as $t, y: 2 as $t, z: 3 as $t, }; let g = $vec3::from(m); assert_eq!(g, $vec3::new(1 as $t, 2 as $t, 3 as $t)); assert_eq!(m, g.into()); } #[test] fn test_vector4() { let m = mint::Vector4 { x: 1 as $t, y: 2 as $t, z: 3 as $t, w: 4 as $t, }; let g = $vec4::from(m); assert_eq!(g, $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t)); assert_eq!(m, g.into()); } }; } macro_rules! impl_float_tests { ($t:ty, $mat2:ident, $mat3:ident, $mat4:ident, $quat:ident, $vec2:ident, $vec3:ident, $vec4:ident) => { impl_vec_tests!($t, $vec2, $vec3, $vec4); use crate::{$mat2, $mat3, $mat4, $quat}; #[test] fn test_quaternion() { let m = mint::Quaternion { v: mint::Vector3 { x: 1.0, y: 2.0, z: 3.0, }, s: 4.0, }; let g = $quat::from(m); assert_eq!(g, $quat::from_xyzw(1.0, 2.0, 3.0, 4.0)); assert_eq!(m, g.into()); } #[test] fn test_matrix2() { let g = $mat2::from_cols_array_2d(&[[1.0, 2.0], [3.0, 4.0]]); let m = mint::ColumnMatrix2::from(g); assert_eq!(g, $mat2::from(m)); let mt = mint::RowMatrix2::from(g); assert_eq!(mt, mint::RowMatrix2::from([[1.0, 3.0], [2.0, 4.0]])); assert_eq!(g, $mat2::from(mt)); } #[test] fn test_matrix3() { let g = $mat3::from_cols_array_2d(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]); let m = mint::ColumnMatrix3::from(g); assert_eq!(g, $mat3::from(m)); let mt = mint::RowMatrix3::from(g); assert_eq!( mt, mint::RowMatrix3::from([[1.0, 4.0, 7.0], [2.0, 5.0, 8.0], [3.0, 6.0, 9.0]]) ); assert_eq!(g, $mat3::from(mt)); } #[test] fn test_matrix4() { let g = $mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0], ]); let m = mint::ColumnMatrix4::from(g); assert_eq!(g, $mat4::from(m)); let mt = mint::RowMatrix4::from(g); assert_eq!( mt, mint::RowMatrix4::from([ [1.0, 5.0, 9.0, 13.0], [2.0, 6.0, 10.0, 14.0], [3.0, 7.0, 11.0, 15.0], [4.0, 8.0, 12.0, 16.0] ]) ); assert_eq!(g, $mat4::from(mt)); } }; } mod f32 { impl_float_tests!(f32, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec4); #[test] fn test_point3a() { use crate::Vec3A; let m = mint::Point3 { x: 1.0, y: 2.0, z: 3.0, }; let g = Vec3A::from(m); assert_eq!(g, Vec3A::new(1.0, 2.0, 3.0)); assert_eq!(m, g.into()); } #[test] fn test_vector3a() { use crate::Vec3A; let m = mint::Vector3 { x: 1.0, y: 2.0, z: 3.0, }; let g = Vec3A::from(m); assert_eq!(g, Vec3A::new(1.0, 2.0, 3.0)); assert_eq!(m, g.into()); } #[test] fn test_mat3a_col_major() { use crate::Mat3A; let m = mint::ColumnMatrix3 { x: [0.0, 1.0, 2.0].into(), y: [3.0, 4.0, 5.0].into(), z: [6.0, 7.0, 8.0].into(), }; let expected = Mat3A::from_cols( [0.0, 1.0, 2.0].into(), [3.0, 4.0, 5.0].into(), [6.0, 7.0, 8.0].into(), ); assert_eq!(expected, m.into()); assert_eq!(m, expected.into()); } #[test] fn test_mat3a_row_major() { use crate::Mat3A; let m = mint::RowMatrix3 { x: [0.0, 1.0, 2.0].into(), y: [3.0, 4.0, 5.0].into(), z: [6.0, 7.0, 8.0].into(), }; let expected = Mat3A::from_cols( [0.0, 3.0, 6.0].into(), [1.0, 4.0, 7.0].into(), [2.0, 5.0, 8.0].into(), ); assert_eq!(expected, m.into()); assert_eq!(m, expected.into()); } } mod f64 { impl_float_tests!(f64, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4); } mod i32 { impl_vec_tests!(i32, IVec2, IVec3, IVec4); } mod u32 { impl_vec_tests!(u32, UVec2, UVec3, UVec4); } } glam-0.30.1/src/features/impl_rand.rs000064400000000000000000000555011046102023000155530ustar 00000000000000macro_rules! impl_vec_types { ( $t:ty, $vec2:ident, $vec3:ident, $vec4:ident, $uniform:ident, $upper_range_multiplier:expr ) => { use super::{UniformVec2, UniformVec3, UniformVec4}; use rand::{ distr::{ uniform::{Error as UniformError, SampleBorrow, SampleUniform, UniformSampler}, Distribution, StandardUniform, }, Rng, }; impl Distribution<$vec2> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $vec2 { rng.random::<[$t; 2]>().into() } } impl SampleUniform for $vec2 { type Sampler = UniformVec2<$uniform<$t>>; } impl UniformSampler for UniformVec2<$uniform<$t>> { type X = $vec2; fn new(low_b: B1, high_b: B2) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y { return Err(UniformError::EmptyRange); } Ok(Self { x_gen: $uniform::new(low.x, high.x)?, y_gen: $uniform::new(low.y, high.y)?, }) } fn new_inclusive(low_b: B1, high_b: B2) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y { return Err(UniformError::EmptyRange); } Ok(Self { x_gen: $uniform::new_inclusive(low.x, high.x)?, y_gen: $uniform::new_inclusive(low.y, high.y)?, }) } fn sample(&self, rng: &mut R) -> Self::X { Self::X::from([self.x_gen.sample(rng), self.y_gen.sample(rng)]) } fn sample_single( low_b: B1, high_b: B2, rng: &mut R, ) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y { return Err(UniformError::EmptyRange); } Ok(Self::X::from([ $uniform::<$t>::sample_single(low.x, high.x, rng)?, $uniform::<$t>::sample_single(low.y, high.y, rng)?, ])) } fn sample_single_inclusive( low_b: B1, high_b: B2, rng: &mut R, ) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y { return Err(UniformError::EmptyRange); } Ok(Self::X::from([ $uniform::<$t>::sample_single_inclusive(low.x, high.x, rng)?, $uniform::<$t>::sample_single_inclusive(low.y, high.y, rng)?, ])) } } impl Distribution<$vec3> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $vec3 { rng.random::<[$t; 3]>().into() } } impl SampleUniform for $vec3 { type Sampler = UniformVec3<$uniform<$t>>; } impl UniformSampler for UniformVec3<$uniform<$t>> { type X = $vec3; fn new(low_b: B1, high_b: B2) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z { return Err(UniformError::EmptyRange); } Ok(Self { x_gen: $uniform::new(low.x, high.x)?, y_gen: $uniform::new(low.y, high.y)?, z_gen: $uniform::new(low.z, high.z)?, }) } fn new_inclusive(low_b: B1, high_b: B2) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z { return Err(UniformError::EmptyRange); } Ok(Self { x_gen: $uniform::new_inclusive(low.x, high.x)?, y_gen: $uniform::new_inclusive(low.y, high.y)?, z_gen: $uniform::new_inclusive(low.z, high.z)?, }) } fn sample(&self, rng: &mut R) -> Self::X { Self::X::from([ self.x_gen.sample(rng), self.y_gen.sample(rng), self.z_gen.sample(rng), ]) } fn sample_single( low_b: B1, high_b: B2, rng: &mut R, ) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z { return Err(UniformError::EmptyRange); } Ok(Self::X::from([ $uniform::<$t>::sample_single(low.x, high.x, rng)?, $uniform::<$t>::sample_single(low.y, high.y, rng)?, $uniform::<$t>::sample_single(low.z, high.z, rng)?, ])) } fn sample_single_inclusive( low_b: B1, high_b: B2, rng: &mut R, ) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z { return Err(UniformError::EmptyRange); } Ok(Self::X::from([ $uniform::<$t>::sample_single_inclusive(low.x, high.x, rng)?, $uniform::<$t>::sample_single_inclusive(low.y, high.y, rng)?, $uniform::<$t>::sample_single_inclusive(low.z, high.z, rng)?, ])) } } impl Distribution<$vec4> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $vec4 { rng.random::<[$t; 4]>().into() } } impl SampleUniform for $vec4 { type Sampler = UniformVec4<$uniform<$t>>; } impl UniformSampler for UniformVec4<$uniform<$t>> { type X = $vec4; fn new(low_b: B1, high_b: B2) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z || low.w >= high.w { return Err(UniformError::EmptyRange); } Ok(Self { x_gen: $uniform::new(low.x, high.x)?, y_gen: $uniform::new(low.y, high.y)?, z_gen: $uniform::new(low.z, high.z)?, w_gen: $uniform::new(low.w, high.w)?, }) } fn new_inclusive(low_b: B1, high_b: B2) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z || low.w >= high.w { return Err(UniformError::EmptyRange); } Ok(Self { x_gen: $uniform::new_inclusive(low.x, high.x)?, y_gen: $uniform::new_inclusive(low.y, high.y)?, z_gen: $uniform::new_inclusive(low.z, high.z)?, w_gen: $uniform::new_inclusive(low.w, high.w)?, }) } fn sample(&self, rng: &mut R) -> Self::X { Self::X::from([ self.x_gen.sample(rng), self.y_gen.sample(rng), self.z_gen.sample(rng), self.w_gen.sample(rng), ]) } fn sample_single( low_b: B1, high_b: B2, rng: &mut R, ) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z || low.w >= high.w { return Err(UniformError::EmptyRange); } Ok(Self::X::from([ $uniform::<$t>::sample_single(low.x, high.x, rng)?, $uniform::<$t>::sample_single(low.y, high.y, rng)?, $uniform::<$t>::sample_single(low.z, high.z, rng)?, $uniform::<$t>::sample_single(low.w, high.w, rng)?, ])) } fn sample_single_inclusive( low_b: B1, high_b: B2, rng: &mut R, ) -> Result where B1: SampleBorrow + Sized, B2: SampleBorrow + Sized, { let low = *low_b.borrow(); let high = *high_b.borrow(); if low.x >= high.x || low.y >= high.y || low.z >= high.z || low.w >= high.w { return Err(UniformError::EmptyRange); } Ok(Self::X::from([ $uniform::<$t>::sample_single_inclusive(low.x, high.x, rng)?, $uniform::<$t>::sample_single_inclusive(low.y, high.y, rng)?, $uniform::<$t>::sample_single_inclusive(low.z, high.z, rng)?, $uniform::<$t>::sample_single_inclusive(low.w, high.w, rng)?, ])) } } #[test] fn test_vec2_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a: ($t, $t) = rng1.random(); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b: $vec2 = rng2.random(); assert_eq!(a, b.into()); } #[test] fn test_vec3_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a: ($t, $t, $t) = rng1.random(); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b: $vec3 = rng2.random(); assert_eq!(a, b.into()); } #[test] fn test_vec4_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a: ($t, $t, $t, $t) = rng1.random(); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b: $vec4 = rng2.random(); assert_eq!(a, b.into()); } test_vec_type_uniform!( test_vec2_rand_uniform_equality, $vec2, $t, 2, $upper_range_multiplier ); test_vec_type_uniform!( test_vec3_rand_uniform_equality, $vec3, $t, 3, $upper_range_multiplier ); test_vec_type_uniform!( test_vec4_rand_uniform_equality, $vec4, $t, 4, $upper_range_multiplier ); }; } macro_rules! test_vec_type_uniform { // NOTE: These were intended to be placed in a `macro_rules!` statement in // the main rule below, but rustc wants to complain about unused macros if I // try to do that... even if I do use the macros. (__repeat_code 2, $code:expr) => { ($code, $code) }; (__repeat_code 3, $code:expr) => { ($code, $code, $code) }; (__repeat_code 4, $code:expr) => { ($code, $code, $code, $code) }; ( $equality_test_name:ident, $vec:ident, $t:ty, $t_count:tt, $upper_range_divisor:expr ) => { /// Tests that we reach the same result, whether we generate the vector /// type directly, or generate its internal values $t_count times and /// convert the result into the vector type. #[test] fn $equality_test_name() { use rand::{distr::Uniform, Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut int_rng = Xoshiro256Plus::seed_from_u64(0); let mut vec_rng = Xoshiro256Plus::seed_from_u64(0); macro_rules! test_uniform { ( __single_test, $uniform_function_name:ident, $t_low:expr, $t_high:expr, $vec_low:expr, $vec_high:expr ) => { let int_u = Uniform::$uniform_function_name($t_low, $t_high).unwrap(); let vec_u = Uniform::$uniform_function_name($vec_low, $vec_high).unwrap(); let v_int = test_vec_type_uniform!( __repeat_code $t_count, int_rng.sample(int_u) ); let v_vec: $vec = vec_rng.sample(vec_u); assert_eq!(v_int, v_vec.into()); }; ( $uniform_function_name:ident, $t_low:expr, $t_high:expr, $vec_low:expr, $vec_high:expr ) => { test_uniform!( __single_test, $uniform_function_name, $t_low, $t_high, $vec_low, $vec_high ); test_uniform!( __single_test, $uniform_function_name, &$t_low, &$t_high, &$vec_low, &$vec_high ); }; } test_uniform!( new, <$t>::default(), <$t>::MAX / $upper_range_divisor, $vec::default(), $vec::MAX / $upper_range_divisor ); test_uniform!( new_inclusive, <$t>::default(), <$t>::MAX / $upper_range_divisor, $vec::default(), $vec::MAX / $upper_range_divisor ); macro_rules! test_sample_uniform_sampler { ($sampler_function_name:ident) => { let v_int = test_vec_type_uniform!( __repeat_code $t_count, <$t as SampleUniform>::Sampler::$sampler_function_name( <$t>::default(), <$t>::MAX / $upper_range_divisor, &mut int_rng, ).unwrap() ); let v_vec: $vec = <$vec as SampleUniform>::Sampler::$sampler_function_name( $vec::default(), $vec::MAX / $upper_range_divisor, &mut vec_rng, ).unwrap(); assert_eq!(v_int, v_vec.into()); }; } test_sample_uniform_sampler!(sample_single); test_sample_uniform_sampler!(sample_single_inclusive); } }; } macro_rules! impl_int_types { ($t:ty, $vec2:ident, $vec3:ident, $vec4:ident) => { use rand::distr::uniform::UniformInt; impl_vec_types!($t, $vec2, $vec3, $vec4, UniformInt, 1); }; } macro_rules! impl_float_types { ($t:ident, $mat2:ident, $mat3:ident, $mat4:ident, $quat:ident, $vec2:ident, $vec3:ident, $vec4:ident) => { use rand::distr::uniform::UniformFloat; impl_vec_types!($t, $vec2, $vec3, $vec4, UniformFloat, 10.0); impl Distribution<$mat2> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $mat2 { $mat2::from_cols_array(&rng.random()) } } impl Distribution<$mat3> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $mat3 { $mat3::from_cols_array(&rng.random()) } } impl Distribution<$mat4> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $mat4 { $mat4::from_cols_array(&rng.random()) } } impl Distribution<$quat> for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> $quat { let z = rng.random_range::<$t, _>(-1.0..=1.0); let (y, x) = math::sin_cos(rng.random_range::<$t, _>(0.0..TAU)); let r = math::sqrt(1.0 - z * z); let axis = $vec3::new(r * x, r * y, z); let angle = rng.random_range::<$t, _>(0.0..TAU); $quat::from_axis_angle(axis, angle) } } #[test] fn test_mat2_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a = $mat2::from_cols_array(&rng1.random::<[$t; 4]>()); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b = rng2.random::<$mat2>(); assert_eq!(a, b); } #[test] fn test_mat3_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a = $mat3::from_cols_array(&rng1.random::<[$t; 9]>()); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b = rng2.random::<$mat3>(); assert_eq!(a, b); } #[test] fn test_mat4_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a = $mat4::from_cols_array(&rng1.random::<[$t; 16]>()); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b = rng2.random::<$mat4>(); assert_eq!(a, b); } #[test] fn test_quat_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a: $quat = rng1.random(); assert!(a.is_normalized()); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b: $quat = rng2.random(); assert_eq!(a, b); } }; } #[derive(Clone, Copy, Debug, PartialEq)] pub struct UniformVec2 { x_gen: G, y_gen: G, } #[derive(Clone, Copy, Debug, PartialEq)] pub struct UniformVec3 { x_gen: G, y_gen: G, z_gen: G, } #[derive(Clone, Copy, Debug, PartialEq)] pub struct UniformVec4 { x_gen: G, y_gen: G, z_gen: G, w_gen: G, } mod f32 { use crate::f32::math; use crate::{Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4}; use core::f32::consts::TAU; impl_float_types!(f32, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec4); impl Distribution for StandardUniform { #[inline] fn sample(&self, rng: &mut R) -> Vec3A { rng.random::<[f32; 3]>().into() } } #[test] fn test_vec3a_rand_standard() { use rand::{Rng, SeedableRng}; use rand_xoshiro::Xoshiro256Plus; let mut rng1 = Xoshiro256Plus::seed_from_u64(0); let a: (f32, f32, f32) = rng1.random(); let mut rng2 = Xoshiro256Plus::seed_from_u64(0); let b: Vec3A = rng2.random(); assert_eq!(a, b.into()); } } mod f64 { use crate::f64::math; use crate::{DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4}; use core::f64::consts::TAU; impl_float_types!(f64, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4); } mod i8 { use crate::{I8Vec2, I8Vec3, I8Vec4}; impl_int_types!(i8, I8Vec2, I8Vec3, I8Vec4); } mod i16 { use crate::{I16Vec2, I16Vec3, I16Vec4}; impl_int_types!(i16, I16Vec2, I16Vec3, I16Vec4); } mod i32 { use crate::{IVec2, IVec3, IVec4}; impl_int_types!(i32, IVec2, IVec3, IVec4); } mod i64 { use crate::{I64Vec2, I64Vec3, I64Vec4}; impl_int_types!(i64, I64Vec2, I64Vec3, I64Vec4); } mod u8 { use crate::{U8Vec2, U8Vec3, U8Vec4}; impl_int_types!(u8, U8Vec2, U8Vec3, U8Vec4); } mod u16 { use crate::{U16Vec2, U16Vec3, U16Vec4}; impl_int_types!(u16, U16Vec2, U16Vec3, U16Vec4); } mod u32 { use crate::{UVec2, UVec3, UVec4}; impl_int_types!(u32, UVec2, UVec3, UVec4); } mod u64 { use crate::{U64Vec2, U64Vec3, U64Vec4}; impl_int_types!(u64, U64Vec2, U64Vec3, U64Vec4); } glam-0.30.1/src/features/impl_rkyv.rs000064400000000000000000000216061046102023000156210ustar 00000000000000#[cfg(feature = "bytecheck")] macro_rules! impl_rkyv { (@bytecheck $type:ty) => { // SAFETY: All bit patterns are valid for these primitive types. // https://docs.rs/bytecheck/0.8.1/src/bytecheck/lib.rs.html#352 unsafe impl rkyv::bytecheck::CheckBytes for $type { #[inline] unsafe fn check_bytes( _value: *const Self, _: &mut C, ) -> Result<(), C::Error> { Ok(()) } } }; ($type:ty) => { impl_rkyv_derive!(@serialize $type); impl_rkyv_derive!(@archive_deserialize $type); impl_rkyv!(@bytecheck $type); }; } #[cfg(not(feature = "bytecheck"))] macro_rules! impl_rkyv { ($type:ty) => { impl_rkyv_derive!(@serialize $type); impl_rkyv_derive!(@archive_deserialize $type); }; } macro_rules! impl_rkyv_derive { (@serialize $type:ty) => { impl Serialize for $type { #[inline] fn serialize(&self, _: &mut S) -> Result { Ok(()) } } }; (@archive_deserialize $type:ty) => { // SAFETY: All glam types have a fully defined data layout. unsafe impl rkyv::traits::NoUndef for $type {} // SAFETY: All glam types have a stable, well-defined layout that is identical on all // targets. unsafe impl rkyv::Portable for $type {} impl Archive for $type { type Archived = $type; type Resolver = (); #[inline] fn resolve(&self, _: Self::Resolver, out: Place) { out.write(*self) } } impl Deserialize<$type, D> for $type { #[inline] fn deserialize(&self, _: &mut D) -> Result<$type, D::Error> { Ok(*self) } } }; } mod f32 { use crate::{Affine2, Affine3A, Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(Affine2); impl_rkyv!(Affine3A); impl_rkyv!(Mat2); impl_rkyv!(Mat3); impl_rkyv!(Mat3A); impl_rkyv!(Mat4); impl_rkyv!(Quat); impl_rkyv!(Vec2); impl_rkyv!(Vec3); impl_rkyv!(Vec3A); impl_rkyv!(Vec4); } mod f64 { use crate::{DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(DAffine2); impl_rkyv!(DAffine3); impl_rkyv!(DMat2); impl_rkyv!(DMat3); impl_rkyv!(DMat4); impl_rkyv!(DQuat); impl_rkyv!(DVec2); impl_rkyv!(DVec3); impl_rkyv!(DVec4); } mod i8 { use crate::{I8Vec2, I8Vec3, I8Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(I8Vec2); impl_rkyv!(I8Vec3); impl_rkyv!(I8Vec4); } mod i16 { use crate::{I16Vec2, I16Vec3, I16Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(I16Vec2); impl_rkyv!(I16Vec3); impl_rkyv!(I16Vec4); } mod i32 { use crate::{IVec2, IVec3, IVec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(IVec2); impl_rkyv!(IVec3); impl_rkyv!(IVec4); } mod i64 { use crate::{I64Vec2, I64Vec3, I64Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(I64Vec2); impl_rkyv!(I64Vec3); impl_rkyv!(I64Vec4); } mod u8 { use crate::{U8Vec2, U8Vec3, U8Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(U8Vec2); impl_rkyv!(U8Vec3); impl_rkyv!(U8Vec4); } mod u16 { use crate::{U16Vec2, U16Vec3, U16Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(U16Vec2); impl_rkyv!(U16Vec3); impl_rkyv!(U16Vec4); } mod u32 { use crate::{UVec2, UVec3, UVec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(UVec2); impl_rkyv!(UVec3); impl_rkyv!(UVec4); } mod u64 { use crate::{U64Vec2, U64Vec3, U64Vec4}; use rkyv::{rancor::Fallible, Archive, Deserialize, Place, Serialize}; impl_rkyv!(U64Vec2); impl_rkyv!(U64Vec3); impl_rkyv!(U64Vec4); } #[cfg(test)] mod test { /// The serializer type expected by [`rkyv::to_bytes()`]. pub type TestSerializer<'a> = rkyv::api::high::HighSerializer< rkyv::util::AlignedVec, rkyv::ser::allocator::ArenaHandle<'a>, rkyv::rancor::Panic, >; /// The deserializer type expected by [`rkyv::deserialize()`]. pub type TestDeserializer = rkyv::api::high::HighDeserializer; pub fn test_archive(value: &T) where T: core::fmt::Debug + PartialEq + rkyv::Portable + for<'a> rkyv::Serialize>, T::Archived: core::fmt::Debug + PartialEq + rkyv::Deserialize, { let buffer = rkyv::to_bytes(value).unwrap(); // SAFETY: all bit patterns are valid for the primitive types used by glam. There is // no need to write special-cased conditional tests that rely on bytecheck for the safe // rkyv::access() wrapper. let archived_value = unsafe { rkyv::access_unchecked::(&buffer) }; assert_eq!(archived_value, value); assert_eq!( &rkyv::deserialize::(archived_value).unwrap(), value ); } #[test] fn test_rkyv() { use crate::{Affine2, Affine3A, Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4}; test_archive(&Affine2::from_cols_array(&[1.0, 0.0, 2.0, 0.0, 3.0, 4.0])); test_archive(&Affine3A::from_cols_array(&[ 1.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 3.0, 4.0, 5.0, 6.0, ])); test_archive(&Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0])); test_archive(&Mat3::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, ])); test_archive(&Mat3A::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, ])); test_archive(&Mat4::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, ])); test_archive(&Quat::from_xyzw(1.0, 2.0, 3.0, 4.0)); test_archive(&Vec2::new(1.0, 2.0)); test_archive(&Vec3::new(1.0, 2.0, 3.0)); test_archive(&Vec3A::new(1.0, 2.0, 3.0)); test_archive(&Vec4::new(1.0, 2.0, 3.0, 4.0)); use crate::{DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4}; test_archive(&DAffine2::from_cols_array(&[1.0, 0.0, 2.0, 0.0, 3.0, 4.0])); test_archive(&DAffine3::from_cols_array(&[ 1.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 3.0, 4.0, 5.0, 6.0, ])); test_archive(&DMat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0])); test_archive(&DMat3::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, ])); test_archive(&DMat4::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, ])); test_archive(&DQuat::from_xyzw(1.0, 2.0, 3.0, 4.0)); test_archive(&DVec2::new(1.0, 2.0)); test_archive(&DVec3::new(1.0, 2.0, 3.0)); test_archive(&DVec4::new(1.0, 2.0, 3.0, 4.0)); use crate::{I8Vec2, I8Vec3, I8Vec4}; test_archive(&I8Vec2::new(-1, 2)); test_archive(&I8Vec3::new(-1, 2, 3)); test_archive(&I8Vec4::new(-1, 2, 3, 4)); 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::{U8Vec2, U8Vec3, U8Vec4}; test_archive(&U8Vec2::new(1, 2)); test_archive(&U8Vec3::new(1, 2, 3)); test_archive(&U8Vec4::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)); } } glam-0.30.1/src/features/impl_serde.rs000064400000000000000000001715251046102023000157360ustar 00000000000000macro_rules! impl_serde_vec2 { ($t:ty, $vec2:ident) => { /// Serialize as a sequence of 2 values. impl Serialize for $vec2 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct(stringify!($vec2), 2)?; state.serialize_field(&self.x)?; state.serialize_field(&self.y)?; state.end() } } /// Deserialize expects a sequence of 2 values. impl<'de> Deserialize<'de> for $vec2 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Vec2Visitor; impl<'de> Visitor<'de> for Vec2Visitor { type Value = $vec2; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 2 ", stringify!($t), " values")) } fn visit_seq(self, mut seq: V) -> Result<$vec2, V::Error> where V: SeqAccess<'de>, { let x = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; let y = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(1, &self))?; Ok($vec2::new(x, y)) } } deserializer.deserialize_tuple_struct(stringify!($vec2), 2, Vec2Visitor) } } #[test] fn test_vec2_serde() { let a = $vec2::new(V1, V2); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(SX2, serialized); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$vec2>(SX0); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec2>(SX1); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec2>(SX3); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec2>(ST0); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_vec3 { ($t:ty, $vec3:ident) => { impl_serde_vec3!($t, $vec3, test_vec3_serde); }; ($t:ty, $vec3:ident, $test_name:ident) => { /// Serialize as a sequence of 3 values. impl Serialize for $vec3 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct(stringify!($vec3), 3)?; state.serialize_field(&self.x)?; state.serialize_field(&self.y)?; state.serialize_field(&self.z)?; state.end() } } /// Deserialize expects a sequence of 3 values. impl<'de> Deserialize<'de> for $vec3 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Vec3Visitor; impl<'de> Visitor<'de> for Vec3Visitor { type Value = $vec3; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 3 ", stringify!($t), " values")) } fn visit_seq(self, mut seq: V) -> Result<$vec3, V::Error> where V: SeqAccess<'de>, { let x = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; let y = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(1, &self))?; let z = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(2, &self))?; Ok($vec3::new(x, y, z)) } } deserializer.deserialize_tuple_struct(stringify!($vec3), 3, Vec3Visitor) } } #[test] fn $test_name() { let a = $vec3::new(V1, V2, V3); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(SX3, serialized); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$vec3>(SX0); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec3>(SX1); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec3>(SX2); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec3>(SX4); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec3>(ST0); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_vec4 { ($t:ty, $vec4:ident) => { /// Serialize as a sequence of 4 values. impl Serialize for $vec4 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct(stringify!($vec4), 4)?; state.serialize_field(&self.x)?; state.serialize_field(&self.y)?; state.serialize_field(&self.z)?; state.serialize_field(&self.w)?; state.end() } } /// Deserialize expects a sequence of 4 values. impl<'de> Deserialize<'de> for $vec4 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Vec4Visitor; impl<'de> Visitor<'de> for Vec4Visitor { type Value = $vec4; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 4 ", stringify!($t), " values")) } fn visit_seq(self, mut seq: V) -> Result<$vec4, V::Error> where V: SeqAccess<'de>, { let x = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; let y = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(1, &self))?; let z = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(2, &self))?; let w = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(3, &self))?; Ok($vec4::new(x, y, z, w)) } } deserializer.deserialize_tuple_struct(stringify!($vec4), 4, Vec4Visitor) } } #[test] fn test_vec4_serde() { let a = $vec4::new(V1, V2, V3, V4); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(SX4, serialized); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$vec4>(SX0); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec4>(SX1); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec4>(SX2); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec4>(SX3); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec4>(SX5); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$vec4>(ST0); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_quat { ($t:ty, $quat:ident) => { /// Serialize as a sequence of 4 values. impl Serialize for $quat { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct(stringify!($quat), 4)?; state.serialize_field(&self.x)?; state.serialize_field(&self.y)?; state.serialize_field(&self.z)?; state.serialize_field(&self.w)?; state.end() } } /// Deserialize expects a sequence of 4 values. impl<'de> Deserialize<'de> for $quat { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct QuatVisitor; impl<'de> Visitor<'de> for QuatVisitor { type Value = $quat; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 4 ", stringify!($t), " values")) } fn visit_seq(self, mut seq: V) -> Result<$quat, V::Error> where V: SeqAccess<'de>, { let x = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; let y = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(1, &self))?; let z = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(2, &self))?; let w = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(3, &self))?; Ok($quat::from_xyzw(x, y, z, w)) } } deserializer.deserialize_tuple_struct(stringify!($quat), 4, QuatVisitor) } } #[test] fn test_quat_serde() { let a = $quat::from_xyzw(1.0, 2.0, 3.0, 4.0); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(serialized, "[1.0,2.0,3.0,4.0]"); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$quat>("[]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$quat>("[1.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$quat>("[1.0,2.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$quat>("[1.0,2.0,3.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$quat>("[1.0,2.0,3.0,4.0,5.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$quat>("{}"); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_mat2 { ($t:ty, $mat2:ident) => { /// Serialize as a sequence of 4 values. impl Serialize for $mat2 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let f: &[_; 4] = self.as_ref(); let mut state = serializer.serialize_tuple_struct(stringify!($mat2), 4)?; state.serialize_field(&f[0])?; state.serialize_field(&f[1])?; state.serialize_field(&f[2])?; state.serialize_field(&f[3])?; state.end() } } /// Deserialize expects a sequence of 4 values. impl<'de> Deserialize<'de> for $mat2 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Mat2Visitor; impl<'de> Visitor<'de> for Mat2Visitor { type Value = $mat2; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 4 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result<$mat2, V::Error> where V: SeqAccess<'de>, { let mut f = { [0.0; 4] }; for i in 0..4 { f[i] = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(i, &self))?; } Ok($mat2::from_cols_array(&f)) } } deserializer.deserialize_tuple_struct(stringify!($mat2), 4, Mat2Visitor) } } #[test] fn test_mat2_serde() { let a = $mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(serialized, "[1.0,2.0,3.0,4.0]"); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$mat2>("[]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat2>("[1.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat2>("[1.0,2.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat2>("[1.0,2.0,3.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat2>("[1.0,2.0,3.0,4.0,5.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat2>("[[1.0,2.0],[3.0,4.0]]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat2>("{}"); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_mat3 { ($t:ty, $mat3:ident) => { impl_serde_mat3!($t, $mat3, test_mat3_serde); }; ($t:ty, $mat3:ident, $test_name:ident) => { /// Serialize as a sequence of 9 values. impl Serialize for $mat3 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let (m00, m01, m02) = self.x_axis.into(); let (m10, m11, m12) = self.y_axis.into(); let (m20, m21, m22) = self.z_axis.into(); let mut state = serializer.serialize_tuple_struct(stringify!($mat3), 9)?; state.serialize_field(&m00)?; state.serialize_field(&m01)?; state.serialize_field(&m02)?; state.serialize_field(&m10)?; state.serialize_field(&m11)?; state.serialize_field(&m12)?; state.serialize_field(&m20)?; state.serialize_field(&m21)?; state.serialize_field(&m22)?; state.end() } } /// Deserialize expects a sequence of 9 values. impl<'de> Deserialize<'de> for $mat3 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Mat3Visitor; impl<'de> Visitor<'de> for Mat3Visitor { type Value = $mat3; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 9 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result<$mat3, V::Error> where V: SeqAccess<'de>, { let mut f = { [0.0; 9] }; for i in 0..9 { f[i] = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(i, &self))?; } Ok($mat3::from_cols_array(&f)) } } deserializer.deserialize_tuple_struct(stringify!($mat3), 9, Mat3Visitor) } } #[test] fn $test_name() { let a = $mat3::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(serialized, "[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]"); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$mat3>("[]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat3>("[1.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat3>("[1.0,2.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat3>("[1.0,2.0,3.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat3>("[1.0,2.0,3.0,4.0,5.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat3>("[[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat3>("{}"); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_mat4 { ($t:ty, $mat4:ident) => { /// Serialize as a sequence of 16 values. impl Serialize for $mat4 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct(stringify!($mat4), 16)?; for f in self.as_ref() { state.serialize_field(f)?; } state.end() } } /// Deserialize expects a sequence of 16 values. impl<'de> Deserialize<'de> for $mat4 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Mat4Visitor; impl<'de> Visitor<'de> for Mat4Visitor { type Value = $mat4; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 16 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result<$mat4, V::Error> where V: SeqAccess<'de>, { let mut f = { [0.0; 16] }; for i in 0..16 { f[i] = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(i, &self))?; } Ok($mat4::from_cols_array(&f)) } } deserializer.deserialize_tuple_struct(stringify!($mat4), 16, Mat4Visitor) } } #[test] fn test_mat4_serde() { let a = $mat4::from_cols_array(&[ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, ]); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!( serialized, "[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0]" ); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$mat4>("[]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>("[1.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>("[1.0,2.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>("[1.0,2.0,3.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>("[1.0,2.0,3.0,4.0,5.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>("[[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>( "[[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0][13.0,14.0,15.0,16.0]]", ); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$mat4>("{}"); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_affine2 { ($t:ty, $affine2:ident) => { /// Serialize as a sequence of 6 values. impl Serialize for $affine2 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { // Serialize column-wise as 3x4 matrix: let mut state = serializer.serialize_tuple_struct(stringify!($affine2), 6)?; state.serialize_field(&self.x_axis.x)?; state.serialize_field(&self.x_axis.y)?; state.serialize_field(&self.y_axis.x)?; state.serialize_field(&self.y_axis.y)?; state.serialize_field(&self.z_axis.x)?; state.serialize_field(&self.z_axis.y)?; state.end() } } /// Deserialize expects a sequence of 6 values. impl<'de> Deserialize<'de> for $affine2 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Affine2Visitor; impl<'de> Visitor<'de> for Affine2Visitor { type Value = $affine2; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 6 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result<$affine2, V::Error> where V: SeqAccess<'de>, { let mut f = [0.0; 6]; for (i, v) in f.iter_mut().enumerate() { *v = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(i, &self))?; } Ok($affine2::from_cols_array(&f)) } } deserializer.deserialize_tuple_struct(stringify!($affine2), 6, Affine2Visitor) } } #[test] fn test_affine2_serde() { let a = $affine2::from_cols_array(&[1.0, 0.0, 2.0, 0.0, 3.0, 4.0]); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(serialized, "[1.0,0.0,2.0,0.0,3.0,4.0]"); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$affine2>("[]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>("[1.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>("[1.0,2.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>("[1.0,2.0,3.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>("[1.0,2.0,3.0,4.0,5.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>("[[1.0,2.0],[3.0,4.0],[5.0,6.0]]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>( "[[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0][13.0,14.0,15.0,16.0]]", ); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine2>("{}"); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_affine3 { ($t:ty, $affine3:ident) => { /// Serialize as a sequence of 12 values. impl Serialize for $affine3 { fn serialize(&self, serializer: S) -> Result where S: Serializer, { // Serialize column-wise as 3x4 matrix: let mut state = serializer.serialize_tuple_struct(stringify!($affine3), 12)?; state.serialize_field(&self.x_axis.x)?; state.serialize_field(&self.x_axis.y)?; state.serialize_field(&self.x_axis.z)?; state.serialize_field(&self.y_axis.x)?; state.serialize_field(&self.y_axis.y)?; state.serialize_field(&self.y_axis.z)?; state.serialize_field(&self.z_axis.x)?; state.serialize_field(&self.z_axis.y)?; state.serialize_field(&self.z_axis.z)?; state.serialize_field(&self.w_axis.x)?; state.serialize_field(&self.w_axis.y)?; state.serialize_field(&self.w_axis.z)?; state.end() } } /// Deserialize expects a sequence of 12 values. impl<'de> Deserialize<'de> for $affine3 { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Affine3Visitor; impl<'de> Visitor<'de> for Affine3Visitor { type Value = $affine3; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(&concat!("a sequence of 12 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result<$affine3, V::Error> where V: SeqAccess<'de>, { let mut f = [0.0; 12]; for (i, v) in f.iter_mut().enumerate() { *v = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(i, &self))?; } Ok($affine3::from_cols_array(&f)) } } deserializer.deserialize_tuple_struct(stringify!($affine3), 12, Affine3Visitor) } } #[test] fn test_affine3_serde() { let a = $affine3::from_cols_array(&[ 1.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 3.0, 4.0, 5.0, 6.0, ]); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!( serialized, "[1.0,0.0,0.0,0.0,2.0,0.0,0.0,0.0,3.0,4.0,5.0,6.0]" ); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::<$affine3>("[]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>("[1.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>("[1.0,2.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>("[1.0,2.0,3.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>("[1.0,2.0,3.0,4.0,5.0]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>("[[1.0,2.0,3.0],[4.0,5.0,6.0],[7.0,8.0,9.0]]"); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>( "[[1.0,2.0,3.0,4.0],[5.0,6.0,7.0,8.0],[9.0,10.0,11.0,12.0][13.0,14.0,15.0,16.0]]", ); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::<$affine3>("{}"); assert!(deserialized.is_err()); } }; } macro_rules! impl_serde_vec_types { ($t:ty, $vec2:ident, $vec3:ident, $vec4:ident) => { impl_serde_vec2!($t, $vec2); impl_serde_vec3!($t, $vec3); impl_serde_vec4!($t, $vec4); }; } macro_rules! impl_serde_float_types { ($t:ty, $affine2:ident, $affine3:ident, $mat2:ident, $mat3:ident, $mat4:ident, $quat:ident, $vec2:ident, $vec3:ident, $vec4:ident) => { impl_serde_affine2!($t, $affine2); impl_serde_affine3!($t, $affine3); impl_serde_mat2!($t, $mat2); impl_serde_mat3!($t, $mat3); impl_serde_mat4!($t, $mat4); impl_serde_quat!($t, $quat); impl_serde_vec_types!($t, $vec2, $vec3, $vec4); }; } #[cfg(test)] mod test_f32 { pub const V1: f32 = 1.0; pub const V2: f32 = 2.0; pub const V3: f32 = 3.0; pub const V4: f32 = 4.0; } #[cfg(test)] mod test_f64 { pub const V1: f64 = 1.0; pub const V2: f64 = 2.0; pub const V3: f64 = 3.0; pub const V4: f64 = 4.0; } #[cfg(test)] mod test_i8 { pub const V1: i8 = 1; pub const V2: i8 = 2; pub const V3: i8 = 3; pub const V4: i8 = 4; } #[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; pub const V3: i32 = 3; pub const V4: i32 = 4; } #[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_u8 { pub const V1: u8 = 1; pub const V2: u8 = 2; pub const V3: u8 = 3; pub const V4: u8 = 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; pub const V3: u32 = 3; pub const V4: u32 = 4; } #[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_usize { pub const V1: usize = 1; pub const V2: usize = 2; pub const V3: usize = 3; pub const V4: usize = 4; } #[cfg(test)] mod test_float { pub const SX0: &str = "[]"; pub const SX1: &str = "[1.0]"; pub const SX2: &str = "[1.0,2.0]"; pub const SX3: &str = "[1.0,2.0,3.0]"; pub const SX4: &str = "[1.0,2.0,3.0,4.0]"; pub const SX5: &str = "[1.0,2.0,3.0,4.0,5.0]"; pub const ST0: &str = "{}"; } #[cfg(test)] mod test_int { pub const SX0: &str = "[]"; pub const SX1: &str = "[1]"; pub const SX2: &str = "[1,2]"; pub const SX3: &str = "[1,2,3]"; pub const SX4: &str = "[1,2,3,4]"; pub const SX5: &str = "[1,2,3,4,5]"; pub const ST0: &str = "{}"; } #[cfg(test)] mod test_bool_mask { pub const SX0: &str = "[]"; pub const SX1: &str = "[true]"; pub const SX2: &str = "[true,true]"; pub const SX3: &str = "[true,true,true]"; pub const SX4: &str = "[true,true,true,true]"; pub const SX5: &str = "[true,true,true,true,true]"; pub const ST0: &str = "{}"; pub const V1: bool = true; pub const V2: bool = true; pub const V3: bool = true; pub const V4: bool = true; } mod bool { #[cfg(test)] use super::test_bool_mask::*; use crate::{BVec2, BVec3, BVec4}; #[cfg(not(feature = "scalar-math"))] use crate::{BVec3A, BVec4A}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; impl_serde_vec2!(bool, BVec2); impl_serde_vec3!(bool, BVec3); impl_serde_vec4!(bool, BVec4); #[cfg(not(feature = "scalar-math"))] impl Serialize for BVec3A { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct("BVec3A", 3)?; let a: [bool; 3] = (*self).into(); state.serialize_field(&a[0])?; state.serialize_field(&a[1])?; state.serialize_field(&a[2])?; state.end() } } #[cfg(not(feature = "scalar-math"))] impl<'de> Deserialize<'de> for BVec3A { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Vec3Visitor; impl<'de> Visitor<'de> for Vec3Visitor { type Value = BVec3A; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(concat!("a sequence of 3 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result where V: SeqAccess<'de>, { let x = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; let y = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(1, &self))?; let z = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(2, &self))?; Ok(BVec3A::new(x, y, z)) } } deserializer.deserialize_tuple_struct(stringify!($vec3), 3, Vec3Visitor) } } #[cfg(not(feature = "scalar-math"))] #[test] fn test_bvec3a_serde() { let a = BVec3A::new(V1, V2, V3); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(SX3, serialized); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::(SX0); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX1); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX2); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX4); assert!(deserialized.is_err()); } #[cfg(not(feature = "scalar-math"))] impl Serialize for BVec4A { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut state = serializer.serialize_tuple_struct(stringify!(BVec4A), 4)?; let a: [bool; 4] = (*self).into(); state.serialize_field(&a[0])?; state.serialize_field(&a[1])?; state.serialize_field(&a[2])?; state.serialize_field(&a[2])?; state.end() } } #[cfg(not(feature = "scalar-math"))] impl<'de> Deserialize<'de> for BVec4A { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { struct Vec4Visitor; impl<'de> Visitor<'de> for Vec4Visitor { type Value = BVec4A; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str(concat!("a sequence of 4 ", stringify!($t), "values")) } fn visit_seq(self, mut seq: V) -> Result where V: SeqAccess<'de>, { let x = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(0, &self))?; let y = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(1, &self))?; let z = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(2, &self))?; let w = seq .next_element()? .ok_or_else(|| de::Error::invalid_length(3, &self))?; Ok(BVec4A::new(x, y, z, w)) } } deserializer.deserialize_tuple_struct(stringify!(BVec4A), 4, Vec4Visitor) } } #[cfg(not(feature = "scalar-math"))] #[test] fn test_bvec4a_serde() { let a = BVec4A::new(V1, V2, V3, V4); let serialized = serde_json::to_string(&a).unwrap(); assert_eq!(SX4, serialized); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(a, deserialized); let deserialized = serde_json::from_str::(SX0); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX1); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX2); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX3); assert!(deserialized.is_err()); let deserialized = serde_json::from_str::(SX5); assert!(deserialized.is_err()); } } mod f32 { #[cfg(test)] use super::test_f32::*; #[cfg(test)] use super::test_float::*; use crate::{Affine2, Affine3A, Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; impl_serde_float_types!(f32, Affine2, Affine3A, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec4); impl_serde_mat3!(f32, Mat3A, test_mat3a_serde); impl_serde_vec3!(f32, Vec3A, test_vec3a_serde); } mod f64 { #[cfg(test)] use super::test_f64::*; #[cfg(test)] use super::test_float::*; use crate::{DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; impl_serde_float_types!( f64, DAffine2, DAffine3, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4 ); } mod i8 { #[cfg(test)] use super::test_i8::*; #[cfg(test)] use super::test_int::*; use crate::{I8Vec2, I8Vec3, I8Vec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; impl_serde_vec_types!(i8, I8Vec2, I8Vec3, I8Vec4); } 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::*; #[cfg(test)] use super::test_int::*; use crate::{IVec2, IVec3, IVec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; 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 u8 { #[cfg(test)] use super::test_int::*; #[cfg(test)] use super::test_u8::*; use crate::{U8Vec2, U8Vec3, U8Vec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; impl_serde_vec_types!(u8, U8Vec2, U8Vec3, U8Vec4); } 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::*; #[cfg(test)] use super::test_u32::*; use crate::{UVec2, UVec3, UVec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; 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 usize { #[cfg(test)] use super::test_int::*; #[cfg(test)] use super::test_usize::*; use crate::{USizeVec2, USizeVec3, USizeVec4}; use core::fmt; use serde::{ de::{self, Deserialize, Deserializer, SeqAccess, Visitor}, ser::{Serialize, SerializeTupleStruct, Serializer}, }; impl_serde_vec_types!(usize, USizeVec2, USizeVec3, USizeVec4); } mod euler { use crate::EulerRot; impl serde::Serialize for EulerRot { fn serialize(&self, serializer: S) -> Result { 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") } EulerRot::ZYZ => { serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 6u32, "ZYZ") } EulerRot::ZXZ => { serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 7u32, "ZXZ") } EulerRot::YXY => { serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 8u32, "YXY") } EulerRot::YZY => { serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 9u32, "YZY") } EulerRot::XYX => { serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 10u32, "XYX") } EulerRot::XZX => { serde::Serializer::serialize_unit_variant(serializer, "EulerRot", 11u32, "XZX") } EulerRot::ZYXEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 12u32, "ZYXEx", ), EulerRot::ZXYEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 13u32, "ZXYEx", ), EulerRot::YXZEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 14u32, "YXZEx", ), EulerRot::YZXEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 15u32, "YZXEx", ), EulerRot::XYZEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 16u32, "XYZEx", ), EulerRot::XZYEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 17u32, "XZYEx", ), EulerRot::ZYZEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 18u32, "ZYZEx", ), EulerRot::ZXZEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 19u32, "ZXZEx", ), EulerRot::YXYEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 20u32, "YXYEx", ), EulerRot::YZYEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 21u32, "YZYEx", ), EulerRot::XYXEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 22u32, "XYXEx", ), EulerRot::XZXEx => serde::Serializer::serialize_unit_variant( serializer, "EulerRot", 23u32, "XZXEx", ), } } } impl<'de> serde::Deserialize<'de> for EulerRot { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { #[allow(clippy::upper_case_acronyms)] enum Field { ZYX, ZXY, YXZ, YZX, XYZ, XZY, ZYZ, ZXZ, YXY, YZY, XYX, XZX, ZYXEx, ZXYEx, YXZEx, YZXEx, XYZEx, XZYEx, ZYZEx, ZXZEx, YXYEx, YZYEx, XYXEx, XZXEx, } struct FieldVisitor; impl serde::de::Visitor<'_> for FieldVisitor { type Value = Field; fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { core::fmt::Formatter::write_str(formatter, "a variant identifier") } fn visit_u64(self, value: u64) -> Result 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), 6u64 => Ok(Field::ZYZ), 7u64 => Ok(Field::ZXZ), 8u64 => Ok(Field::YXY), 9u64 => Ok(Field::YZY), 10u64 => Ok(Field::XYX), 11u64 => Ok(Field::XZX), 12u64 => Ok(Field::ZYXEx), 13u64 => Ok(Field::ZXYEx), 14u64 => Ok(Field::YXZEx), 15u64 => Ok(Field::YZXEx), 16u64 => Ok(Field::XYZEx), 17u64 => Ok(Field::XZYEx), 18u64 => Ok(Field::ZYZEx), 19u64 => Ok(Field::ZXZEx), 20u64 => Ok(Field::YXYEx), 21u64 => Ok(Field::YZYEx), 22u64 => Ok(Field::XYXEx), 23u64 => Ok(Field::XZXEx), _ => Err(serde::de::Error::invalid_value( serde::de::Unexpected::Unsigned(value), &"variant index 0 <= i < 24", )), } } fn visit_str(self, value: &str) -> Result 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), "ZYZ" => Ok(Field::ZYZ), "ZXZ" => Ok(Field::ZXZ), "YXY" => Ok(Field::YXY), "YZY" => Ok(Field::YZY), "XYX" => Ok(Field::XYX), "XZX" => Ok(Field::XZX), "ZYXEx" => Ok(Field::ZYXEx), "ZXYEx" => Ok(Field::ZXYEx), "YXZEx" => Ok(Field::YXZEx), "YZXEx" => Ok(Field::YZXEx), "XYZEx" => Ok(Field::XYZEx), "XZYEx" => Ok(Field::XZYEx), "ZYZEx" => Ok(Field::ZYZEx), "ZXZEx" => Ok(Field::ZXZEx), "YXYEx" => Ok(Field::YXYEx), "YZYEx" => Ok(Field::YZYEx), "XYXEx" => Ok(Field::XYXEx), "XZXEx" => Ok(Field::XZXEx), _ => Err(serde::de::Error::unknown_variant(value, VARIANTS)), } } fn visit_bytes(self, value: &[u8]) -> Result 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), b"ZYZ" => Ok(Field::ZYZ), b"ZXZ" => Ok(Field::ZXZ), b"YXY" => Ok(Field::YXY), b"YZY" => Ok(Field::YZY), b"XYX" => Ok(Field::XYX), b"XZX" => Ok(Field::XZX), b"ZYXEx" => Ok(Field::ZYXEx), b"ZXYEx" => Ok(Field::ZXYEx), b"YXZEx" => Ok(Field::YXZEx), b"YZXEx" => Ok(Field::YZXEx), b"XYZEx" => Ok(Field::XYZEx), b"XZYEx" => Ok(Field::XZYEx), b"ZYZEx" => Ok(Field::ZYZEx), b"ZXZEx" => Ok(Field::ZXZEx), b"YXYEx" => Ok(Field::YXYEx), b"YZYEx" => Ok(Field::YZYEx), b"XYXEx" => Ok(Field::XYXEx), b"XZXEx" => Ok(Field::XZXEx), _ => { #[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(deserializer: D) -> Result where D: serde::Deserializer<'de>, { serde::Deserializer::deserialize_identifier(deserializer, FieldVisitor) } } struct Visitor<'de> { marker: core::marker::PhantomData, 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, "an EulerRot enum") } fn visit_enum(self, data: A) -> Result 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) } (Field::ZYZ, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::ZYZ) } (Field::ZXZ, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::ZXZ) } (Field::YXY, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::YXY) } (Field::YZY, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::YZY) } (Field::XYX, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::XYX) } (Field::XZX, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::XZX) } (Field::ZYXEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::ZYXEx) } (Field::ZXYEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::ZXYEx) } (Field::YXZEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::YXZEx) } (Field::YZXEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::YZXEx) } (Field::XYZEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::XYZEx) } (Field::XZYEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::XZYEx) } (Field::ZYZEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::ZYZEx) } (Field::ZXZEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::ZXZEx) } (Field::YXYEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::YXYEx) } (Field::YZYEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::YZYEx) } (Field::XYXEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::XYXEx) } (Field::XZXEx, variant) => { serde::de::VariantAccess::unit_variant(variant)?; Ok(EulerRot::XZXEx) } } } } const VARIANTS: &[&str] = &[ "ZYX", "ZXY", "YXZ", "YZX", "XYZ", "XZY", "ZYZ", "ZXZ", "YXY", "YZY", "XYX", "XZX", "ZYXEx", "ZXYEx", "YXZEx", "YZXEx", "XYZEx", "XZYEx", "ZYZEx", "ZXZEx", "YXYEx", "YZYEx", "XYXEx", "XZXEx", ]; serde::Deserializer::deserialize_enum( deserializer, "EulerRot", VARIANTS, Visitor { marker: core::marker::PhantomData::, lifetime: core::marker::PhantomData, }, ) } } #[test] fn test_euler_rot_serde() { const PAIRS: [(EulerRot, &str); 24] = [ (EulerRot::ZYX, "\"ZYX\""), (EulerRot::ZXY, "\"ZXY\""), (EulerRot::YXZ, "\"YXZ\""), (EulerRot::YZX, "\"YZX\""), (EulerRot::XYZ, "\"XYZ\""), (EulerRot::XZY, "\"XZY\""), (EulerRot::ZYZ, "\"ZYZ\""), (EulerRot::ZXZ, "\"ZXZ\""), (EulerRot::YXY, "\"YXY\""), (EulerRot::YZY, "\"YZY\""), (EulerRot::XYX, "\"XYX\""), (EulerRot::XZX, "\"XZX\""), (EulerRot::ZYXEx, "\"ZYXEx\""), (EulerRot::ZXYEx, "\"ZXYEx\""), (EulerRot::YXZEx, "\"YXZEx\""), (EulerRot::YZXEx, "\"YZXEx\""), (EulerRot::XYZEx, "\"XYZEx\""), (EulerRot::XZYEx, "\"XZYEx\""), (EulerRot::ZYZEx, "\"ZYZEx\""), (EulerRot::ZXZEx, "\"ZXZEx\""), (EulerRot::YXYEx, "\"YXYEx\""), (EulerRot::YZYEx, "\"YZYEx\""), (EulerRot::XYXEx, "\"XYXEx\""), (EulerRot::XZXEx, "\"XZXEx\""), ]; for (enum_value, enum_string) in PAIRS { let serialized = serde_json::to_string(&enum_value).unwrap(); assert_eq!(enum_string, serialized); let deserialized = serde_json::from_str(&serialized).unwrap(); assert_eq!(enum_value, deserialized); } } } glam-0.30.1/src/features.rs000064400000000000000000000004331046102023000136000ustar 00000000000000#[cfg(feature = "approx")] pub mod impl_approx; #[cfg(feature = "bytemuck")] pub mod impl_bytemuck; #[cfg(feature = "mint")] pub mod impl_mint; #[cfg(feature = "rand")] pub mod impl_rand; #[cfg(feature = "serde")] pub mod impl_serde; #[cfg(feature = "rkyv")] pub mod impl_rkyv; glam-0.30.1/src/float.rs000064400000000000000000000025711046102023000130740ustar 00000000000000/// 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 `s`. /// /// When `s` is `0`, the result will be `self`. When `s` is `1`, the result /// will be `rhs`. When `s` 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; } glam-0.30.1/src/i16/i16vec2.rs000064400000000000000000001350761046102023000135540ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec3, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2}; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i16) -> i16, { Self::new(f(self.x), f(self.y)) } /// 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 { assert!(slice.len() >= 2); 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[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i16) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i16) -> Self { self.y = y; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i16 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i16 { self.x * 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)) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u16::MAX`]. /// /// See also [`checked_manhattan_distance`][I16Vec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u16 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u16::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u16 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U16Vec2) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U16Vec2) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U16Vec2) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U16Vec2) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U16Vec2) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U16Vec2) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), } } } impl Default for I16Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&I16Vec2> for I16Vec2 { type Output = I16Vec2; #[inline] fn div(self, rhs: &I16Vec2) -> I16Vec2 { self.div(*rhs) } } impl Div<&I16Vec2> for &I16Vec2 { type Output = I16Vec2; #[inline] fn div(self, rhs: &I16Vec2) -> I16Vec2 { (*self).div(*rhs) } } impl Div for &I16Vec2 { type Output = I16Vec2; #[inline] fn div(self, rhs: I16Vec2) -> I16Vec2 { (*self).div(rhs) } } impl DivAssign for I16Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&I16Vec2> for I16Vec2 { #[inline] fn div_assign(&mut self, rhs: &I16Vec2) { self.div_assign(*rhs) } } impl Div for I16Vec2 { type Output = Self; #[inline] fn div(self, rhs: i16) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&i16> for I16Vec2 { type Output = I16Vec2; #[inline] fn div(self, rhs: &i16) -> I16Vec2 { self.div(*rhs) } } impl Div<&i16> for &I16Vec2 { type Output = I16Vec2; #[inline] fn div(self, rhs: &i16) -> I16Vec2 { (*self).div(*rhs) } } impl Div for &I16Vec2 { type Output = I16Vec2; #[inline] fn div(self, rhs: i16) -> I16Vec2 { (*self).div(rhs) } } impl DivAssign for I16Vec2 { #[inline] fn div_assign(&mut self, rhs: i16) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&i16> for I16Vec2 { #[inline] fn div_assign(&mut self, rhs: &i16) { self.div_assign(*rhs) } } impl Div for i16 { type Output = I16Vec2; #[inline] fn div(self, rhs: I16Vec2) -> I16Vec2 { I16Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&I16Vec2> for i16 { type Output = I16Vec2; #[inline] fn div(self, rhs: &I16Vec2) -> I16Vec2 { self.div(*rhs) } } impl Div<&I16Vec2> for &i16 { type Output = I16Vec2; #[inline] fn div(self, rhs: &I16Vec2) -> I16Vec2 { (*self).div(*rhs) } } impl Div for &i16 { type Output = I16Vec2; #[inline] fn div(self, rhs: I16Vec2) -> I16Vec2 { (*self).div(rhs) } } impl Mul 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 Mul<&I16Vec2> for I16Vec2 { type Output = I16Vec2; #[inline] fn mul(self, rhs: &I16Vec2) -> I16Vec2 { self.mul(*rhs) } } impl Mul<&I16Vec2> for &I16Vec2 { type Output = I16Vec2; #[inline] fn mul(self, rhs: &I16Vec2) -> I16Vec2 { (*self).mul(*rhs) } } impl Mul for &I16Vec2 { type Output = I16Vec2; #[inline] fn mul(self, rhs: I16Vec2) -> I16Vec2 { (*self).mul(rhs) } } impl MulAssign for I16Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&I16Vec2> for I16Vec2 { #[inline] fn mul_assign(&mut self, rhs: &I16Vec2) { self.mul_assign(*rhs) } } impl Mul for I16Vec2 { type Output = Self; #[inline] fn mul(self, rhs: i16) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&i16> for I16Vec2 { type Output = I16Vec2; #[inline] fn mul(self, rhs: &i16) -> I16Vec2 { self.mul(*rhs) } } impl Mul<&i16> for &I16Vec2 { type Output = I16Vec2; #[inline] fn mul(self, rhs: &i16) -> I16Vec2 { (*self).mul(*rhs) } } impl Mul for &I16Vec2 { type Output = I16Vec2; #[inline] fn mul(self, rhs: i16) -> I16Vec2 { (*self).mul(rhs) } } impl MulAssign for I16Vec2 { #[inline] fn mul_assign(&mut self, rhs: i16) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&i16> for I16Vec2 { #[inline] fn mul_assign(&mut self, rhs: &i16) { self.mul_assign(*rhs) } } impl Mul for i16 { type Output = I16Vec2; #[inline] fn mul(self, rhs: I16Vec2) -> I16Vec2 { I16Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&I16Vec2> for i16 { type Output = I16Vec2; #[inline] fn mul(self, rhs: &I16Vec2) -> I16Vec2 { self.mul(*rhs) } } impl Mul<&I16Vec2> for &i16 { type Output = I16Vec2; #[inline] fn mul(self, rhs: &I16Vec2) -> I16Vec2 { (*self).mul(*rhs) } } impl Mul for &i16 { type Output = I16Vec2; #[inline] fn mul(self, rhs: I16Vec2) -> I16Vec2 { (*self).mul(rhs) } } impl Add 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 Add<&I16Vec2> for I16Vec2 { type Output = I16Vec2; #[inline] fn add(self, rhs: &I16Vec2) -> I16Vec2 { self.add(*rhs) } } impl Add<&I16Vec2> for &I16Vec2 { type Output = I16Vec2; #[inline] fn add(self, rhs: &I16Vec2) -> I16Vec2 { (*self).add(*rhs) } } impl Add for &I16Vec2 { type Output = I16Vec2; #[inline] fn add(self, rhs: I16Vec2) -> I16Vec2 { (*self).add(rhs) } } impl AddAssign for I16Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&I16Vec2> for I16Vec2 { #[inline] fn add_assign(&mut self, rhs: &I16Vec2) { self.add_assign(*rhs) } } impl Add for I16Vec2 { type Output = Self; #[inline] fn add(self, rhs: i16) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&i16> for I16Vec2 { type Output = I16Vec2; #[inline] fn add(self, rhs: &i16) -> I16Vec2 { self.add(*rhs) } } impl Add<&i16> for &I16Vec2 { type Output = I16Vec2; #[inline] fn add(self, rhs: &i16) -> I16Vec2 { (*self).add(*rhs) } } impl Add for &I16Vec2 { type Output = I16Vec2; #[inline] fn add(self, rhs: i16) -> I16Vec2 { (*self).add(rhs) } } impl AddAssign for I16Vec2 { #[inline] fn add_assign(&mut self, rhs: i16) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&i16> for I16Vec2 { #[inline] fn add_assign(&mut self, rhs: &i16) { self.add_assign(*rhs) } } impl Add for i16 { type Output = I16Vec2; #[inline] fn add(self, rhs: I16Vec2) -> I16Vec2 { I16Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&I16Vec2> for i16 { type Output = I16Vec2; #[inline] fn add(self, rhs: &I16Vec2) -> I16Vec2 { self.add(*rhs) } } impl Add<&I16Vec2> for &i16 { type Output = I16Vec2; #[inline] fn add(self, rhs: &I16Vec2) -> I16Vec2 { (*self).add(*rhs) } } impl Add for &i16 { type Output = I16Vec2; #[inline] fn add(self, rhs: I16Vec2) -> I16Vec2 { (*self).add(rhs) } } impl Sub 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 Sub<&I16Vec2> for I16Vec2 { type Output = I16Vec2; #[inline] fn sub(self, rhs: &I16Vec2) -> I16Vec2 { self.sub(*rhs) } } impl Sub<&I16Vec2> for &I16Vec2 { type Output = I16Vec2; #[inline] fn sub(self, rhs: &I16Vec2) -> I16Vec2 { (*self).sub(*rhs) } } impl Sub for &I16Vec2 { type Output = I16Vec2; #[inline] fn sub(self, rhs: I16Vec2) -> I16Vec2 { (*self).sub(rhs) } } impl SubAssign for I16Vec2 { #[inline] fn sub_assign(&mut self, rhs: I16Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&I16Vec2> for I16Vec2 { #[inline] fn sub_assign(&mut self, rhs: &I16Vec2) { self.sub_assign(*rhs) } } impl Sub for I16Vec2 { type Output = Self; #[inline] fn sub(self, rhs: i16) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&i16> for I16Vec2 { type Output = I16Vec2; #[inline] fn sub(self, rhs: &i16) -> I16Vec2 { self.sub(*rhs) } } impl Sub<&i16> for &I16Vec2 { type Output = I16Vec2; #[inline] fn sub(self, rhs: &i16) -> I16Vec2 { (*self).sub(*rhs) } } impl Sub for &I16Vec2 { type Output = I16Vec2; #[inline] fn sub(self, rhs: i16) -> I16Vec2 { (*self).sub(rhs) } } impl SubAssign for I16Vec2 { #[inline] fn sub_assign(&mut self, rhs: i16) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&i16> for I16Vec2 { #[inline] fn sub_assign(&mut self, rhs: &i16) { self.sub_assign(*rhs) } } impl Sub for i16 { type Output = I16Vec2; #[inline] fn sub(self, rhs: I16Vec2) -> I16Vec2 { I16Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&I16Vec2> for i16 { type Output = I16Vec2; #[inline] fn sub(self, rhs: &I16Vec2) -> I16Vec2 { self.sub(*rhs) } } impl Sub<&I16Vec2> for &i16 { type Output = I16Vec2; #[inline] fn sub(self, rhs: &I16Vec2) -> I16Vec2 { (*self).sub(*rhs) } } impl Sub for &i16 { type Output = I16Vec2; #[inline] fn sub(self, rhs: I16Vec2) -> I16Vec2 { (*self).sub(rhs) } } impl Rem 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 Rem<&I16Vec2> for I16Vec2 { type Output = I16Vec2; #[inline] fn rem(self, rhs: &I16Vec2) -> I16Vec2 { self.rem(*rhs) } } impl Rem<&I16Vec2> for &I16Vec2 { type Output = I16Vec2; #[inline] fn rem(self, rhs: &I16Vec2) -> I16Vec2 { (*self).rem(*rhs) } } impl Rem for &I16Vec2 { type Output = I16Vec2; #[inline] fn rem(self, rhs: I16Vec2) -> I16Vec2 { (*self).rem(rhs) } } impl RemAssign for I16Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&I16Vec2> for I16Vec2 { #[inline] fn rem_assign(&mut self, rhs: &I16Vec2) { self.rem_assign(*rhs) } } impl Rem for I16Vec2 { type Output = Self; #[inline] fn rem(self, rhs: i16) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&i16> for I16Vec2 { type Output = I16Vec2; #[inline] fn rem(self, rhs: &i16) -> I16Vec2 { self.rem(*rhs) } } impl Rem<&i16> for &I16Vec2 { type Output = I16Vec2; #[inline] fn rem(self, rhs: &i16) -> I16Vec2 { (*self).rem(*rhs) } } impl Rem for &I16Vec2 { type Output = I16Vec2; #[inline] fn rem(self, rhs: i16) -> I16Vec2 { (*self).rem(rhs) } } impl RemAssign for I16Vec2 { #[inline] fn rem_assign(&mut self, rhs: i16) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&i16> for I16Vec2 { #[inline] fn rem_assign(&mut self, rhs: &i16) { self.rem_assign(*rhs) } } impl Rem for i16 { type Output = I16Vec2; #[inline] fn rem(self, rhs: I16Vec2) -> I16Vec2 { I16Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&I16Vec2> for i16 { type Output = I16Vec2; #[inline] fn rem(self, rhs: &I16Vec2) -> I16Vec2 { self.rem(*rhs) } } impl Rem<&I16Vec2> for &i16 { type Output = I16Vec2; #[inline] fn rem(self, rhs: &I16Vec2) -> I16Vec2 { (*self).rem(*rhs) } } impl Rem for &i16 { type Output = I16Vec2; #[inline] fn rem(self, rhs: I16Vec2) -> I16Vec2 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I16Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I16Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I16Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 Neg for &I16Vec2 { type Output = I16Vec2; #[inline] fn neg(self) -> I16Vec2 { (*self).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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for I16Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } 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 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 for (i16, i16) { #[inline] fn from(v: I16Vec2) -> Self { (v.x, v.y) } } impl From for I16Vec2 { #[inline] fn from(v: I8Vec2) -> Self { Self::new(i16::from(v.x), i16::from(v.y)) } } impl From for I16Vec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(i16::from(v.x), i16::from(v.y)) } } impl TryFrom for I16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec2) -> Result { Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?)) } } impl TryFrom for I16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?)) } } impl TryFrom for I16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec2) -> Result { Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?)) } } impl TryFrom for I16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?)) } } impl TryFrom for I16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?)) } } impl TryFrom for I16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(i16::try_from(v.x)?, i16::try_from(v.y)?)) } } impl From for I16Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(i16::from(v.x), i16::from(v.y)) } } glam-0.30.1/src/i16/i16vec3.rs000064400000000000000000001503471046102023000135530ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec2, I16Vec4, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i16) -> i16, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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 { assert!(slice.len() >= 3); 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[..3].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i16) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i16) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i16) -> Self { self.z = z; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i16 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i16 { self.x * self.y * 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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u16::MAX`]. /// /// See also [`checked_manhattan_distance`][I16Vec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u16 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u16::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u16 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U16Vec3) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U16Vec3) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U16Vec3) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U16Vec3) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U16Vec3) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U16Vec3) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), } } } impl Default for I16Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&I16Vec3> for I16Vec3 { type Output = I16Vec3; #[inline] fn div(self, rhs: &I16Vec3) -> I16Vec3 { self.div(*rhs) } } impl Div<&I16Vec3> for &I16Vec3 { type Output = I16Vec3; #[inline] fn div(self, rhs: &I16Vec3) -> I16Vec3 { (*self).div(*rhs) } } impl Div for &I16Vec3 { type Output = I16Vec3; #[inline] fn div(self, rhs: I16Vec3) -> I16Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&I16Vec3> for I16Vec3 { #[inline] fn div_assign(&mut self, rhs: &I16Vec3) { self.div_assign(*rhs) } } impl Div 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 Div<&i16> for I16Vec3 { type Output = I16Vec3; #[inline] fn div(self, rhs: &i16) -> I16Vec3 { self.div(*rhs) } } impl Div<&i16> for &I16Vec3 { type Output = I16Vec3; #[inline] fn div(self, rhs: &i16) -> I16Vec3 { (*self).div(*rhs) } } impl Div for &I16Vec3 { type Output = I16Vec3; #[inline] fn div(self, rhs: i16) -> I16Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&i16> for I16Vec3 { #[inline] fn div_assign(&mut self, rhs: &i16) { self.div_assign(*rhs) } } impl Div 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 Div<&I16Vec3> for i16 { type Output = I16Vec3; #[inline] fn div(self, rhs: &I16Vec3) -> I16Vec3 { self.div(*rhs) } } impl Div<&I16Vec3> for &i16 { type Output = I16Vec3; #[inline] fn div(self, rhs: &I16Vec3) -> I16Vec3 { (*self).div(*rhs) } } impl Div for &i16 { type Output = I16Vec3; #[inline] fn div(self, rhs: I16Vec3) -> I16Vec3 { (*self).div(rhs) } } impl Mul 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 Mul<&I16Vec3> for I16Vec3 { type Output = I16Vec3; #[inline] fn mul(self, rhs: &I16Vec3) -> I16Vec3 { self.mul(*rhs) } } impl Mul<&I16Vec3> for &I16Vec3 { type Output = I16Vec3; #[inline] fn mul(self, rhs: &I16Vec3) -> I16Vec3 { (*self).mul(*rhs) } } impl Mul for &I16Vec3 { type Output = I16Vec3; #[inline] fn mul(self, rhs: I16Vec3) -> I16Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&I16Vec3> for I16Vec3 { #[inline] fn mul_assign(&mut self, rhs: &I16Vec3) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&i16> for I16Vec3 { type Output = I16Vec3; #[inline] fn mul(self, rhs: &i16) -> I16Vec3 { self.mul(*rhs) } } impl Mul<&i16> for &I16Vec3 { type Output = I16Vec3; #[inline] fn mul(self, rhs: &i16) -> I16Vec3 { (*self).mul(*rhs) } } impl Mul for &I16Vec3 { type Output = I16Vec3; #[inline] fn mul(self, rhs: i16) -> I16Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&i16> for I16Vec3 { #[inline] fn mul_assign(&mut self, rhs: &i16) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&I16Vec3> for i16 { type Output = I16Vec3; #[inline] fn mul(self, rhs: &I16Vec3) -> I16Vec3 { self.mul(*rhs) } } impl Mul<&I16Vec3> for &i16 { type Output = I16Vec3; #[inline] fn mul(self, rhs: &I16Vec3) -> I16Vec3 { (*self).mul(*rhs) } } impl Mul for &i16 { type Output = I16Vec3; #[inline] fn mul(self, rhs: I16Vec3) -> I16Vec3 { (*self).mul(rhs) } } impl Add 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 Add<&I16Vec3> for I16Vec3 { type Output = I16Vec3; #[inline] fn add(self, rhs: &I16Vec3) -> I16Vec3 { self.add(*rhs) } } impl Add<&I16Vec3> for &I16Vec3 { type Output = I16Vec3; #[inline] fn add(self, rhs: &I16Vec3) -> I16Vec3 { (*self).add(*rhs) } } impl Add for &I16Vec3 { type Output = I16Vec3; #[inline] fn add(self, rhs: I16Vec3) -> I16Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&I16Vec3> for I16Vec3 { #[inline] fn add_assign(&mut self, rhs: &I16Vec3) { self.add_assign(*rhs) } } impl Add 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 Add<&i16> for I16Vec3 { type Output = I16Vec3; #[inline] fn add(self, rhs: &i16) -> I16Vec3 { self.add(*rhs) } } impl Add<&i16> for &I16Vec3 { type Output = I16Vec3; #[inline] fn add(self, rhs: &i16) -> I16Vec3 { (*self).add(*rhs) } } impl Add for &I16Vec3 { type Output = I16Vec3; #[inline] fn add(self, rhs: i16) -> I16Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&i16> for I16Vec3 { #[inline] fn add_assign(&mut self, rhs: &i16) { self.add_assign(*rhs) } } impl Add 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 Add<&I16Vec3> for i16 { type Output = I16Vec3; #[inline] fn add(self, rhs: &I16Vec3) -> I16Vec3 { self.add(*rhs) } } impl Add<&I16Vec3> for &i16 { type Output = I16Vec3; #[inline] fn add(self, rhs: &I16Vec3) -> I16Vec3 { (*self).add(*rhs) } } impl Add for &i16 { type Output = I16Vec3; #[inline] fn add(self, rhs: I16Vec3) -> I16Vec3 { (*self).add(rhs) } } impl Sub 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 Sub<&I16Vec3> for I16Vec3 { type Output = I16Vec3; #[inline] fn sub(self, rhs: &I16Vec3) -> I16Vec3 { self.sub(*rhs) } } impl Sub<&I16Vec3> for &I16Vec3 { type Output = I16Vec3; #[inline] fn sub(self, rhs: &I16Vec3) -> I16Vec3 { (*self).sub(*rhs) } } impl Sub for &I16Vec3 { type Output = I16Vec3; #[inline] fn sub(self, rhs: I16Vec3) -> I16Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&I16Vec3> for I16Vec3 { #[inline] fn sub_assign(&mut self, rhs: &I16Vec3) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&i16> for I16Vec3 { type Output = I16Vec3; #[inline] fn sub(self, rhs: &i16) -> I16Vec3 { self.sub(*rhs) } } impl Sub<&i16> for &I16Vec3 { type Output = I16Vec3; #[inline] fn sub(self, rhs: &i16) -> I16Vec3 { (*self).sub(*rhs) } } impl Sub for &I16Vec3 { type Output = I16Vec3; #[inline] fn sub(self, rhs: i16) -> I16Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&i16> for I16Vec3 { #[inline] fn sub_assign(&mut self, rhs: &i16) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&I16Vec3> for i16 { type Output = I16Vec3; #[inline] fn sub(self, rhs: &I16Vec3) -> I16Vec3 { self.sub(*rhs) } } impl Sub<&I16Vec3> for &i16 { type Output = I16Vec3; #[inline] fn sub(self, rhs: &I16Vec3) -> I16Vec3 { (*self).sub(*rhs) } } impl Sub for &i16 { type Output = I16Vec3; #[inline] fn sub(self, rhs: I16Vec3) -> I16Vec3 { (*self).sub(rhs) } } impl Rem 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 Rem<&I16Vec3> for I16Vec3 { type Output = I16Vec3; #[inline] fn rem(self, rhs: &I16Vec3) -> I16Vec3 { self.rem(*rhs) } } impl Rem<&I16Vec3> for &I16Vec3 { type Output = I16Vec3; #[inline] fn rem(self, rhs: &I16Vec3) -> I16Vec3 { (*self).rem(*rhs) } } impl Rem for &I16Vec3 { type Output = I16Vec3; #[inline] fn rem(self, rhs: I16Vec3) -> I16Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&I16Vec3> for I16Vec3 { #[inline] fn rem_assign(&mut self, rhs: &I16Vec3) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&i16> for I16Vec3 { type Output = I16Vec3; #[inline] fn rem(self, rhs: &i16) -> I16Vec3 { self.rem(*rhs) } } impl Rem<&i16> for &I16Vec3 { type Output = I16Vec3; #[inline] fn rem(self, rhs: &i16) -> I16Vec3 { (*self).rem(*rhs) } } impl Rem for &I16Vec3 { type Output = I16Vec3; #[inline] fn rem(self, rhs: i16) -> I16Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&i16> for I16Vec3 { #[inline] fn rem_assign(&mut self, rhs: &i16) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&I16Vec3> for i16 { type Output = I16Vec3; #[inline] fn rem(self, rhs: &I16Vec3) -> I16Vec3 { self.rem(*rhs) } } impl Rem<&I16Vec3> for &i16 { type Output = I16Vec3; #[inline] fn rem(self, rhs: &I16Vec3) -> I16Vec3 { (*self).rem(*rhs) } } impl Rem for &i16 { type Output = I16Vec3; #[inline] fn rem(self, rhs: I16Vec3) -> I16Vec3 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I16Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I16Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I16Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 Neg for &I16Vec3 { type Output = I16Vec3; #[inline] fn neg(self) -> I16Vec3 { (*self).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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for I16Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } 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 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 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 From for I16Vec3 { #[inline] fn from(v: I8Vec3) -> Self { Self::new(i16::from(v.x), i16::from(v.y), i16::from(v.z)) } } impl From for I16Vec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(i16::from(v.x), i16::from(v.y), i16::from(v.z)) } } impl TryFrom for I16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec3) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, )) } } impl TryFrom for I16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, )) } } impl TryFrom for I16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec3) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, )) } } impl TryFrom for I16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, )) } } impl TryFrom for I16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, )) } } impl TryFrom for I16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, )) } } impl From for I16Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(i16::from(v.x), i16::from(v.y), i16::from(v.z)) } } impl From for I16Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( i16::from(bool_array[0]), i16::from(bool_array[1]), i16::from(bool_array[2]), ) } } glam-0.30.1/src/i16/i16vec4.rs000064400000000000000000001625431046102023000135550ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec2, I16Vec3, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; 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, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i16) -> i16, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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 { assert!(slice.len() >= 4); 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[..4].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i16) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i16) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i16) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: i16) -> Self { self.w = w; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i16 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i16 { self.x * self.y * self.z * 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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u16::MAX`]. /// /// See also [`checked_manhattan_distance`][I16Vec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u16 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u16::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u16 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U16Vec4) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U16Vec4) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U16Vec4) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), w: self.w.wrapping_add_unsigned(rhs.w), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U16Vec4) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), w: self.w.wrapping_sub_unsigned(rhs.w), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U16Vec4) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), w: self.w.saturating_add_unsigned(rhs.w), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U16Vec4) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), w: self.w.saturating_sub_unsigned(rhs.w), } } } impl Default for I16Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&I16Vec4> for I16Vec4 { type Output = I16Vec4; #[inline] fn div(self, rhs: &I16Vec4) -> I16Vec4 { self.div(*rhs) } } impl Div<&I16Vec4> for &I16Vec4 { type Output = I16Vec4; #[inline] fn div(self, rhs: &I16Vec4) -> I16Vec4 { (*self).div(*rhs) } } impl Div for &I16Vec4 { type Output = I16Vec4; #[inline] fn div(self, rhs: I16Vec4) -> I16Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&I16Vec4> for I16Vec4 { #[inline] fn div_assign(&mut self, rhs: &I16Vec4) { self.div_assign(*rhs) } } impl Div 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 Div<&i16> for I16Vec4 { type Output = I16Vec4; #[inline] fn div(self, rhs: &i16) -> I16Vec4 { self.div(*rhs) } } impl Div<&i16> for &I16Vec4 { type Output = I16Vec4; #[inline] fn div(self, rhs: &i16) -> I16Vec4 { (*self).div(*rhs) } } impl Div for &I16Vec4 { type Output = I16Vec4; #[inline] fn div(self, rhs: i16) -> I16Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&i16> for I16Vec4 { #[inline] fn div_assign(&mut self, rhs: &i16) { self.div_assign(*rhs) } } impl Div 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 Div<&I16Vec4> for i16 { type Output = I16Vec4; #[inline] fn div(self, rhs: &I16Vec4) -> I16Vec4 { self.div(*rhs) } } impl Div<&I16Vec4> for &i16 { type Output = I16Vec4; #[inline] fn div(self, rhs: &I16Vec4) -> I16Vec4 { (*self).div(*rhs) } } impl Div for &i16 { type Output = I16Vec4; #[inline] fn div(self, rhs: I16Vec4) -> I16Vec4 { (*self).div(rhs) } } impl Mul 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 Mul<&I16Vec4> for I16Vec4 { type Output = I16Vec4; #[inline] fn mul(self, rhs: &I16Vec4) -> I16Vec4 { self.mul(*rhs) } } impl Mul<&I16Vec4> for &I16Vec4 { type Output = I16Vec4; #[inline] fn mul(self, rhs: &I16Vec4) -> I16Vec4 { (*self).mul(*rhs) } } impl Mul for &I16Vec4 { type Output = I16Vec4; #[inline] fn mul(self, rhs: I16Vec4) -> I16Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&I16Vec4> for I16Vec4 { #[inline] fn mul_assign(&mut self, rhs: &I16Vec4) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&i16> for I16Vec4 { type Output = I16Vec4; #[inline] fn mul(self, rhs: &i16) -> I16Vec4 { self.mul(*rhs) } } impl Mul<&i16> for &I16Vec4 { type Output = I16Vec4; #[inline] fn mul(self, rhs: &i16) -> I16Vec4 { (*self).mul(*rhs) } } impl Mul for &I16Vec4 { type Output = I16Vec4; #[inline] fn mul(self, rhs: i16) -> I16Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&i16> for I16Vec4 { #[inline] fn mul_assign(&mut self, rhs: &i16) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&I16Vec4> for i16 { type Output = I16Vec4; #[inline] fn mul(self, rhs: &I16Vec4) -> I16Vec4 { self.mul(*rhs) } } impl Mul<&I16Vec4> for &i16 { type Output = I16Vec4; #[inline] fn mul(self, rhs: &I16Vec4) -> I16Vec4 { (*self).mul(*rhs) } } impl Mul for &i16 { type Output = I16Vec4; #[inline] fn mul(self, rhs: I16Vec4) -> I16Vec4 { (*self).mul(rhs) } } impl Add 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 Add<&I16Vec4> for I16Vec4 { type Output = I16Vec4; #[inline] fn add(self, rhs: &I16Vec4) -> I16Vec4 { self.add(*rhs) } } impl Add<&I16Vec4> for &I16Vec4 { type Output = I16Vec4; #[inline] fn add(self, rhs: &I16Vec4) -> I16Vec4 { (*self).add(*rhs) } } impl Add for &I16Vec4 { type Output = I16Vec4; #[inline] fn add(self, rhs: I16Vec4) -> I16Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&I16Vec4> for I16Vec4 { #[inline] fn add_assign(&mut self, rhs: &I16Vec4) { self.add_assign(*rhs) } } impl Add 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 Add<&i16> for I16Vec4 { type Output = I16Vec4; #[inline] fn add(self, rhs: &i16) -> I16Vec4 { self.add(*rhs) } } impl Add<&i16> for &I16Vec4 { type Output = I16Vec4; #[inline] fn add(self, rhs: &i16) -> I16Vec4 { (*self).add(*rhs) } } impl Add for &I16Vec4 { type Output = I16Vec4; #[inline] fn add(self, rhs: i16) -> I16Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&i16> for I16Vec4 { #[inline] fn add_assign(&mut self, rhs: &i16) { self.add_assign(*rhs) } } impl Add 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 Add<&I16Vec4> for i16 { type Output = I16Vec4; #[inline] fn add(self, rhs: &I16Vec4) -> I16Vec4 { self.add(*rhs) } } impl Add<&I16Vec4> for &i16 { type Output = I16Vec4; #[inline] fn add(self, rhs: &I16Vec4) -> I16Vec4 { (*self).add(*rhs) } } impl Add for &i16 { type Output = I16Vec4; #[inline] fn add(self, rhs: I16Vec4) -> I16Vec4 { (*self).add(rhs) } } impl Sub 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 Sub<&I16Vec4> for I16Vec4 { type Output = I16Vec4; #[inline] fn sub(self, rhs: &I16Vec4) -> I16Vec4 { self.sub(*rhs) } } impl Sub<&I16Vec4> for &I16Vec4 { type Output = I16Vec4; #[inline] fn sub(self, rhs: &I16Vec4) -> I16Vec4 { (*self).sub(*rhs) } } impl Sub for &I16Vec4 { type Output = I16Vec4; #[inline] fn sub(self, rhs: I16Vec4) -> I16Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&I16Vec4> for I16Vec4 { #[inline] fn sub_assign(&mut self, rhs: &I16Vec4) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&i16> for I16Vec4 { type Output = I16Vec4; #[inline] fn sub(self, rhs: &i16) -> I16Vec4 { self.sub(*rhs) } } impl Sub<&i16> for &I16Vec4 { type Output = I16Vec4; #[inline] fn sub(self, rhs: &i16) -> I16Vec4 { (*self).sub(*rhs) } } impl Sub for &I16Vec4 { type Output = I16Vec4; #[inline] fn sub(self, rhs: i16) -> I16Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&i16> for I16Vec4 { #[inline] fn sub_assign(&mut self, rhs: &i16) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&I16Vec4> for i16 { type Output = I16Vec4; #[inline] fn sub(self, rhs: &I16Vec4) -> I16Vec4 { self.sub(*rhs) } } impl Sub<&I16Vec4> for &i16 { type Output = I16Vec4; #[inline] fn sub(self, rhs: &I16Vec4) -> I16Vec4 { (*self).sub(*rhs) } } impl Sub for &i16 { type Output = I16Vec4; #[inline] fn sub(self, rhs: I16Vec4) -> I16Vec4 { (*self).sub(rhs) } } impl Rem 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 Rem<&I16Vec4> for I16Vec4 { type Output = I16Vec4; #[inline] fn rem(self, rhs: &I16Vec4) -> I16Vec4 { self.rem(*rhs) } } impl Rem<&I16Vec4> for &I16Vec4 { type Output = I16Vec4; #[inline] fn rem(self, rhs: &I16Vec4) -> I16Vec4 { (*self).rem(*rhs) } } impl Rem for &I16Vec4 { type Output = I16Vec4; #[inline] fn rem(self, rhs: I16Vec4) -> I16Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&I16Vec4> for I16Vec4 { #[inline] fn rem_assign(&mut self, rhs: &I16Vec4) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&i16> for I16Vec4 { type Output = I16Vec4; #[inline] fn rem(self, rhs: &i16) -> I16Vec4 { self.rem(*rhs) } } impl Rem<&i16> for &I16Vec4 { type Output = I16Vec4; #[inline] fn rem(self, rhs: &i16) -> I16Vec4 { (*self).rem(*rhs) } } impl Rem for &I16Vec4 { type Output = I16Vec4; #[inline] fn rem(self, rhs: i16) -> I16Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&i16> for I16Vec4 { #[inline] fn rem_assign(&mut self, rhs: &i16) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&I16Vec4> for i16 { type Output = I16Vec4; #[inline] fn rem(self, rhs: &I16Vec4) -> I16Vec4 { self.rem(*rhs) } } impl Rem<&I16Vec4> for &i16 { type Output = I16Vec4; #[inline] fn rem(self, rhs: &I16Vec4) -> I16Vec4 { (*self).rem(*rhs) } } impl Rem for &i16 { type Output = I16Vec4; #[inline] fn rem(self, rhs: I16Vec4) -> I16Vec4 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I16Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I16Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I16Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 Neg for &I16Vec4 { type Output = I16Vec4; #[inline] fn neg(self) -> I16Vec4 { (*self).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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for I16Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } 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 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 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 From for I16Vec4 { #[inline] fn from(v: I8Vec4) -> Self { Self::new( i16::from(v.x), i16::from(v.y), i16::from(v.z), i16::from(v.w), ) } } impl From for I16Vec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( i16::from(v.x), i16::from(v.y), i16::from(v.z), i16::from(v.w), ) } } impl TryFrom for I16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec4) -> Result { 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 for I16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { 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 for I16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec4) -> Result { 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 for I16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { 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 for I16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { 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 for I16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( i16::try_from(v.x)?, i16::try_from(v.y)?, i16::try_from(v.z)?, i16::try_from(v.w)?, )) } } impl From for I16Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( i16::from(v.x), i16::from(v.y), i16::from(v.z), i16::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for I16Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( i16::from(bool_array[0]), i16::from(bool_array[1]), i16::from(bool_array[2]), i16::from(bool_array[3]), ) } } glam-0.30.1/src/i16.rs000064400000000000000000000022721046102023000123640ustar 00000000000000mod 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::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(4, core::mem::align_of::()); } mod const_test_i16vec3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(6, core::mem::size_of::()); } mod const_test_i16vec4 { const_assert_eq!(8, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(8, core::mem::align_of::()); } } glam-0.30.1/src/i32/ivec2.rs000064400000000000000000001334041046102023000133740ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec2, IVec3, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn ivec2(x: i32, y: i32) -> IVec2 { IVec2::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(8)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct IVec2 { pub x: i32, pub y: i32, } impl IVec2 { /// 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 `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 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i32) -> i32, { Self::new(f(self.x), f(self.y)) } /// 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: [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] } /// 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: &[i32]) -> Self { assert!(slice.len() >= 2); 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 [i32]) { slice[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i32) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i32) -> Self { self.y = y; self } /// 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)) } /// 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 [`i32::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) -> i32 { 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) -> i32 { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i32 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i32 { self.x * 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) -> 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)) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u32::MAX`]. /// /// See also [`checked_manhattan_distance`][IVec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u32 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u32::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u32 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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) -> i32 { (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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: UVec2) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: UVec2) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: UVec2) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: UVec2) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: UVec2) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: UVec2) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), } } } impl Default for IVec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for IVec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&IVec2> for IVec2 { type Output = IVec2; #[inline] fn div(self, rhs: &IVec2) -> IVec2 { self.div(*rhs) } } impl Div<&IVec2> for &IVec2 { type Output = IVec2; #[inline] fn div(self, rhs: &IVec2) -> IVec2 { (*self).div(*rhs) } } impl Div for &IVec2 { type Output = IVec2; #[inline] fn div(self, rhs: IVec2) -> IVec2 { (*self).div(rhs) } } impl DivAssign for IVec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&IVec2> for IVec2 { #[inline] fn div_assign(&mut self, rhs: &IVec2) { self.div_assign(*rhs) } } impl Div for IVec2 { type Output = Self; #[inline] fn div(self, rhs: i32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&i32> for IVec2 { type Output = IVec2; #[inline] fn div(self, rhs: &i32) -> IVec2 { self.div(*rhs) } } impl Div<&i32> for &IVec2 { type Output = IVec2; #[inline] fn div(self, rhs: &i32) -> IVec2 { (*self).div(*rhs) } } impl Div for &IVec2 { type Output = IVec2; #[inline] fn div(self, rhs: i32) -> IVec2 { (*self).div(rhs) } } impl DivAssign for IVec2 { #[inline] fn div_assign(&mut self, rhs: i32) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&i32> for IVec2 { #[inline] fn div_assign(&mut self, rhs: &i32) { self.div_assign(*rhs) } } impl Div for i32 { type Output = IVec2; #[inline] fn div(self, rhs: IVec2) -> IVec2 { IVec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&IVec2> for i32 { type Output = IVec2; #[inline] fn div(self, rhs: &IVec2) -> IVec2 { self.div(*rhs) } } impl Div<&IVec2> for &i32 { type Output = IVec2; #[inline] fn div(self, rhs: &IVec2) -> IVec2 { (*self).div(*rhs) } } impl Div for &i32 { type Output = IVec2; #[inline] fn div(self, rhs: IVec2) -> IVec2 { (*self).div(rhs) } } impl Mul for IVec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&IVec2> for IVec2 { type Output = IVec2; #[inline] fn mul(self, rhs: &IVec2) -> IVec2 { self.mul(*rhs) } } impl Mul<&IVec2> for &IVec2 { type Output = IVec2; #[inline] fn mul(self, rhs: &IVec2) -> IVec2 { (*self).mul(*rhs) } } impl Mul for &IVec2 { type Output = IVec2; #[inline] fn mul(self, rhs: IVec2) -> IVec2 { (*self).mul(rhs) } } impl MulAssign for IVec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&IVec2> for IVec2 { #[inline] fn mul_assign(&mut self, rhs: &IVec2) { self.mul_assign(*rhs) } } impl Mul for IVec2 { type Output = Self; #[inline] fn mul(self, rhs: i32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&i32> for IVec2 { type Output = IVec2; #[inline] fn mul(self, rhs: &i32) -> IVec2 { self.mul(*rhs) } } impl Mul<&i32> for &IVec2 { type Output = IVec2; #[inline] fn mul(self, rhs: &i32) -> IVec2 { (*self).mul(*rhs) } } impl Mul for &IVec2 { type Output = IVec2; #[inline] fn mul(self, rhs: i32) -> IVec2 { (*self).mul(rhs) } } impl MulAssign for IVec2 { #[inline] fn mul_assign(&mut self, rhs: i32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&i32> for IVec2 { #[inline] fn mul_assign(&mut self, rhs: &i32) { self.mul_assign(*rhs) } } impl Mul for i32 { type Output = IVec2; #[inline] fn mul(self, rhs: IVec2) -> IVec2 { IVec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&IVec2> for i32 { type Output = IVec2; #[inline] fn mul(self, rhs: &IVec2) -> IVec2 { self.mul(*rhs) } } impl Mul<&IVec2> for &i32 { type Output = IVec2; #[inline] fn mul(self, rhs: &IVec2) -> IVec2 { (*self).mul(*rhs) } } impl Mul for &i32 { type Output = IVec2; #[inline] fn mul(self, rhs: IVec2) -> IVec2 { (*self).mul(rhs) } } impl Add for IVec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&IVec2> for IVec2 { type Output = IVec2; #[inline] fn add(self, rhs: &IVec2) -> IVec2 { self.add(*rhs) } } impl Add<&IVec2> for &IVec2 { type Output = IVec2; #[inline] fn add(self, rhs: &IVec2) -> IVec2 { (*self).add(*rhs) } } impl Add for &IVec2 { type Output = IVec2; #[inline] fn add(self, rhs: IVec2) -> IVec2 { (*self).add(rhs) } } impl AddAssign for IVec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&IVec2> for IVec2 { #[inline] fn add_assign(&mut self, rhs: &IVec2) { self.add_assign(*rhs) } } impl Add for IVec2 { type Output = Self; #[inline] fn add(self, rhs: i32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&i32> for IVec2 { type Output = IVec2; #[inline] fn add(self, rhs: &i32) -> IVec2 { self.add(*rhs) } } impl Add<&i32> for &IVec2 { type Output = IVec2; #[inline] fn add(self, rhs: &i32) -> IVec2 { (*self).add(*rhs) } } impl Add for &IVec2 { type Output = IVec2; #[inline] fn add(self, rhs: i32) -> IVec2 { (*self).add(rhs) } } impl AddAssign for IVec2 { #[inline] fn add_assign(&mut self, rhs: i32) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&i32> for IVec2 { #[inline] fn add_assign(&mut self, rhs: &i32) { self.add_assign(*rhs) } } impl Add for i32 { type Output = IVec2; #[inline] fn add(self, rhs: IVec2) -> IVec2 { IVec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&IVec2> for i32 { type Output = IVec2; #[inline] fn add(self, rhs: &IVec2) -> IVec2 { self.add(*rhs) } } impl Add<&IVec2> for &i32 { type Output = IVec2; #[inline] fn add(self, rhs: &IVec2) -> IVec2 { (*self).add(*rhs) } } impl Add for &i32 { type Output = IVec2; #[inline] fn add(self, rhs: IVec2) -> IVec2 { (*self).add(rhs) } } impl Sub for IVec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&IVec2> for IVec2 { type Output = IVec2; #[inline] fn sub(self, rhs: &IVec2) -> IVec2 { self.sub(*rhs) } } impl Sub<&IVec2> for &IVec2 { type Output = IVec2; #[inline] fn sub(self, rhs: &IVec2) -> IVec2 { (*self).sub(*rhs) } } impl Sub for &IVec2 { type Output = IVec2; #[inline] fn sub(self, rhs: IVec2) -> IVec2 { (*self).sub(rhs) } } impl SubAssign for IVec2 { #[inline] fn sub_assign(&mut self, rhs: IVec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&IVec2> for IVec2 { #[inline] fn sub_assign(&mut self, rhs: &IVec2) { self.sub_assign(*rhs) } } impl Sub for IVec2 { type Output = Self; #[inline] fn sub(self, rhs: i32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&i32> for IVec2 { type Output = IVec2; #[inline] fn sub(self, rhs: &i32) -> IVec2 { self.sub(*rhs) } } impl Sub<&i32> for &IVec2 { type Output = IVec2; #[inline] fn sub(self, rhs: &i32) -> IVec2 { (*self).sub(*rhs) } } impl Sub for &IVec2 { type Output = IVec2; #[inline] fn sub(self, rhs: i32) -> IVec2 { (*self).sub(rhs) } } impl SubAssign for IVec2 { #[inline] fn sub_assign(&mut self, rhs: i32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&i32> for IVec2 { #[inline] fn sub_assign(&mut self, rhs: &i32) { self.sub_assign(*rhs) } } impl Sub for i32 { type Output = IVec2; #[inline] fn sub(self, rhs: IVec2) -> IVec2 { IVec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&IVec2> for i32 { type Output = IVec2; #[inline] fn sub(self, rhs: &IVec2) -> IVec2 { self.sub(*rhs) } } impl Sub<&IVec2> for &i32 { type Output = IVec2; #[inline] fn sub(self, rhs: &IVec2) -> IVec2 { (*self).sub(*rhs) } } impl Sub for &i32 { type Output = IVec2; #[inline] fn sub(self, rhs: IVec2) -> IVec2 { (*self).sub(rhs) } } impl Rem for IVec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&IVec2> for IVec2 { type Output = IVec2; #[inline] fn rem(self, rhs: &IVec2) -> IVec2 { self.rem(*rhs) } } impl Rem<&IVec2> for &IVec2 { type Output = IVec2; #[inline] fn rem(self, rhs: &IVec2) -> IVec2 { (*self).rem(*rhs) } } impl Rem for &IVec2 { type Output = IVec2; #[inline] fn rem(self, rhs: IVec2) -> IVec2 { (*self).rem(rhs) } } impl RemAssign for IVec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&IVec2> for IVec2 { #[inline] fn rem_assign(&mut self, rhs: &IVec2) { self.rem_assign(*rhs) } } impl Rem for IVec2 { type Output = Self; #[inline] fn rem(self, rhs: i32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&i32> for IVec2 { type Output = IVec2; #[inline] fn rem(self, rhs: &i32) -> IVec2 { self.rem(*rhs) } } impl Rem<&i32> for &IVec2 { type Output = IVec2; #[inline] fn rem(self, rhs: &i32) -> IVec2 { (*self).rem(*rhs) } } impl Rem for &IVec2 { type Output = IVec2; #[inline] fn rem(self, rhs: i32) -> IVec2 { (*self).rem(rhs) } } impl RemAssign for IVec2 { #[inline] fn rem_assign(&mut self, rhs: i32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&i32> for IVec2 { #[inline] fn rem_assign(&mut self, rhs: &i32) { self.rem_assign(*rhs) } } impl Rem for i32 { type Output = IVec2; #[inline] fn rem(self, rhs: IVec2) -> IVec2 { IVec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&IVec2> for i32 { type Output = IVec2; #[inline] fn rem(self, rhs: &IVec2) -> IVec2 { self.rem(*rhs) } } impl Rem<&IVec2> for &i32 { type Output = IVec2; #[inline] fn rem(self, rhs: &IVec2) -> IVec2 { (*self).rem(*rhs) } } impl Rem for &i32 { type Output = IVec2; #[inline] fn rem(self, rhs: IVec2) -> IVec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[i32; 2]> for IVec2 { #[inline] fn as_ref(&self) -> &[i32; 2] { unsafe { &*(self as *const IVec2 as *const [i32; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[i32; 2]> for IVec2 { #[inline] fn as_mut(&mut self) -> &mut [i32; 2] { unsafe { &mut *(self as *mut IVec2 as *mut [i32; 2]) } } } impl Sum for IVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for IVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for IVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for IVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for IVec2 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), } } } impl Neg for &IVec2 { type Output = IVec2; #[inline] fn neg(self) -> IVec2 { (*self).neg() } } impl Not for IVec2 { type Output = Self; #[inline] fn not(self) -> Self::Output { Self { x: self.x.not(), y: self.y.not(), } } } impl BitAnd for IVec2 { 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 IVec2 { 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 IVec2 { 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 for IVec2 { type Output = Self; #[inline] fn bitand(self, rhs: i32) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), } } } impl BitOr for IVec2 { type Output = Self; #[inline] fn bitor(self, rhs: i32) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), } } } impl BitXor for IVec2 { type Output = Self; #[inline] fn bitxor(self, rhs: i32) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), } } } impl Shl for IVec2 { type Output = Self; #[inline] fn shl(self, rhs: i8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for IVec2 { type Output = Self; #[inline] fn shr(self, rhs: i8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for IVec2 { type Output = Self; #[inline] fn shl(self, rhs: i16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for IVec2 { type Output = Self; #[inline] fn shr(self, rhs: i16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for IVec2 { type Output = Self; #[inline] fn shl(self, rhs: i32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for IVec2 { type Output = Self; #[inline] fn shr(self, rhs: i32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl 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 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 for IVec2 { type Output = Self; #[inline] fn shl(self, rhs: u8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for IVec2 { type Output = Self; #[inline] fn shr(self, rhs: u8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for IVec2 { type Output = Self; #[inline] fn shl(self, rhs: u16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for IVec2 { type Output = Self; #[inline] fn shr(self, rhs: u16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for IVec2 { type Output = Self; #[inline] fn shl(self, rhs: u32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for IVec2 { type Output = Self; #[inline] fn shr(self, rhs: u32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl 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 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 for IVec2 { 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 for IVec2 { 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 for IVec2 { 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 for IVec2 { 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 for IVec2 { type Output = i32; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for IVec2 { #[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"), } } } impl fmt::Display for IVec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } impl fmt::Debug for IVec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(IVec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[i32; 2]> for IVec2 { #[inline] fn from(a: [i32; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [i32; 2] { #[inline] fn from(v: IVec2) -> Self { [v.x, v.y] } } impl From<(i32, i32)> for IVec2 { #[inline] fn from(t: (i32, i32)) -> Self { Self::new(t.0, t.1) } } impl From for (i32, i32) { #[inline] fn from(v: IVec2) -> Self { (v.x, v.y) } } impl From for IVec2 { #[inline] fn from(v: I8Vec2) -> Self { Self::new(i32::from(v.x), i32::from(v.y)) } } impl From for IVec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(i32::from(v.x), i32::from(v.y)) } } impl From for IVec2 { #[inline] fn from(v: I16Vec2) -> Self { Self::new(i32::from(v.x), i32::from(v.y)) } } impl From for IVec2 { #[inline] fn from(v: U16Vec2) -> Self { Self::new(i32::from(v.x), i32::from(v.y)) } } impl TryFrom for IVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec2) -> Result { Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?)) } } impl TryFrom for IVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?)) } } impl TryFrom for IVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?)) } } impl TryFrom for IVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(i32::try_from(v.x)?, i32::try_from(v.y)?)) } } impl From for IVec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(i32::from(v.x), i32::from(v.y)) } } glam-0.30.1/src/i32/ivec3.rs000064400000000000000000001464671046102023000134120ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec3, IVec2, IVec4, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// 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 IVec3 { pub x: i32, pub y: i32, pub z: i32, } impl IVec3 { /// 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 `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 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i32) -> i32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [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] } /// 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: &[i32]) -> Self { assert!(slice.len() >= 3); 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 [i32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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, 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: 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> IVec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i32) -> Self { self.z = z; self } /// 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, 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 [`i32::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) -> i32 { 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) -> i32 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i32 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i32 { self.x * self.y * 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) -> 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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u32::MAX`]. /// /// See also [`checked_manhattan_distance`][IVec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u32 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u32::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u32 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: UVec3) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: UVec3) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: UVec3) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: UVec3) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: UVec3) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: UVec3) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), } } } impl Default for IVec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for IVec3 { 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 Div<&IVec3> for IVec3 { type Output = IVec3; #[inline] fn div(self, rhs: &IVec3) -> IVec3 { self.div(*rhs) } } impl Div<&IVec3> for &IVec3 { type Output = IVec3; #[inline] fn div(self, rhs: &IVec3) -> IVec3 { (*self).div(*rhs) } } impl Div for &IVec3 { type Output = IVec3; #[inline] fn div(self, rhs: IVec3) -> IVec3 { (*self).div(rhs) } } impl DivAssign for IVec3 { #[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 DivAssign<&IVec3> for IVec3 { #[inline] fn div_assign(&mut self, rhs: &IVec3) { self.div_assign(*rhs) } } impl Div for IVec3 { type Output = Self; #[inline] fn div(self, rhs: i32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&i32> for IVec3 { type Output = IVec3; #[inline] fn div(self, rhs: &i32) -> IVec3 { self.div(*rhs) } } impl Div<&i32> for &IVec3 { type Output = IVec3; #[inline] fn div(self, rhs: &i32) -> IVec3 { (*self).div(*rhs) } } impl Div for &IVec3 { type Output = IVec3; #[inline] fn div(self, rhs: i32) -> IVec3 { (*self).div(rhs) } } impl DivAssign for IVec3 { #[inline] fn div_assign(&mut self, rhs: i32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&i32> for IVec3 { #[inline] fn div_assign(&mut self, rhs: &i32) { self.div_assign(*rhs) } } impl Div for i32 { type Output = IVec3; #[inline] fn div(self, rhs: IVec3) -> IVec3 { IVec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&IVec3> for i32 { type Output = IVec3; #[inline] fn div(self, rhs: &IVec3) -> IVec3 { self.div(*rhs) } } impl Div<&IVec3> for &i32 { type Output = IVec3; #[inline] fn div(self, rhs: &IVec3) -> IVec3 { (*self).div(*rhs) } } impl Div for &i32 { type Output = IVec3; #[inline] fn div(self, rhs: IVec3) -> IVec3 { (*self).div(rhs) } } impl Mul for IVec3 { 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 Mul<&IVec3> for IVec3 { type Output = IVec3; #[inline] fn mul(self, rhs: &IVec3) -> IVec3 { self.mul(*rhs) } } impl Mul<&IVec3> for &IVec3 { type Output = IVec3; #[inline] fn mul(self, rhs: &IVec3) -> IVec3 { (*self).mul(*rhs) } } impl Mul for &IVec3 { type Output = IVec3; #[inline] fn mul(self, rhs: IVec3) -> IVec3 { (*self).mul(rhs) } } impl MulAssign for IVec3 { #[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 MulAssign<&IVec3> for IVec3 { #[inline] fn mul_assign(&mut self, rhs: &IVec3) { self.mul_assign(*rhs) } } impl Mul for IVec3 { type Output = Self; #[inline] fn mul(self, rhs: i32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&i32> for IVec3 { type Output = IVec3; #[inline] fn mul(self, rhs: &i32) -> IVec3 { self.mul(*rhs) } } impl Mul<&i32> for &IVec3 { type Output = IVec3; #[inline] fn mul(self, rhs: &i32) -> IVec3 { (*self).mul(*rhs) } } impl Mul for &IVec3 { type Output = IVec3; #[inline] fn mul(self, rhs: i32) -> IVec3 { (*self).mul(rhs) } } impl MulAssign for IVec3 { #[inline] fn mul_assign(&mut self, rhs: i32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&i32> for IVec3 { #[inline] fn mul_assign(&mut self, rhs: &i32) { self.mul_assign(*rhs) } } impl Mul for i32 { type Output = IVec3; #[inline] fn mul(self, rhs: IVec3) -> IVec3 { IVec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&IVec3> for i32 { type Output = IVec3; #[inline] fn mul(self, rhs: &IVec3) -> IVec3 { self.mul(*rhs) } } impl Mul<&IVec3> for &i32 { type Output = IVec3; #[inline] fn mul(self, rhs: &IVec3) -> IVec3 { (*self).mul(*rhs) } } impl Mul for &i32 { type Output = IVec3; #[inline] fn mul(self, rhs: IVec3) -> IVec3 { (*self).mul(rhs) } } impl Add for IVec3 { 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 Add<&IVec3> for IVec3 { type Output = IVec3; #[inline] fn add(self, rhs: &IVec3) -> IVec3 { self.add(*rhs) } } impl Add<&IVec3> for &IVec3 { type Output = IVec3; #[inline] fn add(self, rhs: &IVec3) -> IVec3 { (*self).add(*rhs) } } impl Add for &IVec3 { type Output = IVec3; #[inline] fn add(self, rhs: IVec3) -> IVec3 { (*self).add(rhs) } } impl AddAssign for IVec3 { #[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 AddAssign<&IVec3> for IVec3 { #[inline] fn add_assign(&mut self, rhs: &IVec3) { self.add_assign(*rhs) } } impl Add for IVec3 { type Output = Self; #[inline] fn add(self, rhs: i32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&i32> for IVec3 { type Output = IVec3; #[inline] fn add(self, rhs: &i32) -> IVec3 { self.add(*rhs) } } impl Add<&i32> for &IVec3 { type Output = IVec3; #[inline] fn add(self, rhs: &i32) -> IVec3 { (*self).add(*rhs) } } impl Add for &IVec3 { type Output = IVec3; #[inline] fn add(self, rhs: i32) -> IVec3 { (*self).add(rhs) } } impl AddAssign for IVec3 { #[inline] fn add_assign(&mut self, rhs: i32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&i32> for IVec3 { #[inline] fn add_assign(&mut self, rhs: &i32) { self.add_assign(*rhs) } } impl Add for i32 { type Output = IVec3; #[inline] fn add(self, rhs: IVec3) -> IVec3 { IVec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&IVec3> for i32 { type Output = IVec3; #[inline] fn add(self, rhs: &IVec3) -> IVec3 { self.add(*rhs) } } impl Add<&IVec3> for &i32 { type Output = IVec3; #[inline] fn add(self, rhs: &IVec3) -> IVec3 { (*self).add(*rhs) } } impl Add for &i32 { type Output = IVec3; #[inline] fn add(self, rhs: IVec3) -> IVec3 { (*self).add(rhs) } } impl Sub for IVec3 { 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 Sub<&IVec3> for IVec3 { type Output = IVec3; #[inline] fn sub(self, rhs: &IVec3) -> IVec3 { self.sub(*rhs) } } impl Sub<&IVec3> for &IVec3 { type Output = IVec3; #[inline] fn sub(self, rhs: &IVec3) -> IVec3 { (*self).sub(*rhs) } } impl Sub for &IVec3 { type Output = IVec3; #[inline] fn sub(self, rhs: IVec3) -> IVec3 { (*self).sub(rhs) } } impl SubAssign for IVec3 { #[inline] fn sub_assign(&mut self, rhs: IVec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&IVec3> for IVec3 { #[inline] fn sub_assign(&mut self, rhs: &IVec3) { self.sub_assign(*rhs) } } impl Sub for IVec3 { type Output = Self; #[inline] fn sub(self, rhs: i32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&i32> for IVec3 { type Output = IVec3; #[inline] fn sub(self, rhs: &i32) -> IVec3 { self.sub(*rhs) } } impl Sub<&i32> for &IVec3 { type Output = IVec3; #[inline] fn sub(self, rhs: &i32) -> IVec3 { (*self).sub(*rhs) } } impl Sub for &IVec3 { type Output = IVec3; #[inline] fn sub(self, rhs: i32) -> IVec3 { (*self).sub(rhs) } } impl SubAssign for IVec3 { #[inline] fn sub_assign(&mut self, rhs: i32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&i32> for IVec3 { #[inline] fn sub_assign(&mut self, rhs: &i32) { self.sub_assign(*rhs) } } impl Sub for i32 { type Output = IVec3; #[inline] fn sub(self, rhs: IVec3) -> IVec3 { IVec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&IVec3> for i32 { type Output = IVec3; #[inline] fn sub(self, rhs: &IVec3) -> IVec3 { self.sub(*rhs) } } impl Sub<&IVec3> for &i32 { type Output = IVec3; #[inline] fn sub(self, rhs: &IVec3) -> IVec3 { (*self).sub(*rhs) } } impl Sub for &i32 { type Output = IVec3; #[inline] fn sub(self, rhs: IVec3) -> IVec3 { (*self).sub(rhs) } } impl Rem for IVec3 { 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 Rem<&IVec3> for IVec3 { type Output = IVec3; #[inline] fn rem(self, rhs: &IVec3) -> IVec3 { self.rem(*rhs) } } impl Rem<&IVec3> for &IVec3 { type Output = IVec3; #[inline] fn rem(self, rhs: &IVec3) -> IVec3 { (*self).rem(*rhs) } } impl Rem for &IVec3 { type Output = IVec3; #[inline] fn rem(self, rhs: IVec3) -> IVec3 { (*self).rem(rhs) } } impl RemAssign for IVec3 { #[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 RemAssign<&IVec3> for IVec3 { #[inline] fn rem_assign(&mut self, rhs: &IVec3) { self.rem_assign(*rhs) } } impl Rem for IVec3 { type Output = Self; #[inline] fn rem(self, rhs: i32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&i32> for IVec3 { type Output = IVec3; #[inline] fn rem(self, rhs: &i32) -> IVec3 { self.rem(*rhs) } } impl Rem<&i32> for &IVec3 { type Output = IVec3; #[inline] fn rem(self, rhs: &i32) -> IVec3 { (*self).rem(*rhs) } } impl Rem for &IVec3 { type Output = IVec3; #[inline] fn rem(self, rhs: i32) -> IVec3 { (*self).rem(rhs) } } impl RemAssign for IVec3 { #[inline] fn rem_assign(&mut self, rhs: i32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&i32> for IVec3 { #[inline] fn rem_assign(&mut self, rhs: &i32) { self.rem_assign(*rhs) } } impl Rem for i32 { type Output = IVec3; #[inline] fn rem(self, rhs: IVec3) -> IVec3 { IVec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&IVec3> for i32 { type Output = IVec3; #[inline] fn rem(self, rhs: &IVec3) -> IVec3 { self.rem(*rhs) } } impl Rem<&IVec3> for &i32 { type Output = IVec3; #[inline] fn rem(self, rhs: &IVec3) -> IVec3 { (*self).rem(*rhs) } } impl Rem for &i32 { type Output = IVec3; #[inline] fn rem(self, rhs: IVec3) -> IVec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[i32; 3]> for IVec3 { #[inline] fn as_ref(&self) -> &[i32; 3] { unsafe { &*(self as *const IVec3 as *const [i32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[i32; 3]> for IVec3 { #[inline] fn as_mut(&mut self) -> &mut [i32; 3] { unsafe { &mut *(self as *mut IVec3 as *mut [i32; 3]) } } } impl Sum for IVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for IVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for IVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for IVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for IVec3 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), z: self.z.neg(), } } } impl Neg for &IVec3 { type Output = IVec3; #[inline] fn neg(self) -> IVec3 { (*self).neg() } } impl Not for IVec3 { 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 IVec3 { 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 IVec3 { 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 IVec3 { 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 for IVec3 { type Output = Self; #[inline] fn bitand(self, rhs: i32) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), z: self.z.bitand(rhs), } } } impl BitOr for IVec3 { type Output = Self; #[inline] fn bitor(self, rhs: i32) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), z: self.z.bitor(rhs), } } } impl BitXor for IVec3 { type Output = Self; #[inline] fn bitxor(self, rhs: i32) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), z: self.z.bitxor(rhs), } } } impl Shl for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 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 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 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 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { 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 for IVec3 { type Output = i32; #[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 for IVec3 { #[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"), } } } impl fmt::Display for IVec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } impl fmt::Debug for IVec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(IVec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[i32; 3]> for IVec3 { #[inline] fn from(a: [i32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [i32; 3] { #[inline] fn from(v: IVec3) -> Self { [v.x, v.y, v.z] } } impl From<(i32, i32, i32)> for IVec3 { #[inline] fn from(t: (i32, i32, i32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (i32, i32, i32) { #[inline] fn from(v: IVec3) -> Self { (v.x, v.y, v.z) } } impl From<(IVec2, i32)> for IVec3 { #[inline] fn from((v, z): (IVec2, i32)) -> Self { Self::new(v.x, v.y, z) } } impl From for IVec3 { #[inline] fn from(v: I8Vec3) -> Self { Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z)) } } impl From for IVec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z)) } } impl From for IVec3 { #[inline] fn from(v: I16Vec3) -> Self { Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z)) } } impl From for IVec3 { #[inline] fn from(v: U16Vec3) -> Self { Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z)) } } impl TryFrom for IVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec3) -> Result { Ok(Self::new( i32::try_from(v.x)?, i32::try_from(v.y)?, i32::try_from(v.z)?, )) } } impl TryFrom for IVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( i32::try_from(v.x)?, i32::try_from(v.y)?, i32::try_from(v.z)?, )) } } impl TryFrom for IVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( i32::try_from(v.x)?, i32::try_from(v.y)?, i32::try_from(v.z)?, )) } } impl TryFrom for IVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( i32::try_from(v.x)?, i32::try_from(v.y)?, i32::try_from(v.z)?, )) } } impl From for IVec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(i32::from(v.x), i32::from(v.y), i32::from(v.z)) } } impl From for IVec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( i32::from(bool_array[0]), i32::from(bool_array[1]), i32::from(bool_array[2]), ) } } glam-0.30.1/src/i32/ivec4.rs000064400000000000000000001607661046102023000134110ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec4, IVec2, IVec3, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// 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 IVec4 { pub x: i32, pub y: i32, pub z: i32, pub w: i32, } impl IVec4 { /// 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 `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 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: 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, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i32) -> i32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: [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] } /// 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: &[i32]) -> Self { assert!(slice.len() >= 4); 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 [i32]) { slice[..4].copy_from_slice(&self.to_array()); } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. #[inline] #[must_use] pub fn truncate(self) -> IVec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: i32) -> Self { self.w = w; self } /// 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)) } /// 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 [`i32::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) -> i32 { 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) -> i32 { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i32 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i32 { self.x * self.y * self.z * 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) -> 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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u32::MAX`]. /// /// See also [`checked_manhattan_distance`][IVec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u32 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u32::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u32 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: UVec4) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: UVec4) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: UVec4) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), w: self.w.wrapping_add_unsigned(rhs.w), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: UVec4) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), w: self.w.wrapping_sub_unsigned(rhs.w), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: UVec4) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), w: self.w.saturating_add_unsigned(rhs.w), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: UVec4) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), w: self.w.saturating_sub_unsigned(rhs.w), } } } impl Default for IVec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for IVec4 { 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 Div<&IVec4> for IVec4 { type Output = IVec4; #[inline] fn div(self, rhs: &IVec4) -> IVec4 { self.div(*rhs) } } impl Div<&IVec4> for &IVec4 { type Output = IVec4; #[inline] fn div(self, rhs: &IVec4) -> IVec4 { (*self).div(*rhs) } } impl Div for &IVec4 { type Output = IVec4; #[inline] fn div(self, rhs: IVec4) -> IVec4 { (*self).div(rhs) } } impl DivAssign for IVec4 { #[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 DivAssign<&IVec4> for IVec4 { #[inline] fn div_assign(&mut self, rhs: &IVec4) { self.div_assign(*rhs) } } impl Div for IVec4 { type Output = Self; #[inline] fn div(self, rhs: i32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&i32> for IVec4 { type Output = IVec4; #[inline] fn div(self, rhs: &i32) -> IVec4 { self.div(*rhs) } } impl Div<&i32> for &IVec4 { type Output = IVec4; #[inline] fn div(self, rhs: &i32) -> IVec4 { (*self).div(*rhs) } } impl Div for &IVec4 { type Output = IVec4; #[inline] fn div(self, rhs: i32) -> IVec4 { (*self).div(rhs) } } impl DivAssign for IVec4 { #[inline] fn div_assign(&mut self, rhs: i32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&i32> for IVec4 { #[inline] fn div_assign(&mut self, rhs: &i32) { self.div_assign(*rhs) } } impl Div for i32 { type Output = IVec4; #[inline] fn div(self, rhs: IVec4) -> IVec4 { IVec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&IVec4> for i32 { type Output = IVec4; #[inline] fn div(self, rhs: &IVec4) -> IVec4 { self.div(*rhs) } } impl Div<&IVec4> for &i32 { type Output = IVec4; #[inline] fn div(self, rhs: &IVec4) -> IVec4 { (*self).div(*rhs) } } impl Div for &i32 { type Output = IVec4; #[inline] fn div(self, rhs: IVec4) -> IVec4 { (*self).div(rhs) } } impl Mul for IVec4 { 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 Mul<&IVec4> for IVec4 { type Output = IVec4; #[inline] fn mul(self, rhs: &IVec4) -> IVec4 { self.mul(*rhs) } } impl Mul<&IVec4> for &IVec4 { type Output = IVec4; #[inline] fn mul(self, rhs: &IVec4) -> IVec4 { (*self).mul(*rhs) } } impl Mul for &IVec4 { type Output = IVec4; #[inline] fn mul(self, rhs: IVec4) -> IVec4 { (*self).mul(rhs) } } impl MulAssign for IVec4 { #[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 MulAssign<&IVec4> for IVec4 { #[inline] fn mul_assign(&mut self, rhs: &IVec4) { self.mul_assign(*rhs) } } impl Mul for IVec4 { type Output = Self; #[inline] fn mul(self, rhs: i32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&i32> for IVec4 { type Output = IVec4; #[inline] fn mul(self, rhs: &i32) -> IVec4 { self.mul(*rhs) } } impl Mul<&i32> for &IVec4 { type Output = IVec4; #[inline] fn mul(self, rhs: &i32) -> IVec4 { (*self).mul(*rhs) } } impl Mul for &IVec4 { type Output = IVec4; #[inline] fn mul(self, rhs: i32) -> IVec4 { (*self).mul(rhs) } } impl MulAssign for IVec4 { #[inline] fn mul_assign(&mut self, rhs: i32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&i32> for IVec4 { #[inline] fn mul_assign(&mut self, rhs: &i32) { self.mul_assign(*rhs) } } impl Mul for i32 { type Output = IVec4; #[inline] fn mul(self, rhs: IVec4) -> IVec4 { IVec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&IVec4> for i32 { type Output = IVec4; #[inline] fn mul(self, rhs: &IVec4) -> IVec4 { self.mul(*rhs) } } impl Mul<&IVec4> for &i32 { type Output = IVec4; #[inline] fn mul(self, rhs: &IVec4) -> IVec4 { (*self).mul(*rhs) } } impl Mul for &i32 { type Output = IVec4; #[inline] fn mul(self, rhs: IVec4) -> IVec4 { (*self).mul(rhs) } } impl Add for IVec4 { 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 Add<&IVec4> for IVec4 { type Output = IVec4; #[inline] fn add(self, rhs: &IVec4) -> IVec4 { self.add(*rhs) } } impl Add<&IVec4> for &IVec4 { type Output = IVec4; #[inline] fn add(self, rhs: &IVec4) -> IVec4 { (*self).add(*rhs) } } impl Add for &IVec4 { type Output = IVec4; #[inline] fn add(self, rhs: IVec4) -> IVec4 { (*self).add(rhs) } } impl AddAssign for IVec4 { #[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 AddAssign<&IVec4> for IVec4 { #[inline] fn add_assign(&mut self, rhs: &IVec4) { self.add_assign(*rhs) } } impl Add for IVec4 { type Output = Self; #[inline] fn add(self, rhs: i32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&i32> for IVec4 { type Output = IVec4; #[inline] fn add(self, rhs: &i32) -> IVec4 { self.add(*rhs) } } impl Add<&i32> for &IVec4 { type Output = IVec4; #[inline] fn add(self, rhs: &i32) -> IVec4 { (*self).add(*rhs) } } impl Add for &IVec4 { type Output = IVec4; #[inline] fn add(self, rhs: i32) -> IVec4 { (*self).add(rhs) } } impl AddAssign for IVec4 { #[inline] fn add_assign(&mut self, rhs: i32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&i32> for IVec4 { #[inline] fn add_assign(&mut self, rhs: &i32) { self.add_assign(*rhs) } } impl Add for i32 { type Output = IVec4; #[inline] fn add(self, rhs: IVec4) -> IVec4 { IVec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&IVec4> for i32 { type Output = IVec4; #[inline] fn add(self, rhs: &IVec4) -> IVec4 { self.add(*rhs) } } impl Add<&IVec4> for &i32 { type Output = IVec4; #[inline] fn add(self, rhs: &IVec4) -> IVec4 { (*self).add(*rhs) } } impl Add for &i32 { type Output = IVec4; #[inline] fn add(self, rhs: IVec4) -> IVec4 { (*self).add(rhs) } } impl Sub for IVec4 { 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 Sub<&IVec4> for IVec4 { type Output = IVec4; #[inline] fn sub(self, rhs: &IVec4) -> IVec4 { self.sub(*rhs) } } impl Sub<&IVec4> for &IVec4 { type Output = IVec4; #[inline] fn sub(self, rhs: &IVec4) -> IVec4 { (*self).sub(*rhs) } } impl Sub for &IVec4 { type Output = IVec4; #[inline] fn sub(self, rhs: IVec4) -> IVec4 { (*self).sub(rhs) } } impl SubAssign for IVec4 { #[inline] fn sub_assign(&mut self, rhs: IVec4) { 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 SubAssign<&IVec4> for IVec4 { #[inline] fn sub_assign(&mut self, rhs: &IVec4) { self.sub_assign(*rhs) } } impl Sub for IVec4 { type Output = Self; #[inline] fn sub(self, rhs: i32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&i32> for IVec4 { type Output = IVec4; #[inline] fn sub(self, rhs: &i32) -> IVec4 { self.sub(*rhs) } } impl Sub<&i32> for &IVec4 { type Output = IVec4; #[inline] fn sub(self, rhs: &i32) -> IVec4 { (*self).sub(*rhs) } } impl Sub for &IVec4 { type Output = IVec4; #[inline] fn sub(self, rhs: i32) -> IVec4 { (*self).sub(rhs) } } impl SubAssign for IVec4 { #[inline] fn sub_assign(&mut self, rhs: i32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&i32> for IVec4 { #[inline] fn sub_assign(&mut self, rhs: &i32) { self.sub_assign(*rhs) } } impl Sub for i32 { type Output = IVec4; #[inline] fn sub(self, rhs: IVec4) -> IVec4 { IVec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&IVec4> for i32 { type Output = IVec4; #[inline] fn sub(self, rhs: &IVec4) -> IVec4 { self.sub(*rhs) } } impl Sub<&IVec4> for &i32 { type Output = IVec4; #[inline] fn sub(self, rhs: &IVec4) -> IVec4 { (*self).sub(*rhs) } } impl Sub for &i32 { type Output = IVec4; #[inline] fn sub(self, rhs: IVec4) -> IVec4 { (*self).sub(rhs) } } impl Rem for IVec4 { 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 Rem<&IVec4> for IVec4 { type Output = IVec4; #[inline] fn rem(self, rhs: &IVec4) -> IVec4 { self.rem(*rhs) } } impl Rem<&IVec4> for &IVec4 { type Output = IVec4; #[inline] fn rem(self, rhs: &IVec4) -> IVec4 { (*self).rem(*rhs) } } impl Rem for &IVec4 { type Output = IVec4; #[inline] fn rem(self, rhs: IVec4) -> IVec4 { (*self).rem(rhs) } } impl RemAssign for IVec4 { #[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 RemAssign<&IVec4> for IVec4 { #[inline] fn rem_assign(&mut self, rhs: &IVec4) { self.rem_assign(*rhs) } } impl Rem for IVec4 { type Output = Self; #[inline] fn rem(self, rhs: i32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&i32> for IVec4 { type Output = IVec4; #[inline] fn rem(self, rhs: &i32) -> IVec4 { self.rem(*rhs) } } impl Rem<&i32> for &IVec4 { type Output = IVec4; #[inline] fn rem(self, rhs: &i32) -> IVec4 { (*self).rem(*rhs) } } impl Rem for &IVec4 { type Output = IVec4; #[inline] fn rem(self, rhs: i32) -> IVec4 { (*self).rem(rhs) } } impl RemAssign for IVec4 { #[inline] fn rem_assign(&mut self, rhs: i32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&i32> for IVec4 { #[inline] fn rem_assign(&mut self, rhs: &i32) { self.rem_assign(*rhs) } } impl Rem for i32 { type Output = IVec4; #[inline] fn rem(self, rhs: IVec4) -> IVec4 { IVec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&IVec4> for i32 { type Output = IVec4; #[inline] fn rem(self, rhs: &IVec4) -> IVec4 { self.rem(*rhs) } } impl Rem<&IVec4> for &i32 { type Output = IVec4; #[inline] fn rem(self, rhs: &IVec4) -> IVec4 { (*self).rem(*rhs) } } impl Rem for &i32 { type Output = IVec4; #[inline] fn rem(self, rhs: IVec4) -> IVec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[i32; 4]> for IVec4 { #[inline] fn as_ref(&self) -> &[i32; 4] { unsafe { &*(self as *const IVec4 as *const [i32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[i32; 4]> for IVec4 { #[inline] fn as_mut(&mut self) -> &mut [i32; 4] { unsafe { &mut *(self as *mut IVec4 as *mut [i32; 4]) } } } impl Sum for IVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for IVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for IVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for IVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for IVec4 { 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 Neg for &IVec4 { type Output = IVec4; #[inline] fn neg(self) -> IVec4 { (*self).neg() } } impl Not for IVec4 { 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 IVec4 { 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 IVec4 { 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 IVec4 { 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 for IVec4 { type Output = Self; #[inline] fn bitand(self, rhs: i32) -> 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 for IVec4 { type Output = Self; #[inline] fn bitor(self, rhs: i32) -> 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 for IVec4 { type Output = Self; #[inline] fn bitxor(self, rhs: i32) -> 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 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 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 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 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { 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 for IVec4 { type Output = i32; #[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 for IVec4 { #[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"), } } } impl fmt::Display for IVec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } impl fmt::Debug for IVec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(IVec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[i32; 4]> for IVec4 { #[inline] fn from(a: [i32; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [i32; 4] { #[inline] fn from(v: IVec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(i32, i32, i32, i32)> for IVec4 { #[inline] fn from(t: (i32, i32, i32, i32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (i32, i32, i32, i32) { #[inline] fn from(v: IVec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(IVec3, i32)> for IVec4 { #[inline] fn from((v, w): (IVec3, i32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(i32, IVec3)> for IVec4 { #[inline] fn from((x, v): (i32, IVec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(IVec2, i32, i32)> for IVec4 { #[inline] fn from((v, z, w): (IVec2, i32, i32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(IVec2, IVec2)> for IVec4 { #[inline] fn from((v, u): (IVec2, IVec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl From for IVec4 { #[inline] fn from(v: I8Vec4) -> Self { Self::new( i32::from(v.x), i32::from(v.y), i32::from(v.z), i32::from(v.w), ) } } impl From for IVec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( i32::from(v.x), i32::from(v.y), i32::from(v.z), i32::from(v.w), ) } } impl From 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 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 for IVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec4) -> Result { 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 for IVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { 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 for IVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { 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 for IVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( i32::try_from(v.x)?, i32::try_from(v.y)?, i32::try_from(v.z)?, i32::try_from(v.w)?, )) } } impl From for IVec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( i32::from(v.x), i32::from(v.y), i32::from(v.z), i32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for IVec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( i32::from(bool_array[0]), i32::from(bool_array[1]), i32::from(bool_array[2]), i32::from(bool_array[3]), ) } } glam-0.30.1/src/i32.rs000064400000000000000000000022171046102023000123610ustar 00000000000000mod ivec2; mod ivec3; mod ivec4; pub use ivec2::{ivec2, IVec2}; pub use ivec3::{ivec3, IVec3}; pub use ivec4::{ivec4, IVec4}; #[cfg(not(target_arch = "spirv"))] mod test { use super::*; mod const_test_ivec2 { const_assert_eq!(8, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(8, core::mem::align_of::()); } mod const_test_ivec3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(12, core::mem::size_of::()); } mod const_test_ivec4 { const_assert_eq!(16, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } } glam-0.30.1/src/i64/i64vec2.rs000064400000000000000000001343371046102023000135610ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec3, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2}; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i64) -> i64, { Self::new(f(self.x), f(self.y)) } /// 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 { assert!(slice.len() >= 2); 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[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i64) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i64) -> Self { self.y = y; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i64 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i64 { self.x * 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)) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u64::MAX`]. /// /// See also [`checked_manhattan_distance`][I64Vec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u64 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u64::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u64 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U64Vec2) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U64Vec2) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U64Vec2) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U64Vec2) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U64Vec2) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U64Vec2) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), } } } impl Default for I64Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&I64Vec2> for I64Vec2 { type Output = I64Vec2; #[inline] fn div(self, rhs: &I64Vec2) -> I64Vec2 { self.div(*rhs) } } impl Div<&I64Vec2> for &I64Vec2 { type Output = I64Vec2; #[inline] fn div(self, rhs: &I64Vec2) -> I64Vec2 { (*self).div(*rhs) } } impl Div for &I64Vec2 { type Output = I64Vec2; #[inline] fn div(self, rhs: I64Vec2) -> I64Vec2 { (*self).div(rhs) } } impl DivAssign for I64Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&I64Vec2> for I64Vec2 { #[inline] fn div_assign(&mut self, rhs: &I64Vec2) { self.div_assign(*rhs) } } impl Div for I64Vec2 { type Output = Self; #[inline] fn div(self, rhs: i64) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&i64> for I64Vec2 { type Output = I64Vec2; #[inline] fn div(self, rhs: &i64) -> I64Vec2 { self.div(*rhs) } } impl Div<&i64> for &I64Vec2 { type Output = I64Vec2; #[inline] fn div(self, rhs: &i64) -> I64Vec2 { (*self).div(*rhs) } } impl Div for &I64Vec2 { type Output = I64Vec2; #[inline] fn div(self, rhs: i64) -> I64Vec2 { (*self).div(rhs) } } impl DivAssign for I64Vec2 { #[inline] fn div_assign(&mut self, rhs: i64) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&i64> for I64Vec2 { #[inline] fn div_assign(&mut self, rhs: &i64) { self.div_assign(*rhs) } } impl Div for i64 { type Output = I64Vec2; #[inline] fn div(self, rhs: I64Vec2) -> I64Vec2 { I64Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&I64Vec2> for i64 { type Output = I64Vec2; #[inline] fn div(self, rhs: &I64Vec2) -> I64Vec2 { self.div(*rhs) } } impl Div<&I64Vec2> for &i64 { type Output = I64Vec2; #[inline] fn div(self, rhs: &I64Vec2) -> I64Vec2 { (*self).div(*rhs) } } impl Div for &i64 { type Output = I64Vec2; #[inline] fn div(self, rhs: I64Vec2) -> I64Vec2 { (*self).div(rhs) } } impl Mul 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 Mul<&I64Vec2> for I64Vec2 { type Output = I64Vec2; #[inline] fn mul(self, rhs: &I64Vec2) -> I64Vec2 { self.mul(*rhs) } } impl Mul<&I64Vec2> for &I64Vec2 { type Output = I64Vec2; #[inline] fn mul(self, rhs: &I64Vec2) -> I64Vec2 { (*self).mul(*rhs) } } impl Mul for &I64Vec2 { type Output = I64Vec2; #[inline] fn mul(self, rhs: I64Vec2) -> I64Vec2 { (*self).mul(rhs) } } impl MulAssign for I64Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&I64Vec2> for I64Vec2 { #[inline] fn mul_assign(&mut self, rhs: &I64Vec2) { self.mul_assign(*rhs) } } impl Mul for I64Vec2 { type Output = Self; #[inline] fn mul(self, rhs: i64) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&i64> for I64Vec2 { type Output = I64Vec2; #[inline] fn mul(self, rhs: &i64) -> I64Vec2 { self.mul(*rhs) } } impl Mul<&i64> for &I64Vec2 { type Output = I64Vec2; #[inline] fn mul(self, rhs: &i64) -> I64Vec2 { (*self).mul(*rhs) } } impl Mul for &I64Vec2 { type Output = I64Vec2; #[inline] fn mul(self, rhs: i64) -> I64Vec2 { (*self).mul(rhs) } } impl MulAssign for I64Vec2 { #[inline] fn mul_assign(&mut self, rhs: i64) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&i64> for I64Vec2 { #[inline] fn mul_assign(&mut self, rhs: &i64) { self.mul_assign(*rhs) } } impl Mul for i64 { type Output = I64Vec2; #[inline] fn mul(self, rhs: I64Vec2) -> I64Vec2 { I64Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&I64Vec2> for i64 { type Output = I64Vec2; #[inline] fn mul(self, rhs: &I64Vec2) -> I64Vec2 { self.mul(*rhs) } } impl Mul<&I64Vec2> for &i64 { type Output = I64Vec2; #[inline] fn mul(self, rhs: &I64Vec2) -> I64Vec2 { (*self).mul(*rhs) } } impl Mul for &i64 { type Output = I64Vec2; #[inline] fn mul(self, rhs: I64Vec2) -> I64Vec2 { (*self).mul(rhs) } } impl Add 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 Add<&I64Vec2> for I64Vec2 { type Output = I64Vec2; #[inline] fn add(self, rhs: &I64Vec2) -> I64Vec2 { self.add(*rhs) } } impl Add<&I64Vec2> for &I64Vec2 { type Output = I64Vec2; #[inline] fn add(self, rhs: &I64Vec2) -> I64Vec2 { (*self).add(*rhs) } } impl Add for &I64Vec2 { type Output = I64Vec2; #[inline] fn add(self, rhs: I64Vec2) -> I64Vec2 { (*self).add(rhs) } } impl AddAssign for I64Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&I64Vec2> for I64Vec2 { #[inline] fn add_assign(&mut self, rhs: &I64Vec2) { self.add_assign(*rhs) } } impl Add for I64Vec2 { type Output = Self; #[inline] fn add(self, rhs: i64) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&i64> for I64Vec2 { type Output = I64Vec2; #[inline] fn add(self, rhs: &i64) -> I64Vec2 { self.add(*rhs) } } impl Add<&i64> for &I64Vec2 { type Output = I64Vec2; #[inline] fn add(self, rhs: &i64) -> I64Vec2 { (*self).add(*rhs) } } impl Add for &I64Vec2 { type Output = I64Vec2; #[inline] fn add(self, rhs: i64) -> I64Vec2 { (*self).add(rhs) } } impl AddAssign for I64Vec2 { #[inline] fn add_assign(&mut self, rhs: i64) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&i64> for I64Vec2 { #[inline] fn add_assign(&mut self, rhs: &i64) { self.add_assign(*rhs) } } impl Add for i64 { type Output = I64Vec2; #[inline] fn add(self, rhs: I64Vec2) -> I64Vec2 { I64Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&I64Vec2> for i64 { type Output = I64Vec2; #[inline] fn add(self, rhs: &I64Vec2) -> I64Vec2 { self.add(*rhs) } } impl Add<&I64Vec2> for &i64 { type Output = I64Vec2; #[inline] fn add(self, rhs: &I64Vec2) -> I64Vec2 { (*self).add(*rhs) } } impl Add for &i64 { type Output = I64Vec2; #[inline] fn add(self, rhs: I64Vec2) -> I64Vec2 { (*self).add(rhs) } } impl Sub 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 Sub<&I64Vec2> for I64Vec2 { type Output = I64Vec2; #[inline] fn sub(self, rhs: &I64Vec2) -> I64Vec2 { self.sub(*rhs) } } impl Sub<&I64Vec2> for &I64Vec2 { type Output = I64Vec2; #[inline] fn sub(self, rhs: &I64Vec2) -> I64Vec2 { (*self).sub(*rhs) } } impl Sub for &I64Vec2 { type Output = I64Vec2; #[inline] fn sub(self, rhs: I64Vec2) -> I64Vec2 { (*self).sub(rhs) } } impl SubAssign for I64Vec2 { #[inline] fn sub_assign(&mut self, rhs: I64Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&I64Vec2> for I64Vec2 { #[inline] fn sub_assign(&mut self, rhs: &I64Vec2) { self.sub_assign(*rhs) } } impl Sub for I64Vec2 { type Output = Self; #[inline] fn sub(self, rhs: i64) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&i64> for I64Vec2 { type Output = I64Vec2; #[inline] fn sub(self, rhs: &i64) -> I64Vec2 { self.sub(*rhs) } } impl Sub<&i64> for &I64Vec2 { type Output = I64Vec2; #[inline] fn sub(self, rhs: &i64) -> I64Vec2 { (*self).sub(*rhs) } } impl Sub for &I64Vec2 { type Output = I64Vec2; #[inline] fn sub(self, rhs: i64) -> I64Vec2 { (*self).sub(rhs) } } impl SubAssign for I64Vec2 { #[inline] fn sub_assign(&mut self, rhs: i64) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&i64> for I64Vec2 { #[inline] fn sub_assign(&mut self, rhs: &i64) { self.sub_assign(*rhs) } } impl Sub for i64 { type Output = I64Vec2; #[inline] fn sub(self, rhs: I64Vec2) -> I64Vec2 { I64Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&I64Vec2> for i64 { type Output = I64Vec2; #[inline] fn sub(self, rhs: &I64Vec2) -> I64Vec2 { self.sub(*rhs) } } impl Sub<&I64Vec2> for &i64 { type Output = I64Vec2; #[inline] fn sub(self, rhs: &I64Vec2) -> I64Vec2 { (*self).sub(*rhs) } } impl Sub for &i64 { type Output = I64Vec2; #[inline] fn sub(self, rhs: I64Vec2) -> I64Vec2 { (*self).sub(rhs) } } impl Rem 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 Rem<&I64Vec2> for I64Vec2 { type Output = I64Vec2; #[inline] fn rem(self, rhs: &I64Vec2) -> I64Vec2 { self.rem(*rhs) } } impl Rem<&I64Vec2> for &I64Vec2 { type Output = I64Vec2; #[inline] fn rem(self, rhs: &I64Vec2) -> I64Vec2 { (*self).rem(*rhs) } } impl Rem for &I64Vec2 { type Output = I64Vec2; #[inline] fn rem(self, rhs: I64Vec2) -> I64Vec2 { (*self).rem(rhs) } } impl RemAssign for I64Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&I64Vec2> for I64Vec2 { #[inline] fn rem_assign(&mut self, rhs: &I64Vec2) { self.rem_assign(*rhs) } } impl Rem for I64Vec2 { type Output = Self; #[inline] fn rem(self, rhs: i64) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&i64> for I64Vec2 { type Output = I64Vec2; #[inline] fn rem(self, rhs: &i64) -> I64Vec2 { self.rem(*rhs) } } impl Rem<&i64> for &I64Vec2 { type Output = I64Vec2; #[inline] fn rem(self, rhs: &i64) -> I64Vec2 { (*self).rem(*rhs) } } impl Rem for &I64Vec2 { type Output = I64Vec2; #[inline] fn rem(self, rhs: i64) -> I64Vec2 { (*self).rem(rhs) } } impl RemAssign for I64Vec2 { #[inline] fn rem_assign(&mut self, rhs: i64) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&i64> for I64Vec2 { #[inline] fn rem_assign(&mut self, rhs: &i64) { self.rem_assign(*rhs) } } impl Rem for i64 { type Output = I64Vec2; #[inline] fn rem(self, rhs: I64Vec2) -> I64Vec2 { I64Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&I64Vec2> for i64 { type Output = I64Vec2; #[inline] fn rem(self, rhs: &I64Vec2) -> I64Vec2 { self.rem(*rhs) } } impl Rem<&I64Vec2> for &i64 { type Output = I64Vec2; #[inline] fn rem(self, rhs: &I64Vec2) -> I64Vec2 { (*self).rem(*rhs) } } impl Rem for &i64 { type Output = I64Vec2; #[inline] fn rem(self, rhs: I64Vec2) -> I64Vec2 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I64Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I64Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I64Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 Neg for &I64Vec2 { type Output = I64Vec2; #[inline] fn neg(self) -> I64Vec2 { (*self).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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for I64Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } 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 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 for (i64, i64) { #[inline] fn from(v: I64Vec2) -> Self { (v.x, v.y) } } impl From for I64Vec2 { #[inline] fn from(v: I8Vec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } impl From for I64Vec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } impl From for I64Vec2 { #[inline] fn from(v: I16Vec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } impl From for I64Vec2 { #[inline] fn from(v: U16Vec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } impl From for I64Vec2 { #[inline] fn from(v: IVec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } impl From for I64Vec2 { #[inline] fn from(v: UVec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } impl TryFrom for I64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(i64::try_from(v.x)?, i64::try_from(v.y)?)) } } impl TryFrom for I64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(i64::try_from(v.x)?, i64::try_from(v.y)?)) } } impl From for I64Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(i64::from(v.x), i64::from(v.y)) } } glam-0.30.1/src/i64/i64vec3.rs000064400000000000000000001472671046102023000135700ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec2, I64Vec4, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i64) -> i64, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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 { assert!(slice.len() >= 3); 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[..3].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i64) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i64) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i64) -> Self { self.z = z; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i64 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i64 { self.x * self.y * 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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u64::MAX`]. /// /// See also [`checked_manhattan_distance`][I64Vec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u64 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u64::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u64 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U64Vec3) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U64Vec3) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U64Vec3) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U64Vec3) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U64Vec3) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U64Vec3) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), } } } impl Default for I64Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&I64Vec3> for I64Vec3 { type Output = I64Vec3; #[inline] fn div(self, rhs: &I64Vec3) -> I64Vec3 { self.div(*rhs) } } impl Div<&I64Vec3> for &I64Vec3 { type Output = I64Vec3; #[inline] fn div(self, rhs: &I64Vec3) -> I64Vec3 { (*self).div(*rhs) } } impl Div for &I64Vec3 { type Output = I64Vec3; #[inline] fn div(self, rhs: I64Vec3) -> I64Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&I64Vec3> for I64Vec3 { #[inline] fn div_assign(&mut self, rhs: &I64Vec3) { self.div_assign(*rhs) } } impl Div 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 Div<&i64> for I64Vec3 { type Output = I64Vec3; #[inline] fn div(self, rhs: &i64) -> I64Vec3 { self.div(*rhs) } } impl Div<&i64> for &I64Vec3 { type Output = I64Vec3; #[inline] fn div(self, rhs: &i64) -> I64Vec3 { (*self).div(*rhs) } } impl Div for &I64Vec3 { type Output = I64Vec3; #[inline] fn div(self, rhs: i64) -> I64Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&i64> for I64Vec3 { #[inline] fn div_assign(&mut self, rhs: &i64) { self.div_assign(*rhs) } } impl Div 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 Div<&I64Vec3> for i64 { type Output = I64Vec3; #[inline] fn div(self, rhs: &I64Vec3) -> I64Vec3 { self.div(*rhs) } } impl Div<&I64Vec3> for &i64 { type Output = I64Vec3; #[inline] fn div(self, rhs: &I64Vec3) -> I64Vec3 { (*self).div(*rhs) } } impl Div for &i64 { type Output = I64Vec3; #[inline] fn div(self, rhs: I64Vec3) -> I64Vec3 { (*self).div(rhs) } } impl Mul 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 Mul<&I64Vec3> for I64Vec3 { type Output = I64Vec3; #[inline] fn mul(self, rhs: &I64Vec3) -> I64Vec3 { self.mul(*rhs) } } impl Mul<&I64Vec3> for &I64Vec3 { type Output = I64Vec3; #[inline] fn mul(self, rhs: &I64Vec3) -> I64Vec3 { (*self).mul(*rhs) } } impl Mul for &I64Vec3 { type Output = I64Vec3; #[inline] fn mul(self, rhs: I64Vec3) -> I64Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&I64Vec3> for I64Vec3 { #[inline] fn mul_assign(&mut self, rhs: &I64Vec3) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&i64> for I64Vec3 { type Output = I64Vec3; #[inline] fn mul(self, rhs: &i64) -> I64Vec3 { self.mul(*rhs) } } impl Mul<&i64> for &I64Vec3 { type Output = I64Vec3; #[inline] fn mul(self, rhs: &i64) -> I64Vec3 { (*self).mul(*rhs) } } impl Mul for &I64Vec3 { type Output = I64Vec3; #[inline] fn mul(self, rhs: i64) -> I64Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&i64> for I64Vec3 { #[inline] fn mul_assign(&mut self, rhs: &i64) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&I64Vec3> for i64 { type Output = I64Vec3; #[inline] fn mul(self, rhs: &I64Vec3) -> I64Vec3 { self.mul(*rhs) } } impl Mul<&I64Vec3> for &i64 { type Output = I64Vec3; #[inline] fn mul(self, rhs: &I64Vec3) -> I64Vec3 { (*self).mul(*rhs) } } impl Mul for &i64 { type Output = I64Vec3; #[inline] fn mul(self, rhs: I64Vec3) -> I64Vec3 { (*self).mul(rhs) } } impl Add 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 Add<&I64Vec3> for I64Vec3 { type Output = I64Vec3; #[inline] fn add(self, rhs: &I64Vec3) -> I64Vec3 { self.add(*rhs) } } impl Add<&I64Vec3> for &I64Vec3 { type Output = I64Vec3; #[inline] fn add(self, rhs: &I64Vec3) -> I64Vec3 { (*self).add(*rhs) } } impl Add for &I64Vec3 { type Output = I64Vec3; #[inline] fn add(self, rhs: I64Vec3) -> I64Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&I64Vec3> for I64Vec3 { #[inline] fn add_assign(&mut self, rhs: &I64Vec3) { self.add_assign(*rhs) } } impl Add 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 Add<&i64> for I64Vec3 { type Output = I64Vec3; #[inline] fn add(self, rhs: &i64) -> I64Vec3 { self.add(*rhs) } } impl Add<&i64> for &I64Vec3 { type Output = I64Vec3; #[inline] fn add(self, rhs: &i64) -> I64Vec3 { (*self).add(*rhs) } } impl Add for &I64Vec3 { type Output = I64Vec3; #[inline] fn add(self, rhs: i64) -> I64Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&i64> for I64Vec3 { #[inline] fn add_assign(&mut self, rhs: &i64) { self.add_assign(*rhs) } } impl Add 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 Add<&I64Vec3> for i64 { type Output = I64Vec3; #[inline] fn add(self, rhs: &I64Vec3) -> I64Vec3 { self.add(*rhs) } } impl Add<&I64Vec3> for &i64 { type Output = I64Vec3; #[inline] fn add(self, rhs: &I64Vec3) -> I64Vec3 { (*self).add(*rhs) } } impl Add for &i64 { type Output = I64Vec3; #[inline] fn add(self, rhs: I64Vec3) -> I64Vec3 { (*self).add(rhs) } } impl Sub 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 Sub<&I64Vec3> for I64Vec3 { type Output = I64Vec3; #[inline] fn sub(self, rhs: &I64Vec3) -> I64Vec3 { self.sub(*rhs) } } impl Sub<&I64Vec3> for &I64Vec3 { type Output = I64Vec3; #[inline] fn sub(self, rhs: &I64Vec3) -> I64Vec3 { (*self).sub(*rhs) } } impl Sub for &I64Vec3 { type Output = I64Vec3; #[inline] fn sub(self, rhs: I64Vec3) -> I64Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&I64Vec3> for I64Vec3 { #[inline] fn sub_assign(&mut self, rhs: &I64Vec3) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&i64> for I64Vec3 { type Output = I64Vec3; #[inline] fn sub(self, rhs: &i64) -> I64Vec3 { self.sub(*rhs) } } impl Sub<&i64> for &I64Vec3 { type Output = I64Vec3; #[inline] fn sub(self, rhs: &i64) -> I64Vec3 { (*self).sub(*rhs) } } impl Sub for &I64Vec3 { type Output = I64Vec3; #[inline] fn sub(self, rhs: i64) -> I64Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&i64> for I64Vec3 { #[inline] fn sub_assign(&mut self, rhs: &i64) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&I64Vec3> for i64 { type Output = I64Vec3; #[inline] fn sub(self, rhs: &I64Vec3) -> I64Vec3 { self.sub(*rhs) } } impl Sub<&I64Vec3> for &i64 { type Output = I64Vec3; #[inline] fn sub(self, rhs: &I64Vec3) -> I64Vec3 { (*self).sub(*rhs) } } impl Sub for &i64 { type Output = I64Vec3; #[inline] fn sub(self, rhs: I64Vec3) -> I64Vec3 { (*self).sub(rhs) } } impl Rem 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 Rem<&I64Vec3> for I64Vec3 { type Output = I64Vec3; #[inline] fn rem(self, rhs: &I64Vec3) -> I64Vec3 { self.rem(*rhs) } } impl Rem<&I64Vec3> for &I64Vec3 { type Output = I64Vec3; #[inline] fn rem(self, rhs: &I64Vec3) -> I64Vec3 { (*self).rem(*rhs) } } impl Rem for &I64Vec3 { type Output = I64Vec3; #[inline] fn rem(self, rhs: I64Vec3) -> I64Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&I64Vec3> for I64Vec3 { #[inline] fn rem_assign(&mut self, rhs: &I64Vec3) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&i64> for I64Vec3 { type Output = I64Vec3; #[inline] fn rem(self, rhs: &i64) -> I64Vec3 { self.rem(*rhs) } } impl Rem<&i64> for &I64Vec3 { type Output = I64Vec3; #[inline] fn rem(self, rhs: &i64) -> I64Vec3 { (*self).rem(*rhs) } } impl Rem for &I64Vec3 { type Output = I64Vec3; #[inline] fn rem(self, rhs: i64) -> I64Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&i64> for I64Vec3 { #[inline] fn rem_assign(&mut self, rhs: &i64) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&I64Vec3> for i64 { type Output = I64Vec3; #[inline] fn rem(self, rhs: &I64Vec3) -> I64Vec3 { self.rem(*rhs) } } impl Rem<&I64Vec3> for &i64 { type Output = I64Vec3; #[inline] fn rem(self, rhs: &I64Vec3) -> I64Vec3 { (*self).rem(*rhs) } } impl Rem for &i64 { type Output = I64Vec3; #[inline] fn rem(self, rhs: I64Vec3) -> I64Vec3 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I64Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I64Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I64Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 Neg for &I64Vec3 { type Output = I64Vec3; #[inline] fn neg(self) -> I64Vec3 { (*self).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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for I64Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } 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 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 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 for I64Vec3 { #[inline] fn from(v: I8Vec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl From for I64Vec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl From for I64Vec3 { #[inline] fn from(v: I16Vec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl From for I64Vec3 { #[inline] fn from(v: U16Vec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl From for I64Vec3 { #[inline] fn from(v: IVec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl From for I64Vec3 { #[inline] fn from(v: UVec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl TryFrom for I64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( i64::try_from(v.x)?, i64::try_from(v.y)?, i64::try_from(v.z)?, )) } } impl TryFrom for I64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( i64::try_from(v.x)?, i64::try_from(v.y)?, i64::try_from(v.z)?, )) } } impl From for I64Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(i64::from(v.x), i64::from(v.y), i64::from(v.z)) } } impl From for I64Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( i64::from(bool_array[0]), i64::from(bool_array[1]), i64::from(bool_array[2]), ) } } glam-0.30.1/src/i64/i64vec4.rs000064400000000000000000001617341046102023000135640ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec2, I64Vec3, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; 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, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i64) -> i64, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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 { assert!(slice.len() >= 4); 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[..4].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i64) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i64) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i64) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: i64) -> Self { self.w = w; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i64 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i64 { self.x * self.y * self.z * 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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u64::MAX`]. /// /// See also [`checked_manhattan_distance`][I64Vec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u64 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u64::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u64 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U64Vec4) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U64Vec4) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U64Vec4) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), w: self.w.wrapping_add_unsigned(rhs.w), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U64Vec4) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), w: self.w.wrapping_sub_unsigned(rhs.w), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U64Vec4) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), w: self.w.saturating_add_unsigned(rhs.w), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U64Vec4) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), w: self.w.saturating_sub_unsigned(rhs.w), } } } impl Default for I64Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&I64Vec4> for I64Vec4 { type Output = I64Vec4; #[inline] fn div(self, rhs: &I64Vec4) -> I64Vec4 { self.div(*rhs) } } impl Div<&I64Vec4> for &I64Vec4 { type Output = I64Vec4; #[inline] fn div(self, rhs: &I64Vec4) -> I64Vec4 { (*self).div(*rhs) } } impl Div for &I64Vec4 { type Output = I64Vec4; #[inline] fn div(self, rhs: I64Vec4) -> I64Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&I64Vec4> for I64Vec4 { #[inline] fn div_assign(&mut self, rhs: &I64Vec4) { self.div_assign(*rhs) } } impl Div 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 Div<&i64> for I64Vec4 { type Output = I64Vec4; #[inline] fn div(self, rhs: &i64) -> I64Vec4 { self.div(*rhs) } } impl Div<&i64> for &I64Vec4 { type Output = I64Vec4; #[inline] fn div(self, rhs: &i64) -> I64Vec4 { (*self).div(*rhs) } } impl Div for &I64Vec4 { type Output = I64Vec4; #[inline] fn div(self, rhs: i64) -> I64Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&i64> for I64Vec4 { #[inline] fn div_assign(&mut self, rhs: &i64) { self.div_assign(*rhs) } } impl Div 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 Div<&I64Vec4> for i64 { type Output = I64Vec4; #[inline] fn div(self, rhs: &I64Vec4) -> I64Vec4 { self.div(*rhs) } } impl Div<&I64Vec4> for &i64 { type Output = I64Vec4; #[inline] fn div(self, rhs: &I64Vec4) -> I64Vec4 { (*self).div(*rhs) } } impl Div for &i64 { type Output = I64Vec4; #[inline] fn div(self, rhs: I64Vec4) -> I64Vec4 { (*self).div(rhs) } } impl Mul 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 Mul<&I64Vec4> for I64Vec4 { type Output = I64Vec4; #[inline] fn mul(self, rhs: &I64Vec4) -> I64Vec4 { self.mul(*rhs) } } impl Mul<&I64Vec4> for &I64Vec4 { type Output = I64Vec4; #[inline] fn mul(self, rhs: &I64Vec4) -> I64Vec4 { (*self).mul(*rhs) } } impl Mul for &I64Vec4 { type Output = I64Vec4; #[inline] fn mul(self, rhs: I64Vec4) -> I64Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&I64Vec4> for I64Vec4 { #[inline] fn mul_assign(&mut self, rhs: &I64Vec4) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&i64> for I64Vec4 { type Output = I64Vec4; #[inline] fn mul(self, rhs: &i64) -> I64Vec4 { self.mul(*rhs) } } impl Mul<&i64> for &I64Vec4 { type Output = I64Vec4; #[inline] fn mul(self, rhs: &i64) -> I64Vec4 { (*self).mul(*rhs) } } impl Mul for &I64Vec4 { type Output = I64Vec4; #[inline] fn mul(self, rhs: i64) -> I64Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&i64> for I64Vec4 { #[inline] fn mul_assign(&mut self, rhs: &i64) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&I64Vec4> for i64 { type Output = I64Vec4; #[inline] fn mul(self, rhs: &I64Vec4) -> I64Vec4 { self.mul(*rhs) } } impl Mul<&I64Vec4> for &i64 { type Output = I64Vec4; #[inline] fn mul(self, rhs: &I64Vec4) -> I64Vec4 { (*self).mul(*rhs) } } impl Mul for &i64 { type Output = I64Vec4; #[inline] fn mul(self, rhs: I64Vec4) -> I64Vec4 { (*self).mul(rhs) } } impl Add 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 Add<&I64Vec4> for I64Vec4 { type Output = I64Vec4; #[inline] fn add(self, rhs: &I64Vec4) -> I64Vec4 { self.add(*rhs) } } impl Add<&I64Vec4> for &I64Vec4 { type Output = I64Vec4; #[inline] fn add(self, rhs: &I64Vec4) -> I64Vec4 { (*self).add(*rhs) } } impl Add for &I64Vec4 { type Output = I64Vec4; #[inline] fn add(self, rhs: I64Vec4) -> I64Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&I64Vec4> for I64Vec4 { #[inline] fn add_assign(&mut self, rhs: &I64Vec4) { self.add_assign(*rhs) } } impl Add 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 Add<&i64> for I64Vec4 { type Output = I64Vec4; #[inline] fn add(self, rhs: &i64) -> I64Vec4 { self.add(*rhs) } } impl Add<&i64> for &I64Vec4 { type Output = I64Vec4; #[inline] fn add(self, rhs: &i64) -> I64Vec4 { (*self).add(*rhs) } } impl Add for &I64Vec4 { type Output = I64Vec4; #[inline] fn add(self, rhs: i64) -> I64Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&i64> for I64Vec4 { #[inline] fn add_assign(&mut self, rhs: &i64) { self.add_assign(*rhs) } } impl Add 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 Add<&I64Vec4> for i64 { type Output = I64Vec4; #[inline] fn add(self, rhs: &I64Vec4) -> I64Vec4 { self.add(*rhs) } } impl Add<&I64Vec4> for &i64 { type Output = I64Vec4; #[inline] fn add(self, rhs: &I64Vec4) -> I64Vec4 { (*self).add(*rhs) } } impl Add for &i64 { type Output = I64Vec4; #[inline] fn add(self, rhs: I64Vec4) -> I64Vec4 { (*self).add(rhs) } } impl Sub 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 Sub<&I64Vec4> for I64Vec4 { type Output = I64Vec4; #[inline] fn sub(self, rhs: &I64Vec4) -> I64Vec4 { self.sub(*rhs) } } impl Sub<&I64Vec4> for &I64Vec4 { type Output = I64Vec4; #[inline] fn sub(self, rhs: &I64Vec4) -> I64Vec4 { (*self).sub(*rhs) } } impl Sub for &I64Vec4 { type Output = I64Vec4; #[inline] fn sub(self, rhs: I64Vec4) -> I64Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&I64Vec4> for I64Vec4 { #[inline] fn sub_assign(&mut self, rhs: &I64Vec4) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&i64> for I64Vec4 { type Output = I64Vec4; #[inline] fn sub(self, rhs: &i64) -> I64Vec4 { self.sub(*rhs) } } impl Sub<&i64> for &I64Vec4 { type Output = I64Vec4; #[inline] fn sub(self, rhs: &i64) -> I64Vec4 { (*self).sub(*rhs) } } impl Sub for &I64Vec4 { type Output = I64Vec4; #[inline] fn sub(self, rhs: i64) -> I64Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&i64> for I64Vec4 { #[inline] fn sub_assign(&mut self, rhs: &i64) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&I64Vec4> for i64 { type Output = I64Vec4; #[inline] fn sub(self, rhs: &I64Vec4) -> I64Vec4 { self.sub(*rhs) } } impl Sub<&I64Vec4> for &i64 { type Output = I64Vec4; #[inline] fn sub(self, rhs: &I64Vec4) -> I64Vec4 { (*self).sub(*rhs) } } impl Sub for &i64 { type Output = I64Vec4; #[inline] fn sub(self, rhs: I64Vec4) -> I64Vec4 { (*self).sub(rhs) } } impl Rem 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 Rem<&I64Vec4> for I64Vec4 { type Output = I64Vec4; #[inline] fn rem(self, rhs: &I64Vec4) -> I64Vec4 { self.rem(*rhs) } } impl Rem<&I64Vec4> for &I64Vec4 { type Output = I64Vec4; #[inline] fn rem(self, rhs: &I64Vec4) -> I64Vec4 { (*self).rem(*rhs) } } impl Rem for &I64Vec4 { type Output = I64Vec4; #[inline] fn rem(self, rhs: I64Vec4) -> I64Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&I64Vec4> for I64Vec4 { #[inline] fn rem_assign(&mut self, rhs: &I64Vec4) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&i64> for I64Vec4 { type Output = I64Vec4; #[inline] fn rem(self, rhs: &i64) -> I64Vec4 { self.rem(*rhs) } } impl Rem<&i64> for &I64Vec4 { type Output = I64Vec4; #[inline] fn rem(self, rhs: &i64) -> I64Vec4 { (*self).rem(*rhs) } } impl Rem for &I64Vec4 { type Output = I64Vec4; #[inline] fn rem(self, rhs: i64) -> I64Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&i64> for I64Vec4 { #[inline] fn rem_assign(&mut self, rhs: &i64) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&I64Vec4> for i64 { type Output = I64Vec4; #[inline] fn rem(self, rhs: &I64Vec4) -> I64Vec4 { self.rem(*rhs) } } impl Rem<&I64Vec4> for &i64 { type Output = I64Vec4; #[inline] fn rem(self, rhs: &I64Vec4) -> I64Vec4 { (*self).rem(*rhs) } } impl Rem for &i64 { type Output = I64Vec4; #[inline] fn rem(self, rhs: I64Vec4) -> I64Vec4 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I64Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I64Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I64Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 Neg for &I64Vec4 { type Output = I64Vec4; #[inline] fn neg(self) -> I64Vec4 { (*self).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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for I64Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } 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 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 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 for I64Vec4 { #[inline] fn from(v: I8Vec4) -> Self { Self::new( i64::from(v.x), i64::from(v.y), i64::from(v.z), i64::from(v.w), ) } } impl From for I64Vec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( i64::from(v.x), i64::from(v.y), i64::from(v.z), i64::from(v.w), ) } } impl From 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 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 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 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 for I64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { Ok(Self::new( i64::try_from(v.x)?, i64::try_from(v.y)?, i64::try_from(v.z)?, i64::try_from(v.w)?, )) } } impl TryFrom for I64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( i64::try_from(v.x)?, i64::try_from(v.y)?, i64::try_from(v.z)?, i64::try_from(v.w)?, )) } } impl From for I64Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( i64::from(v.x), i64::from(v.y), i64::from(v.z), i64::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for I64Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( i64::from(bool_array[0]), i64::from(bool_array[1]), i64::from(bool_array[2]), i64::from(bool_array[3]), ) } } glam-0.30.1/src/i64.rs000064400000000000000000000023001046102023000123570ustar 00000000000000mod 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::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } mod const_test_i64vec3 { const_assert_eq!(24, core::mem::size_of::()); const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); } mod const_test_i64vec4 { const_assert_eq!(32, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } } glam-0.30.1/src/i8/i8vec2.rs000064400000000000000000001344211046102023000134070ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec3, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn i8vec2(x: i8, y: i8) -> I8Vec2 { I8Vec2::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(2)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct I8Vec2 { pub x: i8, pub y: i8, } impl I8Vec2 { /// 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 `i8::MIN`. pub const MIN: Self = Self::splat(i8::MIN); /// All `i8::MAX`. pub const MAX: Self = Self::splat(i8::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: i8, y: i8) -> Self { Self { x, y } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: i8) -> Self { Self { x: v, y: v } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i8) -> i8, { Self::new(f(self.x), f(self.y)) } /// 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: [i8; 2]) -> Self { Self::new(a[0], a[1]) } /// `[x, y]` #[inline] #[must_use] pub const fn to_array(&self) -> [i8; 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: &[i8]) -> Self { assert!(slice.len() >= 2); 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 [i8]) { slice[..2].copy_from_slice(&self.to_array()); } /// Creates a 3D vector from `self` and the given `z` value. #[inline] #[must_use] pub const fn extend(self, z: i8) -> I8Vec3 { I8Vec3::new(self.x, self.y, z) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i8) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i8) -> Self { self.y = y; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> i8 { (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 [`i8::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) -> i8 { 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) -> i8 { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i8 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i8 { self.x * 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) -> i8 { self.dot(self) } /// Compute the squared euclidean distance between two points in space. #[inline] #[must_use] pub fn distance_squared(self, rhs: Self) -> i8 { (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]: i8::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)) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u8::MAX`]. /// /// See also [`checked_manhattan_distance`][I8Vec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u8 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u8::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u8 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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) -> i8 { (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 `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U8Vec2) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U8Vec2) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U8Vec2) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U8Vec2) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U8Vec2) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U8Vec2) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), } } } impl Default for I8Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for I8Vec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&I8Vec2> for I8Vec2 { type Output = I8Vec2; #[inline] fn div(self, rhs: &I8Vec2) -> I8Vec2 { self.div(*rhs) } } impl Div<&I8Vec2> for &I8Vec2 { type Output = I8Vec2; #[inline] fn div(self, rhs: &I8Vec2) -> I8Vec2 { (*self).div(*rhs) } } impl Div for &I8Vec2 { type Output = I8Vec2; #[inline] fn div(self, rhs: I8Vec2) -> I8Vec2 { (*self).div(rhs) } } impl DivAssign for I8Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&I8Vec2> for I8Vec2 { #[inline] fn div_assign(&mut self, rhs: &I8Vec2) { self.div_assign(*rhs) } } impl Div for I8Vec2 { type Output = Self; #[inline] fn div(self, rhs: i8) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&i8> for I8Vec2 { type Output = I8Vec2; #[inline] fn div(self, rhs: &i8) -> I8Vec2 { self.div(*rhs) } } impl Div<&i8> for &I8Vec2 { type Output = I8Vec2; #[inline] fn div(self, rhs: &i8) -> I8Vec2 { (*self).div(*rhs) } } impl Div for &I8Vec2 { type Output = I8Vec2; #[inline] fn div(self, rhs: i8) -> I8Vec2 { (*self).div(rhs) } } impl DivAssign for I8Vec2 { #[inline] fn div_assign(&mut self, rhs: i8) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&i8> for I8Vec2 { #[inline] fn div_assign(&mut self, rhs: &i8) { self.div_assign(*rhs) } } impl Div for i8 { type Output = I8Vec2; #[inline] fn div(self, rhs: I8Vec2) -> I8Vec2 { I8Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&I8Vec2> for i8 { type Output = I8Vec2; #[inline] fn div(self, rhs: &I8Vec2) -> I8Vec2 { self.div(*rhs) } } impl Div<&I8Vec2> for &i8 { type Output = I8Vec2; #[inline] fn div(self, rhs: &I8Vec2) -> I8Vec2 { (*self).div(*rhs) } } impl Div for &i8 { type Output = I8Vec2; #[inline] fn div(self, rhs: I8Vec2) -> I8Vec2 { (*self).div(rhs) } } impl Mul for I8Vec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&I8Vec2> for I8Vec2 { type Output = I8Vec2; #[inline] fn mul(self, rhs: &I8Vec2) -> I8Vec2 { self.mul(*rhs) } } impl Mul<&I8Vec2> for &I8Vec2 { type Output = I8Vec2; #[inline] fn mul(self, rhs: &I8Vec2) -> I8Vec2 { (*self).mul(*rhs) } } impl Mul for &I8Vec2 { type Output = I8Vec2; #[inline] fn mul(self, rhs: I8Vec2) -> I8Vec2 { (*self).mul(rhs) } } impl MulAssign for I8Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&I8Vec2> for I8Vec2 { #[inline] fn mul_assign(&mut self, rhs: &I8Vec2) { self.mul_assign(*rhs) } } impl Mul for I8Vec2 { type Output = Self; #[inline] fn mul(self, rhs: i8) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&i8> for I8Vec2 { type Output = I8Vec2; #[inline] fn mul(self, rhs: &i8) -> I8Vec2 { self.mul(*rhs) } } impl Mul<&i8> for &I8Vec2 { type Output = I8Vec2; #[inline] fn mul(self, rhs: &i8) -> I8Vec2 { (*self).mul(*rhs) } } impl Mul for &I8Vec2 { type Output = I8Vec2; #[inline] fn mul(self, rhs: i8) -> I8Vec2 { (*self).mul(rhs) } } impl MulAssign for I8Vec2 { #[inline] fn mul_assign(&mut self, rhs: i8) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&i8> for I8Vec2 { #[inline] fn mul_assign(&mut self, rhs: &i8) { self.mul_assign(*rhs) } } impl Mul for i8 { type Output = I8Vec2; #[inline] fn mul(self, rhs: I8Vec2) -> I8Vec2 { I8Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&I8Vec2> for i8 { type Output = I8Vec2; #[inline] fn mul(self, rhs: &I8Vec2) -> I8Vec2 { self.mul(*rhs) } } impl Mul<&I8Vec2> for &i8 { type Output = I8Vec2; #[inline] fn mul(self, rhs: &I8Vec2) -> I8Vec2 { (*self).mul(*rhs) } } impl Mul for &i8 { type Output = I8Vec2; #[inline] fn mul(self, rhs: I8Vec2) -> I8Vec2 { (*self).mul(rhs) } } impl Add for I8Vec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&I8Vec2> for I8Vec2 { type Output = I8Vec2; #[inline] fn add(self, rhs: &I8Vec2) -> I8Vec2 { self.add(*rhs) } } impl Add<&I8Vec2> for &I8Vec2 { type Output = I8Vec2; #[inline] fn add(self, rhs: &I8Vec2) -> I8Vec2 { (*self).add(*rhs) } } impl Add for &I8Vec2 { type Output = I8Vec2; #[inline] fn add(self, rhs: I8Vec2) -> I8Vec2 { (*self).add(rhs) } } impl AddAssign for I8Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&I8Vec2> for I8Vec2 { #[inline] fn add_assign(&mut self, rhs: &I8Vec2) { self.add_assign(*rhs) } } impl Add for I8Vec2 { type Output = Self; #[inline] fn add(self, rhs: i8) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&i8> for I8Vec2 { type Output = I8Vec2; #[inline] fn add(self, rhs: &i8) -> I8Vec2 { self.add(*rhs) } } impl Add<&i8> for &I8Vec2 { type Output = I8Vec2; #[inline] fn add(self, rhs: &i8) -> I8Vec2 { (*self).add(*rhs) } } impl Add for &I8Vec2 { type Output = I8Vec2; #[inline] fn add(self, rhs: i8) -> I8Vec2 { (*self).add(rhs) } } impl AddAssign for I8Vec2 { #[inline] fn add_assign(&mut self, rhs: i8) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&i8> for I8Vec2 { #[inline] fn add_assign(&mut self, rhs: &i8) { self.add_assign(*rhs) } } impl Add for i8 { type Output = I8Vec2; #[inline] fn add(self, rhs: I8Vec2) -> I8Vec2 { I8Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&I8Vec2> for i8 { type Output = I8Vec2; #[inline] fn add(self, rhs: &I8Vec2) -> I8Vec2 { self.add(*rhs) } } impl Add<&I8Vec2> for &i8 { type Output = I8Vec2; #[inline] fn add(self, rhs: &I8Vec2) -> I8Vec2 { (*self).add(*rhs) } } impl Add for &i8 { type Output = I8Vec2; #[inline] fn add(self, rhs: I8Vec2) -> I8Vec2 { (*self).add(rhs) } } impl Sub for I8Vec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&I8Vec2> for I8Vec2 { type Output = I8Vec2; #[inline] fn sub(self, rhs: &I8Vec2) -> I8Vec2 { self.sub(*rhs) } } impl Sub<&I8Vec2> for &I8Vec2 { type Output = I8Vec2; #[inline] fn sub(self, rhs: &I8Vec2) -> I8Vec2 { (*self).sub(*rhs) } } impl Sub for &I8Vec2 { type Output = I8Vec2; #[inline] fn sub(self, rhs: I8Vec2) -> I8Vec2 { (*self).sub(rhs) } } impl SubAssign for I8Vec2 { #[inline] fn sub_assign(&mut self, rhs: I8Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&I8Vec2> for I8Vec2 { #[inline] fn sub_assign(&mut self, rhs: &I8Vec2) { self.sub_assign(*rhs) } } impl Sub for I8Vec2 { type Output = Self; #[inline] fn sub(self, rhs: i8) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&i8> for I8Vec2 { type Output = I8Vec2; #[inline] fn sub(self, rhs: &i8) -> I8Vec2 { self.sub(*rhs) } } impl Sub<&i8> for &I8Vec2 { type Output = I8Vec2; #[inline] fn sub(self, rhs: &i8) -> I8Vec2 { (*self).sub(*rhs) } } impl Sub for &I8Vec2 { type Output = I8Vec2; #[inline] fn sub(self, rhs: i8) -> I8Vec2 { (*self).sub(rhs) } } impl SubAssign for I8Vec2 { #[inline] fn sub_assign(&mut self, rhs: i8) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&i8> for I8Vec2 { #[inline] fn sub_assign(&mut self, rhs: &i8) { self.sub_assign(*rhs) } } impl Sub for i8 { type Output = I8Vec2; #[inline] fn sub(self, rhs: I8Vec2) -> I8Vec2 { I8Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&I8Vec2> for i8 { type Output = I8Vec2; #[inline] fn sub(self, rhs: &I8Vec2) -> I8Vec2 { self.sub(*rhs) } } impl Sub<&I8Vec2> for &i8 { type Output = I8Vec2; #[inline] fn sub(self, rhs: &I8Vec2) -> I8Vec2 { (*self).sub(*rhs) } } impl Sub for &i8 { type Output = I8Vec2; #[inline] fn sub(self, rhs: I8Vec2) -> I8Vec2 { (*self).sub(rhs) } } impl Rem for I8Vec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&I8Vec2> for I8Vec2 { type Output = I8Vec2; #[inline] fn rem(self, rhs: &I8Vec2) -> I8Vec2 { self.rem(*rhs) } } impl Rem<&I8Vec2> for &I8Vec2 { type Output = I8Vec2; #[inline] fn rem(self, rhs: &I8Vec2) -> I8Vec2 { (*self).rem(*rhs) } } impl Rem for &I8Vec2 { type Output = I8Vec2; #[inline] fn rem(self, rhs: I8Vec2) -> I8Vec2 { (*self).rem(rhs) } } impl RemAssign for I8Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&I8Vec2> for I8Vec2 { #[inline] fn rem_assign(&mut self, rhs: &I8Vec2) { self.rem_assign(*rhs) } } impl Rem for I8Vec2 { type Output = Self; #[inline] fn rem(self, rhs: i8) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&i8> for I8Vec2 { type Output = I8Vec2; #[inline] fn rem(self, rhs: &i8) -> I8Vec2 { self.rem(*rhs) } } impl Rem<&i8> for &I8Vec2 { type Output = I8Vec2; #[inline] fn rem(self, rhs: &i8) -> I8Vec2 { (*self).rem(*rhs) } } impl Rem for &I8Vec2 { type Output = I8Vec2; #[inline] fn rem(self, rhs: i8) -> I8Vec2 { (*self).rem(rhs) } } impl RemAssign for I8Vec2 { #[inline] fn rem_assign(&mut self, rhs: i8) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&i8> for I8Vec2 { #[inline] fn rem_assign(&mut self, rhs: &i8) { self.rem_assign(*rhs) } } impl Rem for i8 { type Output = I8Vec2; #[inline] fn rem(self, rhs: I8Vec2) -> I8Vec2 { I8Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&I8Vec2> for i8 { type Output = I8Vec2; #[inline] fn rem(self, rhs: &I8Vec2) -> I8Vec2 { self.rem(*rhs) } } impl Rem<&I8Vec2> for &i8 { type Output = I8Vec2; #[inline] fn rem(self, rhs: &I8Vec2) -> I8Vec2 { (*self).rem(*rhs) } } impl Rem for &i8 { type Output = I8Vec2; #[inline] fn rem(self, rhs: I8Vec2) -> I8Vec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[i8; 2]> for I8Vec2 { #[inline] fn as_ref(&self) -> &[i8; 2] { unsafe { &*(self as *const I8Vec2 as *const [i8; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[i8; 2]> for I8Vec2 { #[inline] fn as_mut(&mut self) -> &mut [i8; 2] { unsafe { &mut *(self as *mut I8Vec2 as *mut [i8; 2]) } } } impl Sum for I8Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I8Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I8Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I8Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for I8Vec2 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), } } } impl Neg for &I8Vec2 { type Output = I8Vec2; #[inline] fn neg(self) -> I8Vec2 { (*self).neg() } } impl Not for I8Vec2 { type Output = Self; #[inline] fn not(self) -> Self::Output { Self { x: self.x.not(), y: self.y.not(), } } } impl BitAnd for I8Vec2 { 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 I8Vec2 { 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 I8Vec2 { 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 for I8Vec2 { type Output = Self; #[inline] fn bitand(self, rhs: i8) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), } } } impl BitOr for I8Vec2 { type Output = Self; #[inline] fn bitor(self, rhs: i8) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), } } } impl BitXor for I8Vec2 { type Output = Self; #[inline] fn bitxor(self, rhs: i8) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i64) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i64) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u64) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for I8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u64) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for I8Vec2 { 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 for I8Vec2 { 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 for I8Vec2 { 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 for I8Vec2 { 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 for I8Vec2 { type Output = i8; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for I8Vec2 { #[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"), } } } impl fmt::Display for I8Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } impl fmt::Debug for I8Vec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(I8Vec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[i8; 2]> for I8Vec2 { #[inline] fn from(a: [i8; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [i8; 2] { #[inline] fn from(v: I8Vec2) -> Self { [v.x, v.y] } } impl From<(i8, i8)> for I8Vec2 { #[inline] fn from(t: (i8, i8)) -> Self { Self::new(t.0, t.1) } } impl From for (i8, i8) { #[inline] fn from(v: I8Vec2) -> Self { (v.x, v.y) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U8Vec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl TryFrom for I8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(i8::try_from(v.x)?, i8::try_from(v.y)?)) } } impl From for I8Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(i8::from(v.x), i8::from(v.y)) } } glam-0.30.1/src/i8/i8vec3.rs000064400000000000000000001500101046102023000134000ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec2, I8Vec4, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 3-dimensional vector. #[inline(always)] #[must_use] pub const fn i8vec3(x: i8, y: i8, z: i8) -> I8Vec3 { I8Vec3::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 I8Vec3 { pub x: i8, pub y: i8, pub z: i8, } impl I8Vec3 { /// 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 `i8::MIN`. pub const MIN: Self = Self::splat(i8::MIN); /// All `i8::MAX`. pub const MAX: Self = Self::splat(i8::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: i8, y: i8, z: i8) -> Self { Self { x, y, z } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: i8) -> Self { Self { x: v, y: v, z: v } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i8) -> i8, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [i8; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// `[x, y, z]` #[inline] #[must_use] pub const fn to_array(&self) -> [i8; 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: &[i8]) -> Self { assert!(slice.len() >= 3); 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 [i8]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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: I8Vec4) -> 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: i8) -> I8Vec4 { I8Vec4::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) -> I8Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i8) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i8) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i8) -> Self { self.z = z; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> i8 { (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 [`i8::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) -> i8 { 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) -> i8 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i8 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i8 { self.x * self.y * 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) -> i8 { self.dot(self) } /// Compute the squared euclidean distance between two points in space. #[inline] #[must_use] pub fn distance_squared(self, rhs: Self) -> i8 { (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]: i8::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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u8::MAX`]. /// /// See also [`checked_manhattan_distance`][I8Vec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u8 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u8::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u8 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U8Vec3) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U8Vec3) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U8Vec3) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U8Vec3) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U8Vec3) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U8Vec3) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), } } } impl Default for I8Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for I8Vec3 { 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 Div<&I8Vec3> for I8Vec3 { type Output = I8Vec3; #[inline] fn div(self, rhs: &I8Vec3) -> I8Vec3 { self.div(*rhs) } } impl Div<&I8Vec3> for &I8Vec3 { type Output = I8Vec3; #[inline] fn div(self, rhs: &I8Vec3) -> I8Vec3 { (*self).div(*rhs) } } impl Div for &I8Vec3 { type Output = I8Vec3; #[inline] fn div(self, rhs: I8Vec3) -> I8Vec3 { (*self).div(rhs) } } impl DivAssign for I8Vec3 { #[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 DivAssign<&I8Vec3> for I8Vec3 { #[inline] fn div_assign(&mut self, rhs: &I8Vec3) { self.div_assign(*rhs) } } impl Div for I8Vec3 { type Output = Self; #[inline] fn div(self, rhs: i8) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&i8> for I8Vec3 { type Output = I8Vec3; #[inline] fn div(self, rhs: &i8) -> I8Vec3 { self.div(*rhs) } } impl Div<&i8> for &I8Vec3 { type Output = I8Vec3; #[inline] fn div(self, rhs: &i8) -> I8Vec3 { (*self).div(*rhs) } } impl Div for &I8Vec3 { type Output = I8Vec3; #[inline] fn div(self, rhs: i8) -> I8Vec3 { (*self).div(rhs) } } impl DivAssign for I8Vec3 { #[inline] fn div_assign(&mut self, rhs: i8) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&i8> for I8Vec3 { #[inline] fn div_assign(&mut self, rhs: &i8) { self.div_assign(*rhs) } } impl Div for i8 { type Output = I8Vec3; #[inline] fn div(self, rhs: I8Vec3) -> I8Vec3 { I8Vec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&I8Vec3> for i8 { type Output = I8Vec3; #[inline] fn div(self, rhs: &I8Vec3) -> I8Vec3 { self.div(*rhs) } } impl Div<&I8Vec3> for &i8 { type Output = I8Vec3; #[inline] fn div(self, rhs: &I8Vec3) -> I8Vec3 { (*self).div(*rhs) } } impl Div for &i8 { type Output = I8Vec3; #[inline] fn div(self, rhs: I8Vec3) -> I8Vec3 { (*self).div(rhs) } } impl Mul for I8Vec3 { 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 Mul<&I8Vec3> for I8Vec3 { type Output = I8Vec3; #[inline] fn mul(self, rhs: &I8Vec3) -> I8Vec3 { self.mul(*rhs) } } impl Mul<&I8Vec3> for &I8Vec3 { type Output = I8Vec3; #[inline] fn mul(self, rhs: &I8Vec3) -> I8Vec3 { (*self).mul(*rhs) } } impl Mul for &I8Vec3 { type Output = I8Vec3; #[inline] fn mul(self, rhs: I8Vec3) -> I8Vec3 { (*self).mul(rhs) } } impl MulAssign for I8Vec3 { #[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 MulAssign<&I8Vec3> for I8Vec3 { #[inline] fn mul_assign(&mut self, rhs: &I8Vec3) { self.mul_assign(*rhs) } } impl Mul for I8Vec3 { type Output = Self; #[inline] fn mul(self, rhs: i8) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&i8> for I8Vec3 { type Output = I8Vec3; #[inline] fn mul(self, rhs: &i8) -> I8Vec3 { self.mul(*rhs) } } impl Mul<&i8> for &I8Vec3 { type Output = I8Vec3; #[inline] fn mul(self, rhs: &i8) -> I8Vec3 { (*self).mul(*rhs) } } impl Mul for &I8Vec3 { type Output = I8Vec3; #[inline] fn mul(self, rhs: i8) -> I8Vec3 { (*self).mul(rhs) } } impl MulAssign for I8Vec3 { #[inline] fn mul_assign(&mut self, rhs: i8) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&i8> for I8Vec3 { #[inline] fn mul_assign(&mut self, rhs: &i8) { self.mul_assign(*rhs) } } impl Mul for i8 { type Output = I8Vec3; #[inline] fn mul(self, rhs: I8Vec3) -> I8Vec3 { I8Vec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&I8Vec3> for i8 { type Output = I8Vec3; #[inline] fn mul(self, rhs: &I8Vec3) -> I8Vec3 { self.mul(*rhs) } } impl Mul<&I8Vec3> for &i8 { type Output = I8Vec3; #[inline] fn mul(self, rhs: &I8Vec3) -> I8Vec3 { (*self).mul(*rhs) } } impl Mul for &i8 { type Output = I8Vec3; #[inline] fn mul(self, rhs: I8Vec3) -> I8Vec3 { (*self).mul(rhs) } } impl Add for I8Vec3 { 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 Add<&I8Vec3> for I8Vec3 { type Output = I8Vec3; #[inline] fn add(self, rhs: &I8Vec3) -> I8Vec3 { self.add(*rhs) } } impl Add<&I8Vec3> for &I8Vec3 { type Output = I8Vec3; #[inline] fn add(self, rhs: &I8Vec3) -> I8Vec3 { (*self).add(*rhs) } } impl Add for &I8Vec3 { type Output = I8Vec3; #[inline] fn add(self, rhs: I8Vec3) -> I8Vec3 { (*self).add(rhs) } } impl AddAssign for I8Vec3 { #[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 AddAssign<&I8Vec3> for I8Vec3 { #[inline] fn add_assign(&mut self, rhs: &I8Vec3) { self.add_assign(*rhs) } } impl Add for I8Vec3 { type Output = Self; #[inline] fn add(self, rhs: i8) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&i8> for I8Vec3 { type Output = I8Vec3; #[inline] fn add(self, rhs: &i8) -> I8Vec3 { self.add(*rhs) } } impl Add<&i8> for &I8Vec3 { type Output = I8Vec3; #[inline] fn add(self, rhs: &i8) -> I8Vec3 { (*self).add(*rhs) } } impl Add for &I8Vec3 { type Output = I8Vec3; #[inline] fn add(self, rhs: i8) -> I8Vec3 { (*self).add(rhs) } } impl AddAssign for I8Vec3 { #[inline] fn add_assign(&mut self, rhs: i8) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&i8> for I8Vec3 { #[inline] fn add_assign(&mut self, rhs: &i8) { self.add_assign(*rhs) } } impl Add for i8 { type Output = I8Vec3; #[inline] fn add(self, rhs: I8Vec3) -> I8Vec3 { I8Vec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&I8Vec3> for i8 { type Output = I8Vec3; #[inline] fn add(self, rhs: &I8Vec3) -> I8Vec3 { self.add(*rhs) } } impl Add<&I8Vec3> for &i8 { type Output = I8Vec3; #[inline] fn add(self, rhs: &I8Vec3) -> I8Vec3 { (*self).add(*rhs) } } impl Add for &i8 { type Output = I8Vec3; #[inline] fn add(self, rhs: I8Vec3) -> I8Vec3 { (*self).add(rhs) } } impl Sub for I8Vec3 { 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 Sub<&I8Vec3> for I8Vec3 { type Output = I8Vec3; #[inline] fn sub(self, rhs: &I8Vec3) -> I8Vec3 { self.sub(*rhs) } } impl Sub<&I8Vec3> for &I8Vec3 { type Output = I8Vec3; #[inline] fn sub(self, rhs: &I8Vec3) -> I8Vec3 { (*self).sub(*rhs) } } impl Sub for &I8Vec3 { type Output = I8Vec3; #[inline] fn sub(self, rhs: I8Vec3) -> I8Vec3 { (*self).sub(rhs) } } impl SubAssign for I8Vec3 { #[inline] fn sub_assign(&mut self, rhs: I8Vec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&I8Vec3> for I8Vec3 { #[inline] fn sub_assign(&mut self, rhs: &I8Vec3) { self.sub_assign(*rhs) } } impl Sub for I8Vec3 { type Output = Self; #[inline] fn sub(self, rhs: i8) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&i8> for I8Vec3 { type Output = I8Vec3; #[inline] fn sub(self, rhs: &i8) -> I8Vec3 { self.sub(*rhs) } } impl Sub<&i8> for &I8Vec3 { type Output = I8Vec3; #[inline] fn sub(self, rhs: &i8) -> I8Vec3 { (*self).sub(*rhs) } } impl Sub for &I8Vec3 { type Output = I8Vec3; #[inline] fn sub(self, rhs: i8) -> I8Vec3 { (*self).sub(rhs) } } impl SubAssign for I8Vec3 { #[inline] fn sub_assign(&mut self, rhs: i8) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&i8> for I8Vec3 { #[inline] fn sub_assign(&mut self, rhs: &i8) { self.sub_assign(*rhs) } } impl Sub for i8 { type Output = I8Vec3; #[inline] fn sub(self, rhs: I8Vec3) -> I8Vec3 { I8Vec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&I8Vec3> for i8 { type Output = I8Vec3; #[inline] fn sub(self, rhs: &I8Vec3) -> I8Vec3 { self.sub(*rhs) } } impl Sub<&I8Vec3> for &i8 { type Output = I8Vec3; #[inline] fn sub(self, rhs: &I8Vec3) -> I8Vec3 { (*self).sub(*rhs) } } impl Sub for &i8 { type Output = I8Vec3; #[inline] fn sub(self, rhs: I8Vec3) -> I8Vec3 { (*self).sub(rhs) } } impl Rem for I8Vec3 { 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 Rem<&I8Vec3> for I8Vec3 { type Output = I8Vec3; #[inline] fn rem(self, rhs: &I8Vec3) -> I8Vec3 { self.rem(*rhs) } } impl Rem<&I8Vec3> for &I8Vec3 { type Output = I8Vec3; #[inline] fn rem(self, rhs: &I8Vec3) -> I8Vec3 { (*self).rem(*rhs) } } impl Rem for &I8Vec3 { type Output = I8Vec3; #[inline] fn rem(self, rhs: I8Vec3) -> I8Vec3 { (*self).rem(rhs) } } impl RemAssign for I8Vec3 { #[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 RemAssign<&I8Vec3> for I8Vec3 { #[inline] fn rem_assign(&mut self, rhs: &I8Vec3) { self.rem_assign(*rhs) } } impl Rem for I8Vec3 { type Output = Self; #[inline] fn rem(self, rhs: i8) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&i8> for I8Vec3 { type Output = I8Vec3; #[inline] fn rem(self, rhs: &i8) -> I8Vec3 { self.rem(*rhs) } } impl Rem<&i8> for &I8Vec3 { type Output = I8Vec3; #[inline] fn rem(self, rhs: &i8) -> I8Vec3 { (*self).rem(*rhs) } } impl Rem for &I8Vec3 { type Output = I8Vec3; #[inline] fn rem(self, rhs: i8) -> I8Vec3 { (*self).rem(rhs) } } impl RemAssign for I8Vec3 { #[inline] fn rem_assign(&mut self, rhs: i8) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&i8> for I8Vec3 { #[inline] fn rem_assign(&mut self, rhs: &i8) { self.rem_assign(*rhs) } } impl Rem for i8 { type Output = I8Vec3; #[inline] fn rem(self, rhs: I8Vec3) -> I8Vec3 { I8Vec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&I8Vec3> for i8 { type Output = I8Vec3; #[inline] fn rem(self, rhs: &I8Vec3) -> I8Vec3 { self.rem(*rhs) } } impl Rem<&I8Vec3> for &i8 { type Output = I8Vec3; #[inline] fn rem(self, rhs: &I8Vec3) -> I8Vec3 { (*self).rem(*rhs) } } impl Rem for &i8 { type Output = I8Vec3; #[inline] fn rem(self, rhs: I8Vec3) -> I8Vec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[i8; 3]> for I8Vec3 { #[inline] fn as_ref(&self) -> &[i8; 3] { unsafe { &*(self as *const I8Vec3 as *const [i8; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[i8; 3]> for I8Vec3 { #[inline] fn as_mut(&mut self) -> &mut [i8; 3] { unsafe { &mut *(self as *mut I8Vec3 as *mut [i8; 3]) } } } impl Sum for I8Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I8Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I8Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I8Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for I8Vec3 { type Output = Self; #[inline] fn neg(self) -> Self { Self { x: self.x.neg(), y: self.y.neg(), z: self.z.neg(), } } } impl Neg for &I8Vec3 { type Output = I8Vec3; #[inline] fn neg(self) -> I8Vec3 { (*self).neg() } } impl Not for I8Vec3 { 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 I8Vec3 { 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 I8Vec3 { 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 I8Vec3 { 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 for I8Vec3 { type Output = Self; #[inline] fn bitand(self, rhs: i8) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), z: self.z.bitand(rhs), } } } impl BitOr for I8Vec3 { type Output = Self; #[inline] fn bitor(self, rhs: i8) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), z: self.z.bitor(rhs), } } } impl BitXor for I8Vec3 { type Output = Self; #[inline] fn bitxor(self, rhs: i8) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), z: self.z.bitxor(rhs), } } } impl Shl for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { 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 for I8Vec3 { type Output = i8; #[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 for I8Vec3 { #[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"), } } } impl fmt::Display for I8Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } impl fmt::Debug for I8Vec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(I8Vec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[i8; 3]> for I8Vec3 { #[inline] fn from(a: [i8; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [i8; 3] { #[inline] fn from(v: I8Vec3) -> Self { [v.x, v.y, v.z] } } impl From<(i8, i8, i8)> for I8Vec3 { #[inline] fn from(t: (i8, i8, i8)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (i8, i8, i8) { #[inline] fn from(v: I8Vec3) -> Self { (v.x, v.y, v.z) } } impl From<(I8Vec2, i8)> for I8Vec3 { #[inline] fn from((v, z): (I8Vec2, i8)) -> Self { Self::new(v.x, v.y, z) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U8Vec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl TryFrom for I8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, )) } } impl From for I8Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(i8::from(v.x), i8::from(v.y), i8::from(v.z)) } } impl From for I8Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( i8::from(bool_array[0]), i8::from(bool_array[1]), i8::from(bool_array[2]), ) } } glam-0.30.1/src/i8/i8vec4.rs000064400000000000000000001617271046102023000134220ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec2, I8Vec3, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 4-dimensional vector. #[inline(always)] #[must_use] pub const fn i8vec4(x: i8, y: i8, z: i8, w: i8) -> I8Vec4 { I8Vec4::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(4)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct I8Vec4 { pub x: i8, pub y: i8, pub z: i8, pub w: i8, } impl I8Vec4 { /// 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 `i8::MIN`. pub const MIN: Self = Self::splat(i8::MIN); /// All `i8::MAX`. pub const MAX: Self = Self::splat(i8::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: i8, y: i8, z: i8, w: i8) -> Self { Self { x, y, z, w } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: i8) -> Self { Self { x: v, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(i8) -> i8, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: [i8; 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) -> [i8; 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: &[i8]) -> Self { assert!(slice.len() >= 4); 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 [i8]) { slice[..4].copy_from_slice(&self.to_array()); } /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`. /// /// Truncation to [`I8Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()]. #[inline] #[must_use] pub fn truncate(self) -> I8Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: i8) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: i8) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: i8) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: i8) -> Self { self.w = w; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> i8 { (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 [`i8::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) -> i8 { 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) -> i8 { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> i8 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> i8 { self.x * self.y * self.z * 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) -> i8 { self.dot(self) } /// Compute the squared euclidean distance between two points in space. #[inline] #[must_use] pub fn distance_squared(self, rhs: Self) -> i8 { (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]: i8::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), ) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u8::MAX`]. /// /// See also [`checked_manhattan_distance`][I8Vec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u8 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u8::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u8 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: U8Vec4) -> Option { let x = match self.x.checked_add_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: U8Vec4) -> Option { let x = match self.x.checked_sub_unsigned(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub_unsigned(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub_unsigned(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub_unsigned(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: U8Vec4) -> Self { Self { x: self.x.wrapping_add_unsigned(rhs.x), y: self.y.wrapping_add_unsigned(rhs.y), z: self.z.wrapping_add_unsigned(rhs.z), w: self.w.wrapping_add_unsigned(rhs.w), } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: U8Vec4) -> Self { Self { x: self.x.wrapping_sub_unsigned(rhs.x), y: self.y.wrapping_sub_unsigned(rhs.y), z: self.z.wrapping_sub_unsigned(rhs.z), w: self.w.wrapping_sub_unsigned(rhs.w), } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: U8Vec4) -> Self { Self { x: self.x.saturating_add_unsigned(rhs.x), y: self.y.saturating_add_unsigned(rhs.y), z: self.z.saturating_add_unsigned(rhs.z), w: self.w.saturating_add_unsigned(rhs.w), } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: U8Vec4) -> Self { Self { x: self.x.saturating_sub_unsigned(rhs.x), y: self.y.saturating_sub_unsigned(rhs.y), z: self.z.saturating_sub_unsigned(rhs.z), w: self.w.saturating_sub_unsigned(rhs.w), } } } impl Default for I8Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for I8Vec4 { 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 Div<&I8Vec4> for I8Vec4 { type Output = I8Vec4; #[inline] fn div(self, rhs: &I8Vec4) -> I8Vec4 { self.div(*rhs) } } impl Div<&I8Vec4> for &I8Vec4 { type Output = I8Vec4; #[inline] fn div(self, rhs: &I8Vec4) -> I8Vec4 { (*self).div(*rhs) } } impl Div for &I8Vec4 { type Output = I8Vec4; #[inline] fn div(self, rhs: I8Vec4) -> I8Vec4 { (*self).div(rhs) } } impl DivAssign for I8Vec4 { #[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 DivAssign<&I8Vec4> for I8Vec4 { #[inline] fn div_assign(&mut self, rhs: &I8Vec4) { self.div_assign(*rhs) } } impl Div for I8Vec4 { type Output = Self; #[inline] fn div(self, rhs: i8) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&i8> for I8Vec4 { type Output = I8Vec4; #[inline] fn div(self, rhs: &i8) -> I8Vec4 { self.div(*rhs) } } impl Div<&i8> for &I8Vec4 { type Output = I8Vec4; #[inline] fn div(self, rhs: &i8) -> I8Vec4 { (*self).div(*rhs) } } impl Div for &I8Vec4 { type Output = I8Vec4; #[inline] fn div(self, rhs: i8) -> I8Vec4 { (*self).div(rhs) } } impl DivAssign for I8Vec4 { #[inline] fn div_assign(&mut self, rhs: i8) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&i8> for I8Vec4 { #[inline] fn div_assign(&mut self, rhs: &i8) { self.div_assign(*rhs) } } impl Div for i8 { type Output = I8Vec4; #[inline] fn div(self, rhs: I8Vec4) -> I8Vec4 { I8Vec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&I8Vec4> for i8 { type Output = I8Vec4; #[inline] fn div(self, rhs: &I8Vec4) -> I8Vec4 { self.div(*rhs) } } impl Div<&I8Vec4> for &i8 { type Output = I8Vec4; #[inline] fn div(self, rhs: &I8Vec4) -> I8Vec4 { (*self).div(*rhs) } } impl Div for &i8 { type Output = I8Vec4; #[inline] fn div(self, rhs: I8Vec4) -> I8Vec4 { (*self).div(rhs) } } impl Mul for I8Vec4 { 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 Mul<&I8Vec4> for I8Vec4 { type Output = I8Vec4; #[inline] fn mul(self, rhs: &I8Vec4) -> I8Vec4 { self.mul(*rhs) } } impl Mul<&I8Vec4> for &I8Vec4 { type Output = I8Vec4; #[inline] fn mul(self, rhs: &I8Vec4) -> I8Vec4 { (*self).mul(*rhs) } } impl Mul for &I8Vec4 { type Output = I8Vec4; #[inline] fn mul(self, rhs: I8Vec4) -> I8Vec4 { (*self).mul(rhs) } } impl MulAssign for I8Vec4 { #[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 MulAssign<&I8Vec4> for I8Vec4 { #[inline] fn mul_assign(&mut self, rhs: &I8Vec4) { self.mul_assign(*rhs) } } impl Mul for I8Vec4 { type Output = Self; #[inline] fn mul(self, rhs: i8) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&i8> for I8Vec4 { type Output = I8Vec4; #[inline] fn mul(self, rhs: &i8) -> I8Vec4 { self.mul(*rhs) } } impl Mul<&i8> for &I8Vec4 { type Output = I8Vec4; #[inline] fn mul(self, rhs: &i8) -> I8Vec4 { (*self).mul(*rhs) } } impl Mul for &I8Vec4 { type Output = I8Vec4; #[inline] fn mul(self, rhs: i8) -> I8Vec4 { (*self).mul(rhs) } } impl MulAssign for I8Vec4 { #[inline] fn mul_assign(&mut self, rhs: i8) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&i8> for I8Vec4 { #[inline] fn mul_assign(&mut self, rhs: &i8) { self.mul_assign(*rhs) } } impl Mul for i8 { type Output = I8Vec4; #[inline] fn mul(self, rhs: I8Vec4) -> I8Vec4 { I8Vec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&I8Vec4> for i8 { type Output = I8Vec4; #[inline] fn mul(self, rhs: &I8Vec4) -> I8Vec4 { self.mul(*rhs) } } impl Mul<&I8Vec4> for &i8 { type Output = I8Vec4; #[inline] fn mul(self, rhs: &I8Vec4) -> I8Vec4 { (*self).mul(*rhs) } } impl Mul for &i8 { type Output = I8Vec4; #[inline] fn mul(self, rhs: I8Vec4) -> I8Vec4 { (*self).mul(rhs) } } impl Add for I8Vec4 { 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 Add<&I8Vec4> for I8Vec4 { type Output = I8Vec4; #[inline] fn add(self, rhs: &I8Vec4) -> I8Vec4 { self.add(*rhs) } } impl Add<&I8Vec4> for &I8Vec4 { type Output = I8Vec4; #[inline] fn add(self, rhs: &I8Vec4) -> I8Vec4 { (*self).add(*rhs) } } impl Add for &I8Vec4 { type Output = I8Vec4; #[inline] fn add(self, rhs: I8Vec4) -> I8Vec4 { (*self).add(rhs) } } impl AddAssign for I8Vec4 { #[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 AddAssign<&I8Vec4> for I8Vec4 { #[inline] fn add_assign(&mut self, rhs: &I8Vec4) { self.add_assign(*rhs) } } impl Add for I8Vec4 { type Output = Self; #[inline] fn add(self, rhs: i8) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&i8> for I8Vec4 { type Output = I8Vec4; #[inline] fn add(self, rhs: &i8) -> I8Vec4 { self.add(*rhs) } } impl Add<&i8> for &I8Vec4 { type Output = I8Vec4; #[inline] fn add(self, rhs: &i8) -> I8Vec4 { (*self).add(*rhs) } } impl Add for &I8Vec4 { type Output = I8Vec4; #[inline] fn add(self, rhs: i8) -> I8Vec4 { (*self).add(rhs) } } impl AddAssign for I8Vec4 { #[inline] fn add_assign(&mut self, rhs: i8) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&i8> for I8Vec4 { #[inline] fn add_assign(&mut self, rhs: &i8) { self.add_assign(*rhs) } } impl Add for i8 { type Output = I8Vec4; #[inline] fn add(self, rhs: I8Vec4) -> I8Vec4 { I8Vec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&I8Vec4> for i8 { type Output = I8Vec4; #[inline] fn add(self, rhs: &I8Vec4) -> I8Vec4 { self.add(*rhs) } } impl Add<&I8Vec4> for &i8 { type Output = I8Vec4; #[inline] fn add(self, rhs: &I8Vec4) -> I8Vec4 { (*self).add(*rhs) } } impl Add for &i8 { type Output = I8Vec4; #[inline] fn add(self, rhs: I8Vec4) -> I8Vec4 { (*self).add(rhs) } } impl Sub for I8Vec4 { 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 Sub<&I8Vec4> for I8Vec4 { type Output = I8Vec4; #[inline] fn sub(self, rhs: &I8Vec4) -> I8Vec4 { self.sub(*rhs) } } impl Sub<&I8Vec4> for &I8Vec4 { type Output = I8Vec4; #[inline] fn sub(self, rhs: &I8Vec4) -> I8Vec4 { (*self).sub(*rhs) } } impl Sub for &I8Vec4 { type Output = I8Vec4; #[inline] fn sub(self, rhs: I8Vec4) -> I8Vec4 { (*self).sub(rhs) } } impl SubAssign for I8Vec4 { #[inline] fn sub_assign(&mut self, rhs: I8Vec4) { 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 SubAssign<&I8Vec4> for I8Vec4 { #[inline] fn sub_assign(&mut self, rhs: &I8Vec4) { self.sub_assign(*rhs) } } impl Sub for I8Vec4 { type Output = Self; #[inline] fn sub(self, rhs: i8) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&i8> for I8Vec4 { type Output = I8Vec4; #[inline] fn sub(self, rhs: &i8) -> I8Vec4 { self.sub(*rhs) } } impl Sub<&i8> for &I8Vec4 { type Output = I8Vec4; #[inline] fn sub(self, rhs: &i8) -> I8Vec4 { (*self).sub(*rhs) } } impl Sub for &I8Vec4 { type Output = I8Vec4; #[inline] fn sub(self, rhs: i8) -> I8Vec4 { (*self).sub(rhs) } } impl SubAssign for I8Vec4 { #[inline] fn sub_assign(&mut self, rhs: i8) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&i8> for I8Vec4 { #[inline] fn sub_assign(&mut self, rhs: &i8) { self.sub_assign(*rhs) } } impl Sub for i8 { type Output = I8Vec4; #[inline] fn sub(self, rhs: I8Vec4) -> I8Vec4 { I8Vec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&I8Vec4> for i8 { type Output = I8Vec4; #[inline] fn sub(self, rhs: &I8Vec4) -> I8Vec4 { self.sub(*rhs) } } impl Sub<&I8Vec4> for &i8 { type Output = I8Vec4; #[inline] fn sub(self, rhs: &I8Vec4) -> I8Vec4 { (*self).sub(*rhs) } } impl Sub for &i8 { type Output = I8Vec4; #[inline] fn sub(self, rhs: I8Vec4) -> I8Vec4 { (*self).sub(rhs) } } impl Rem for I8Vec4 { 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 Rem<&I8Vec4> for I8Vec4 { type Output = I8Vec4; #[inline] fn rem(self, rhs: &I8Vec4) -> I8Vec4 { self.rem(*rhs) } } impl Rem<&I8Vec4> for &I8Vec4 { type Output = I8Vec4; #[inline] fn rem(self, rhs: &I8Vec4) -> I8Vec4 { (*self).rem(*rhs) } } impl Rem for &I8Vec4 { type Output = I8Vec4; #[inline] fn rem(self, rhs: I8Vec4) -> I8Vec4 { (*self).rem(rhs) } } impl RemAssign for I8Vec4 { #[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 RemAssign<&I8Vec4> for I8Vec4 { #[inline] fn rem_assign(&mut self, rhs: &I8Vec4) { self.rem_assign(*rhs) } } impl Rem for I8Vec4 { type Output = Self; #[inline] fn rem(self, rhs: i8) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&i8> for I8Vec4 { type Output = I8Vec4; #[inline] fn rem(self, rhs: &i8) -> I8Vec4 { self.rem(*rhs) } } impl Rem<&i8> for &I8Vec4 { type Output = I8Vec4; #[inline] fn rem(self, rhs: &i8) -> I8Vec4 { (*self).rem(*rhs) } } impl Rem for &I8Vec4 { type Output = I8Vec4; #[inline] fn rem(self, rhs: i8) -> I8Vec4 { (*self).rem(rhs) } } impl RemAssign for I8Vec4 { #[inline] fn rem_assign(&mut self, rhs: i8) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&i8> for I8Vec4 { #[inline] fn rem_assign(&mut self, rhs: &i8) { self.rem_assign(*rhs) } } impl Rem for i8 { type Output = I8Vec4; #[inline] fn rem(self, rhs: I8Vec4) -> I8Vec4 { I8Vec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&I8Vec4> for i8 { type Output = I8Vec4; #[inline] fn rem(self, rhs: &I8Vec4) -> I8Vec4 { self.rem(*rhs) } } impl Rem<&I8Vec4> for &i8 { type Output = I8Vec4; #[inline] fn rem(self, rhs: &I8Vec4) -> I8Vec4 { (*self).rem(*rhs) } } impl Rem for &i8 { type Output = I8Vec4; #[inline] fn rem(self, rhs: I8Vec4) -> I8Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[i8; 4]> for I8Vec4 { #[inline] fn as_ref(&self) -> &[i8; 4] { unsafe { &*(self as *const I8Vec4 as *const [i8; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[i8; 4]> for I8Vec4 { #[inline] fn as_mut(&mut self) -> &mut [i8; 4] { unsafe { &mut *(self as *mut I8Vec4 as *mut [i8; 4]) } } } impl Sum for I8Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for I8Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for I8Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for I8Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Neg for I8Vec4 { 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 Neg for &I8Vec4 { type Output = I8Vec4; #[inline] fn neg(self) -> I8Vec4 { (*self).neg() } } impl Not for I8Vec4 { 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 I8Vec4 { 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 I8Vec4 { 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 I8Vec4 { 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 for I8Vec4 { type Output = Self; #[inline] fn bitand(self, rhs: i8) -> 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 for I8Vec4 { type Output = Self; #[inline] fn bitor(self, rhs: i8) -> 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 for I8Vec4 { type Output = Self; #[inline] fn bitxor(self, rhs: i8) -> 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { 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 for I8Vec4 { type Output = i8; #[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 for I8Vec4 { #[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"), } } } impl fmt::Display for I8Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } impl fmt::Debug for I8Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(I8Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[i8; 4]> for I8Vec4 { #[inline] fn from(a: [i8; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [i8; 4] { #[inline] fn from(v: I8Vec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(i8, i8, i8, i8)> for I8Vec4 { #[inline] fn from(t: (i8, i8, i8, i8)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (i8, i8, i8, i8) { #[inline] fn from(v: I8Vec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(I8Vec3, i8)> for I8Vec4 { #[inline] fn from((v, w): (I8Vec3, i8)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(i8, I8Vec3)> for I8Vec4 { #[inline] fn from((x, v): (i8, I8Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(I8Vec2, i8, i8)> for I8Vec4 { #[inline] fn from((v, z, w): (I8Vec2, i8, i8)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(I8Vec2, I8Vec2)> for I8Vec4 { #[inline] fn from((v, u): (I8Vec2, I8Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U8Vec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl TryFrom for I8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( i8::try_from(v.x)?, i8::try_from(v.y)?, i8::try_from(v.z)?, i8::try_from(v.w)?, )) } } impl From for I8Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new(i8::from(v.x), i8::from(v.y), i8::from(v.z), i8::from(v.w)) } } #[cfg(not(feature = "scalar-math"))] impl From for I8Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( i8::from(bool_array[0]), i8::from(bool_array[1]), i8::from(bool_array[2]), i8::from(bool_array[3]), ) } } glam-0.30.1/src/i8.rs000064400000000000000000000022401046102023000123000ustar 00000000000000mod i8vec2; mod i8vec3; mod i8vec4; pub use i8vec2::{i8vec2, I8Vec2}; pub use i8vec3::{i8vec3, I8Vec3}; pub use i8vec4::{i8vec4, I8Vec4}; #[cfg(not(target_arch = "spirv"))] mod test { use super::*; mod const_test_i8vec2 { const_assert_eq!(2, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(2, core::mem::align_of::()); } mod const_test_i8vec3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(3, core::mem::size_of::()); } mod const_test_i8vec4 { const_assert_eq!(4, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(4, core::mem::align_of::()); } } glam-0.30.1/src/lib.rs000064400000000000000000000313341046102023000125340ustar 00000000000000/*! # glam `glam` is a simple and fast linear algebra library for games and graphics. ## Features * [`f32`](mod@f32) types * vectors: [`Vec2`], [`Vec3`], [`Vec3A`] and [`Vec4`] * square matrices: [`Mat2`], [`Mat3`], [`Mat3A`] and [`Mat4`] * a quaternion type: [`Quat`] * affine transformation types: [`Affine2`] and [`Affine3A`] * [`f64`](mod@f64) types * vectors: [`DVec2`], [`DVec3`] and [`DVec4`] * square matrices: [`DMat2`], [`DMat3`] and [`DMat4`] * a quaternion type: [`DQuat`] * affine transformation types: [`DAffine2`] and [`DAffine3`] * [`i8`](mod@i8) types * vectors: [`I8Vec2`], [`I8Vec3`] and [`I8Vec4`] * [`u8`](mod@u8) types * vectors: [`U8Vec2`], [`U8Vec3`] and [`U8Vec4`] * [`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`] * [`usize`](mod@usize) types * vectors: [`USizeVec2`], [`USizeVec3`] and [`USizeVec4`] * [`bool`](mod@bool) types * vectors: [`BVec2`], [`BVec3`] and [`BVec4`] ## SIMD `glam` is built with SIMD in mind. Many `f32` types use 128-bit SIMD vector types for storage and/or implementation. The use of SIMD generally enables better performance than using primitive numeric types such as `f32`. Some `glam` types use SIMD for storage meaning they are 16 byte aligned, these types include `Mat2`, `Mat3A`, `Mat4`, `Quat`, `Vec3A`, `Vec4`, `Affine2` an `Affine3A`. Types with an `A` suffix are a SIMD alternative to a scalar type, e.g. `Vec3` uses `f32` storage and `Vec3A` uses SIMD storage. When SIMD is not available on the target the types will maintain 16 byte alignment and internal padding so that object sizes and layouts will not change between architectures. There are scalar math fallback implementations exist when SIMD is not available. It is intended to add support for other SIMD architectures once they appear in stable Rust. Currently only SSE2 on x86/x86_64, NEON on Aarch64, and simd128 on WASM are supported. ## Vec3A and Mat3A `Vec3A` is a SIMD optimized version of the `Vec3` type, which due to 16 byte alignment results in `Vec3A` containing 4 bytes of padding making it 16 bytes in size in total. `Mat3A` is composed of three `Vec3A` columns. | Type | `f32` bytes | Align bytes | Size bytes | Padding | |:-----------|------------:|------------:|-----------:|--------:| |[`Vec3`] | 12| 4| 12| 0| |[`Vec3A`] | 12| 16| 16| 4| |[`Mat3`] | 36| 4| 36| 0| |[`Mat3A`] | 36| 16| 48| 12| Despite this wasted space the SIMD implementations tend to outperform `f32` implementations in [**mathbench**](https://github.com/bitshifter/mathbench-rs) benchmarks. `glam` treats [`Vec3`] as the default 3D vector type and [`Vec3A`] a special case for optimization. When methods need to return a 3D vector they will generally return [`Vec3`]. There are [`From`] trait implementations for converting from [`Vec4`] to a [`Vec3A`] and between [`Vec3`] and [`Vec3A`] (and vice versa). ``` use glam::{Vec3, Vec3A, Vec4}; let v4 = Vec4::new(1.0, 2.0, 3.0, 4.0); // Convert from `Vec4` to `Vec3A`, this is a no-op if SIMD is supported. // We use an explicit method here instead of a From impl as data is lost in the conversion. let v3a = Vec3A::from_vec4(v4); assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a); // Convert from `Vec3A` to `Vec3`. let v3 = Vec3::from(v3a); assert_eq!(Vec3::new(1.0, 2.0, 3.0), v3); // Convert from `Vec3` to `Vec3A`. let v3a = Vec3A::from(v3); assert_eq!(Vec3A::new(1.0, 2.0, 3.0), v3a); ``` ## Affine2 and Affine3A `Affine2` and `Affine3A` are composed of a linear transform matrix and a vector translation. The represent 2D and 3D affine transformations which are commonly used in games. The table below shows the performance advantage of `Affine2` over `Mat3A` and `Mat3A` over `Mat3`. | operation | `Mat3` | `Mat3A` | `Affine2` | |--------------------|-------------|------------|------------| | inverse | 11.4±0.09ns | 7.1±0.09ns | 5.4±0.06ns | | mul self | 10.5±0.04ns | 5.2±0.05ns | 4.0±0.05ns | | transform point2 | 2.7±0.02ns | 2.7±0.03ns | 2.8±0.04ns | | transform vector2 | 2.6±0.01ns | 2.6±0.03ns | 2.3±0.02ns | Performance is much closer between `Mat4` and `Affine3A` with the affine type being faster to invert. | operation | `Mat4` | `Affine3A` | |--------------------|-------------|-------------| | inverse | 15.9±0.11ns | 10.8±0.06ns | | mul self | 7.3±0.05ns | 7.0±0.06ns | | transform point3 | 3.6±0.02ns | 4.3±0.04ns | | transform point3a | 3.0±0.02ns | 3.0±0.04ns | | transform vector3 | 4.1±0.02ns | 3.9±0.04ns | | transform vector3a | 2.8±0.02ns | 2.8±0.02ns | Benchmarks were taken on an Intel Core i7-4710HQ. ## Linear algebra conventions `glam` interprets vectors as column matrices (also known as column vectors) meaning when transforming a vector with a matrix the matrix goes on the left. ``` use glam::{Mat3, Vec3}; let m = Mat3::IDENTITY; let x = Vec3::X; let v = m * x; assert_eq!(v, x); ``` Matrices are stored in memory in column-major order. All angles are in radians. Rust provides the `f32::to_radians()` and `f64::to_radians()` methods to convert from degrees. ## Direct element access Because some types may internally be implemented using SIMD types, direct access to vector elements is supported by implementing the [`Deref`] and [`DerefMut`] traits. ``` use glam::Vec3A; let mut v = Vec3A::new(1.0, 2.0, 3.0); assert_eq!(3.0, v.z); v.z += 1.0; assert_eq!(4.0, v.z); ``` [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html [`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html ## glam assertions `glam` does not enforce validity checks on method parameters at runtime. For example methods that require normalized vectors as input such as `Quat::from_axis_angle(axis, angle)` will not check that axis is a valid normalized vector. To help catch unintended misuse of `glam` the `debug-glam-assert` or `glam-assert` features can be enabled to add checks ensure that inputs to are valid. ## Vector swizzles `glam` vector types have functions allowing elements of vectors to be reordered, this includes creating a vector of a different size from the vectors elements. The swizzle functions are implemented using traits to add them to each vector type. This is primarily because there are a lot of swizzle functions which can obfuscate the other vector functions in documentation and so on. The traits are [`Vec2Swizzles`], [`Vec3Swizzles`] and [`Vec4Swizzles`]. Note that the [`Vec3Swizzles`] implementation for [`Vec3A`] will return a [`Vec3A`] for 3 element swizzles, all other implementations will return [`Vec3`]. ``` use glam::{swizzles::*, Vec2, Vec3, Vec3A, Vec4}; let v = Vec4::new(1.0, 2.0, 3.0, 4.0); // Reverse elements of `v`, if SIMD is supported this will use a vector shuffle. let wzyx = v.wzyx(); assert_eq!(Vec4::new(4.0, 3.0, 2.0, 1.0), wzyx); // Swizzle the yzw elements of `v` into a `Vec3` let yzw = v.yzw(); assert_eq!(Vec3::new(2.0, 3.0, 4.0), yzw); // To swizzle a `Vec4` into a `Vec3A` swizzle the `Vec4` first then convert to // `Vec3A`. If SIMD is supported this will use a vector shuffle. The last // element of the shuffled `Vec4` is ignored by the `Vec3A`. let yzw = Vec3A::from_vec4(v.yzwx()); assert_eq!(Vec3A::new(2.0, 3.0, 4.0), yzw); // You can swizzle from a `Vec4` to a `Vec2` let xy = v.xy(); assert_eq!(Vec2::new(1.0, 2.0), xy); // And back again let yyxx = xy.yyxx(); assert_eq!(Vec4::new(2.0, 2.0, 1.0, 1.0), yyxx); ``` ## SIMD and scalar consistency `glam` types implement `serde` `Serialize` and `Deserialize` traits to ensure that they will serialize and deserialize exactly the same whether or not SIMD support is being used. The SIMD versions implement the `core::fmt::Debug` and `core::fmt::Display` traits so they print the same as the scalar version. ``` use glam::Vec4; let a = Vec4::new(1.0, 2.0, 3.0, 4.0); assert_eq!(format!("{}", a), "[1, 2, 3, 4]"); ``` ## Feature gates All `glam` dependencies are optional, however some are required for tests and benchmarks. * `std` - the default feature, has no dependencies. * `approx` - traits and macros for approximate float comparisons * `bytemuck` - for casting into slices of bytes * `libm` - uses `libm` math functions instead of `std` * `nostd-libm` - uses `libm` math functions if `std` is not available * `mint` - for interoperating with other 3D math libraries * `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 `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 * `serde` - implementations of `Serialize` and `Deserialize` for all `glam` types. Note that serialization should work between builds of `glam` with and without SIMD enabled * `scalar-math` - disables SIMD support and uses native alignment for all types. * `debug-glam-assert` - adds assertions in debug builds which check the validity of parameters passed to `glam` to help catch runtime errors. * `glam-assert` - adds assertions to all builds which check the validity of parameters passed to `glam` to help catch runtime errors. * `cuda` - forces `glam` types to match expected cuda alignment * `fast-math` - By default, glam attempts to provide bit-for-bit identical results on all platforms. Using this feature will enable platform specific optimizations that may not be identical to other platforms. **Intermediate libraries should not use this feature and defer the decision to the final binary build**. * `core-simd` - enables SIMD support via the portable simd module. This is an unstable feature which requires a nightly Rust toolchain and `std` support. ## Minimum Supported Rust Version (MSRV) The minimum supported Rust version is `1.68.2`. */ #![doc(html_root_url = "https://docs.rs/glam/0.30.1")] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(target_arch = "spirv", feature(repr_simd))] #![deny( rust_2018_compatibility, rust_2018_idioms, future_incompatible, nonstandard_style )] // clippy doesn't like `to_array(&self)` #![allow(clippy::wrong_self_convention)] #![cfg_attr( all(feature = "core-simd", not(feature = "scalar-math")), feature(portable_simd) )] #[cfg(all( not(feature = "std"), not(feature = "libm"), not(feature = "nostd-libm") ))] compile_error!( "You must specify a math backend. Consider enabling either `std`, `libm`, or `nostd-libm`." ); #[macro_use] mod macros; mod align16; mod deref; mod euler; mod features; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod neon; #[cfg(target_arch = "spirv")] mod spirv; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod sse2; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod wasm32; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] mod coresimd; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] use align16::Align16; /** `bool` vector mask types. */ pub mod bool; pub use self::bool::*; /** `f32` vector, quaternion and matrix types. */ pub mod f32; pub use self::f32::*; /** `f64` vector, quaternion and matrix types. */ pub mod f64; pub use self::f64::*; /** `i8` vector types. */ pub mod i8; pub use self::i8::*; /** `u8` vector types. */ pub mod u8; pub use self::u8::*; /** `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::*; /** `u32` vector types. */ 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::*; /** `usize` vector types. */ pub mod usize; pub use self::usize::*; /** 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; glam-0.30.1/src/macros.rs000064400000000000000000000011131046102023000132420ustar 00000000000000#[cfg(any( all(debug_assertions, feature = "debug-glam-assert"), feature = "glam-assert" ))] macro_rules! glam_assert { ($($arg:tt)*) => ( assert!($($arg)*); ) } #[cfg(not(any( all(debug_assertions, feature = "debug-glam-assert"), feature = "glam-assert" )))] macro_rules! glam_assert { ($($arg:tt)*) => {}; } macro_rules! const_assert { ($x:expr $(,)?) => { #[allow(unknown_lints, clippy::eq_op)] const _: () = assert!($x); }; } macro_rules! const_assert_eq { ($x:expr, $y:expr $(,)?) => { const_assert!($x == $y); }; } glam-0.30.1/src/neon.rs000064400000000000000000000026431046102023000127260ustar 00000000000000use core::arch::aarch64::*; union UnionCast { // u32x4: [u32; 4], f32x4: [f32; 4], v: float32x4_t, } #[inline] pub const fn f32x4_from_array(f32x4: [f32; 4]) -> float32x4_t { unsafe { UnionCast { f32x4 }.v } } // #[inline] // pub(crate) unsafe fn dot3_in_x(lhs: float32x4_t, rhs: float32x4_t) -> float32x4_t { // let x2_y2_z2_w2 = vmulq_f32(lhs, rhs); // let y2 = vdupq_laneq_f32(x2_y2_z2_w2, 1); // let z2 = vdupq_laneq_f32(x2_y2_z2_w2, 2); // let x2y2 = vaddq_f32(x2_y2_z2_w2, y2); // vaddq_f32(x2y2, z2) // } #[inline] pub(crate) unsafe fn dot3(lhs: float32x4_t, rhs: float32x4_t) -> f32 { let x2_y2_z2_w2 = vmulq_f32(lhs, rhs); let x2_y2_z2 = vsetq_lane_f32(0.0, x2_y2_z2_w2, 3); vaddvq_f32(x2_y2_z2) // let dot = dot3_in_x(lhs, rhs); // vdups_laneq_f32(dot, 0) } #[inline] pub(crate) unsafe fn dot3_into_f32x4(lhs: float32x4_t, rhs: float32x4_t) -> float32x4_t { let dot = dot3(lhs, rhs); vld1q_dup_f32(&dot as *const f32) // let dot = dot3_in_x(lhs, rhs); // vdupq_laneq_f32(dot, 0) } #[inline] pub(crate) unsafe fn dot4(lhs: float32x4_t, rhs: float32x4_t) -> f32 { let x2_y2_z2_w2 = vmulq_f32(lhs, rhs); // TODO: horizontal add - might perform bad? vaddvq_f32(x2_y2_z2_w2) } #[inline] pub(crate) unsafe fn dot4_into_f32x4(lhs: float32x4_t, rhs: float32x4_t) -> float32x4_t { let dot = dot4(lhs, rhs); vld1q_dup_f32(&dot as *const f32) } glam-0.30.1/src/spirv.rs000064400000000000000000000010661046102023000131300ustar 00000000000000#[cfg(target_arch = "spirv")] macro_rules! unsupported_features { ($($feature:literal),+ $(,)?) => { $( #[cfg(feature = $feature)] compile_error!( concat!( "`", $feature, "`", " feature is not supported when building for SPIR-V.", ) ); )+ } } #[cfg(target_arch = "spirv")] unsupported_features! { "approx", "debug-glam-assert", "glam-assert", "rand", "serde", "std", } glam-0.30.1/src/sse2.rs000064400000000000000000000223261046102023000126430ustar 00000000000000#[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C)] union UnionCast { u32x4: [u32; 4], f32x4: [f32; 4], m128: __m128, } pub const fn m128_from_f32x4(f32x4: [f32; 4]) -> __m128 { unsafe { UnionCast { f32x4 }.m128 } } const fn m128_from_u32x4(u32x4: [u32; 4]) -> __m128 { 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]); const PS_NEGATIVE_ZERO: __m128 = m128_from_u32x4([0x8000_0000; 4]); const PS_PI: __m128 = m128_from_f32x4([core::f32::consts::PI; 4]); const PS_HALF_PI: __m128 = m128_from_f32x4([core::f32::consts::FRAC_PI_2; 4]); const PS_SIN_COEFFICIENTS0: __m128 = m128_from_f32x4([-0.16666667, 0.008_333_331, -0.00019840874, 2.752_556_2e-6]); const PS_SIN_COEFFICIENTS1: __m128 = m128_from_f32x4([ -2.388_985_9e-8, -0.16665852, /*Est1*/ 0.008_313_95, /*Est2*/ -0.000_185_246_7, /*Est3*/ ]); const PS_ONE: __m128 = m128_from_f32x4([1.0; 4]); const PS_TWO_PI: __m128 = m128_from_f32x4([core::f32::consts::TAU; 4]); const PS_RECIPROCAL_TWO_PI: __m128 = m128_from_f32x4([0.159_154_94; 4]); /// Calculates the vector 3 dot product and returns answer in x lane of __m128. #[inline(always)] pub(crate) unsafe fn dot3_in_x(lhs: __m128, rhs: __m128) -> __m128 { let x2_y2_z2_w2 = _mm_mul_ps(lhs, rhs); let y2_0_0_0 = _mm_shuffle_ps(x2_y2_z2_w2, x2_y2_z2_w2, 0b00_00_00_01); let z2_0_0_0 = _mm_shuffle_ps(x2_y2_z2_w2, x2_y2_z2_w2, 0b00_00_00_10); let x2y2_0_0_0 = _mm_add_ss(x2_y2_z2_w2, y2_0_0_0); _mm_add_ss(x2y2_0_0_0, z2_0_0_0) } /// Calculates the vector 4 dot product and returns answer in x lane of __m128. #[inline(always)] pub(crate) unsafe fn dot4_in_x(lhs: __m128, rhs: __m128) -> __m128 { let x2_y2_z2_w2 = _mm_mul_ps(lhs, rhs); let z2_w2_0_0 = _mm_shuffle_ps(x2_y2_z2_w2, x2_y2_z2_w2, 0b00_00_11_10); let x2z2_y2w2_0_0 = _mm_add_ps(x2_y2_z2_w2, z2_w2_0_0); let y2w2_0_0_0 = _mm_shuffle_ps(x2z2_y2w2_0_0, x2z2_y2w2_0_0, 0b00_00_00_01); _mm_add_ps(x2z2_y2w2_0_0, y2w2_0_0_0) } #[inline] pub(crate) unsafe fn dot3(lhs: __m128, rhs: __m128) -> f32 { _mm_cvtss_f32(dot3_in_x(lhs, rhs)) } #[inline] pub(crate) unsafe fn dot3_into_m128(lhs: __m128, rhs: __m128) -> __m128 { let dot_in_x = dot3_in_x(lhs, rhs); _mm_shuffle_ps(dot_in_x, dot_in_x, 0b00_00_00_00) } #[inline] pub(crate) unsafe fn dot4(lhs: __m128, rhs: __m128) -> f32 { _mm_cvtss_f32(dot4_in_x(lhs, rhs)) } #[inline] pub(crate) unsafe fn dot4_into_m128(lhs: __m128, rhs: __m128) -> __m128 { let dot_in_x = dot4_in_x(lhs, rhs); _mm_shuffle_ps(dot_in_x, dot_in_x, 0b00_00_00_00) } #[inline] pub(crate) unsafe fn m128_floor(v: __m128) -> __m128 { // Based on https://github.com/microsoft/DirectXMath `XMVectorFloor` // To handle NAN, INF and numbers greater than 8388608, use masking let test = _mm_and_si128(_mm_castps_si128(v), _mm_castps_si128(PS_INV_SIGN_MASK)); let test = _mm_cmplt_epi32(test, _mm_castps_si128(PS_NO_FRACTION)); // Truncate let vint = _mm_cvttps_epi32(v); let result = _mm_cvtepi32_ps(vint); let larger = _mm_cmpgt_ps(result, v); // 0 -> 0, 0xffffffff -> -1.0f let larger = _mm_cvtepi32_ps(_mm_castps_si128(larger)); let result = _mm_add_ps(result, larger); // All numbers less than 8388608 will use the round to int let result = _mm_and_ps(result, _mm_castsi128_ps(test)); // All others, use the ORIGINAL value let test = _mm_andnot_si128(test, _mm_castps_si128(v)); _mm_or_ps(result, _mm_castsi128_ps(test)) } #[inline] pub(crate) unsafe fn m128_ceil(v: __m128) -> __m128 { // Based on https://github.com/microsoft/DirectXMath `XMVectorCeil` // To handle NAN, INF and numbers greater than 8388608, use masking let test = _mm_and_si128(_mm_castps_si128(v), _mm_castps_si128(PS_INV_SIGN_MASK)); let test = _mm_cmplt_epi32(test, _mm_castps_si128(PS_NO_FRACTION)); // Truncate let vint = _mm_cvttps_epi32(v); let result = _mm_cvtepi32_ps(vint); let smaller = _mm_cmplt_ps(result, v); // 0 -> 0, 0xffffffff -> -1.0f let smaller = _mm_cvtepi32_ps(_mm_castps_si128(smaller)); let result = _mm_sub_ps(result, smaller); // All numbers less than 8388608 will use the round to int let result = _mm_and_ps(result, _mm_castsi128_ps(test)); // All others, use the ORIGINAL value let test = _mm_andnot_si128(test, _mm_castps_si128(v)); _mm_or_ps(result, _mm_castsi128_ps(test)) } #[inline] pub(crate) unsafe fn m128_abs(v: __m128) -> __m128 { _mm_and_ps(v, _mm_castsi128_ps(_mm_set1_epi32(0x7f_ff_ff_ff))) } #[inline(always)] pub(crate) unsafe fn m128_mul_add(a: __m128, b: __m128, c: __m128) -> __m128 { // Only enable fused multiply-adds here if "fast-math" is enabled and the // platform supports it. Otherwise this may break cross-platform determinism. #[cfg(all(feature = "fast-math", target_feature = "fma"))] { _mm_fmadd_ps(a, b, c) } #[cfg(any(not(feature = "fast-math"), not(target_feature = "fma")))] { _mm_add_ps(_mm_mul_ps(a, b), c) } } #[inline(always)] pub(crate) unsafe fn m128_neg_mul_sub(a: __m128, b: __m128, c: __m128) -> __m128 { _mm_sub_ps(c, _mm_mul_ps(a, b)) } #[inline] pub(crate) unsafe fn m128_round(v: __m128) -> __m128 { // Based on https://github.com/microsoft/DirectXMath `XMVectorRound` let sign = _mm_and_ps(v, PS_SIGN_MASK); let s_magic = _mm_or_ps(PS_NO_FRACTION, sign); let r1 = _mm_add_ps(v, s_magic); let r1 = _mm_sub_ps(r1, s_magic); let r2 = _mm_and_ps(v, PS_INV_SIGN_MASK); let mask = _mm_cmple_ps(r2, PS_NO_FRACTION); let r2 = _mm_andnot_ps(mask, v); let r1 = _mm_and_ps(r1, mask); _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 { // Based on https://github.com/microsoft/DirectXMath `XMVectorModAngles` let v = _mm_mul_ps(angles, PS_RECIPROCAL_TWO_PI); let v = m128_round(v); m128_neg_mul_sub(PS_TWO_PI, v, angles) } /// Computes the sine of the angle in each lane of `v`. Values outside /// the bounds of PI may produce an increasing error as the input angle /// drifts from `[-PI, PI]`. #[inline] pub(crate) unsafe fn m128_sin(v: __m128) -> __m128 { // Based on https://github.com/microsoft/DirectXMath `XMVectorSin` // 11-degree minimax approximation // Force the value within the bounds of pi let mut x = m128_mod_angles(v); // Map in [-pi/2,pi/2] with sin(y) = sin(x). let sign = _mm_and_ps(x, PS_NEGATIVE_ZERO); // pi when x >= 0, -pi when x < 0 let c = _mm_or_ps(PS_PI, sign); // |x| let absx = _mm_andnot_ps(sign, x); let rflx = _mm_sub_ps(c, x); let comp = _mm_cmple_ps(absx, PS_HALF_PI); let select0 = _mm_and_ps(comp, x); let select1 = _mm_andnot_ps(comp, rflx); x = _mm_or_ps(select0, select1); let x2 = _mm_mul_ps(x, x); // Compute polynomial approximation const SC1: __m128 = PS_SIN_COEFFICIENTS1; let v_constants_b = _mm_shuffle_ps(SC1, SC1, 0b00_00_00_00); const SC0: __m128 = PS_SIN_COEFFICIENTS0; let mut v_constants = _mm_shuffle_ps(SC0, SC0, 0b11_11_11_11); let mut result = m128_mul_add(v_constants_b, x2, v_constants); v_constants = _mm_shuffle_ps(SC0, SC0, 0b10_10_10_10); result = m128_mul_add(result, x2, v_constants); v_constants = _mm_shuffle_ps(SC0, SC0, 0b01_01_01_01); result = m128_mul_add(result, x2, v_constants); v_constants = _mm_shuffle_ps(SC0, SC0, 0b00_00_00_00); result = m128_mul_add(result, x2, v_constants); result = m128_mul_add(result, x2, PS_ONE); result = _mm_mul_ps(result, x); result } #[test] fn test_sse2_m128_sin() { use crate::Vec4; use core::f32::consts::PI; fn test_sse2_m128_sin_angle(a: f32) { let v = unsafe { m128_sin(_mm_set_ps1(a)) }; let v = Vec4(v); let a_sin = a.sin(); // dbg!((a, a_sin, v)); assert!(v.abs_diff_eq(Vec4::splat(a_sin), 1e-6)); } let mut a = -PI; let end = PI; let step = PI / 8192.0; while a <= end { test_sse2_m128_sin_angle(a); a += step; } } glam-0.30.1/src/swizzles/coresimd/vec3a_impl.rs000064400000000000000000000345651046102023000175200ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. #![allow(clippy::useless_conversion)] use crate::{Vec2, Vec3A, Vec3Swizzles, Vec4}; use core::simd::*; impl Vec3Swizzles for Vec3A { type Vec2 = Vec2; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[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 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])) } } glam-0.30.1/src/swizzles/coresimd/vec4_impl.rs000064400000000000000000001241331046102023000173470ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. #![allow(clippy::useless_conversion)] use crate::{Vec2, Vec3, Vec4, Vec4Swizzles}; use core::simd::*; impl Vec4Swizzles for Vec4 { type Vec2 = Vec2; type Vec3 = Vec3; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> Vec2 { Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> Vec2 { Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> Vec2 { Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> Vec2 { Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> Vec2 { Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> Vec2 { Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> Vec2 { Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3 { Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> Vec3 { Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> Vec3 { Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> Vec3 { Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> Vec3 { Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3 { Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> Vec3 { Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> Vec3 { Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> Vec3 { Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> Vec3 { Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> Vec3 { Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> Vec3 { Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3 { Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> Vec3 { Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3 { Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> Vec3 { Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> Vec3 { Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> Vec3 { Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3 { Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> Vec3 { Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> Vec3 { Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> Vec3 { Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> Vec3 { Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> Vec3 { Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> Vec3 { Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3 { Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> Vec3 { Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> Vec3 { Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> Vec3 { Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> Vec3 { Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3 { Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> Vec3 { Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> Vec3 { Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3 { Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3 { Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> Vec3 { Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> Vec3 { Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> Vec3 { Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> Vec3 { Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> Vec3 { Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> Vec3 { Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> Vec3 { Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> Vec3 { Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> Vec3 { Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> Vec3 { Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> Vec3 { Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> Vec3 { Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> Vec3 { Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> Vec3 { Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> Vec3 { Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> Vec3 { Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> Vec3 { Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> Vec3 { Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> Vec3 { Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> Vec3 { Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> Vec3 { Vec3::new(self.w, self.w, self.w) } #[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 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])) } } glam-0.30.1/src/swizzles/coresimd.rs000064400000000000000000000000371046102023000154610ustar 00000000000000mod vec3a_impl; mod vec4_impl; glam-0.30.1/src/swizzles/dvec2_impl.rs000064400000000000000000000064451046102023000157110ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{DVec2, DVec3, DVec4, Vec2Swizzles}; impl Vec2Swizzles for DVec2 { type Vec3 = DVec3; type Vec4 = DVec4; #[inline] #[must_use] fn xx(self) -> DVec2 { DVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> DVec2 { DVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> DVec2 { DVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> DVec3 { DVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> DVec3 { DVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> DVec3 { DVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> DVec3 { DVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> DVec3 { DVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> DVec3 { DVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> DVec3 { DVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> DVec3 { DVec3::new(self.y, self.y, self.y) } #[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) } } glam-0.30.1/src/swizzles/dvec3_impl.rs000064400000000000000000000341621046102023000157070ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{DVec2, DVec3, DVec4, Vec3Swizzles}; impl Vec3Swizzles for DVec3 { type Vec2 = DVec2; type Vec4 = DVec4; #[inline] #[must_use] fn xx(self) -> DVec2 { DVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> DVec2 { DVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: DVec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> DVec2 { DVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: DVec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> DVec2 { DVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: DVec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> DVec2 { DVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> DVec2 { DVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: DVec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> DVec2 { DVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: DVec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> DVec2 { DVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: DVec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> DVec2 { DVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> DVec3 { DVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> DVec3 { DVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> DVec3 { DVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> DVec3 { DVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> DVec3 { DVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> DVec3 { DVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> DVec3 { DVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> DVec3 { DVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> DVec3 { DVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> DVec3 { DVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> DVec3 { DVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> DVec3 { DVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> DVec3 { DVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> DVec3 { DVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> DVec3 { DVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> DVec3 { DVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> DVec3 { DVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> DVec3 { DVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> DVec3 { DVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> DVec3 { DVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> DVec3 { DVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> DVec3 { DVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> DVec3 { DVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> DVec3 { DVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> DVec3 { DVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> DVec3 { DVec3::new(self.z, self.z, self.z) } #[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) } } glam-0.30.1/src/swizzles/dvec4_impl.rs000064400000000000000000001253501046102023000157100ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{DVec2, DVec3, DVec4, Vec4Swizzles}; impl Vec4Swizzles for DVec4 { type Vec2 = DVec2; type Vec3 = DVec3; #[inline] #[must_use] fn xx(self) -> DVec2 { DVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> DVec2 { DVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: DVec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> DVec2 { DVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: DVec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> DVec2 { DVec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: DVec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> DVec2 { DVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: DVec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> DVec2 { DVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> DVec2 { DVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: DVec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> DVec2 { DVec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: DVec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> DVec2 { DVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: DVec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> DVec2 { DVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: DVec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> DVec2 { DVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> DVec2 { DVec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: DVec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> DVec2 { DVec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: DVec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> DVec2 { DVec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: DVec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> DVec2 { DVec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: DVec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> DVec2 { DVec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> DVec3 { DVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> DVec3 { DVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> DVec3 { DVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> DVec3 { DVec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> DVec3 { DVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> DVec3 { DVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> DVec3 { DVec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: DVec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> DVec3 { DVec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: DVec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> DVec3 { DVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> DVec3 { DVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: DVec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> DVec3 { DVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> DVec3 { DVec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: DVec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> DVec3 { DVec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> DVec3 { DVec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: DVec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> DVec3 { DVec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: DVec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> DVec3 { DVec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> DVec3 { DVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> DVec3 { DVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> DVec3 { DVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: DVec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> DVec3 { DVec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: DVec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> DVec3 { DVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> DVec3 { DVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> DVec3 { DVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> DVec3 { DVec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> DVec3 { DVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: DVec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> DVec3 { DVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> DVec3 { DVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> DVec3 { DVec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: DVec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> DVec3 { DVec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: DVec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> DVec3 { DVec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> DVec3 { DVec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: DVec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> DVec3 { DVec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> DVec3 { DVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> DVec3 { DVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: DVec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> DVec3 { DVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> DVec3 { DVec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: DVec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> DVec3 { DVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: DVec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> DVec3 { DVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> DVec3 { DVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> DVec3 { DVec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: DVec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> DVec3 { DVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> DVec3 { DVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> DVec3 { DVec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> DVec3 { DVec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> DVec3 { DVec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: DVec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> DVec3 { DVec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: DVec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> DVec3 { DVec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> DVec3 { DVec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> DVec3 { DVec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> DVec3 { DVec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: DVec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> DVec3 { DVec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: DVec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> DVec3 { DVec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> DVec3 { DVec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: DVec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> DVec3 { DVec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> DVec3 { DVec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: DVec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> DVec3 { DVec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> DVec3 { DVec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: DVec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> DVec3 { DVec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: DVec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> DVec3 { DVec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> DVec3 { DVec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> DVec3 { DVec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> DVec3 { DVec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> DVec3 { DVec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> DVec3 { DVec3::new(self.w, self.w, self.w) } #[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 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) } } glam-0.30.1/src/swizzles/i16vec2_impl.rs000064400000000000000000000066351046102023000160660ustar 00000000000000// 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 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::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, 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) } } glam-0.30.1/src/swizzles/i16vec3_impl.rs000064400000000000000000000351321046102023000160610ustar 00000000000000// 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 with_xy(self, rhs: I16Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> I16Vec2 { I16Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: I16Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> I16Vec2 { I16Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: I16Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[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 with_yz(self, rhs: I16Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> I16Vec2 { I16Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: I16Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> I16Vec2 { I16Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: I16Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> I16Vec2 { I16Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> I16Vec3 { I16Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> I16Vec3 { I16Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> I16Vec3 { I16Vec3::new(self.z, self.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) } } glam-0.30.1/src/swizzles/i16vec4_impl.rs000064400000000000000000001301701046102023000160600ustar 00000000000000// 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 with_xy(self, rhs: I16Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> I16Vec2 { I16Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: I16Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> I16Vec2 { I16Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: I16Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> I16Vec2 { I16Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: I16Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[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 with_yz(self, rhs: I16Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> I16Vec2 { I16Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: I16Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> I16Vec2 { I16Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: I16Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> I16Vec2 { I16Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: I16Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[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 with_zw(self, rhs: I16Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> I16Vec2 { I16Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: I16Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> I16Vec2 { I16Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: I16Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> I16Vec2 { I16Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: I16Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> I16Vec2 { I16Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> I16Vec3 { I16Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: I16Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> I16Vec3 { I16Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: I16Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: I16Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> I16Vec3 { I16Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: I16Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> I16Vec3 { I16Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> I16Vec3 { I16Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: I16Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> I16Vec3 { I16Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: I16Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> I16Vec3 { I16Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: I16Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> I16Vec3 { I16Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: I16Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> I16Vec3 { I16Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: I16Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> I16Vec3 { I16Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: I16Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> I16Vec3 { I16Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: I16Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> I16Vec3 { I16Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> I16Vec3 { I16Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: I16Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> I16Vec3 { I16Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: I16Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> I16Vec3 { I16Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: I16Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: I16Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> I16Vec3 { I16Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: I16Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> I16Vec3 { I16Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> I16Vec3 { I16Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> I16Vec3 { I16Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> I16Vec3 { I16Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> I16Vec3 { I16Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: I16Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> I16Vec3 { I16Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: I16Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> I16Vec3 { I16Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> I16Vec3 { I16Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> I16Vec3 { I16Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> I16Vec3 { I16Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: I16Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> I16Vec3 { I16Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: I16Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> I16Vec3 { I16Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> I16Vec3 { I16Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: I16Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> I16Vec3 { I16Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> I16Vec3 { I16Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: I16Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> I16Vec3 { I16Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> I16Vec3 { I16Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: I16Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> I16Vec3 { I16Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: I16Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> I16Vec3 { I16Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> I16Vec3 { I16Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> I16Vec3 { I16Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> I16Vec3 { I16Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> I16Vec3 { I16Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> I16Vec3 { I16Vec3::new(self.w, self.w, 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 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) } } glam-0.30.1/src/swizzles/i64vec2_impl.rs000064400000000000000000000066351046102023000160710ustar 00000000000000// 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 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::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, 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) } } glam-0.30.1/src/swizzles/i64vec3_impl.rs000064400000000000000000000351321046102023000160640ustar 00000000000000// 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 with_xy(self, rhs: I64Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> I64Vec2 { I64Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: I64Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> I64Vec2 { I64Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: I64Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[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 with_yz(self, rhs: I64Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> I64Vec2 { I64Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: I64Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> I64Vec2 { I64Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: I64Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> I64Vec2 { I64Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> I64Vec3 { I64Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> I64Vec3 { I64Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> I64Vec3 { I64Vec3::new(self.z, self.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) } } glam-0.30.1/src/swizzles/i64vec4_impl.rs000064400000000000000000001301701046102023000160630ustar 00000000000000// 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 with_xy(self, rhs: I64Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> I64Vec2 { I64Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: I64Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> I64Vec2 { I64Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: I64Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> I64Vec2 { I64Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: I64Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[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 with_yz(self, rhs: I64Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> I64Vec2 { I64Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: I64Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> I64Vec2 { I64Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: I64Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> I64Vec2 { I64Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: I64Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[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 with_zw(self, rhs: I64Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> I64Vec2 { I64Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: I64Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> I64Vec2 { I64Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: I64Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> I64Vec2 { I64Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: I64Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> I64Vec2 { I64Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> I64Vec3 { I64Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: I64Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> I64Vec3 { I64Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: I64Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: I64Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> I64Vec3 { I64Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: I64Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> I64Vec3 { I64Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> I64Vec3 { I64Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: I64Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> I64Vec3 { I64Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: I64Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> I64Vec3 { I64Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: I64Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> I64Vec3 { I64Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: I64Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> I64Vec3 { I64Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: I64Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> I64Vec3 { I64Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: I64Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> I64Vec3 { I64Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: I64Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> I64Vec3 { I64Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> I64Vec3 { I64Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: I64Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> I64Vec3 { I64Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: I64Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> I64Vec3 { I64Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: I64Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: I64Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> I64Vec3 { I64Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: I64Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> I64Vec3 { I64Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> I64Vec3 { I64Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> I64Vec3 { I64Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> I64Vec3 { I64Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> I64Vec3 { I64Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: I64Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> I64Vec3 { I64Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: I64Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> I64Vec3 { I64Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> I64Vec3 { I64Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> I64Vec3 { I64Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> I64Vec3 { I64Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: I64Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> I64Vec3 { I64Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: I64Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> I64Vec3 { I64Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> I64Vec3 { I64Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: I64Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> I64Vec3 { I64Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> I64Vec3 { I64Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: I64Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> I64Vec3 { I64Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> I64Vec3 { I64Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: I64Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> I64Vec3 { I64Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: I64Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> I64Vec3 { I64Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> I64Vec3 { I64Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> I64Vec3 { I64Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> I64Vec3 { I64Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> I64Vec3 { I64Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> I64Vec3 { I64Vec3::new(self.w, self.w, 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 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) } } glam-0.30.1/src/swizzles/i8vec2_impl.rs000064400000000000000000000065411046102023000160030ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{I8Vec2, I8Vec3, I8Vec4, Vec2Swizzles}; impl Vec2Swizzles for I8Vec2 { type Vec3 = I8Vec3; type Vec4 = I8Vec4; #[inline] #[must_use] fn xx(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn xxxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xyxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn yxxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yyxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.y) } } glam-0.30.1/src/swizzles/i8vec3_impl.rs000064400000000000000000000345461046102023000160120ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{I8Vec2, I8Vec3, I8Vec4, Vec3Swizzles}; impl Vec3Swizzles for I8Vec3 { type Vec2 = I8Vec2; type Vec4 = I8Vec4; #[inline] #[must_use] fn xx(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: I8Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: I8Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: I8Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: I8Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: I8Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: I8Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn xxxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.z) } #[inline] #[must_use] fn xxyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xxyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.z) } #[inline] #[must_use] fn xxzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.x) } #[inline] #[must_use] fn xxzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.y) } #[inline] #[must_use] fn xxzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.z) } #[inline] #[must_use] fn xyxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.z) } #[inline] #[must_use] fn xyyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn xyyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.z) } #[inline] #[must_use] fn xyzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.z, self.x) } #[inline] #[must_use] fn xyzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.z, self.y) } #[inline] #[must_use] fn xyzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.z, self.z) } #[inline] #[must_use] fn xzxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.x) } #[inline] #[must_use] fn xzxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.y) } #[inline] #[must_use] fn xzxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.z) } #[inline] #[must_use] fn xzyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.x) } #[inline] #[must_use] fn xzyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.y) } #[inline] #[must_use] fn xzyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.z) } #[inline] #[must_use] fn xzzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.x) } #[inline] #[must_use] fn xzzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.y) } #[inline] #[must_use] fn xzzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.z) } #[inline] #[must_use] fn yxxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.z) } #[inline] #[must_use] fn yxyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yxyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.z) } #[inline] #[must_use] fn yxzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.x) } #[inline] #[must_use] fn yxzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.y) } #[inline] #[must_use] fn yxzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.z) } #[inline] #[must_use] fn yyxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.z) } #[inline] #[must_use] fn yyyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.y) } #[inline] #[must_use] fn yyyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.z) } #[inline] #[must_use] fn yyzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.x) } #[inline] #[must_use] fn yyzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.y) } #[inline] #[must_use] fn yyzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.z) } #[inline] #[must_use] fn yzxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.x) } #[inline] #[must_use] fn yzxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.y) } #[inline] #[must_use] fn yzxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.z) } #[inline] #[must_use] fn yzyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.x) } #[inline] #[must_use] fn yzyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.y) } #[inline] #[must_use] fn yzyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.z) } #[inline] #[must_use] fn yzzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.x) } #[inline] #[must_use] fn yzzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.y) } #[inline] #[must_use] fn yzzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.z) } #[inline] #[must_use] fn zxxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.x) } #[inline] #[must_use] fn zxxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.y) } #[inline] #[must_use] fn zxxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.z) } #[inline] #[must_use] fn zxyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.x) } #[inline] #[must_use] fn zxyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.y) } #[inline] #[must_use] fn zxyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.z) } #[inline] #[must_use] fn zxzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.x) } #[inline] #[must_use] fn zxzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.y) } #[inline] #[must_use] fn zxzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.z) } #[inline] #[must_use] fn zyxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.x) } #[inline] #[must_use] fn zyxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.y) } #[inline] #[must_use] fn zyxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.z) } #[inline] #[must_use] fn zyyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.x) } #[inline] #[must_use] fn zyyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.y) } #[inline] #[must_use] fn zyyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.z) } #[inline] #[must_use] fn zyzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.x) } #[inline] #[must_use] fn zyzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.y) } #[inline] #[must_use] fn zyzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.z) } #[inline] #[must_use] fn zzxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.x) } #[inline] #[must_use] fn zzxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.y) } #[inline] #[must_use] fn zzxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.z) } #[inline] #[must_use] fn zzyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.x) } #[inline] #[must_use] fn zzyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.y) } #[inline] #[must_use] fn zzyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.z) } #[inline] #[must_use] fn zzzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.x) } #[inline] #[must_use] fn zzzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.y) } #[inline] #[must_use] fn zzzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.z) } } glam-0.30.1/src/swizzles/i8vec4_impl.rs000064400000000000000000001266601046102023000160120ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{I8Vec2, I8Vec3, I8Vec4, Vec4Swizzles}; impl Vec4Swizzles for I8Vec4 { type Vec2 = I8Vec2; type Vec3 = I8Vec3; #[inline] #[must_use] fn xx(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: I8Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: I8Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> I8Vec2 { I8Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: I8Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: I8Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: I8Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> I8Vec2 { I8Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: I8Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: I8Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: I8Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> I8Vec2 { I8Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: I8Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> I8Vec2 { I8Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: I8Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> I8Vec2 { I8Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: I8Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> I8Vec2 { I8Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: I8Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> I8Vec2 { I8Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> I8Vec3 { I8Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: I8Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> I8Vec3 { I8Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: I8Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: I8Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> I8Vec3 { I8Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: I8Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> I8Vec3 { I8Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> I8Vec3 { I8Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: I8Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> I8Vec3 { I8Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: I8Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> I8Vec3 { I8Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: I8Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> I8Vec3 { I8Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: I8Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> I8Vec3 { I8Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: I8Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> I8Vec3 { I8Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: I8Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> I8Vec3 { I8Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: I8Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> I8Vec3 { I8Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> I8Vec3 { I8Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: I8Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> I8Vec3 { I8Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: I8Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> I8Vec3 { I8Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: I8Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: I8Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> I8Vec3 { I8Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: I8Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> I8Vec3 { I8Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> I8Vec3 { I8Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: I8Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> I8Vec3 { I8Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: I8Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> I8Vec3 { I8Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> I8Vec3 { I8Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> I8Vec3 { I8Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> I8Vec3 { I8Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: I8Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> I8Vec3 { I8Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: I8Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> I8Vec3 { I8Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> I8Vec3 { I8Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: I8Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> I8Vec3 { I8Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> I8Vec3 { I8Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: I8Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> I8Vec3 { I8Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> I8Vec3 { I8Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: I8Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> I8Vec3 { I8Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: I8Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> I8Vec3 { I8Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> I8Vec3 { I8Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> I8Vec3 { I8Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> I8Vec3 { I8Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> I8Vec3 { I8Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> I8Vec3 { I8Vec3::new(self.w, self.w, self.w) } #[inline] #[must_use] fn xxxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.z) } #[inline] #[must_use] fn xxxw(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.x, self.w) } #[inline] #[must_use] fn xxyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xxyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.z) } #[inline] #[must_use] fn xxyw(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.y, self.w) } #[inline] #[must_use] fn xxzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.x) } #[inline] #[must_use] fn xxzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.y) } #[inline] #[must_use] fn xxzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.z) } #[inline] #[must_use] fn xxzw(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.z, self.w) } #[inline] #[must_use] fn xxwx(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.w, self.x) } #[inline] #[must_use] fn xxwy(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.w, self.y) } #[inline] #[must_use] fn xxwz(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.w, self.z) } #[inline] #[must_use] fn xxww(self) -> I8Vec4 { I8Vec4::new(self.x, self.x, self.w, self.w) } #[inline] #[must_use] fn xyxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.z) } #[inline] #[must_use] fn xyxw(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.x, self.w) } #[inline] #[must_use] fn xyyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn xyyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.z) } #[inline] #[must_use] fn xyyw(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.y, self.w) } #[inline] #[must_use] fn xyzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.z, self.x) } #[inline] #[must_use] fn xyzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.z, self.y) } #[inline] #[must_use] fn xyzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.z, self.z) } #[inline] #[must_use] fn xywx(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.w, self.x) } #[inline] #[must_use] fn xywy(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.w, self.y) } #[inline] #[must_use] fn xywz(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.w, self.z) } #[inline] #[must_use] fn xyww(self) -> I8Vec4 { I8Vec4::new(self.x, self.y, self.w, self.w) } #[inline] #[must_use] fn xzxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.x) } #[inline] #[must_use] fn xzxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.y) } #[inline] #[must_use] fn xzxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.z) } #[inline] #[must_use] fn xzxw(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.x, self.w) } #[inline] #[must_use] fn xzyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.x) } #[inline] #[must_use] fn xzyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.y) } #[inline] #[must_use] fn xzyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.z) } #[inline] #[must_use] fn xzyw(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.y, self.w) } #[inline] #[must_use] fn xzzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.x) } #[inline] #[must_use] fn xzzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.y) } #[inline] #[must_use] fn xzzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.z) } #[inline] #[must_use] fn xzzw(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.z, self.w) } #[inline] #[must_use] fn xzwx(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.w, self.x) } #[inline] #[must_use] fn xzwy(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.w, self.y) } #[inline] #[must_use] fn xzwz(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.w, self.z) } #[inline] #[must_use] fn xzww(self) -> I8Vec4 { I8Vec4::new(self.x, self.z, self.w, self.w) } #[inline] #[must_use] fn xwxx(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.x, self.x) } #[inline] #[must_use] fn xwxy(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.x, self.y) } #[inline] #[must_use] fn xwxz(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.x, self.z) } #[inline] #[must_use] fn xwxw(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.x, self.w) } #[inline] #[must_use] fn xwyx(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.y, self.x) } #[inline] #[must_use] fn xwyy(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.y, self.y) } #[inline] #[must_use] fn xwyz(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.y, self.z) } #[inline] #[must_use] fn xwyw(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.y, self.w) } #[inline] #[must_use] fn xwzx(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.z, self.x) } #[inline] #[must_use] fn xwzy(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.z, self.y) } #[inline] #[must_use] fn xwzz(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.z, self.z) } #[inline] #[must_use] fn xwzw(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.z, self.w) } #[inline] #[must_use] fn xwwx(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.w, self.x) } #[inline] #[must_use] fn xwwy(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.w, self.y) } #[inline] #[must_use] fn xwwz(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.w, self.z) } #[inline] #[must_use] fn xwww(self) -> I8Vec4 { I8Vec4::new(self.x, self.w, self.w, self.w) } #[inline] #[must_use] fn yxxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.z) } #[inline] #[must_use] fn yxxw(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.x, self.w) } #[inline] #[must_use] fn yxyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yxyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.z) } #[inline] #[must_use] fn yxyw(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.y, self.w) } #[inline] #[must_use] fn yxzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.x) } #[inline] #[must_use] fn yxzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.y) } #[inline] #[must_use] fn yxzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.z) } #[inline] #[must_use] fn yxzw(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.z, self.w) } #[inline] #[must_use] fn yxwx(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.w, self.x) } #[inline] #[must_use] fn yxwy(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.w, self.y) } #[inline] #[must_use] fn yxwz(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.w, self.z) } #[inline] #[must_use] fn yxww(self) -> I8Vec4 { I8Vec4::new(self.y, self.x, self.w, self.w) } #[inline] #[must_use] fn yyxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.z) } #[inline] #[must_use] fn yyxw(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.x, self.w) } #[inline] #[must_use] fn yyyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.y) } #[inline] #[must_use] fn yyyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.z) } #[inline] #[must_use] fn yyyw(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.y, self.w) } #[inline] #[must_use] fn yyzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.x) } #[inline] #[must_use] fn yyzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.y) } #[inline] #[must_use] fn yyzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.z) } #[inline] #[must_use] fn yyzw(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.z, self.w) } #[inline] #[must_use] fn yywx(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.w, self.x) } #[inline] #[must_use] fn yywy(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.w, self.y) } #[inline] #[must_use] fn yywz(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.w, self.z) } #[inline] #[must_use] fn yyww(self) -> I8Vec4 { I8Vec4::new(self.y, self.y, self.w, self.w) } #[inline] #[must_use] fn yzxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.x) } #[inline] #[must_use] fn yzxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.y) } #[inline] #[must_use] fn yzxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.z) } #[inline] #[must_use] fn yzxw(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.x, self.w) } #[inline] #[must_use] fn yzyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.x) } #[inline] #[must_use] fn yzyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.y) } #[inline] #[must_use] fn yzyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.z) } #[inline] #[must_use] fn yzyw(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.y, self.w) } #[inline] #[must_use] fn yzzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.x) } #[inline] #[must_use] fn yzzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.y) } #[inline] #[must_use] fn yzzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.z) } #[inline] #[must_use] fn yzzw(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.z, self.w) } #[inline] #[must_use] fn yzwx(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.w, self.x) } #[inline] #[must_use] fn yzwy(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.w, self.y) } #[inline] #[must_use] fn yzwz(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.w, self.z) } #[inline] #[must_use] fn yzww(self) -> I8Vec4 { I8Vec4::new(self.y, self.z, self.w, self.w) } #[inline] #[must_use] fn ywxx(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.x, self.x) } #[inline] #[must_use] fn ywxy(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.x, self.y) } #[inline] #[must_use] fn ywxz(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.x, self.z) } #[inline] #[must_use] fn ywxw(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.x, self.w) } #[inline] #[must_use] fn ywyx(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.y, self.x) } #[inline] #[must_use] fn ywyy(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.y, self.y) } #[inline] #[must_use] fn ywyz(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.y, self.z) } #[inline] #[must_use] fn ywyw(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.y, self.w) } #[inline] #[must_use] fn ywzx(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.z, self.x) } #[inline] #[must_use] fn ywzy(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.z, self.y) } #[inline] #[must_use] fn ywzz(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.z, self.z) } #[inline] #[must_use] fn ywzw(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.z, self.w) } #[inline] #[must_use] fn ywwx(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.w, self.x) } #[inline] #[must_use] fn ywwy(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.w, self.y) } #[inline] #[must_use] fn ywwz(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.w, self.z) } #[inline] #[must_use] fn ywww(self) -> I8Vec4 { I8Vec4::new(self.y, self.w, self.w, self.w) } #[inline] #[must_use] fn zxxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.x) } #[inline] #[must_use] fn zxxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.y) } #[inline] #[must_use] fn zxxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.z) } #[inline] #[must_use] fn zxxw(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.x, self.w) } #[inline] #[must_use] fn zxyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.x) } #[inline] #[must_use] fn zxyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.y) } #[inline] #[must_use] fn zxyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.z) } #[inline] #[must_use] fn zxyw(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.y, self.w) } #[inline] #[must_use] fn zxzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.x) } #[inline] #[must_use] fn zxzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.y) } #[inline] #[must_use] fn zxzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.z) } #[inline] #[must_use] fn zxzw(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.z, self.w) } #[inline] #[must_use] fn zxwx(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.w, self.x) } #[inline] #[must_use] fn zxwy(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.w, self.y) } #[inline] #[must_use] fn zxwz(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.w, self.z) } #[inline] #[must_use] fn zxww(self) -> I8Vec4 { I8Vec4::new(self.z, self.x, self.w, self.w) } #[inline] #[must_use] fn zyxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.x) } #[inline] #[must_use] fn zyxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.y) } #[inline] #[must_use] fn zyxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.z) } #[inline] #[must_use] fn zyxw(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.x, self.w) } #[inline] #[must_use] fn zyyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.x) } #[inline] #[must_use] fn zyyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.y) } #[inline] #[must_use] fn zyyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.z) } #[inline] #[must_use] fn zyyw(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.y, self.w) } #[inline] #[must_use] fn zyzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.x) } #[inline] #[must_use] fn zyzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.y) } #[inline] #[must_use] fn zyzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.z) } #[inline] #[must_use] fn zyzw(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.z, self.w) } #[inline] #[must_use] fn zywx(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.w, self.x) } #[inline] #[must_use] fn zywy(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.w, self.y) } #[inline] #[must_use] fn zywz(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.w, self.z) } #[inline] #[must_use] fn zyww(self) -> I8Vec4 { I8Vec4::new(self.z, self.y, self.w, self.w) } #[inline] #[must_use] fn zzxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.x) } #[inline] #[must_use] fn zzxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.y) } #[inline] #[must_use] fn zzxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.z) } #[inline] #[must_use] fn zzxw(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.x, self.w) } #[inline] #[must_use] fn zzyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.x) } #[inline] #[must_use] fn zzyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.y) } #[inline] #[must_use] fn zzyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.z) } #[inline] #[must_use] fn zzyw(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.y, self.w) } #[inline] #[must_use] fn zzzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.x) } #[inline] #[must_use] fn zzzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.y) } #[inline] #[must_use] fn zzzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.z) } #[inline] #[must_use] fn zzzw(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.z, self.w) } #[inline] #[must_use] fn zzwx(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.w, self.x) } #[inline] #[must_use] fn zzwy(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.w, self.y) } #[inline] #[must_use] fn zzwz(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.w, self.z) } #[inline] #[must_use] fn zzww(self) -> I8Vec4 { I8Vec4::new(self.z, self.z, self.w, self.w) } #[inline] #[must_use] fn zwxx(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.x, self.x) } #[inline] #[must_use] fn zwxy(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.x, self.y) } #[inline] #[must_use] fn zwxz(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.x, self.z) } #[inline] #[must_use] fn zwxw(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.x, self.w) } #[inline] #[must_use] fn zwyx(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.y, self.x) } #[inline] #[must_use] fn zwyy(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.y, self.y) } #[inline] #[must_use] fn zwyz(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.y, self.z) } #[inline] #[must_use] fn zwyw(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.y, self.w) } #[inline] #[must_use] fn zwzx(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.z, self.x) } #[inline] #[must_use] fn zwzy(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.z, self.y) } #[inline] #[must_use] fn zwzz(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.z, self.z) } #[inline] #[must_use] fn zwzw(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.z, self.w) } #[inline] #[must_use] fn zwwx(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.w, self.x) } #[inline] #[must_use] fn zwwy(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.w, self.y) } #[inline] #[must_use] fn zwwz(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.w, self.z) } #[inline] #[must_use] fn zwww(self) -> I8Vec4 { I8Vec4::new(self.z, self.w, self.w, self.w) } #[inline] #[must_use] fn wxxx(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.x, self.x) } #[inline] #[must_use] fn wxxy(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.x, self.y) } #[inline] #[must_use] fn wxxz(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.x, self.z) } #[inline] #[must_use] fn wxxw(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.x, self.w) } #[inline] #[must_use] fn wxyx(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.y, self.x) } #[inline] #[must_use] fn wxyy(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.y, self.y) } #[inline] #[must_use] fn wxyz(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.y, self.z) } #[inline] #[must_use] fn wxyw(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.y, self.w) } #[inline] #[must_use] fn wxzx(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.z, self.x) } #[inline] #[must_use] fn wxzy(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.z, self.y) } #[inline] #[must_use] fn wxzz(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.z, self.z) } #[inline] #[must_use] fn wxzw(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.z, self.w) } #[inline] #[must_use] fn wxwx(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.w, self.x) } #[inline] #[must_use] fn wxwy(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.w, self.y) } #[inline] #[must_use] fn wxwz(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.w, self.z) } #[inline] #[must_use] fn wxww(self) -> I8Vec4 { I8Vec4::new(self.w, self.x, self.w, self.w) } #[inline] #[must_use] fn wyxx(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.x, self.x) } #[inline] #[must_use] fn wyxy(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.x, self.y) } #[inline] #[must_use] fn wyxz(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.x, self.z) } #[inline] #[must_use] fn wyxw(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.x, self.w) } #[inline] #[must_use] fn wyyx(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.y, self.x) } #[inline] #[must_use] fn wyyy(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.y, self.y) } #[inline] #[must_use] fn wyyz(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.y, self.z) } #[inline] #[must_use] fn wyyw(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.y, self.w) } #[inline] #[must_use] fn wyzx(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.z, self.x) } #[inline] #[must_use] fn wyzy(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.z, self.y) } #[inline] #[must_use] fn wyzz(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.z, self.z) } #[inline] #[must_use] fn wyzw(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.z, self.w) } #[inline] #[must_use] fn wywx(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.w, self.x) } #[inline] #[must_use] fn wywy(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.w, self.y) } #[inline] #[must_use] fn wywz(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.w, self.z) } #[inline] #[must_use] fn wyww(self) -> I8Vec4 { I8Vec4::new(self.w, self.y, self.w, self.w) } #[inline] #[must_use] fn wzxx(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.x, self.x) } #[inline] #[must_use] fn wzxy(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.x, self.y) } #[inline] #[must_use] fn wzxz(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.x, self.z) } #[inline] #[must_use] fn wzxw(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.x, self.w) } #[inline] #[must_use] fn wzyx(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.y, self.x) } #[inline] #[must_use] fn wzyy(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.y, self.y) } #[inline] #[must_use] fn wzyz(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.y, self.z) } #[inline] #[must_use] fn wzyw(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.y, self.w) } #[inline] #[must_use] fn wzzx(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.z, self.x) } #[inline] #[must_use] fn wzzy(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.z, self.y) } #[inline] #[must_use] fn wzzz(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.z, self.z) } #[inline] #[must_use] fn wzzw(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.z, self.w) } #[inline] #[must_use] fn wzwx(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.w, self.x) } #[inline] #[must_use] fn wzwy(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.w, self.y) } #[inline] #[must_use] fn wzwz(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.w, self.z) } #[inline] #[must_use] fn wzww(self) -> I8Vec4 { I8Vec4::new(self.w, self.z, self.w, self.w) } #[inline] #[must_use] fn wwxx(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.x, self.x) } #[inline] #[must_use] fn wwxy(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.x, self.y) } #[inline] #[must_use] fn wwxz(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.x, self.z) } #[inline] #[must_use] fn wwxw(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.x, self.w) } #[inline] #[must_use] fn wwyx(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.y, self.x) } #[inline] #[must_use] fn wwyy(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.y, self.y) } #[inline] #[must_use] fn wwyz(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.y, self.z) } #[inline] #[must_use] fn wwyw(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.y, self.w) } #[inline] #[must_use] fn wwzx(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.z, self.x) } #[inline] #[must_use] fn wwzy(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.z, self.y) } #[inline] #[must_use] fn wwzz(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.z, self.z) } #[inline] #[must_use] fn wwzw(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.z, self.w) } #[inline] #[must_use] fn wwwx(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.w, self.x) } #[inline] #[must_use] fn wwwy(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.w, self.y) } #[inline] #[must_use] fn wwwz(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.w, self.z) } #[inline] #[must_use] fn wwww(self) -> I8Vec4 { I8Vec4::new(self.w, self.w, self.w, self.w) } } glam-0.30.1/src/swizzles/ivec2_impl.rs000064400000000000000000000064451046102023000157160ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{IVec2, IVec3, IVec4, Vec2Swizzles}; impl Vec2Swizzles for IVec2 { type Vec3 = IVec3; type Vec4 = IVec4; #[inline] #[must_use] fn xx(self) -> IVec2 { IVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> IVec2 { IVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> IVec2 { IVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> IVec3 { IVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> IVec3 { IVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> IVec3 { IVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> IVec3 { IVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> IVec3 { IVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> IVec3 { IVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> IVec3 { IVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> IVec3 { IVec3::new(self.y, self.y, self.y) } #[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) } } glam-0.30.1/src/swizzles/ivec3_impl.rs000064400000000000000000000341621046102023000157140ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{IVec2, IVec3, IVec4, Vec3Swizzles}; impl Vec3Swizzles for IVec3 { type Vec2 = IVec2; type Vec4 = IVec4; #[inline] #[must_use] fn xx(self) -> IVec2 { IVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> IVec2 { IVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: IVec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> IVec2 { IVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: IVec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> IVec2 { IVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: IVec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> IVec2 { IVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> IVec2 { IVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: IVec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> IVec2 { IVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: IVec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> IVec2 { IVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: IVec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> IVec2 { IVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> IVec3 { IVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> IVec3 { IVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> IVec3 { IVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> IVec3 { IVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> IVec3 { IVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> IVec3 { IVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> IVec3 { IVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> IVec3 { IVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> IVec3 { IVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> IVec3 { IVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> IVec3 { IVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> IVec3 { IVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> IVec3 { IVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> IVec3 { IVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> IVec3 { IVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> IVec3 { IVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> IVec3 { IVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> IVec3 { IVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> IVec3 { IVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> IVec3 { IVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> IVec3 { IVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> IVec3 { IVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> IVec3 { IVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> IVec3 { IVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> IVec3 { IVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> IVec3 { IVec3::new(self.z, self.z, self.z) } #[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) } } glam-0.30.1/src/swizzles/ivec4_impl.rs000064400000000000000000001253501046102023000157150ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{IVec2, IVec3, IVec4, Vec4Swizzles}; impl Vec4Swizzles for IVec4 { type Vec2 = IVec2; type Vec3 = IVec3; #[inline] #[must_use] fn xx(self) -> IVec2 { IVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> IVec2 { IVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: IVec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> IVec2 { IVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: IVec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> IVec2 { IVec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: IVec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> IVec2 { IVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: IVec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> IVec2 { IVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> IVec2 { IVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: IVec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> IVec2 { IVec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: IVec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> IVec2 { IVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: IVec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> IVec2 { IVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: IVec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> IVec2 { IVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> IVec2 { IVec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: IVec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> IVec2 { IVec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: IVec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> IVec2 { IVec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: IVec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> IVec2 { IVec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: IVec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> IVec2 { IVec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> IVec3 { IVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> IVec3 { IVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> IVec3 { IVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> IVec3 { IVec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> IVec3 { IVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> IVec3 { IVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> IVec3 { IVec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: IVec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> IVec3 { IVec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: IVec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> IVec3 { IVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> IVec3 { IVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: IVec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> IVec3 { IVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> IVec3 { IVec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: IVec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> IVec3 { IVec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> IVec3 { IVec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: IVec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> IVec3 { IVec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: IVec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> IVec3 { IVec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> IVec3 { IVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> IVec3 { IVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> IVec3 { IVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: IVec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> IVec3 { IVec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: IVec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> IVec3 { IVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> IVec3 { IVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> IVec3 { IVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> IVec3 { IVec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> IVec3 { IVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: IVec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> IVec3 { IVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> IVec3 { IVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> IVec3 { IVec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: IVec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> IVec3 { IVec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: IVec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> IVec3 { IVec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> IVec3 { IVec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: IVec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> IVec3 { IVec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> IVec3 { IVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> IVec3 { IVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: IVec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> IVec3 { IVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> IVec3 { IVec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: IVec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> IVec3 { IVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: IVec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> IVec3 { IVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> IVec3 { IVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> IVec3 { IVec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: IVec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> IVec3 { IVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> IVec3 { IVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> IVec3 { IVec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> IVec3 { IVec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> IVec3 { IVec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: IVec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> IVec3 { IVec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: IVec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> IVec3 { IVec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> IVec3 { IVec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> IVec3 { IVec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> IVec3 { IVec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: IVec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> IVec3 { IVec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: IVec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> IVec3 { IVec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> IVec3 { IVec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: IVec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> IVec3 { IVec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> IVec3 { IVec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: IVec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> IVec3 { IVec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> IVec3 { IVec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: IVec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> IVec3 { IVec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: IVec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> IVec3 { IVec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> IVec3 { IVec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> IVec3 { IVec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> IVec3 { IVec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> IVec3 { IVec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> IVec3 { IVec3::new(self.w, self.w, self.w) } #[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 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) } } glam-0.30.1/src/swizzles/neon/vec3a_impl.rs000064400000000000000000000336641046102023000166510ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{Vec2, Vec3A, Vec3Swizzles, Vec4}; impl Vec3Swizzles for Vec3A { type Vec2 = Vec2; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> Vec3A { Vec3A::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3A { Vec3A::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3A { Vec3A::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> Vec3A { Vec3A::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3A { Vec3A::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> Vec3A { Vec3A::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3A { Vec3A::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> Vec3A { Vec3A::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> Vec3A { Vec3A::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3A { Vec3A::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3A { Vec3A::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> Vec3A { Vec3A::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3A { Vec3A::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3A { Vec3A::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> Vec3A { Vec3A::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> Vec3A { Vec3A::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3A { Vec3A::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> Vec3A { Vec3A::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3A { Vec3A::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> Vec3A { Vec3A::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> Vec3A { Vec3A::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> Vec3A { Vec3A::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3A { Vec3A::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> Vec3A { Vec3A::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3A { Vec3A::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3A { Vec3A::new(self.z, self.z, self.z) } #[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) } } glam-0.30.1/src/swizzles/neon/vec4_impl.rs000064400000000000000000001240401046102023000164760ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{Vec2, Vec3, Vec4, Vec4Swizzles}; impl Vec4Swizzles for Vec4 { type Vec2 = Vec2; type Vec3 = Vec3; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> Vec2 { Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> Vec2 { Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> Vec2 { Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> Vec2 { Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> Vec2 { Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> Vec2 { Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> Vec2 { Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3 { Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> Vec3 { Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> Vec3 { Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> Vec3 { Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> Vec3 { Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3 { Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> Vec3 { Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> Vec3 { Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> Vec3 { Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> Vec3 { Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> Vec3 { Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> Vec3 { Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3 { Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> Vec3 { Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3 { Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> Vec3 { Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> Vec3 { Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> Vec3 { Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3 { Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> Vec3 { Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> Vec3 { Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> Vec3 { Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> Vec3 { Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> Vec3 { Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> Vec3 { Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3 { Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> Vec3 { Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> Vec3 { Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> Vec3 { Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> Vec3 { Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3 { Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> Vec3 { Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> Vec3 { Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3 { Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3 { Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> Vec3 { Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> Vec3 { Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> Vec3 { Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> Vec3 { Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> Vec3 { Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> Vec3 { Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> Vec3 { Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> Vec3 { Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> Vec3 { Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> Vec3 { Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> Vec3 { Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> Vec3 { Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> Vec3 { Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> Vec3 { Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> Vec3 { Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> Vec3 { Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> Vec3 { Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> Vec3 { Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> Vec3 { Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> Vec3 { Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> Vec3 { Vec3::new(self.w, self.w, self.w) } #[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 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) } } glam-0.30.1/src/swizzles/neon.rs000064400000000000000000000000371046102023000146130ustar 00000000000000mod vec3a_impl; mod vec4_impl; glam-0.30.1/src/swizzles/scalar/vec3a_impl.rs000064400000000000000000000336641046102023000171570ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{Vec2, Vec3A, Vec3Swizzles, Vec4}; impl Vec3Swizzles for Vec3A { type Vec2 = Vec2; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> Vec3A { Vec3A::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3A { Vec3A::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3A { Vec3A::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> Vec3A { Vec3A::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3A { Vec3A::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> Vec3A { Vec3A::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3A { Vec3A::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> Vec3A { Vec3A::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> Vec3A { Vec3A::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3A { Vec3A::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3A { Vec3A::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> Vec3A { Vec3A::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3A { Vec3A::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3A { Vec3A::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> Vec3A { Vec3A::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> Vec3A { Vec3A::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3A { Vec3A::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> Vec3A { Vec3A::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3A { Vec3A::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> Vec3A { Vec3A::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> Vec3A { Vec3A::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> Vec3A { Vec3A::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3A { Vec3A::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> Vec3A { Vec3A::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3A { Vec3A::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3A { Vec3A::new(self.z, self.z, self.z) } #[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) } } glam-0.30.1/src/swizzles/scalar/vec4_impl.rs000064400000000000000000001240401046102023000170040ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{Vec2, Vec3, Vec4, Vec4Swizzles}; impl Vec4Swizzles for Vec4 { type Vec2 = Vec2; type Vec3 = Vec3; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> Vec2 { Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> Vec2 { Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> Vec2 { Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> Vec2 { Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> Vec2 { Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> Vec2 { Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> Vec2 { Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3 { Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> Vec3 { Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> Vec3 { Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> Vec3 { Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> Vec3 { Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3 { Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> Vec3 { Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> Vec3 { Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> Vec3 { Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> Vec3 { Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> Vec3 { Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> Vec3 { Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3 { Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> Vec3 { Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3 { Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> Vec3 { Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> Vec3 { Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> Vec3 { Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3 { Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> Vec3 { Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> Vec3 { Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> Vec3 { Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> Vec3 { Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> Vec3 { Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> Vec3 { Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3 { Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> Vec3 { Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> Vec3 { Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> Vec3 { Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> Vec3 { Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3 { Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> Vec3 { Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> Vec3 { Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3 { Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3 { Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> Vec3 { Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> Vec3 { Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> Vec3 { Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> Vec3 { Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> Vec3 { Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> Vec3 { Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> Vec3 { Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> Vec3 { Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> Vec3 { Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> Vec3 { Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> Vec3 { Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> Vec3 { Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> Vec3 { Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> Vec3 { Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> Vec3 { Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> Vec3 { Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> Vec3 { Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> Vec3 { Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> Vec3 { Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> Vec3 { Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> Vec3 { Vec3::new(self.w, self.w, self.w) } #[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 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) } } glam-0.30.1/src/swizzles/scalar.rs000064400000000000000000000000371046102023000151210ustar 00000000000000mod vec3a_impl; mod vec4_impl; glam-0.30.1/src/swizzles/sse2/vec3a_impl.rs000064400000000000000000000413131046102023000165540ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. #![allow(clippy::useless_conversion)] use crate::{Vec2, Vec3A, Vec3Swizzles, Vec4}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; impl Vec3Swizzles for Vec3A { type Vec2 = Vec2; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[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 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) }) } } glam-0.30.1/src/swizzles/sse2/vec4_impl.rs000064400000000000000000001366411046102023000164250ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. #![allow(clippy::useless_conversion)] use crate::{Vec2, Vec3, Vec4, Vec4Swizzles}; #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; impl Vec4Swizzles for Vec4 { type Vec2 = Vec2; type Vec3 = Vec3; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> Vec2 { Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> Vec2 { Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> Vec2 { Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> Vec2 { Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> Vec2 { Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> Vec2 { Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> Vec2 { Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3 { Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> Vec3 { Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> Vec3 { Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> Vec3 { Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> Vec3 { Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3 { Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> Vec3 { Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> Vec3 { Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> Vec3 { Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> Vec3 { Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> Vec3 { Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> Vec3 { Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3 { Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> Vec3 { Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3 { Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> Vec3 { Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> Vec3 { Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> Vec3 { Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3 { Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> Vec3 { Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> Vec3 { Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> Vec3 { Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> Vec3 { Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> Vec3 { Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> Vec3 { Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3 { Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> Vec3 { Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> Vec3 { Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> Vec3 { Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> Vec3 { Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3 { Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> Vec3 { Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> Vec3 { Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3 { Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3 { Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> Vec3 { Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> Vec3 { Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> Vec3 { Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> Vec3 { Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> Vec3 { Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> Vec3 { Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> Vec3 { Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> Vec3 { Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> Vec3 { Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> Vec3 { Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> Vec3 { Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> Vec3 { Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> Vec3 { Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> Vec3 { Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> Vec3 { Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> Vec3 { Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> Vec3 { Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> Vec3 { Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> Vec3 { Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> Vec3 { Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> Vec3 { Vec3::new(self.w, self.w, self.w) } #[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 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) }) } } glam-0.30.1/src/swizzles/sse2.rs000064400000000000000000000000371046102023000145300ustar 00000000000000mod vec3a_impl; mod vec4_impl; glam-0.30.1/src/swizzles/u16vec2_impl.rs000064400000000000000000000066351046102023000161020ustar 00000000000000// 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 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::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, 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) } } glam-0.30.1/src/swizzles/u16vec3_impl.rs000064400000000000000000000351321046102023000160750ustar 00000000000000// 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 with_xy(self, rhs: U16Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> U16Vec2 { U16Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: U16Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> U16Vec2 { U16Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: U16Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[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 with_yz(self, rhs: U16Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> U16Vec2 { U16Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: U16Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> U16Vec2 { U16Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: U16Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> U16Vec2 { U16Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> U16Vec3 { U16Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> U16Vec3 { U16Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> U16Vec3 { U16Vec3::new(self.z, self.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) } } glam-0.30.1/src/swizzles/u16vec4_impl.rs000064400000000000000000001301701046102023000160740ustar 00000000000000// 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 with_xy(self, rhs: U16Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> U16Vec2 { U16Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: U16Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> U16Vec2 { U16Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: U16Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> U16Vec2 { U16Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: U16Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[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 with_yz(self, rhs: U16Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> U16Vec2 { U16Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: U16Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> U16Vec2 { U16Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: U16Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> U16Vec2 { U16Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: U16Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[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 with_zw(self, rhs: U16Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> U16Vec2 { U16Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: U16Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> U16Vec2 { U16Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: U16Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> U16Vec2 { U16Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: U16Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> U16Vec2 { U16Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> U16Vec3 { U16Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: U16Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> U16Vec3 { U16Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: U16Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: U16Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> U16Vec3 { U16Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: U16Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> U16Vec3 { U16Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> U16Vec3 { U16Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: U16Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> U16Vec3 { U16Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: U16Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> U16Vec3 { U16Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: U16Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> U16Vec3 { U16Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: U16Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> U16Vec3 { U16Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: U16Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> U16Vec3 { U16Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: U16Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> U16Vec3 { U16Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: U16Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> U16Vec3 { U16Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> U16Vec3 { U16Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: U16Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> U16Vec3 { U16Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: U16Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> U16Vec3 { U16Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: U16Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: U16Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> U16Vec3 { U16Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: U16Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> U16Vec3 { U16Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> U16Vec3 { U16Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> U16Vec3 { U16Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> U16Vec3 { U16Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> U16Vec3 { U16Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: U16Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> U16Vec3 { U16Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: U16Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> U16Vec3 { U16Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> U16Vec3 { U16Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> U16Vec3 { U16Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> U16Vec3 { U16Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: U16Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> U16Vec3 { U16Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: U16Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> U16Vec3 { U16Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> U16Vec3 { U16Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: U16Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> U16Vec3 { U16Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> U16Vec3 { U16Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: U16Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> U16Vec3 { U16Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> U16Vec3 { U16Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: U16Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> U16Vec3 { U16Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: U16Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> U16Vec3 { U16Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> U16Vec3 { U16Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> U16Vec3 { U16Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> U16Vec3 { U16Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> U16Vec3 { U16Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> U16Vec3 { U16Vec3::new(self.w, self.w, 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 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) } } glam-0.30.1/src/swizzles/u64vec2_impl.rs000064400000000000000000000066351046102023000161050ustar 00000000000000// 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 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::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, 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) } } glam-0.30.1/src/swizzles/u64vec3_impl.rs000064400000000000000000000351321046102023000161000ustar 00000000000000// 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 with_xy(self, rhs: U64Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> U64Vec2 { U64Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: U64Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> U64Vec2 { U64Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: U64Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[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 with_yz(self, rhs: U64Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> U64Vec2 { U64Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: U64Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> U64Vec2 { U64Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: U64Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> U64Vec2 { U64Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> U64Vec3 { U64Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> U64Vec3 { U64Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> U64Vec3 { U64Vec3::new(self.z, self.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) } } glam-0.30.1/src/swizzles/u64vec4_impl.rs000064400000000000000000001301701046102023000160770ustar 00000000000000// 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 with_xy(self, rhs: U64Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> U64Vec2 { U64Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: U64Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> U64Vec2 { U64Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: U64Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> U64Vec2 { U64Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: U64Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[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 with_yz(self, rhs: U64Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> U64Vec2 { U64Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: U64Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> U64Vec2 { U64Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: U64Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> U64Vec2 { U64Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: U64Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[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 with_zw(self, rhs: U64Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> U64Vec2 { U64Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: U64Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> U64Vec2 { U64Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: U64Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> U64Vec2 { U64Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: U64Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> U64Vec2 { U64Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> U64Vec3 { U64Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: U64Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> U64Vec3 { U64Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: U64Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: U64Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> U64Vec3 { U64Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: U64Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> U64Vec3 { U64Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> U64Vec3 { U64Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: U64Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> U64Vec3 { U64Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: U64Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> U64Vec3 { U64Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: U64Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> U64Vec3 { U64Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: U64Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> U64Vec3 { U64Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: U64Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> U64Vec3 { U64Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: U64Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> U64Vec3 { U64Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: U64Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> U64Vec3 { U64Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> U64Vec3 { U64Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: U64Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> U64Vec3 { U64Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: U64Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> U64Vec3 { U64Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: U64Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: U64Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> U64Vec3 { U64Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: U64Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> U64Vec3 { U64Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> U64Vec3 { U64Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> U64Vec3 { U64Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> U64Vec3 { U64Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> U64Vec3 { U64Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: U64Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> U64Vec3 { U64Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: U64Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> U64Vec3 { U64Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> U64Vec3 { U64Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> U64Vec3 { U64Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> U64Vec3 { U64Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: U64Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> U64Vec3 { U64Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: U64Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> U64Vec3 { U64Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> U64Vec3 { U64Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: U64Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> U64Vec3 { U64Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> U64Vec3 { U64Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: U64Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> U64Vec3 { U64Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> U64Vec3 { U64Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: U64Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> U64Vec3 { U64Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: U64Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> U64Vec3 { U64Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> U64Vec3 { U64Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> U64Vec3 { U64Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> U64Vec3 { U64Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> U64Vec3 { U64Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> U64Vec3 { U64Vec3::new(self.w, self.w, 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 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) } } glam-0.30.1/src/swizzles/u8vec2_impl.rs000064400000000000000000000065411046102023000160170ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{U8Vec2, U8Vec3, U8Vec4, Vec2Swizzles}; impl Vec2Swizzles for U8Vec2 { type Vec3 = U8Vec3; type Vec4 = U8Vec4; #[inline] #[must_use] fn xx(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn xxxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xyxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn yxxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yyxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.y) } } glam-0.30.1/src/swizzles/u8vec3_impl.rs000064400000000000000000000345461046102023000160260ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{U8Vec2, U8Vec3, U8Vec4, Vec3Swizzles}; impl Vec3Swizzles for U8Vec3 { type Vec2 = U8Vec2; type Vec4 = U8Vec4; #[inline] #[must_use] fn xx(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: U8Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: U8Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: U8Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: U8Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: U8Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: U8Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn xxxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.z) } #[inline] #[must_use] fn xxyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xxyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.z) } #[inline] #[must_use] fn xxzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.x) } #[inline] #[must_use] fn xxzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.y) } #[inline] #[must_use] fn xxzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.z) } #[inline] #[must_use] fn xyxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.z) } #[inline] #[must_use] fn xyyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn xyyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.z) } #[inline] #[must_use] fn xyzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.z, self.x) } #[inline] #[must_use] fn xyzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.z, self.y) } #[inline] #[must_use] fn xyzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.z, self.z) } #[inline] #[must_use] fn xzxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.x) } #[inline] #[must_use] fn xzxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.y) } #[inline] #[must_use] fn xzxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.z) } #[inline] #[must_use] fn xzyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.x) } #[inline] #[must_use] fn xzyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.y) } #[inline] #[must_use] fn xzyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.z) } #[inline] #[must_use] fn xzzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.x) } #[inline] #[must_use] fn xzzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.y) } #[inline] #[must_use] fn xzzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.z) } #[inline] #[must_use] fn yxxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.z) } #[inline] #[must_use] fn yxyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yxyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.z) } #[inline] #[must_use] fn yxzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.x) } #[inline] #[must_use] fn yxzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.y) } #[inline] #[must_use] fn yxzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.z) } #[inline] #[must_use] fn yyxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.z) } #[inline] #[must_use] fn yyyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.y) } #[inline] #[must_use] fn yyyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.z) } #[inline] #[must_use] fn yyzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.x) } #[inline] #[must_use] fn yyzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.y) } #[inline] #[must_use] fn yyzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.z) } #[inline] #[must_use] fn yzxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.x) } #[inline] #[must_use] fn yzxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.y) } #[inline] #[must_use] fn yzxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.z) } #[inline] #[must_use] fn yzyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.x) } #[inline] #[must_use] fn yzyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.y) } #[inline] #[must_use] fn yzyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.z) } #[inline] #[must_use] fn yzzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.x) } #[inline] #[must_use] fn yzzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.y) } #[inline] #[must_use] fn yzzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.z) } #[inline] #[must_use] fn zxxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.x) } #[inline] #[must_use] fn zxxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.y) } #[inline] #[must_use] fn zxxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.z) } #[inline] #[must_use] fn zxyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.x) } #[inline] #[must_use] fn zxyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.y) } #[inline] #[must_use] fn zxyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.z) } #[inline] #[must_use] fn zxzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.x) } #[inline] #[must_use] fn zxzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.y) } #[inline] #[must_use] fn zxzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.z) } #[inline] #[must_use] fn zyxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.x) } #[inline] #[must_use] fn zyxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.y) } #[inline] #[must_use] fn zyxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.z) } #[inline] #[must_use] fn zyyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.x) } #[inline] #[must_use] fn zyyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.y) } #[inline] #[must_use] fn zyyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.z) } #[inline] #[must_use] fn zyzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.x) } #[inline] #[must_use] fn zyzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.y) } #[inline] #[must_use] fn zyzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.z) } #[inline] #[must_use] fn zzxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.x) } #[inline] #[must_use] fn zzxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.y) } #[inline] #[must_use] fn zzxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.z) } #[inline] #[must_use] fn zzyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.x) } #[inline] #[must_use] fn zzyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.y) } #[inline] #[must_use] fn zzyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.z) } #[inline] #[must_use] fn zzzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.x) } #[inline] #[must_use] fn zzzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.y) } #[inline] #[must_use] fn zzzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.z) } } glam-0.30.1/src/swizzles/u8vec4_impl.rs000064400000000000000000001266601046102023000160260ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{U8Vec2, U8Vec3, U8Vec4, Vec4Swizzles}; impl Vec4Swizzles for U8Vec4 { type Vec2 = U8Vec2; type Vec3 = U8Vec3; #[inline] #[must_use] fn xx(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: U8Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: U8Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> U8Vec2 { U8Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: U8Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: U8Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: U8Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> U8Vec2 { U8Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: U8Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: U8Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: U8Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> U8Vec2 { U8Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: U8Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> U8Vec2 { U8Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: U8Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> U8Vec2 { U8Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: U8Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> U8Vec2 { U8Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: U8Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> U8Vec2 { U8Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> U8Vec3 { U8Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: U8Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> U8Vec3 { U8Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: U8Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: U8Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> U8Vec3 { U8Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: U8Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> U8Vec3 { U8Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> U8Vec3 { U8Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: U8Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> U8Vec3 { U8Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: U8Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> U8Vec3 { U8Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: U8Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> U8Vec3 { U8Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: U8Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> U8Vec3 { U8Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: U8Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> U8Vec3 { U8Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: U8Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> U8Vec3 { U8Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: U8Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> U8Vec3 { U8Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> U8Vec3 { U8Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: U8Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> U8Vec3 { U8Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: U8Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> U8Vec3 { U8Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: U8Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: U8Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> U8Vec3 { U8Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: U8Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> U8Vec3 { U8Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> U8Vec3 { U8Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: U8Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> U8Vec3 { U8Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: U8Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> U8Vec3 { U8Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> U8Vec3 { U8Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> U8Vec3 { U8Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> U8Vec3 { U8Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: U8Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> U8Vec3 { U8Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: U8Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> U8Vec3 { U8Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> U8Vec3 { U8Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: U8Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> U8Vec3 { U8Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> U8Vec3 { U8Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: U8Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> U8Vec3 { U8Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> U8Vec3 { U8Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: U8Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> U8Vec3 { U8Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: U8Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> U8Vec3 { U8Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> U8Vec3 { U8Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> U8Vec3 { U8Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> U8Vec3 { U8Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> U8Vec3 { U8Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> U8Vec3 { U8Vec3::new(self.w, self.w, self.w) } #[inline] #[must_use] fn xxxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.z) } #[inline] #[must_use] fn xxxw(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.x, self.w) } #[inline] #[must_use] fn xxyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xxyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.z) } #[inline] #[must_use] fn xxyw(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.y, self.w) } #[inline] #[must_use] fn xxzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.x) } #[inline] #[must_use] fn xxzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.y) } #[inline] #[must_use] fn xxzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.z) } #[inline] #[must_use] fn xxzw(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.z, self.w) } #[inline] #[must_use] fn xxwx(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.w, self.x) } #[inline] #[must_use] fn xxwy(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.w, self.y) } #[inline] #[must_use] fn xxwz(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.w, self.z) } #[inline] #[must_use] fn xxww(self) -> U8Vec4 { U8Vec4::new(self.x, self.x, self.w, self.w) } #[inline] #[must_use] fn xyxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.z) } #[inline] #[must_use] fn xyxw(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.x, self.w) } #[inline] #[must_use] fn xyyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn xyyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.z) } #[inline] #[must_use] fn xyyw(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.y, self.w) } #[inline] #[must_use] fn xyzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.z, self.x) } #[inline] #[must_use] fn xyzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.z, self.y) } #[inline] #[must_use] fn xyzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.z, self.z) } #[inline] #[must_use] fn xywx(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.w, self.x) } #[inline] #[must_use] fn xywy(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.w, self.y) } #[inline] #[must_use] fn xywz(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.w, self.z) } #[inline] #[must_use] fn xyww(self) -> U8Vec4 { U8Vec4::new(self.x, self.y, self.w, self.w) } #[inline] #[must_use] fn xzxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.x) } #[inline] #[must_use] fn xzxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.y) } #[inline] #[must_use] fn xzxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.z) } #[inline] #[must_use] fn xzxw(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.x, self.w) } #[inline] #[must_use] fn xzyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.x) } #[inline] #[must_use] fn xzyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.y) } #[inline] #[must_use] fn xzyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.z) } #[inline] #[must_use] fn xzyw(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.y, self.w) } #[inline] #[must_use] fn xzzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.x) } #[inline] #[must_use] fn xzzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.y) } #[inline] #[must_use] fn xzzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.z) } #[inline] #[must_use] fn xzzw(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.z, self.w) } #[inline] #[must_use] fn xzwx(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.w, self.x) } #[inline] #[must_use] fn xzwy(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.w, self.y) } #[inline] #[must_use] fn xzwz(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.w, self.z) } #[inline] #[must_use] fn xzww(self) -> U8Vec4 { U8Vec4::new(self.x, self.z, self.w, self.w) } #[inline] #[must_use] fn xwxx(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.x, self.x) } #[inline] #[must_use] fn xwxy(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.x, self.y) } #[inline] #[must_use] fn xwxz(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.x, self.z) } #[inline] #[must_use] fn xwxw(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.x, self.w) } #[inline] #[must_use] fn xwyx(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.y, self.x) } #[inline] #[must_use] fn xwyy(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.y, self.y) } #[inline] #[must_use] fn xwyz(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.y, self.z) } #[inline] #[must_use] fn xwyw(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.y, self.w) } #[inline] #[must_use] fn xwzx(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.z, self.x) } #[inline] #[must_use] fn xwzy(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.z, self.y) } #[inline] #[must_use] fn xwzz(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.z, self.z) } #[inline] #[must_use] fn xwzw(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.z, self.w) } #[inline] #[must_use] fn xwwx(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.w, self.x) } #[inline] #[must_use] fn xwwy(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.w, self.y) } #[inline] #[must_use] fn xwwz(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.w, self.z) } #[inline] #[must_use] fn xwww(self) -> U8Vec4 { U8Vec4::new(self.x, self.w, self.w, self.w) } #[inline] #[must_use] fn yxxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.z) } #[inline] #[must_use] fn yxxw(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.x, self.w) } #[inline] #[must_use] fn yxyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yxyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.z) } #[inline] #[must_use] fn yxyw(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.y, self.w) } #[inline] #[must_use] fn yxzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.x) } #[inline] #[must_use] fn yxzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.y) } #[inline] #[must_use] fn yxzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.z) } #[inline] #[must_use] fn yxzw(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.z, self.w) } #[inline] #[must_use] fn yxwx(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.w, self.x) } #[inline] #[must_use] fn yxwy(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.w, self.y) } #[inline] #[must_use] fn yxwz(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.w, self.z) } #[inline] #[must_use] fn yxww(self) -> U8Vec4 { U8Vec4::new(self.y, self.x, self.w, self.w) } #[inline] #[must_use] fn yyxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.z) } #[inline] #[must_use] fn yyxw(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.x, self.w) } #[inline] #[must_use] fn yyyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.y) } #[inline] #[must_use] fn yyyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.z) } #[inline] #[must_use] fn yyyw(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.y, self.w) } #[inline] #[must_use] fn yyzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.x) } #[inline] #[must_use] fn yyzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.y) } #[inline] #[must_use] fn yyzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.z) } #[inline] #[must_use] fn yyzw(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.z, self.w) } #[inline] #[must_use] fn yywx(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.w, self.x) } #[inline] #[must_use] fn yywy(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.w, self.y) } #[inline] #[must_use] fn yywz(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.w, self.z) } #[inline] #[must_use] fn yyww(self) -> U8Vec4 { U8Vec4::new(self.y, self.y, self.w, self.w) } #[inline] #[must_use] fn yzxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.x) } #[inline] #[must_use] fn yzxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.y) } #[inline] #[must_use] fn yzxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.z) } #[inline] #[must_use] fn yzxw(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.x, self.w) } #[inline] #[must_use] fn yzyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.x) } #[inline] #[must_use] fn yzyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.y) } #[inline] #[must_use] fn yzyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.z) } #[inline] #[must_use] fn yzyw(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.y, self.w) } #[inline] #[must_use] fn yzzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.x) } #[inline] #[must_use] fn yzzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.y) } #[inline] #[must_use] fn yzzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.z) } #[inline] #[must_use] fn yzzw(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.z, self.w) } #[inline] #[must_use] fn yzwx(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.w, self.x) } #[inline] #[must_use] fn yzwy(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.w, self.y) } #[inline] #[must_use] fn yzwz(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.w, self.z) } #[inline] #[must_use] fn yzww(self) -> U8Vec4 { U8Vec4::new(self.y, self.z, self.w, self.w) } #[inline] #[must_use] fn ywxx(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.x, self.x) } #[inline] #[must_use] fn ywxy(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.x, self.y) } #[inline] #[must_use] fn ywxz(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.x, self.z) } #[inline] #[must_use] fn ywxw(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.x, self.w) } #[inline] #[must_use] fn ywyx(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.y, self.x) } #[inline] #[must_use] fn ywyy(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.y, self.y) } #[inline] #[must_use] fn ywyz(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.y, self.z) } #[inline] #[must_use] fn ywyw(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.y, self.w) } #[inline] #[must_use] fn ywzx(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.z, self.x) } #[inline] #[must_use] fn ywzy(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.z, self.y) } #[inline] #[must_use] fn ywzz(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.z, self.z) } #[inline] #[must_use] fn ywzw(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.z, self.w) } #[inline] #[must_use] fn ywwx(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.w, self.x) } #[inline] #[must_use] fn ywwy(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.w, self.y) } #[inline] #[must_use] fn ywwz(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.w, self.z) } #[inline] #[must_use] fn ywww(self) -> U8Vec4 { U8Vec4::new(self.y, self.w, self.w, self.w) } #[inline] #[must_use] fn zxxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.x) } #[inline] #[must_use] fn zxxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.y) } #[inline] #[must_use] fn zxxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.z) } #[inline] #[must_use] fn zxxw(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.x, self.w) } #[inline] #[must_use] fn zxyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.x) } #[inline] #[must_use] fn zxyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.y) } #[inline] #[must_use] fn zxyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.z) } #[inline] #[must_use] fn zxyw(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.y, self.w) } #[inline] #[must_use] fn zxzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.x) } #[inline] #[must_use] fn zxzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.y) } #[inline] #[must_use] fn zxzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.z) } #[inline] #[must_use] fn zxzw(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.z, self.w) } #[inline] #[must_use] fn zxwx(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.w, self.x) } #[inline] #[must_use] fn zxwy(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.w, self.y) } #[inline] #[must_use] fn zxwz(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.w, self.z) } #[inline] #[must_use] fn zxww(self) -> U8Vec4 { U8Vec4::new(self.z, self.x, self.w, self.w) } #[inline] #[must_use] fn zyxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.x) } #[inline] #[must_use] fn zyxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.y) } #[inline] #[must_use] fn zyxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.z) } #[inline] #[must_use] fn zyxw(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.x, self.w) } #[inline] #[must_use] fn zyyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.x) } #[inline] #[must_use] fn zyyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.y) } #[inline] #[must_use] fn zyyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.z) } #[inline] #[must_use] fn zyyw(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.y, self.w) } #[inline] #[must_use] fn zyzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.x) } #[inline] #[must_use] fn zyzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.y) } #[inline] #[must_use] fn zyzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.z) } #[inline] #[must_use] fn zyzw(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.z, self.w) } #[inline] #[must_use] fn zywx(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.w, self.x) } #[inline] #[must_use] fn zywy(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.w, self.y) } #[inline] #[must_use] fn zywz(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.w, self.z) } #[inline] #[must_use] fn zyww(self) -> U8Vec4 { U8Vec4::new(self.z, self.y, self.w, self.w) } #[inline] #[must_use] fn zzxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.x) } #[inline] #[must_use] fn zzxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.y) } #[inline] #[must_use] fn zzxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.z) } #[inline] #[must_use] fn zzxw(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.x, self.w) } #[inline] #[must_use] fn zzyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.x) } #[inline] #[must_use] fn zzyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.y) } #[inline] #[must_use] fn zzyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.z) } #[inline] #[must_use] fn zzyw(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.y, self.w) } #[inline] #[must_use] fn zzzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.x) } #[inline] #[must_use] fn zzzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.y) } #[inline] #[must_use] fn zzzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.z) } #[inline] #[must_use] fn zzzw(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.z, self.w) } #[inline] #[must_use] fn zzwx(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.w, self.x) } #[inline] #[must_use] fn zzwy(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.w, self.y) } #[inline] #[must_use] fn zzwz(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.w, self.z) } #[inline] #[must_use] fn zzww(self) -> U8Vec4 { U8Vec4::new(self.z, self.z, self.w, self.w) } #[inline] #[must_use] fn zwxx(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.x, self.x) } #[inline] #[must_use] fn zwxy(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.x, self.y) } #[inline] #[must_use] fn zwxz(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.x, self.z) } #[inline] #[must_use] fn zwxw(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.x, self.w) } #[inline] #[must_use] fn zwyx(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.y, self.x) } #[inline] #[must_use] fn zwyy(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.y, self.y) } #[inline] #[must_use] fn zwyz(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.y, self.z) } #[inline] #[must_use] fn zwyw(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.y, self.w) } #[inline] #[must_use] fn zwzx(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.z, self.x) } #[inline] #[must_use] fn zwzy(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.z, self.y) } #[inline] #[must_use] fn zwzz(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.z, self.z) } #[inline] #[must_use] fn zwzw(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.z, self.w) } #[inline] #[must_use] fn zwwx(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.w, self.x) } #[inline] #[must_use] fn zwwy(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.w, self.y) } #[inline] #[must_use] fn zwwz(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.w, self.z) } #[inline] #[must_use] fn zwww(self) -> U8Vec4 { U8Vec4::new(self.z, self.w, self.w, self.w) } #[inline] #[must_use] fn wxxx(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.x, self.x) } #[inline] #[must_use] fn wxxy(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.x, self.y) } #[inline] #[must_use] fn wxxz(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.x, self.z) } #[inline] #[must_use] fn wxxw(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.x, self.w) } #[inline] #[must_use] fn wxyx(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.y, self.x) } #[inline] #[must_use] fn wxyy(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.y, self.y) } #[inline] #[must_use] fn wxyz(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.y, self.z) } #[inline] #[must_use] fn wxyw(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.y, self.w) } #[inline] #[must_use] fn wxzx(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.z, self.x) } #[inline] #[must_use] fn wxzy(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.z, self.y) } #[inline] #[must_use] fn wxzz(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.z, self.z) } #[inline] #[must_use] fn wxzw(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.z, self.w) } #[inline] #[must_use] fn wxwx(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.w, self.x) } #[inline] #[must_use] fn wxwy(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.w, self.y) } #[inline] #[must_use] fn wxwz(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.w, self.z) } #[inline] #[must_use] fn wxww(self) -> U8Vec4 { U8Vec4::new(self.w, self.x, self.w, self.w) } #[inline] #[must_use] fn wyxx(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.x, self.x) } #[inline] #[must_use] fn wyxy(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.x, self.y) } #[inline] #[must_use] fn wyxz(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.x, self.z) } #[inline] #[must_use] fn wyxw(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.x, self.w) } #[inline] #[must_use] fn wyyx(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.y, self.x) } #[inline] #[must_use] fn wyyy(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.y, self.y) } #[inline] #[must_use] fn wyyz(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.y, self.z) } #[inline] #[must_use] fn wyyw(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.y, self.w) } #[inline] #[must_use] fn wyzx(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.z, self.x) } #[inline] #[must_use] fn wyzy(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.z, self.y) } #[inline] #[must_use] fn wyzz(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.z, self.z) } #[inline] #[must_use] fn wyzw(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.z, self.w) } #[inline] #[must_use] fn wywx(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.w, self.x) } #[inline] #[must_use] fn wywy(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.w, self.y) } #[inline] #[must_use] fn wywz(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.w, self.z) } #[inline] #[must_use] fn wyww(self) -> U8Vec4 { U8Vec4::new(self.w, self.y, self.w, self.w) } #[inline] #[must_use] fn wzxx(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.x, self.x) } #[inline] #[must_use] fn wzxy(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.x, self.y) } #[inline] #[must_use] fn wzxz(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.x, self.z) } #[inline] #[must_use] fn wzxw(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.x, self.w) } #[inline] #[must_use] fn wzyx(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.y, self.x) } #[inline] #[must_use] fn wzyy(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.y, self.y) } #[inline] #[must_use] fn wzyz(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.y, self.z) } #[inline] #[must_use] fn wzyw(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.y, self.w) } #[inline] #[must_use] fn wzzx(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.z, self.x) } #[inline] #[must_use] fn wzzy(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.z, self.y) } #[inline] #[must_use] fn wzzz(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.z, self.z) } #[inline] #[must_use] fn wzzw(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.z, self.w) } #[inline] #[must_use] fn wzwx(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.w, self.x) } #[inline] #[must_use] fn wzwy(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.w, self.y) } #[inline] #[must_use] fn wzwz(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.w, self.z) } #[inline] #[must_use] fn wzww(self) -> U8Vec4 { U8Vec4::new(self.w, self.z, self.w, self.w) } #[inline] #[must_use] fn wwxx(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.x, self.x) } #[inline] #[must_use] fn wwxy(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.x, self.y) } #[inline] #[must_use] fn wwxz(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.x, self.z) } #[inline] #[must_use] fn wwxw(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.x, self.w) } #[inline] #[must_use] fn wwyx(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.y, self.x) } #[inline] #[must_use] fn wwyy(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.y, self.y) } #[inline] #[must_use] fn wwyz(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.y, self.z) } #[inline] #[must_use] fn wwyw(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.y, self.w) } #[inline] #[must_use] fn wwzx(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.z, self.x) } #[inline] #[must_use] fn wwzy(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.z, self.y) } #[inline] #[must_use] fn wwzz(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.z, self.z) } #[inline] #[must_use] fn wwzw(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.z, self.w) } #[inline] #[must_use] fn wwwx(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.w, self.x) } #[inline] #[must_use] fn wwwy(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.w, self.y) } #[inline] #[must_use] fn wwwz(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.w, self.z) } #[inline] #[must_use] fn wwww(self) -> U8Vec4 { U8Vec4::new(self.w, self.w, self.w, self.w) } } glam-0.30.1/src/swizzles/usizevec2_impl.rs000064400000000000000000000070251046102023000166200ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{USizeVec2, USizeVec3, USizeVec4, Vec2Swizzles}; impl Vec2Swizzles for USizeVec2 { type Vec3 = USizeVec3; type Vec4 = USizeVec4; #[inline] #[must_use] fn xx(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn xxxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xyxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn yxxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yyxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.y) } } glam-0.30.1/src/swizzles/usizevec3_impl.rs000064400000000000000000000361021046102023000166170ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{USizeVec2, USizeVec3, USizeVec4, Vec3Swizzles}; impl Vec3Swizzles for USizeVec3 { type Vec2 = USizeVec2; type Vec4 = USizeVec4; #[inline] #[must_use] fn xx(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: USizeVec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: USizeVec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: USizeVec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: USizeVec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: USizeVec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: USizeVec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn xxxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.z) } #[inline] #[must_use] fn xxyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xxyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.z) } #[inline] #[must_use] fn xxzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.x) } #[inline] #[must_use] fn xxzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.y) } #[inline] #[must_use] fn xxzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.z) } #[inline] #[must_use] fn xyxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.z) } #[inline] #[must_use] fn xyyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn xyyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.z) } #[inline] #[must_use] fn xyzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.z, self.x) } #[inline] #[must_use] fn xyzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.z, self.y) } #[inline] #[must_use] fn xyzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.z, self.z) } #[inline] #[must_use] fn xzxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.x) } #[inline] #[must_use] fn xzxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.y) } #[inline] #[must_use] fn xzxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.z) } #[inline] #[must_use] fn xzyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.x) } #[inline] #[must_use] fn xzyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.y) } #[inline] #[must_use] fn xzyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.z) } #[inline] #[must_use] fn xzzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.x) } #[inline] #[must_use] fn xzzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.y) } #[inline] #[must_use] fn xzzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.z) } #[inline] #[must_use] fn yxxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.z) } #[inline] #[must_use] fn yxyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yxyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.z) } #[inline] #[must_use] fn yxzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.x) } #[inline] #[must_use] fn yxzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.y) } #[inline] #[must_use] fn yxzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.z) } #[inline] #[must_use] fn yyxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.z) } #[inline] #[must_use] fn yyyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.y) } #[inline] #[must_use] fn yyyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.z) } #[inline] #[must_use] fn yyzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.x) } #[inline] #[must_use] fn yyzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.y) } #[inline] #[must_use] fn yyzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.z) } #[inline] #[must_use] fn yzxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.x) } #[inline] #[must_use] fn yzxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.y) } #[inline] #[must_use] fn yzxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.z) } #[inline] #[must_use] fn yzyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.x) } #[inline] #[must_use] fn yzyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.y) } #[inline] #[must_use] fn yzyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.z) } #[inline] #[must_use] fn yzzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.x) } #[inline] #[must_use] fn yzzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.y) } #[inline] #[must_use] fn yzzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.z) } #[inline] #[must_use] fn zxxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.x) } #[inline] #[must_use] fn zxxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.y) } #[inline] #[must_use] fn zxxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.z) } #[inline] #[must_use] fn zxyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.x) } #[inline] #[must_use] fn zxyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.y) } #[inline] #[must_use] fn zxyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.z) } #[inline] #[must_use] fn zxzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.x) } #[inline] #[must_use] fn zxzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.y) } #[inline] #[must_use] fn zxzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.z) } #[inline] #[must_use] fn zyxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.x) } #[inline] #[must_use] fn zyxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.y) } #[inline] #[must_use] fn zyxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.z) } #[inline] #[must_use] fn zyyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.x) } #[inline] #[must_use] fn zyyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.y) } #[inline] #[must_use] fn zyyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.z) } #[inline] #[must_use] fn zyzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.x) } #[inline] #[must_use] fn zyzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.y) } #[inline] #[must_use] fn zyzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.z) } #[inline] #[must_use] fn zzxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.x) } #[inline] #[must_use] fn zzxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.y) } #[inline] #[must_use] fn zzxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.z) } #[inline] #[must_use] fn zzyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.x) } #[inline] #[must_use] fn zzyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.y) } #[inline] #[must_use] fn zzyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.z) } #[inline] #[must_use] fn zzzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.x) } #[inline] #[must_use] fn zzzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.y) } #[inline] #[must_use] fn zzzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.z) } } glam-0.30.1/src/swizzles/usizevec4_impl.rs000064400000000000000000001330101046102023000166140ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{USizeVec2, USizeVec3, USizeVec4, Vec4Swizzles}; impl Vec4Swizzles for USizeVec4 { type Vec2 = USizeVec2; type Vec3 = USizeVec3; #[inline] #[must_use] fn xx(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: USizeVec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: USizeVec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> USizeVec2 { USizeVec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: USizeVec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: USizeVec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: USizeVec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> USizeVec2 { USizeVec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: USizeVec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: USizeVec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: USizeVec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> USizeVec2 { USizeVec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: USizeVec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> USizeVec2 { USizeVec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: USizeVec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> USizeVec2 { USizeVec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: USizeVec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> USizeVec2 { USizeVec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: USizeVec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> USizeVec2 { USizeVec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> USizeVec3 { USizeVec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: USizeVec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> USizeVec3 { USizeVec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: USizeVec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: USizeVec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> USizeVec3 { USizeVec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: USizeVec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> USizeVec3 { USizeVec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> USizeVec3 { USizeVec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: USizeVec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> USizeVec3 { USizeVec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: USizeVec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> USizeVec3 { USizeVec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: USizeVec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> USizeVec3 { USizeVec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: USizeVec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> USizeVec3 { USizeVec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: USizeVec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> USizeVec3 { USizeVec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: USizeVec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> USizeVec3 { USizeVec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: USizeVec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> USizeVec3 { USizeVec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> USizeVec3 { USizeVec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: USizeVec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> USizeVec3 { USizeVec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: USizeVec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> USizeVec3 { USizeVec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: USizeVec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: USizeVec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> USizeVec3 { USizeVec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: USizeVec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> USizeVec3 { USizeVec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> USizeVec3 { USizeVec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: USizeVec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> USizeVec3 { USizeVec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: USizeVec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> USizeVec3 { USizeVec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> USizeVec3 { USizeVec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> USizeVec3 { USizeVec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> USizeVec3 { USizeVec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: USizeVec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> USizeVec3 { USizeVec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: USizeVec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> USizeVec3 { USizeVec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> USizeVec3 { USizeVec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: USizeVec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> USizeVec3 { USizeVec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> USizeVec3 { USizeVec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: USizeVec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> USizeVec3 { USizeVec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> USizeVec3 { USizeVec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: USizeVec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> USizeVec3 { USizeVec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: USizeVec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> USizeVec3 { USizeVec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> USizeVec3 { USizeVec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> USizeVec3 { USizeVec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> USizeVec3 { USizeVec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> USizeVec3 { USizeVec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> USizeVec3 { USizeVec3::new(self.w, self.w, self.w) } #[inline] #[must_use] fn xxxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.x) } #[inline] #[must_use] fn xxxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.y) } #[inline] #[must_use] fn xxxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.z) } #[inline] #[must_use] fn xxxw(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.x, self.w) } #[inline] #[must_use] fn xxyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.x) } #[inline] #[must_use] fn xxyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.y) } #[inline] #[must_use] fn xxyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.z) } #[inline] #[must_use] fn xxyw(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.y, self.w) } #[inline] #[must_use] fn xxzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.x) } #[inline] #[must_use] fn xxzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.y) } #[inline] #[must_use] fn xxzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.z) } #[inline] #[must_use] fn xxzw(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.z, self.w) } #[inline] #[must_use] fn xxwx(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.w, self.x) } #[inline] #[must_use] fn xxwy(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.w, self.y) } #[inline] #[must_use] fn xxwz(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.w, self.z) } #[inline] #[must_use] fn xxww(self) -> USizeVec4 { USizeVec4::new(self.x, self.x, self.w, self.w) } #[inline] #[must_use] fn xyxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.x) } #[inline] #[must_use] fn xyxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.y) } #[inline] #[must_use] fn xyxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.z) } #[inline] #[must_use] fn xyxw(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.x, self.w) } #[inline] #[must_use] fn xyyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.x) } #[inline] #[must_use] fn xyyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.y) } #[inline] #[must_use] fn xyyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.z) } #[inline] #[must_use] fn xyyw(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.y, self.w) } #[inline] #[must_use] fn xyzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.z, self.x) } #[inline] #[must_use] fn xyzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.z, self.y) } #[inline] #[must_use] fn xyzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.z, self.z) } #[inline] #[must_use] fn xywx(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.w, self.x) } #[inline] #[must_use] fn xywy(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.w, self.y) } #[inline] #[must_use] fn xywz(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.w, self.z) } #[inline] #[must_use] fn xyww(self) -> USizeVec4 { USizeVec4::new(self.x, self.y, self.w, self.w) } #[inline] #[must_use] fn xzxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.x) } #[inline] #[must_use] fn xzxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.y) } #[inline] #[must_use] fn xzxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.z) } #[inline] #[must_use] fn xzxw(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.x, self.w) } #[inline] #[must_use] fn xzyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.x) } #[inline] #[must_use] fn xzyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.y) } #[inline] #[must_use] fn xzyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.z) } #[inline] #[must_use] fn xzyw(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.y, self.w) } #[inline] #[must_use] fn xzzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.x) } #[inline] #[must_use] fn xzzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.y) } #[inline] #[must_use] fn xzzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.z) } #[inline] #[must_use] fn xzzw(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.z, self.w) } #[inline] #[must_use] fn xzwx(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.w, self.x) } #[inline] #[must_use] fn xzwy(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.w, self.y) } #[inline] #[must_use] fn xzwz(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.w, self.z) } #[inline] #[must_use] fn xzww(self) -> USizeVec4 { USizeVec4::new(self.x, self.z, self.w, self.w) } #[inline] #[must_use] fn xwxx(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.x, self.x) } #[inline] #[must_use] fn xwxy(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.x, self.y) } #[inline] #[must_use] fn xwxz(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.x, self.z) } #[inline] #[must_use] fn xwxw(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.x, self.w) } #[inline] #[must_use] fn xwyx(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.y, self.x) } #[inline] #[must_use] fn xwyy(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.y, self.y) } #[inline] #[must_use] fn xwyz(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.y, self.z) } #[inline] #[must_use] fn xwyw(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.y, self.w) } #[inline] #[must_use] fn xwzx(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.z, self.x) } #[inline] #[must_use] fn xwzy(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.z, self.y) } #[inline] #[must_use] fn xwzz(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.z, self.z) } #[inline] #[must_use] fn xwzw(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.z, self.w) } #[inline] #[must_use] fn xwwx(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.w, self.x) } #[inline] #[must_use] fn xwwy(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.w, self.y) } #[inline] #[must_use] fn xwwz(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.w, self.z) } #[inline] #[must_use] fn xwww(self) -> USizeVec4 { USizeVec4::new(self.x, self.w, self.w, self.w) } #[inline] #[must_use] fn yxxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.x) } #[inline] #[must_use] fn yxxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.y) } #[inline] #[must_use] fn yxxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.z) } #[inline] #[must_use] fn yxxw(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.x, self.w) } #[inline] #[must_use] fn yxyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.x) } #[inline] #[must_use] fn yxyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.y) } #[inline] #[must_use] fn yxyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.z) } #[inline] #[must_use] fn yxyw(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.y, self.w) } #[inline] #[must_use] fn yxzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.x) } #[inline] #[must_use] fn yxzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.y) } #[inline] #[must_use] fn yxzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.z) } #[inline] #[must_use] fn yxzw(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.z, self.w) } #[inline] #[must_use] fn yxwx(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.w, self.x) } #[inline] #[must_use] fn yxwy(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.w, self.y) } #[inline] #[must_use] fn yxwz(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.w, self.z) } #[inline] #[must_use] fn yxww(self) -> USizeVec4 { USizeVec4::new(self.y, self.x, self.w, self.w) } #[inline] #[must_use] fn yyxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.x) } #[inline] #[must_use] fn yyxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.y) } #[inline] #[must_use] fn yyxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.z) } #[inline] #[must_use] fn yyxw(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.x, self.w) } #[inline] #[must_use] fn yyyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.x) } #[inline] #[must_use] fn yyyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.y) } #[inline] #[must_use] fn yyyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.z) } #[inline] #[must_use] fn yyyw(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.y, self.w) } #[inline] #[must_use] fn yyzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.x) } #[inline] #[must_use] fn yyzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.y) } #[inline] #[must_use] fn yyzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.z) } #[inline] #[must_use] fn yyzw(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.z, self.w) } #[inline] #[must_use] fn yywx(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.w, self.x) } #[inline] #[must_use] fn yywy(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.w, self.y) } #[inline] #[must_use] fn yywz(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.w, self.z) } #[inline] #[must_use] fn yyww(self) -> USizeVec4 { USizeVec4::new(self.y, self.y, self.w, self.w) } #[inline] #[must_use] fn yzxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.x) } #[inline] #[must_use] fn yzxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.y) } #[inline] #[must_use] fn yzxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.z) } #[inline] #[must_use] fn yzxw(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.x, self.w) } #[inline] #[must_use] fn yzyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.x) } #[inline] #[must_use] fn yzyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.y) } #[inline] #[must_use] fn yzyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.z) } #[inline] #[must_use] fn yzyw(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.y, self.w) } #[inline] #[must_use] fn yzzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.x) } #[inline] #[must_use] fn yzzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.y) } #[inline] #[must_use] fn yzzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.z) } #[inline] #[must_use] fn yzzw(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.z, self.w) } #[inline] #[must_use] fn yzwx(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.w, self.x) } #[inline] #[must_use] fn yzwy(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.w, self.y) } #[inline] #[must_use] fn yzwz(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.w, self.z) } #[inline] #[must_use] fn yzww(self) -> USizeVec4 { USizeVec4::new(self.y, self.z, self.w, self.w) } #[inline] #[must_use] fn ywxx(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.x, self.x) } #[inline] #[must_use] fn ywxy(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.x, self.y) } #[inline] #[must_use] fn ywxz(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.x, self.z) } #[inline] #[must_use] fn ywxw(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.x, self.w) } #[inline] #[must_use] fn ywyx(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.y, self.x) } #[inline] #[must_use] fn ywyy(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.y, self.y) } #[inline] #[must_use] fn ywyz(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.y, self.z) } #[inline] #[must_use] fn ywyw(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.y, self.w) } #[inline] #[must_use] fn ywzx(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.z, self.x) } #[inline] #[must_use] fn ywzy(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.z, self.y) } #[inline] #[must_use] fn ywzz(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.z, self.z) } #[inline] #[must_use] fn ywzw(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.z, self.w) } #[inline] #[must_use] fn ywwx(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.w, self.x) } #[inline] #[must_use] fn ywwy(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.w, self.y) } #[inline] #[must_use] fn ywwz(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.w, self.z) } #[inline] #[must_use] fn ywww(self) -> USizeVec4 { USizeVec4::new(self.y, self.w, self.w, self.w) } #[inline] #[must_use] fn zxxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.x) } #[inline] #[must_use] fn zxxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.y) } #[inline] #[must_use] fn zxxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.z) } #[inline] #[must_use] fn zxxw(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.x, self.w) } #[inline] #[must_use] fn zxyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.x) } #[inline] #[must_use] fn zxyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.y) } #[inline] #[must_use] fn zxyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.z) } #[inline] #[must_use] fn zxyw(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.y, self.w) } #[inline] #[must_use] fn zxzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.x) } #[inline] #[must_use] fn zxzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.y) } #[inline] #[must_use] fn zxzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.z) } #[inline] #[must_use] fn zxzw(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.z, self.w) } #[inline] #[must_use] fn zxwx(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.w, self.x) } #[inline] #[must_use] fn zxwy(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.w, self.y) } #[inline] #[must_use] fn zxwz(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.w, self.z) } #[inline] #[must_use] fn zxww(self) -> USizeVec4 { USizeVec4::new(self.z, self.x, self.w, self.w) } #[inline] #[must_use] fn zyxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.x) } #[inline] #[must_use] fn zyxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.y) } #[inline] #[must_use] fn zyxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.z) } #[inline] #[must_use] fn zyxw(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.x, self.w) } #[inline] #[must_use] fn zyyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.x) } #[inline] #[must_use] fn zyyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.y) } #[inline] #[must_use] fn zyyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.z) } #[inline] #[must_use] fn zyyw(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.y, self.w) } #[inline] #[must_use] fn zyzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.x) } #[inline] #[must_use] fn zyzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.y) } #[inline] #[must_use] fn zyzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.z) } #[inline] #[must_use] fn zyzw(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.z, self.w) } #[inline] #[must_use] fn zywx(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.w, self.x) } #[inline] #[must_use] fn zywy(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.w, self.y) } #[inline] #[must_use] fn zywz(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.w, self.z) } #[inline] #[must_use] fn zyww(self) -> USizeVec4 { USizeVec4::new(self.z, self.y, self.w, self.w) } #[inline] #[must_use] fn zzxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.x) } #[inline] #[must_use] fn zzxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.y) } #[inline] #[must_use] fn zzxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.z) } #[inline] #[must_use] fn zzxw(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.x, self.w) } #[inline] #[must_use] fn zzyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.x) } #[inline] #[must_use] fn zzyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.y) } #[inline] #[must_use] fn zzyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.z) } #[inline] #[must_use] fn zzyw(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.y, self.w) } #[inline] #[must_use] fn zzzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.x) } #[inline] #[must_use] fn zzzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.y) } #[inline] #[must_use] fn zzzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.z) } #[inline] #[must_use] fn zzzw(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.z, self.w) } #[inline] #[must_use] fn zzwx(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.w, self.x) } #[inline] #[must_use] fn zzwy(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.w, self.y) } #[inline] #[must_use] fn zzwz(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.w, self.z) } #[inline] #[must_use] fn zzww(self) -> USizeVec4 { USizeVec4::new(self.z, self.z, self.w, self.w) } #[inline] #[must_use] fn zwxx(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.x, self.x) } #[inline] #[must_use] fn zwxy(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.x, self.y) } #[inline] #[must_use] fn zwxz(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.x, self.z) } #[inline] #[must_use] fn zwxw(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.x, self.w) } #[inline] #[must_use] fn zwyx(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.y, self.x) } #[inline] #[must_use] fn zwyy(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.y, self.y) } #[inline] #[must_use] fn zwyz(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.y, self.z) } #[inline] #[must_use] fn zwyw(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.y, self.w) } #[inline] #[must_use] fn zwzx(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.z, self.x) } #[inline] #[must_use] fn zwzy(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.z, self.y) } #[inline] #[must_use] fn zwzz(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.z, self.z) } #[inline] #[must_use] fn zwzw(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.z, self.w) } #[inline] #[must_use] fn zwwx(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.w, self.x) } #[inline] #[must_use] fn zwwy(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.w, self.y) } #[inline] #[must_use] fn zwwz(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.w, self.z) } #[inline] #[must_use] fn zwww(self) -> USizeVec4 { USizeVec4::new(self.z, self.w, self.w, self.w) } #[inline] #[must_use] fn wxxx(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.x, self.x) } #[inline] #[must_use] fn wxxy(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.x, self.y) } #[inline] #[must_use] fn wxxz(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.x, self.z) } #[inline] #[must_use] fn wxxw(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.x, self.w) } #[inline] #[must_use] fn wxyx(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.y, self.x) } #[inline] #[must_use] fn wxyy(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.y, self.y) } #[inline] #[must_use] fn wxyz(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.y, self.z) } #[inline] #[must_use] fn wxyw(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.y, self.w) } #[inline] #[must_use] fn wxzx(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.z, self.x) } #[inline] #[must_use] fn wxzy(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.z, self.y) } #[inline] #[must_use] fn wxzz(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.z, self.z) } #[inline] #[must_use] fn wxzw(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.z, self.w) } #[inline] #[must_use] fn wxwx(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.w, self.x) } #[inline] #[must_use] fn wxwy(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.w, self.y) } #[inline] #[must_use] fn wxwz(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.w, self.z) } #[inline] #[must_use] fn wxww(self) -> USizeVec4 { USizeVec4::new(self.w, self.x, self.w, self.w) } #[inline] #[must_use] fn wyxx(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.x, self.x) } #[inline] #[must_use] fn wyxy(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.x, self.y) } #[inline] #[must_use] fn wyxz(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.x, self.z) } #[inline] #[must_use] fn wyxw(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.x, self.w) } #[inline] #[must_use] fn wyyx(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.y, self.x) } #[inline] #[must_use] fn wyyy(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.y, self.y) } #[inline] #[must_use] fn wyyz(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.y, self.z) } #[inline] #[must_use] fn wyyw(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.y, self.w) } #[inline] #[must_use] fn wyzx(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.z, self.x) } #[inline] #[must_use] fn wyzy(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.z, self.y) } #[inline] #[must_use] fn wyzz(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.z, self.z) } #[inline] #[must_use] fn wyzw(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.z, self.w) } #[inline] #[must_use] fn wywx(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.w, self.x) } #[inline] #[must_use] fn wywy(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.w, self.y) } #[inline] #[must_use] fn wywz(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.w, self.z) } #[inline] #[must_use] fn wyww(self) -> USizeVec4 { USizeVec4::new(self.w, self.y, self.w, self.w) } #[inline] #[must_use] fn wzxx(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.x, self.x) } #[inline] #[must_use] fn wzxy(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.x, self.y) } #[inline] #[must_use] fn wzxz(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.x, self.z) } #[inline] #[must_use] fn wzxw(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.x, self.w) } #[inline] #[must_use] fn wzyx(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.y, self.x) } #[inline] #[must_use] fn wzyy(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.y, self.y) } #[inline] #[must_use] fn wzyz(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.y, self.z) } #[inline] #[must_use] fn wzyw(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.y, self.w) } #[inline] #[must_use] fn wzzx(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.z, self.x) } #[inline] #[must_use] fn wzzy(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.z, self.y) } #[inline] #[must_use] fn wzzz(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.z, self.z) } #[inline] #[must_use] fn wzzw(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.z, self.w) } #[inline] #[must_use] fn wzwx(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.w, self.x) } #[inline] #[must_use] fn wzwy(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.w, self.y) } #[inline] #[must_use] fn wzwz(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.w, self.z) } #[inline] #[must_use] fn wzww(self) -> USizeVec4 { USizeVec4::new(self.w, self.z, self.w, self.w) } #[inline] #[must_use] fn wwxx(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.x, self.x) } #[inline] #[must_use] fn wwxy(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.x, self.y) } #[inline] #[must_use] fn wwxz(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.x, self.z) } #[inline] #[must_use] fn wwxw(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.x, self.w) } #[inline] #[must_use] fn wwyx(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.y, self.x) } #[inline] #[must_use] fn wwyy(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.y, self.y) } #[inline] #[must_use] fn wwyz(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.y, self.z) } #[inline] #[must_use] fn wwyw(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.y, self.w) } #[inline] #[must_use] fn wwzx(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.z, self.x) } #[inline] #[must_use] fn wwzy(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.z, self.y) } #[inline] #[must_use] fn wwzz(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.z, self.z) } #[inline] #[must_use] fn wwzw(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.z, self.w) } #[inline] #[must_use] fn wwwx(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.w, self.x) } #[inline] #[must_use] fn wwwy(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.w, self.y) } #[inline] #[must_use] fn wwwz(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.w, self.z) } #[inline] #[must_use] fn wwww(self) -> USizeVec4 { USizeVec4::new(self.w, self.w, self.w, self.w) } } glam-0.30.1/src/swizzles/uvec2_impl.rs000064400000000000000000000064451046102023000157320ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{UVec2, UVec3, UVec4, Vec2Swizzles}; impl Vec2Swizzles for UVec2 { type Vec3 = UVec3; type Vec4 = UVec4; #[inline] #[must_use] fn xx(self) -> UVec2 { UVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> UVec2 { UVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> UVec2 { UVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> UVec3 { UVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> UVec3 { UVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> UVec3 { UVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> UVec3 { UVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> UVec3 { UVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> UVec3 { UVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> UVec3 { UVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> UVec3 { UVec3::new(self.y, self.y, self.y) } #[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) } } glam-0.30.1/src/swizzles/uvec3_impl.rs000064400000000000000000000341621046102023000157300ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{UVec2, UVec3, UVec4, Vec3Swizzles}; impl Vec3Swizzles for UVec3 { type Vec2 = UVec2; type Vec4 = UVec4; #[inline] #[must_use] fn xx(self) -> UVec2 { UVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> UVec2 { UVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: UVec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> UVec2 { UVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: UVec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> UVec2 { UVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: UVec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> UVec2 { UVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> UVec2 { UVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: UVec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> UVec2 { UVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: UVec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> UVec2 { UVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: UVec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> UVec2 { UVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> UVec3 { UVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> UVec3 { UVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> UVec3 { UVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> UVec3 { UVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> UVec3 { UVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> UVec3 { UVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> UVec3 { UVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> UVec3 { UVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> UVec3 { UVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> UVec3 { UVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> UVec3 { UVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> UVec3 { UVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> UVec3 { UVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> UVec3 { UVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> UVec3 { UVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> UVec3 { UVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> UVec3 { UVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> UVec3 { UVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> UVec3 { UVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> UVec3 { UVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> UVec3 { UVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> UVec3 { UVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> UVec3 { UVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> UVec3 { UVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> UVec3 { UVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> UVec3 { UVec3::new(self.z, self.z, self.z) } #[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) } } glam-0.30.1/src/swizzles/uvec4_impl.rs000064400000000000000000001253501046102023000157310ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{UVec2, UVec3, UVec4, Vec4Swizzles}; impl Vec4Swizzles for UVec4 { type Vec2 = UVec2; type Vec3 = UVec3; #[inline] #[must_use] fn xx(self) -> UVec2 { UVec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> UVec2 { UVec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: UVec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> UVec2 { UVec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: UVec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> UVec2 { UVec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: UVec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> UVec2 { UVec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: UVec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> UVec2 { UVec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> UVec2 { UVec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: UVec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> UVec2 { UVec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: UVec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> UVec2 { UVec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: UVec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> UVec2 { UVec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: UVec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> UVec2 { UVec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> UVec2 { UVec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: UVec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> UVec2 { UVec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: UVec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> UVec2 { UVec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: UVec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> UVec2 { UVec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: UVec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> UVec2 { UVec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> UVec3 { UVec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> UVec3 { UVec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> UVec3 { UVec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> UVec3 { UVec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> UVec3 { UVec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> UVec3 { UVec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> UVec3 { UVec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: UVec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> UVec3 { UVec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: UVec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> UVec3 { UVec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> UVec3 { UVec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: UVec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> UVec3 { UVec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> UVec3 { UVec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: UVec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> UVec3 { UVec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> UVec3 { UVec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: UVec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> UVec3 { UVec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: UVec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> UVec3 { UVec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> UVec3 { UVec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> UVec3 { UVec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> UVec3 { UVec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: UVec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> UVec3 { UVec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: UVec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> UVec3 { UVec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> UVec3 { UVec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> UVec3 { UVec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> UVec3 { UVec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> UVec3 { UVec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: UVec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> UVec3 { UVec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> UVec3 { UVec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> UVec3 { UVec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: UVec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> UVec3 { UVec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: UVec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> UVec3 { UVec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> UVec3 { UVec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: UVec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> UVec3 { UVec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> UVec3 { UVec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> UVec3 { UVec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: UVec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> UVec3 { UVec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> UVec3 { UVec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: UVec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> UVec3 { UVec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: UVec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> UVec3 { UVec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> UVec3 { UVec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> UVec3 { UVec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: UVec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> UVec3 { UVec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> UVec3 { UVec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> UVec3 { UVec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> UVec3 { UVec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> UVec3 { UVec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: UVec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> UVec3 { UVec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: UVec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> UVec3 { UVec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> UVec3 { UVec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> UVec3 { UVec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> UVec3 { UVec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: UVec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> UVec3 { UVec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: UVec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> UVec3 { UVec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> UVec3 { UVec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: UVec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> UVec3 { UVec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> UVec3 { UVec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: UVec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> UVec3 { UVec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> UVec3 { UVec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: UVec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> UVec3 { UVec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: UVec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> UVec3 { UVec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> UVec3 { UVec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> UVec3 { UVec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> UVec3 { UVec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> UVec3 { UVec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> UVec3 { UVec3::new(self.w, self.w, self.w) } #[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 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) } } glam-0.30.1/src/swizzles/vec2_impl.rs000064400000000000000000000063511046102023000155410ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{Vec2, Vec2Swizzles, Vec3, Vec4}; impl Vec2Swizzles for Vec2 { type Vec3 = Vec3; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[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) } } glam-0.30.1/src/swizzles/vec3_impl.rs000064400000000000000000000335761046102023000155530ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. use crate::{Vec2, Vec3, Vec3Swizzles, Vec4}; impl Vec3Swizzles for Vec3 { type Vec2 = Vec2; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3 { Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xzx(self) -> Vec3 { Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3 { Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn xzz(self) -> Vec3 { Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3 { Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3 { Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yzx(self) -> Vec3 { Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn yzy(self) -> Vec3 { Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3 { Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn zxx(self) -> Vec3 { Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3 { Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn zxz(self) -> Vec3 { Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zyx(self) -> Vec3 { Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn zyy(self) -> Vec3 { Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3 { Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zzx(self) -> Vec3 { Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3 { Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3 { Vec3::new(self.z, self.z, self.z) } #[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) } } glam-0.30.1/src/swizzles/vec_traits.rs000064400000000000000000000411521046102023000160220ustar 00000000000000// Generated from swizzle_traits.rs.tera template. Edit the template, not the generated file. pub trait Vec2Swizzles: Sized + Copy + Clone { type Vec3; type Vec4; #[inline] #[must_use] fn xy(self) -> Self { self } fn xx(self) -> Self; fn yx(self) -> Self; fn yy(self) -> Self; fn xxx(self) -> Self::Vec3; fn xxy(self) -> Self::Vec3; fn xyx(self) -> Self::Vec3; fn xyy(self) -> Self::Vec3; fn yxx(self) -> Self::Vec3; fn yxy(self) -> Self::Vec3; fn yyx(self) -> Self::Vec3; fn yyy(self) -> Self::Vec3; fn xxxx(self) -> Self::Vec4; fn xxxy(self) -> Self::Vec4; fn xxyx(self) -> Self::Vec4; fn xxyy(self) -> Self::Vec4; fn xyxx(self) -> Self::Vec4; fn xyxy(self) -> Self::Vec4; fn xyyx(self) -> Self::Vec4; fn xyyy(self) -> Self::Vec4; fn yxxx(self) -> Self::Vec4; fn yxxy(self) -> Self::Vec4; fn yxyx(self) -> Self::Vec4; fn yxyy(self) -> Self::Vec4; fn yyxx(self) -> Self::Vec4; fn yyxy(self) -> Self::Vec4; fn yyyx(self) -> Self::Vec4; fn yyyy(self) -> Self::Vec4; } pub trait Vec3Swizzles: Sized + Copy + Clone { type Vec2; type Vec4; #[inline] #[must_use] fn xyz(self) -> Self { self } fn xx(self) -> Self::Vec2; fn xy(self) -> Self::Vec2; fn with_xy(self, rhs: Self::Vec2) -> Self; fn xz(self) -> Self::Vec2; fn with_xz(self, rhs: Self::Vec2) -> Self; fn yx(self) -> Self::Vec2; fn with_yx(self, rhs: Self::Vec2) -> Self; fn yy(self) -> Self::Vec2; fn yz(self) -> Self::Vec2; fn with_yz(self, rhs: Self::Vec2) -> Self; fn zx(self) -> Self::Vec2; fn with_zx(self, rhs: Self::Vec2) -> Self; fn zy(self) -> Self::Vec2; fn with_zy(self, rhs: Self::Vec2) -> Self; fn zz(self) -> Self::Vec2; fn xxx(self) -> Self; fn xxy(self) -> Self; fn xxz(self) -> Self; fn xyx(self) -> Self; fn xyy(self) -> Self; fn xzx(self) -> Self; fn xzy(self) -> Self; fn xzz(self) -> Self; fn yxx(self) -> Self; fn yxy(self) -> Self; fn yxz(self) -> Self; fn yyx(self) -> Self; fn yyy(self) -> Self; fn yyz(self) -> Self; fn yzx(self) -> Self; fn yzy(self) -> Self; fn yzz(self) -> Self; fn zxx(self) -> Self; fn zxy(self) -> Self; fn zxz(self) -> Self; fn zyx(self) -> Self; fn zyy(self) -> Self; fn zyz(self) -> Self; fn zzx(self) -> Self; fn zzy(self) -> Self; fn zzz(self) -> Self; fn xxxx(self) -> Self::Vec4; fn xxxy(self) -> Self::Vec4; fn xxxz(self) -> Self::Vec4; fn xxyx(self) -> Self::Vec4; fn xxyy(self) -> Self::Vec4; fn xxyz(self) -> Self::Vec4; fn xxzx(self) -> Self::Vec4; fn xxzy(self) -> Self::Vec4; fn xxzz(self) -> Self::Vec4; fn xyxx(self) -> Self::Vec4; fn xyxy(self) -> Self::Vec4; fn xyxz(self) -> Self::Vec4; fn xyyx(self) -> Self::Vec4; fn xyyy(self) -> Self::Vec4; fn xyyz(self) -> Self::Vec4; fn xyzx(self) -> Self::Vec4; fn xyzy(self) -> Self::Vec4; fn xyzz(self) -> Self::Vec4; fn xzxx(self) -> Self::Vec4; fn xzxy(self) -> Self::Vec4; fn xzxz(self) -> Self::Vec4; fn xzyx(self) -> Self::Vec4; fn xzyy(self) -> Self::Vec4; fn xzyz(self) -> Self::Vec4; fn xzzx(self) -> Self::Vec4; fn xzzy(self) -> Self::Vec4; fn xzzz(self) -> Self::Vec4; fn yxxx(self) -> Self::Vec4; fn yxxy(self) -> Self::Vec4; fn yxxz(self) -> Self::Vec4; fn yxyx(self) -> Self::Vec4; fn yxyy(self) -> Self::Vec4; fn yxyz(self) -> Self::Vec4; fn yxzx(self) -> Self::Vec4; fn yxzy(self) -> Self::Vec4; fn yxzz(self) -> Self::Vec4; fn yyxx(self) -> Self::Vec4; fn yyxy(self) -> Self::Vec4; fn yyxz(self) -> Self::Vec4; fn yyyx(self) -> Self::Vec4; fn yyyy(self) -> Self::Vec4; fn yyyz(self) -> Self::Vec4; fn yyzx(self) -> Self::Vec4; fn yyzy(self) -> Self::Vec4; fn yyzz(self) -> Self::Vec4; fn yzxx(self) -> Self::Vec4; fn yzxy(self) -> Self::Vec4; fn yzxz(self) -> Self::Vec4; fn yzyx(self) -> Self::Vec4; fn yzyy(self) -> Self::Vec4; fn yzyz(self) -> Self::Vec4; fn yzzx(self) -> Self::Vec4; fn yzzy(self) -> Self::Vec4; fn yzzz(self) -> Self::Vec4; fn zxxx(self) -> Self::Vec4; fn zxxy(self) -> Self::Vec4; fn zxxz(self) -> Self::Vec4; fn zxyx(self) -> Self::Vec4; fn zxyy(self) -> Self::Vec4; fn zxyz(self) -> Self::Vec4; fn zxzx(self) -> Self::Vec4; fn zxzy(self) -> Self::Vec4; fn zxzz(self) -> Self::Vec4; fn zyxx(self) -> Self::Vec4; fn zyxy(self) -> Self::Vec4; fn zyxz(self) -> Self::Vec4; fn zyyx(self) -> Self::Vec4; fn zyyy(self) -> Self::Vec4; fn zyyz(self) -> Self::Vec4; fn zyzx(self) -> Self::Vec4; fn zyzy(self) -> Self::Vec4; fn zyzz(self) -> Self::Vec4; fn zzxx(self) -> Self::Vec4; fn zzxy(self) -> Self::Vec4; fn zzxz(self) -> Self::Vec4; fn zzyx(self) -> Self::Vec4; fn zzyy(self) -> Self::Vec4; fn zzyz(self) -> Self::Vec4; fn zzzx(self) -> Self::Vec4; fn zzzy(self) -> Self::Vec4; fn zzzz(self) -> Self::Vec4; } pub trait Vec4Swizzles: Sized + Copy + Clone { type Vec2; type Vec3; #[inline] #[must_use] fn xyzw(self) -> Self { self } fn xx(self) -> Self::Vec2; fn xy(self) -> Self::Vec2; fn with_xy(self, rhs: Self::Vec2) -> Self; fn xz(self) -> Self::Vec2; fn with_xz(self, rhs: Self::Vec2) -> Self; fn xw(self) -> Self::Vec2; fn with_xw(self, rhs: Self::Vec2) -> Self; fn yx(self) -> Self::Vec2; fn with_yx(self, rhs: Self::Vec2) -> Self; fn yy(self) -> Self::Vec2; fn yz(self) -> Self::Vec2; fn with_yz(self, rhs: Self::Vec2) -> Self; fn yw(self) -> Self::Vec2; fn with_yw(self, rhs: Self::Vec2) -> Self; fn zx(self) -> Self::Vec2; fn with_zx(self, rhs: Self::Vec2) -> Self; fn zy(self) -> Self::Vec2; fn with_zy(self, rhs: Self::Vec2) -> Self; fn zz(self) -> Self::Vec2; fn zw(self) -> Self::Vec2; fn with_zw(self, rhs: Self::Vec2) -> Self; fn wx(self) -> Self::Vec2; fn with_wx(self, rhs: Self::Vec2) -> Self; fn wy(self) -> Self::Vec2; fn with_wy(self, rhs: Self::Vec2) -> Self; fn wz(self) -> Self::Vec2; fn with_wz(self, rhs: Self::Vec2) -> Self; fn ww(self) -> Self::Vec2; fn xxx(self) -> Self::Vec3; fn xxy(self) -> Self::Vec3; fn xxz(self) -> Self::Vec3; fn xxw(self) -> Self::Vec3; fn xyx(self) -> Self::Vec3; fn xyy(self) -> Self::Vec3; fn xyz(self) -> Self::Vec3; fn with_xyz(self, rhs: Self::Vec3) -> Self; fn xyw(self) -> Self::Vec3; fn with_xyw(self, rhs: Self::Vec3) -> Self; fn xzx(self) -> Self::Vec3; fn xzy(self) -> Self::Vec3; fn with_xzy(self, rhs: Self::Vec3) -> Self; fn xzz(self) -> Self::Vec3; fn xzw(self) -> Self::Vec3; fn with_xzw(self, rhs: Self::Vec3) -> Self; fn xwx(self) -> Self::Vec3; fn xwy(self) -> Self::Vec3; fn with_xwy(self, rhs: Self::Vec3) -> Self; fn xwz(self) -> Self::Vec3; fn with_xwz(self, rhs: Self::Vec3) -> Self; fn xww(self) -> Self::Vec3; fn yxx(self) -> Self::Vec3; fn yxy(self) -> Self::Vec3; fn yxz(self) -> Self::Vec3; fn with_yxz(self, rhs: Self::Vec3) -> Self; fn yxw(self) -> Self::Vec3; fn with_yxw(self, rhs: Self::Vec3) -> Self; fn yyx(self) -> Self::Vec3; fn yyy(self) -> Self::Vec3; fn yyz(self) -> Self::Vec3; fn yyw(self) -> Self::Vec3; fn yzx(self) -> Self::Vec3; fn with_yzx(self, rhs: Self::Vec3) -> Self; fn yzy(self) -> Self::Vec3; fn yzz(self) -> Self::Vec3; fn yzw(self) -> Self::Vec3; fn with_yzw(self, rhs: Self::Vec3) -> Self; fn ywx(self) -> Self::Vec3; fn with_ywx(self, rhs: Self::Vec3) -> Self; fn ywy(self) -> Self::Vec3; fn ywz(self) -> Self::Vec3; fn with_ywz(self, rhs: Self::Vec3) -> Self; fn yww(self) -> Self::Vec3; fn zxx(self) -> Self::Vec3; fn zxy(self) -> Self::Vec3; fn with_zxy(self, rhs: Self::Vec3) -> Self; fn zxz(self) -> Self::Vec3; fn zxw(self) -> Self::Vec3; fn with_zxw(self, rhs: Self::Vec3) -> Self; fn zyx(self) -> Self::Vec3; fn with_zyx(self, rhs: Self::Vec3) -> Self; fn zyy(self) -> Self::Vec3; fn zyz(self) -> Self::Vec3; fn zyw(self) -> Self::Vec3; fn with_zyw(self, rhs: Self::Vec3) -> Self; fn zzx(self) -> Self::Vec3; fn zzy(self) -> Self::Vec3; fn zzz(self) -> Self::Vec3; fn zzw(self) -> Self::Vec3; fn zwx(self) -> Self::Vec3; fn with_zwx(self, rhs: Self::Vec3) -> Self; fn zwy(self) -> Self::Vec3; fn with_zwy(self, rhs: Self::Vec3) -> Self; fn zwz(self) -> Self::Vec3; fn zww(self) -> Self::Vec3; fn wxx(self) -> Self::Vec3; fn wxy(self) -> Self::Vec3; fn with_wxy(self, rhs: Self::Vec3) -> Self; fn wxz(self) -> Self::Vec3; fn with_wxz(self, rhs: Self::Vec3) -> Self; fn wxw(self) -> Self::Vec3; fn wyx(self) -> Self::Vec3; fn with_wyx(self, rhs: Self::Vec3) -> Self; fn wyy(self) -> Self::Vec3; fn wyz(self) -> Self::Vec3; fn with_wyz(self, rhs: Self::Vec3) -> Self; fn wyw(self) -> Self::Vec3; fn wzx(self) -> Self::Vec3; fn with_wzx(self, rhs: Self::Vec3) -> Self; fn wzy(self) -> Self::Vec3; fn with_wzy(self, rhs: Self::Vec3) -> Self; fn wzz(self) -> Self::Vec3; fn wzw(self) -> Self::Vec3; fn wwx(self) -> Self::Vec3; fn wwy(self) -> Self::Vec3; fn wwz(self) -> Self::Vec3; fn www(self) -> Self::Vec3; fn xxxx(self) -> Self; fn xxxy(self) -> Self; fn xxxz(self) -> Self; fn xxxw(self) -> Self; fn xxyx(self) -> Self; fn xxyy(self) -> Self; fn xxyz(self) -> Self; fn xxyw(self) -> Self; fn xxzx(self) -> Self; fn xxzy(self) -> Self; fn xxzz(self) -> Self; fn xxzw(self) -> Self; fn xxwx(self) -> Self; fn xxwy(self) -> Self; fn xxwz(self) -> Self; fn xxww(self) -> Self; fn xyxx(self) -> Self; fn xyxy(self) -> Self; fn xyxz(self) -> Self; fn xyxw(self) -> Self; fn xyyx(self) -> Self; fn xyyy(self) -> Self; fn xyyz(self) -> Self; fn xyyw(self) -> Self; fn xyzx(self) -> Self; fn xyzy(self) -> Self; fn xyzz(self) -> Self; fn xywx(self) -> Self; fn xywy(self) -> Self; fn xywz(self) -> Self; fn xyww(self) -> Self; fn xzxx(self) -> Self; fn xzxy(self) -> Self; fn xzxz(self) -> Self; fn xzxw(self) -> Self; fn xzyx(self) -> Self; fn xzyy(self) -> Self; fn xzyz(self) -> Self; fn xzyw(self) -> Self; fn xzzx(self) -> Self; fn xzzy(self) -> Self; fn xzzz(self) -> Self; fn xzzw(self) -> Self; fn xzwx(self) -> Self; fn xzwy(self) -> Self; fn xzwz(self) -> Self; fn xzww(self) -> Self; fn xwxx(self) -> Self; fn xwxy(self) -> Self; fn xwxz(self) -> Self; fn xwxw(self) -> Self; fn xwyx(self) -> Self; fn xwyy(self) -> Self; fn xwyz(self) -> Self; fn xwyw(self) -> Self; fn xwzx(self) -> Self; fn xwzy(self) -> Self; fn xwzz(self) -> Self; fn xwzw(self) -> Self; fn xwwx(self) -> Self; fn xwwy(self) -> Self; fn xwwz(self) -> Self; fn xwww(self) -> Self; fn yxxx(self) -> Self; fn yxxy(self) -> Self; fn yxxz(self) -> Self; fn yxxw(self) -> Self; fn yxyx(self) -> Self; fn yxyy(self) -> Self; fn yxyz(self) -> Self; fn yxyw(self) -> Self; fn yxzx(self) -> Self; fn yxzy(self) -> Self; fn yxzz(self) -> Self; fn yxzw(self) -> Self; fn yxwx(self) -> Self; fn yxwy(self) -> Self; fn yxwz(self) -> Self; fn yxww(self) -> Self; fn yyxx(self) -> Self; fn yyxy(self) -> Self; fn yyxz(self) -> Self; fn yyxw(self) -> Self; fn yyyx(self) -> Self; fn yyyy(self) -> Self; fn yyyz(self) -> Self; fn yyyw(self) -> Self; fn yyzx(self) -> Self; fn yyzy(self) -> Self; fn yyzz(self) -> Self; fn yyzw(self) -> Self; fn yywx(self) -> Self; fn yywy(self) -> Self; fn yywz(self) -> Self; fn yyww(self) -> Self; fn yzxx(self) -> Self; fn yzxy(self) -> Self; fn yzxz(self) -> Self; fn yzxw(self) -> Self; fn yzyx(self) -> Self; fn yzyy(self) -> Self; fn yzyz(self) -> Self; fn yzyw(self) -> Self; fn yzzx(self) -> Self; fn yzzy(self) -> Self; fn yzzz(self) -> Self; fn yzzw(self) -> Self; fn yzwx(self) -> Self; fn yzwy(self) -> Self; fn yzwz(self) -> Self; fn yzww(self) -> Self; fn ywxx(self) -> Self; fn ywxy(self) -> Self; fn ywxz(self) -> Self; fn ywxw(self) -> Self; fn ywyx(self) -> Self; fn ywyy(self) -> Self; fn ywyz(self) -> Self; fn ywyw(self) -> Self; fn ywzx(self) -> Self; fn ywzy(self) -> Self; fn ywzz(self) -> Self; fn ywzw(self) -> Self; fn ywwx(self) -> Self; fn ywwy(self) -> Self; fn ywwz(self) -> Self; fn ywww(self) -> Self; fn zxxx(self) -> Self; fn zxxy(self) -> Self; fn zxxz(self) -> Self; fn zxxw(self) -> Self; fn zxyx(self) -> Self; fn zxyy(self) -> Self; fn zxyz(self) -> Self; fn zxyw(self) -> Self; fn zxzx(self) -> Self; fn zxzy(self) -> Self; fn zxzz(self) -> Self; fn zxzw(self) -> Self; fn zxwx(self) -> Self; fn zxwy(self) -> Self; fn zxwz(self) -> Self; fn zxww(self) -> Self; fn zyxx(self) -> Self; fn zyxy(self) -> Self; fn zyxz(self) -> Self; fn zyxw(self) -> Self; fn zyyx(self) -> Self; fn zyyy(self) -> Self; fn zyyz(self) -> Self; fn zyyw(self) -> Self; fn zyzx(self) -> Self; fn zyzy(self) -> Self; fn zyzz(self) -> Self; fn zyzw(self) -> Self; fn zywx(self) -> Self; fn zywy(self) -> Self; fn zywz(self) -> Self; fn zyww(self) -> Self; fn zzxx(self) -> Self; fn zzxy(self) -> Self; fn zzxz(self) -> Self; fn zzxw(self) -> Self; fn zzyx(self) -> Self; fn zzyy(self) -> Self; fn zzyz(self) -> Self; fn zzyw(self) -> Self; fn zzzx(self) -> Self; fn zzzy(self) -> Self; fn zzzz(self) -> Self; fn zzzw(self) -> Self; fn zzwx(self) -> Self; fn zzwy(self) -> Self; fn zzwz(self) -> Self; fn zzww(self) -> Self; fn zwxx(self) -> Self; fn zwxy(self) -> Self; fn zwxz(self) -> Self; fn zwxw(self) -> Self; fn zwyx(self) -> Self; fn zwyy(self) -> Self; fn zwyz(self) -> Self; fn zwyw(self) -> Self; fn zwzx(self) -> Self; fn zwzy(self) -> Self; fn zwzz(self) -> Self; fn zwzw(self) -> Self; fn zwwx(self) -> Self; fn zwwy(self) -> Self; fn zwwz(self) -> Self; fn zwww(self) -> Self; fn wxxx(self) -> Self; fn wxxy(self) -> Self; fn wxxz(self) -> Self; fn wxxw(self) -> Self; fn wxyx(self) -> Self; fn wxyy(self) -> Self; fn wxyz(self) -> Self; fn wxyw(self) -> Self; fn wxzx(self) -> Self; fn wxzy(self) -> Self; fn wxzz(self) -> Self; fn wxzw(self) -> Self; fn wxwx(self) -> Self; fn wxwy(self) -> Self; fn wxwz(self) -> Self; fn wxww(self) -> Self; fn wyxx(self) -> Self; fn wyxy(self) -> Self; fn wyxz(self) -> Self; fn wyxw(self) -> Self; fn wyyx(self) -> Self; fn wyyy(self) -> Self; fn wyyz(self) -> Self; fn wyyw(self) -> Self; fn wyzx(self) -> Self; fn wyzy(self) -> Self; fn wyzz(self) -> Self; fn wyzw(self) -> Self; fn wywx(self) -> Self; fn wywy(self) -> Self; fn wywz(self) -> Self; fn wyww(self) -> Self; fn wzxx(self) -> Self; fn wzxy(self) -> Self; fn wzxz(self) -> Self; fn wzxw(self) -> Self; fn wzyx(self) -> Self; fn wzyy(self) -> Self; fn wzyz(self) -> Self; fn wzyw(self) -> Self; fn wzzx(self) -> Self; fn wzzy(self) -> Self; fn wzzz(self) -> Self; fn wzzw(self) -> Self; fn wzwx(self) -> Self; fn wzwy(self) -> Self; fn wzwz(self) -> Self; fn wzww(self) -> Self; fn wwxx(self) -> Self; fn wwxy(self) -> Self; fn wwxz(self) -> Self; fn wwxw(self) -> Self; fn wwyx(self) -> Self; fn wwyy(self) -> Self; fn wwyz(self) -> Self; fn wwyw(self) -> Self; fn wwzx(self) -> Self; fn wwzy(self) -> Self; fn wwzz(self) -> Self; fn wwzw(self) -> Self; fn wwwx(self) -> Self; fn wwwy(self) -> Self; fn wwwz(self) -> Self; fn wwww(self) -> Self; } glam-0.30.1/src/swizzles/wasm32/vec3a_impl.rs000064400000000000000000000363251046102023000170230ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. #![allow(clippy::useless_conversion)] use crate::{Vec2, Vec3A, Vec3Swizzles, Vec4}; use core::arch::wasm32::*; impl Vec3Swizzles for Vec3A { type Vec2 = Vec2; type Vec4 = Vec4; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[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 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)) } } glam-0.30.1/src/swizzles/wasm32/vec4_impl.rs000064400000000000000000001301331046102023000166530ustar 00000000000000// Generated from swizzle_impl.rs.tera template. Edit the template, not the generated file. #![allow(clippy::useless_conversion)] use crate::{Vec2, Vec3, Vec4, Vec4Swizzles}; use core::arch::wasm32::*; impl Vec4Swizzles for Vec4 { type Vec2 = Vec2; type Vec3 = Vec3; #[inline] #[must_use] fn xx(self) -> Vec2 { Vec2 { x: self.x, y: self.x, } } #[inline] #[must_use] fn xy(self) -> Vec2 { Vec2 { x: self.x, y: self.y, } } #[inline] #[must_use] fn with_xy(self, rhs: Vec2) -> Self { Self::new(rhs.x, rhs.y, self.z, self.w) } #[inline] #[must_use] fn xz(self) -> Vec2 { Vec2 { x: self.x, y: self.z, } } #[inline] #[must_use] fn with_xz(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, rhs.y, self.w) } #[inline] #[must_use] fn xw(self) -> Vec2 { Vec2 { x: self.x, y: self.w, } } #[inline] #[must_use] fn with_xw(self, rhs: Vec2) -> Self { Self::new(rhs.x, self.y, self.z, rhs.y) } #[inline] #[must_use] fn yx(self) -> Vec2 { Vec2 { x: self.y, y: self.x, } } #[inline] #[must_use] fn with_yx(self, rhs: Vec2) -> Self { Self::new(rhs.y, rhs.x, self.z, self.w) } #[inline] #[must_use] fn yy(self) -> Vec2 { Vec2 { x: self.y, y: self.y, } } #[inline] #[must_use] fn yz(self) -> Vec2 { Vec2 { x: self.y, y: self.z, } } #[inline] #[must_use] fn with_yz(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yw(self) -> Vec2 { Vec2 { x: self.y, y: self.w, } } #[inline] #[must_use] fn with_yw(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn zx(self) -> Vec2 { Vec2 { x: self.z, y: self.x, } } #[inline] #[must_use] fn with_zx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, rhs.x, self.w) } #[inline] #[must_use] fn zy(self) -> Vec2 { Vec2 { x: self.z, y: self.y, } } #[inline] #[must_use] fn with_zy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zz(self) -> Vec2 { Vec2 { x: self.z, y: self.z, } } #[inline] #[must_use] fn zw(self) -> Vec2 { Vec2 { x: self.z, y: self.w, } } #[inline] #[must_use] fn with_zw(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn wx(self) -> Vec2 { Vec2 { x: self.w, y: self.x, } } #[inline] #[must_use] fn with_wx(self, rhs: Vec2) -> Self { Self::new(rhs.y, self.y, self.z, rhs.x) } #[inline] #[must_use] fn wy(self) -> Vec2 { Vec2 { x: self.w, y: self.y, } } #[inline] #[must_use] fn with_wy(self, rhs: Vec2) -> Self { Self::new(self.x, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wz(self) -> Vec2 { Vec2 { x: self.w, y: self.z, } } #[inline] #[must_use] fn with_wz(self, rhs: Vec2) -> Self { Self::new(self.x, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn ww(self) -> Vec2 { Vec2 { x: self.w, y: self.w, } } #[inline] #[must_use] fn xxx(self) -> Vec3 { Vec3::new(self.x, self.x, self.x) } #[inline] #[must_use] fn xxy(self) -> Vec3 { Vec3::new(self.x, self.x, self.y) } #[inline] #[must_use] fn xxz(self) -> Vec3 { Vec3::new(self.x, self.x, self.z) } #[inline] #[must_use] fn xxw(self) -> Vec3 { Vec3::new(self.x, self.x, self.w) } #[inline] #[must_use] fn xyx(self) -> Vec3 { Vec3::new(self.x, self.y, self.x) } #[inline] #[must_use] fn xyy(self) -> Vec3 { Vec3::new(self.x, self.y, self.y) } #[inline] #[must_use] fn xyz(self) -> Vec3 { Vec3::new(self.x, self.y, self.z) } #[inline] #[must_use] fn with_xyz(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, rhs.z, self.w) } #[inline] #[must_use] fn xyw(self) -> Vec3 { Vec3::new(self.x, self.y, self.w) } #[inline] #[must_use] fn with_xyw(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.y, self.z, rhs.z) } #[inline] #[must_use] fn xzx(self) -> Vec3 { Vec3::new(self.x, self.z, self.x) } #[inline] #[must_use] fn xzy(self) -> Vec3 { Vec3::new(self.x, self.z, self.y) } #[inline] #[must_use] fn with_xzy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, rhs.y, self.w) } #[inline] #[must_use] fn xzz(self) -> Vec3 { Vec3::new(self.x, self.z, self.z) } #[inline] #[must_use] fn xzw(self) -> Vec3 { Vec3::new(self.x, self.z, self.w) } #[inline] #[must_use] fn with_xzw(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.y, rhs.z) } #[inline] #[must_use] fn xwx(self) -> Vec3 { Vec3::new(self.x, self.w, self.x) } #[inline] #[must_use] fn xwy(self) -> Vec3 { Vec3::new(self.x, self.w, self.y) } #[inline] #[must_use] fn with_xwy(self, rhs: Vec3) -> Self { Self::new(rhs.x, rhs.z, self.z, rhs.y) } #[inline] #[must_use] fn xwz(self) -> Vec3 { Vec3::new(self.x, self.w, self.z) } #[inline] #[must_use] fn with_xwz(self, rhs: Vec3) -> Self { Self::new(rhs.x, self.y, rhs.z, rhs.y) } #[inline] #[must_use] fn xww(self) -> Vec3 { Vec3::new(self.x, self.w, self.w) } #[inline] #[must_use] fn yxx(self) -> Vec3 { Vec3::new(self.y, self.x, self.x) } #[inline] #[must_use] fn yxy(self) -> Vec3 { Vec3::new(self.y, self.x, self.y) } #[inline] #[must_use] fn yxz(self) -> Vec3 { Vec3::new(self.y, self.x, self.z) } #[inline] #[must_use] fn with_yxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, rhs.z, self.w) } #[inline] #[must_use] fn yxw(self) -> Vec3 { Vec3::new(self.y, self.x, self.w) } #[inline] #[must_use] fn with_yxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.x, self.z, rhs.z) } #[inline] #[must_use] fn yyx(self) -> Vec3 { Vec3::new(self.y, self.y, self.x) } #[inline] #[must_use] fn yyy(self) -> Vec3 { Vec3::new(self.y, self.y, self.y) } #[inline] #[must_use] fn yyz(self) -> Vec3 { Vec3::new(self.y, self.y, self.z) } #[inline] #[must_use] fn yyw(self) -> Vec3 { Vec3::new(self.y, self.y, self.w) } #[inline] #[must_use] fn yzx(self) -> Vec3 { Vec3::new(self.y, self.z, self.x) } #[inline] #[must_use] fn with_yzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, rhs.y, self.w) } #[inline] #[must_use] fn yzy(self) -> Vec3 { Vec3::new(self.y, self.z, self.y) } #[inline] #[must_use] fn yzz(self) -> Vec3 { Vec3::new(self.y, self.z, self.z) } #[inline] #[must_use] fn yzw(self) -> Vec3 { Vec3::new(self.y, self.z, self.w) } #[inline] #[must_use] fn with_yzw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.y, rhs.z) } #[inline] #[must_use] fn ywx(self) -> Vec3 { Vec3::new(self.y, self.w, self.x) } #[inline] #[must_use] fn with_ywx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.x, self.z, rhs.y) } #[inline] #[must_use] fn ywy(self) -> Vec3 { Vec3::new(self.y, self.w, self.y) } #[inline] #[must_use] fn ywz(self) -> Vec3 { Vec3::new(self.y, self.w, self.z) } #[inline] #[must_use] fn with_ywz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.x, rhs.z, rhs.y) } #[inline] #[must_use] fn yww(self) -> Vec3 { Vec3::new(self.y, self.w, self.w) } #[inline] #[must_use] fn zxx(self) -> Vec3 { Vec3::new(self.z, self.x, self.x) } #[inline] #[must_use] fn zxy(self) -> Vec3 { Vec3::new(self.z, self.x, self.y) } #[inline] #[must_use] fn with_zxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, rhs.x, self.w) } #[inline] #[must_use] fn zxz(self) -> Vec3 { Vec3::new(self.z, self.x, self.z) } #[inline] #[must_use] fn zxw(self) -> Vec3 { Vec3::new(self.z, self.x, self.w) } #[inline] #[must_use] fn with_zxw(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zyx(self) -> Vec3 { Vec3::new(self.z, self.y, self.x) } #[inline] #[must_use] fn with_zyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, rhs.x, self.w) } #[inline] #[must_use] fn zyy(self) -> Vec3 { Vec3::new(self.z, self.y, self.y) } #[inline] #[must_use] fn zyz(self) -> Vec3 { Vec3::new(self.z, self.y, self.z) } #[inline] #[must_use] fn zyw(self) -> Vec3 { Vec3::new(self.z, self.y, self.w) } #[inline] #[must_use] fn with_zyw(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.x, rhs.z) } #[inline] #[must_use] fn zzx(self) -> Vec3 { Vec3::new(self.z, self.z, self.x) } #[inline] #[must_use] fn zzy(self) -> Vec3 { Vec3::new(self.z, self.z, self.y) } #[inline] #[must_use] fn zzz(self) -> Vec3 { Vec3::new(self.z, self.z, self.z) } #[inline] #[must_use] fn zzw(self) -> Vec3 { Vec3::new(self.z, self.z, self.w) } #[inline] #[must_use] fn zwx(self) -> Vec3 { Vec3::new(self.z, self.w, self.x) } #[inline] #[must_use] fn with_zwx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.x, rhs.y) } #[inline] #[must_use] fn zwy(self) -> Vec3 { Vec3::new(self.z, self.w, self.y) } #[inline] #[must_use] fn with_zwy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.x, rhs.y) } #[inline] #[must_use] fn zwz(self) -> Vec3 { Vec3::new(self.z, self.w, self.z) } #[inline] #[must_use] fn zww(self) -> Vec3 { Vec3::new(self.z, self.w, self.w) } #[inline] #[must_use] fn wxx(self) -> Vec3 { Vec3::new(self.w, self.x, self.x) } #[inline] #[must_use] fn wxy(self) -> Vec3 { Vec3::new(self.w, self.x, self.y) } #[inline] #[must_use] fn with_wxy(self, rhs: Vec3) -> Self { Self::new(rhs.y, rhs.z, self.z, rhs.x) } #[inline] #[must_use] fn wxz(self) -> Vec3 { Vec3::new(self.w, self.x, self.z) } #[inline] #[must_use] fn with_wxz(self, rhs: Vec3) -> Self { Self::new(rhs.y, self.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wxw(self) -> Vec3 { Vec3::new(self.w, self.x, self.w) } #[inline] #[must_use] fn wyx(self) -> Vec3 { Vec3::new(self.w, self.y, self.x) } #[inline] #[must_use] fn with_wyx(self, rhs: Vec3) -> Self { Self::new(rhs.z, rhs.y, self.z, rhs.x) } #[inline] #[must_use] fn wyy(self) -> Vec3 { Vec3::new(self.w, self.y, self.y) } #[inline] #[must_use] fn wyz(self) -> Vec3 { Vec3::new(self.w, self.y, self.z) } #[inline] #[must_use] fn with_wyz(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.y, rhs.z, rhs.x) } #[inline] #[must_use] fn wyw(self) -> Vec3 { Vec3::new(self.w, self.y, self.w) } #[inline] #[must_use] fn wzx(self) -> Vec3 { Vec3::new(self.w, self.z, self.x) } #[inline] #[must_use] fn with_wzx(self, rhs: Vec3) -> Self { Self::new(rhs.z, self.y, rhs.y, rhs.x) } #[inline] #[must_use] fn wzy(self) -> Vec3 { Vec3::new(self.w, self.z, self.y) } #[inline] #[must_use] fn with_wzy(self, rhs: Vec3) -> Self { Self::new(self.x, rhs.z, rhs.y, rhs.x) } #[inline] #[must_use] fn wzz(self) -> Vec3 { Vec3::new(self.w, self.z, self.z) } #[inline] #[must_use] fn wzw(self) -> Vec3 { Vec3::new(self.w, self.z, self.w) } #[inline] #[must_use] fn wwx(self) -> Vec3 { Vec3::new(self.w, self.w, self.x) } #[inline] #[must_use] fn wwy(self) -> Vec3 { Vec3::new(self.w, self.w, self.y) } #[inline] #[must_use] fn wwz(self) -> Vec3 { Vec3::new(self.w, self.w, self.z) } #[inline] #[must_use] fn www(self) -> Vec3 { Vec3::new(self.w, self.w, self.w) } #[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 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)) } } glam-0.30.1/src/swizzles/wasm32.rs000064400000000000000000000000371046102023000147700ustar 00000000000000mod vec3a_impl; mod vec4_impl; glam-0.30.1/src/swizzles.rs000064400000000000000000000023341046102023000136560ustar 00000000000000mod dvec2_impl; mod dvec3_impl; mod dvec4_impl; mod ivec2_impl; mod ivec3_impl; mod ivec4_impl; mod i8vec2_impl; mod i8vec3_impl; mod i8vec4_impl; mod u8vec2_impl; mod u8vec3_impl; mod u8vec4_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 usizevec2_impl; mod usizevec3_impl; mod usizevec4_impl; mod uvec2_impl; mod uvec3_impl; mod uvec4_impl; mod vec2_impl; mod vec3_impl; #[cfg(any( not(any( feature = "core-simd", target_arch = "aarch64", target_feature = "sse2", target_feature = "simd128" )), feature = "scalar-math" ))] mod scalar; #[cfg(all( target_arch = "aarch64", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod neon; #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod sse2; #[cfg(all( target_feature = "simd128", not(any(feature = "core-simd", feature = "scalar-math")) ))] mod wasm32; #[cfg(all(feature = "core-simd", not(feature = "scalar-math")))] mod coresimd; mod vec_traits; pub use vec_traits::*; glam-0.30.1/src/u16/u16vec2.rs000064400000000000000000001231131046102023000135710ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec3, U64Vec2, U8Vec2, USizeVec2, UVec2}; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u16) -> u16, { Self::new(f(self.x), f(self.y)) } /// 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 { assert!(slice.len() >= 2); 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[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u16) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u16) -> Self { self.y = y; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u16 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u16 { self.x * 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) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u16::MAX`]. /// /// See also [`checked_manhattan_distance`][U16Vec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u16 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u16::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u16 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I16Vec2) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I16Vec2) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I16Vec2) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), } } } impl Default for U16Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&U16Vec2> for U16Vec2 { type Output = U16Vec2; #[inline] fn div(self, rhs: &U16Vec2) -> U16Vec2 { self.div(*rhs) } } impl Div<&U16Vec2> for &U16Vec2 { type Output = U16Vec2; #[inline] fn div(self, rhs: &U16Vec2) -> U16Vec2 { (*self).div(*rhs) } } impl Div for &U16Vec2 { type Output = U16Vec2; #[inline] fn div(self, rhs: U16Vec2) -> U16Vec2 { (*self).div(rhs) } } impl DivAssign for U16Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&U16Vec2> for U16Vec2 { #[inline] fn div_assign(&mut self, rhs: &U16Vec2) { self.div_assign(*rhs) } } impl Div for U16Vec2 { type Output = Self; #[inline] fn div(self, rhs: u16) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&u16> for U16Vec2 { type Output = U16Vec2; #[inline] fn div(self, rhs: &u16) -> U16Vec2 { self.div(*rhs) } } impl Div<&u16> for &U16Vec2 { type Output = U16Vec2; #[inline] fn div(self, rhs: &u16) -> U16Vec2 { (*self).div(*rhs) } } impl Div for &U16Vec2 { type Output = U16Vec2; #[inline] fn div(self, rhs: u16) -> U16Vec2 { (*self).div(rhs) } } impl DivAssign for U16Vec2 { #[inline] fn div_assign(&mut self, rhs: u16) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&u16> for U16Vec2 { #[inline] fn div_assign(&mut self, rhs: &u16) { self.div_assign(*rhs) } } impl Div for u16 { type Output = U16Vec2; #[inline] fn div(self, rhs: U16Vec2) -> U16Vec2 { U16Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&U16Vec2> for u16 { type Output = U16Vec2; #[inline] fn div(self, rhs: &U16Vec2) -> U16Vec2 { self.div(*rhs) } } impl Div<&U16Vec2> for &u16 { type Output = U16Vec2; #[inline] fn div(self, rhs: &U16Vec2) -> U16Vec2 { (*self).div(*rhs) } } impl Div for &u16 { type Output = U16Vec2; #[inline] fn div(self, rhs: U16Vec2) -> U16Vec2 { (*self).div(rhs) } } impl Mul 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 Mul<&U16Vec2> for U16Vec2 { type Output = U16Vec2; #[inline] fn mul(self, rhs: &U16Vec2) -> U16Vec2 { self.mul(*rhs) } } impl Mul<&U16Vec2> for &U16Vec2 { type Output = U16Vec2; #[inline] fn mul(self, rhs: &U16Vec2) -> U16Vec2 { (*self).mul(*rhs) } } impl Mul for &U16Vec2 { type Output = U16Vec2; #[inline] fn mul(self, rhs: U16Vec2) -> U16Vec2 { (*self).mul(rhs) } } impl MulAssign for U16Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&U16Vec2> for U16Vec2 { #[inline] fn mul_assign(&mut self, rhs: &U16Vec2) { self.mul_assign(*rhs) } } impl Mul for U16Vec2 { type Output = Self; #[inline] fn mul(self, rhs: u16) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&u16> for U16Vec2 { type Output = U16Vec2; #[inline] fn mul(self, rhs: &u16) -> U16Vec2 { self.mul(*rhs) } } impl Mul<&u16> for &U16Vec2 { type Output = U16Vec2; #[inline] fn mul(self, rhs: &u16) -> U16Vec2 { (*self).mul(*rhs) } } impl Mul for &U16Vec2 { type Output = U16Vec2; #[inline] fn mul(self, rhs: u16) -> U16Vec2 { (*self).mul(rhs) } } impl MulAssign for U16Vec2 { #[inline] fn mul_assign(&mut self, rhs: u16) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&u16> for U16Vec2 { #[inline] fn mul_assign(&mut self, rhs: &u16) { self.mul_assign(*rhs) } } impl Mul for u16 { type Output = U16Vec2; #[inline] fn mul(self, rhs: U16Vec2) -> U16Vec2 { U16Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&U16Vec2> for u16 { type Output = U16Vec2; #[inline] fn mul(self, rhs: &U16Vec2) -> U16Vec2 { self.mul(*rhs) } } impl Mul<&U16Vec2> for &u16 { type Output = U16Vec2; #[inline] fn mul(self, rhs: &U16Vec2) -> U16Vec2 { (*self).mul(*rhs) } } impl Mul for &u16 { type Output = U16Vec2; #[inline] fn mul(self, rhs: U16Vec2) -> U16Vec2 { (*self).mul(rhs) } } impl Add 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 Add<&U16Vec2> for U16Vec2 { type Output = U16Vec2; #[inline] fn add(self, rhs: &U16Vec2) -> U16Vec2 { self.add(*rhs) } } impl Add<&U16Vec2> for &U16Vec2 { type Output = U16Vec2; #[inline] fn add(self, rhs: &U16Vec2) -> U16Vec2 { (*self).add(*rhs) } } impl Add for &U16Vec2 { type Output = U16Vec2; #[inline] fn add(self, rhs: U16Vec2) -> U16Vec2 { (*self).add(rhs) } } impl AddAssign for U16Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&U16Vec2> for U16Vec2 { #[inline] fn add_assign(&mut self, rhs: &U16Vec2) { self.add_assign(*rhs) } } impl Add for U16Vec2 { type Output = Self; #[inline] fn add(self, rhs: u16) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&u16> for U16Vec2 { type Output = U16Vec2; #[inline] fn add(self, rhs: &u16) -> U16Vec2 { self.add(*rhs) } } impl Add<&u16> for &U16Vec2 { type Output = U16Vec2; #[inline] fn add(self, rhs: &u16) -> U16Vec2 { (*self).add(*rhs) } } impl Add for &U16Vec2 { type Output = U16Vec2; #[inline] fn add(self, rhs: u16) -> U16Vec2 { (*self).add(rhs) } } impl AddAssign for U16Vec2 { #[inline] fn add_assign(&mut self, rhs: u16) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&u16> for U16Vec2 { #[inline] fn add_assign(&mut self, rhs: &u16) { self.add_assign(*rhs) } } impl Add for u16 { type Output = U16Vec2; #[inline] fn add(self, rhs: U16Vec2) -> U16Vec2 { U16Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&U16Vec2> for u16 { type Output = U16Vec2; #[inline] fn add(self, rhs: &U16Vec2) -> U16Vec2 { self.add(*rhs) } } impl Add<&U16Vec2> for &u16 { type Output = U16Vec2; #[inline] fn add(self, rhs: &U16Vec2) -> U16Vec2 { (*self).add(*rhs) } } impl Add for &u16 { type Output = U16Vec2; #[inline] fn add(self, rhs: U16Vec2) -> U16Vec2 { (*self).add(rhs) } } impl Sub 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 Sub<&U16Vec2> for U16Vec2 { type Output = U16Vec2; #[inline] fn sub(self, rhs: &U16Vec2) -> U16Vec2 { self.sub(*rhs) } } impl Sub<&U16Vec2> for &U16Vec2 { type Output = U16Vec2; #[inline] fn sub(self, rhs: &U16Vec2) -> U16Vec2 { (*self).sub(*rhs) } } impl Sub for &U16Vec2 { type Output = U16Vec2; #[inline] fn sub(self, rhs: U16Vec2) -> U16Vec2 { (*self).sub(rhs) } } impl SubAssign for U16Vec2 { #[inline] fn sub_assign(&mut self, rhs: U16Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&U16Vec2> for U16Vec2 { #[inline] fn sub_assign(&mut self, rhs: &U16Vec2) { self.sub_assign(*rhs) } } impl Sub for U16Vec2 { type Output = Self; #[inline] fn sub(self, rhs: u16) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&u16> for U16Vec2 { type Output = U16Vec2; #[inline] fn sub(self, rhs: &u16) -> U16Vec2 { self.sub(*rhs) } } impl Sub<&u16> for &U16Vec2 { type Output = U16Vec2; #[inline] fn sub(self, rhs: &u16) -> U16Vec2 { (*self).sub(*rhs) } } impl Sub for &U16Vec2 { type Output = U16Vec2; #[inline] fn sub(self, rhs: u16) -> U16Vec2 { (*self).sub(rhs) } } impl SubAssign for U16Vec2 { #[inline] fn sub_assign(&mut self, rhs: u16) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&u16> for U16Vec2 { #[inline] fn sub_assign(&mut self, rhs: &u16) { self.sub_assign(*rhs) } } impl Sub for u16 { type Output = U16Vec2; #[inline] fn sub(self, rhs: U16Vec2) -> U16Vec2 { U16Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&U16Vec2> for u16 { type Output = U16Vec2; #[inline] fn sub(self, rhs: &U16Vec2) -> U16Vec2 { self.sub(*rhs) } } impl Sub<&U16Vec2> for &u16 { type Output = U16Vec2; #[inline] fn sub(self, rhs: &U16Vec2) -> U16Vec2 { (*self).sub(*rhs) } } impl Sub for &u16 { type Output = U16Vec2; #[inline] fn sub(self, rhs: U16Vec2) -> U16Vec2 { (*self).sub(rhs) } } impl Rem 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 Rem<&U16Vec2> for U16Vec2 { type Output = U16Vec2; #[inline] fn rem(self, rhs: &U16Vec2) -> U16Vec2 { self.rem(*rhs) } } impl Rem<&U16Vec2> for &U16Vec2 { type Output = U16Vec2; #[inline] fn rem(self, rhs: &U16Vec2) -> U16Vec2 { (*self).rem(*rhs) } } impl Rem for &U16Vec2 { type Output = U16Vec2; #[inline] fn rem(self, rhs: U16Vec2) -> U16Vec2 { (*self).rem(rhs) } } impl RemAssign for U16Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&U16Vec2> for U16Vec2 { #[inline] fn rem_assign(&mut self, rhs: &U16Vec2) { self.rem_assign(*rhs) } } impl Rem for U16Vec2 { type Output = Self; #[inline] fn rem(self, rhs: u16) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&u16> for U16Vec2 { type Output = U16Vec2; #[inline] fn rem(self, rhs: &u16) -> U16Vec2 { self.rem(*rhs) } } impl Rem<&u16> for &U16Vec2 { type Output = U16Vec2; #[inline] fn rem(self, rhs: &u16) -> U16Vec2 { (*self).rem(*rhs) } } impl Rem for &U16Vec2 { type Output = U16Vec2; #[inline] fn rem(self, rhs: u16) -> U16Vec2 { (*self).rem(rhs) } } impl RemAssign for U16Vec2 { #[inline] fn rem_assign(&mut self, rhs: u16) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&u16> for U16Vec2 { #[inline] fn rem_assign(&mut self, rhs: &u16) { self.rem_assign(*rhs) } } impl Rem for u16 { type Output = U16Vec2; #[inline] fn rem(self, rhs: U16Vec2) -> U16Vec2 { U16Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&U16Vec2> for u16 { type Output = U16Vec2; #[inline] fn rem(self, rhs: &U16Vec2) -> U16Vec2 { self.rem(*rhs) } } impl Rem<&U16Vec2> for &u16 { type Output = U16Vec2; #[inline] fn rem(self, rhs: &U16Vec2) -> U16Vec2 { (*self).rem(*rhs) } } impl Rem for &u16 { type Output = U16Vec2; #[inline] fn rem(self, rhs: U16Vec2) -> U16Vec2 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U16Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U16Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U16Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for U16Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } 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 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 for (u16, u16) { #[inline] fn from(v: U16Vec2) -> Self { (v.x, v.y) } } impl From for U16Vec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(u16::from(v.x), u16::from(v.y)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl TryFrom for U16Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(u16::try_from(v.x)?, u16::try_from(v.y)?)) } } impl From for U16Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(u16::from(v.x), u16::from(v.y)) } } glam-0.30.1/src/u16/u16vec3.rs000064400000000000000000001371761046102023000136100ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec2, U16Vec4, U64Vec3, U8Vec3, USizeVec3, UVec3, }; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u16) -> u16, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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 { assert!(slice.len() >= 3); 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[..3].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u16) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u16) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u16) -> Self { self.z = z; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u16 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u16 { self.x * self.y * 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) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u16::MAX`]. /// /// See also [`checked_manhattan_distance`][U16Vec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u16 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u16::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u16 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I16Vec3) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I16Vec3) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I16Vec3) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), } } } impl Default for U16Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&U16Vec3> for U16Vec3 { type Output = U16Vec3; #[inline] fn div(self, rhs: &U16Vec3) -> U16Vec3 { self.div(*rhs) } } impl Div<&U16Vec3> for &U16Vec3 { type Output = U16Vec3; #[inline] fn div(self, rhs: &U16Vec3) -> U16Vec3 { (*self).div(*rhs) } } impl Div for &U16Vec3 { type Output = U16Vec3; #[inline] fn div(self, rhs: U16Vec3) -> U16Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&U16Vec3> for U16Vec3 { #[inline] fn div_assign(&mut self, rhs: &U16Vec3) { self.div_assign(*rhs) } } impl Div 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 Div<&u16> for U16Vec3 { type Output = U16Vec3; #[inline] fn div(self, rhs: &u16) -> U16Vec3 { self.div(*rhs) } } impl Div<&u16> for &U16Vec3 { type Output = U16Vec3; #[inline] fn div(self, rhs: &u16) -> U16Vec3 { (*self).div(*rhs) } } impl Div for &U16Vec3 { type Output = U16Vec3; #[inline] fn div(self, rhs: u16) -> U16Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&u16> for U16Vec3 { #[inline] fn div_assign(&mut self, rhs: &u16) { self.div_assign(*rhs) } } impl Div 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 Div<&U16Vec3> for u16 { type Output = U16Vec3; #[inline] fn div(self, rhs: &U16Vec3) -> U16Vec3 { self.div(*rhs) } } impl Div<&U16Vec3> for &u16 { type Output = U16Vec3; #[inline] fn div(self, rhs: &U16Vec3) -> U16Vec3 { (*self).div(*rhs) } } impl Div for &u16 { type Output = U16Vec3; #[inline] fn div(self, rhs: U16Vec3) -> U16Vec3 { (*self).div(rhs) } } impl Mul 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 Mul<&U16Vec3> for U16Vec3 { type Output = U16Vec3; #[inline] fn mul(self, rhs: &U16Vec3) -> U16Vec3 { self.mul(*rhs) } } impl Mul<&U16Vec3> for &U16Vec3 { type Output = U16Vec3; #[inline] fn mul(self, rhs: &U16Vec3) -> U16Vec3 { (*self).mul(*rhs) } } impl Mul for &U16Vec3 { type Output = U16Vec3; #[inline] fn mul(self, rhs: U16Vec3) -> U16Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&U16Vec3> for U16Vec3 { #[inline] fn mul_assign(&mut self, rhs: &U16Vec3) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&u16> for U16Vec3 { type Output = U16Vec3; #[inline] fn mul(self, rhs: &u16) -> U16Vec3 { self.mul(*rhs) } } impl Mul<&u16> for &U16Vec3 { type Output = U16Vec3; #[inline] fn mul(self, rhs: &u16) -> U16Vec3 { (*self).mul(*rhs) } } impl Mul for &U16Vec3 { type Output = U16Vec3; #[inline] fn mul(self, rhs: u16) -> U16Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&u16> for U16Vec3 { #[inline] fn mul_assign(&mut self, rhs: &u16) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&U16Vec3> for u16 { type Output = U16Vec3; #[inline] fn mul(self, rhs: &U16Vec3) -> U16Vec3 { self.mul(*rhs) } } impl Mul<&U16Vec3> for &u16 { type Output = U16Vec3; #[inline] fn mul(self, rhs: &U16Vec3) -> U16Vec3 { (*self).mul(*rhs) } } impl Mul for &u16 { type Output = U16Vec3; #[inline] fn mul(self, rhs: U16Vec3) -> U16Vec3 { (*self).mul(rhs) } } impl Add 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 Add<&U16Vec3> for U16Vec3 { type Output = U16Vec3; #[inline] fn add(self, rhs: &U16Vec3) -> U16Vec3 { self.add(*rhs) } } impl Add<&U16Vec3> for &U16Vec3 { type Output = U16Vec3; #[inline] fn add(self, rhs: &U16Vec3) -> U16Vec3 { (*self).add(*rhs) } } impl Add for &U16Vec3 { type Output = U16Vec3; #[inline] fn add(self, rhs: U16Vec3) -> U16Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&U16Vec3> for U16Vec3 { #[inline] fn add_assign(&mut self, rhs: &U16Vec3) { self.add_assign(*rhs) } } impl Add 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 Add<&u16> for U16Vec3 { type Output = U16Vec3; #[inline] fn add(self, rhs: &u16) -> U16Vec3 { self.add(*rhs) } } impl Add<&u16> for &U16Vec3 { type Output = U16Vec3; #[inline] fn add(self, rhs: &u16) -> U16Vec3 { (*self).add(*rhs) } } impl Add for &U16Vec3 { type Output = U16Vec3; #[inline] fn add(self, rhs: u16) -> U16Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&u16> for U16Vec3 { #[inline] fn add_assign(&mut self, rhs: &u16) { self.add_assign(*rhs) } } impl Add 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 Add<&U16Vec3> for u16 { type Output = U16Vec3; #[inline] fn add(self, rhs: &U16Vec3) -> U16Vec3 { self.add(*rhs) } } impl Add<&U16Vec3> for &u16 { type Output = U16Vec3; #[inline] fn add(self, rhs: &U16Vec3) -> U16Vec3 { (*self).add(*rhs) } } impl Add for &u16 { type Output = U16Vec3; #[inline] fn add(self, rhs: U16Vec3) -> U16Vec3 { (*self).add(rhs) } } impl Sub 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 Sub<&U16Vec3> for U16Vec3 { type Output = U16Vec3; #[inline] fn sub(self, rhs: &U16Vec3) -> U16Vec3 { self.sub(*rhs) } } impl Sub<&U16Vec3> for &U16Vec3 { type Output = U16Vec3; #[inline] fn sub(self, rhs: &U16Vec3) -> U16Vec3 { (*self).sub(*rhs) } } impl Sub for &U16Vec3 { type Output = U16Vec3; #[inline] fn sub(self, rhs: U16Vec3) -> U16Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&U16Vec3> for U16Vec3 { #[inline] fn sub_assign(&mut self, rhs: &U16Vec3) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&u16> for U16Vec3 { type Output = U16Vec3; #[inline] fn sub(self, rhs: &u16) -> U16Vec3 { self.sub(*rhs) } } impl Sub<&u16> for &U16Vec3 { type Output = U16Vec3; #[inline] fn sub(self, rhs: &u16) -> U16Vec3 { (*self).sub(*rhs) } } impl Sub for &U16Vec3 { type Output = U16Vec3; #[inline] fn sub(self, rhs: u16) -> U16Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&u16> for U16Vec3 { #[inline] fn sub_assign(&mut self, rhs: &u16) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&U16Vec3> for u16 { type Output = U16Vec3; #[inline] fn sub(self, rhs: &U16Vec3) -> U16Vec3 { self.sub(*rhs) } } impl Sub<&U16Vec3> for &u16 { type Output = U16Vec3; #[inline] fn sub(self, rhs: &U16Vec3) -> U16Vec3 { (*self).sub(*rhs) } } impl Sub for &u16 { type Output = U16Vec3; #[inline] fn sub(self, rhs: U16Vec3) -> U16Vec3 { (*self).sub(rhs) } } impl Rem 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 Rem<&U16Vec3> for U16Vec3 { type Output = U16Vec3; #[inline] fn rem(self, rhs: &U16Vec3) -> U16Vec3 { self.rem(*rhs) } } impl Rem<&U16Vec3> for &U16Vec3 { type Output = U16Vec3; #[inline] fn rem(self, rhs: &U16Vec3) -> U16Vec3 { (*self).rem(*rhs) } } impl Rem for &U16Vec3 { type Output = U16Vec3; #[inline] fn rem(self, rhs: U16Vec3) -> U16Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&U16Vec3> for U16Vec3 { #[inline] fn rem_assign(&mut self, rhs: &U16Vec3) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&u16> for U16Vec3 { type Output = U16Vec3; #[inline] fn rem(self, rhs: &u16) -> U16Vec3 { self.rem(*rhs) } } impl Rem<&u16> for &U16Vec3 { type Output = U16Vec3; #[inline] fn rem(self, rhs: &u16) -> U16Vec3 { (*self).rem(*rhs) } } impl Rem for &U16Vec3 { type Output = U16Vec3; #[inline] fn rem(self, rhs: u16) -> U16Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&u16> for U16Vec3 { #[inline] fn rem_assign(&mut self, rhs: &u16) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&U16Vec3> for u16 { type Output = U16Vec3; #[inline] fn rem(self, rhs: &U16Vec3) -> U16Vec3 { self.rem(*rhs) } } impl Rem<&U16Vec3> for &u16 { type Output = U16Vec3; #[inline] fn rem(self, rhs: &U16Vec3) -> U16Vec3 { (*self).rem(*rhs) } } impl Rem for &u16 { type Output = U16Vec3; #[inline] fn rem(self, rhs: U16Vec3) -> U16Vec3 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U16Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U16Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U16Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for U16Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } 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 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 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 From for U16Vec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(u16::from(v.x), u16::from(v.y), u16::from(v.z)) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl TryFrom for U16Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, )) } } impl From for U16Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(u16::from(v.x), u16::from(v.y), u16::from(v.z)) } } impl From for U16Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( u16::from(bool_array[0]), u16::from(bool_array[1]), u16::from(bool_array[2]), ) } } glam-0.30.1/src/u16/u16vec4.rs000064400000000000000000001502131046102023000135740ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec2, U16Vec3, U64Vec4, U8Vec4, USizeVec4, UVec4, }; 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, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u16) -> u16, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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 { assert!(slice.len() >= 4); 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[..4].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u16) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u16) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u16) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: u16) -> Self { self.w = w; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u16 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u16 { self.x * self.y * self.z * 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) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u16::MAX`]. /// /// See also [`checked_manhattan_distance`][U16Vec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u16 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u16::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u16 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I16Vec4) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_signed(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I16Vec4) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), w: self.w.wrapping_add_signed(rhs.w), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I16Vec4) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), w: self.w.saturating_add_signed(rhs.w), } } } impl Default for U16Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&U16Vec4> for U16Vec4 { type Output = U16Vec4; #[inline] fn div(self, rhs: &U16Vec4) -> U16Vec4 { self.div(*rhs) } } impl Div<&U16Vec4> for &U16Vec4 { type Output = U16Vec4; #[inline] fn div(self, rhs: &U16Vec4) -> U16Vec4 { (*self).div(*rhs) } } impl Div for &U16Vec4 { type Output = U16Vec4; #[inline] fn div(self, rhs: U16Vec4) -> U16Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&U16Vec4> for U16Vec4 { #[inline] fn div_assign(&mut self, rhs: &U16Vec4) { self.div_assign(*rhs) } } impl Div 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 Div<&u16> for U16Vec4 { type Output = U16Vec4; #[inline] fn div(self, rhs: &u16) -> U16Vec4 { self.div(*rhs) } } impl Div<&u16> for &U16Vec4 { type Output = U16Vec4; #[inline] fn div(self, rhs: &u16) -> U16Vec4 { (*self).div(*rhs) } } impl Div for &U16Vec4 { type Output = U16Vec4; #[inline] fn div(self, rhs: u16) -> U16Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&u16> for U16Vec4 { #[inline] fn div_assign(&mut self, rhs: &u16) { self.div_assign(*rhs) } } impl Div 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 Div<&U16Vec4> for u16 { type Output = U16Vec4; #[inline] fn div(self, rhs: &U16Vec4) -> U16Vec4 { self.div(*rhs) } } impl Div<&U16Vec4> for &u16 { type Output = U16Vec4; #[inline] fn div(self, rhs: &U16Vec4) -> U16Vec4 { (*self).div(*rhs) } } impl Div for &u16 { type Output = U16Vec4; #[inline] fn div(self, rhs: U16Vec4) -> U16Vec4 { (*self).div(rhs) } } impl Mul 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 Mul<&U16Vec4> for U16Vec4 { type Output = U16Vec4; #[inline] fn mul(self, rhs: &U16Vec4) -> U16Vec4 { self.mul(*rhs) } } impl Mul<&U16Vec4> for &U16Vec4 { type Output = U16Vec4; #[inline] fn mul(self, rhs: &U16Vec4) -> U16Vec4 { (*self).mul(*rhs) } } impl Mul for &U16Vec4 { type Output = U16Vec4; #[inline] fn mul(self, rhs: U16Vec4) -> U16Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&U16Vec4> for U16Vec4 { #[inline] fn mul_assign(&mut self, rhs: &U16Vec4) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&u16> for U16Vec4 { type Output = U16Vec4; #[inline] fn mul(self, rhs: &u16) -> U16Vec4 { self.mul(*rhs) } } impl Mul<&u16> for &U16Vec4 { type Output = U16Vec4; #[inline] fn mul(self, rhs: &u16) -> U16Vec4 { (*self).mul(*rhs) } } impl Mul for &U16Vec4 { type Output = U16Vec4; #[inline] fn mul(self, rhs: u16) -> U16Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&u16> for U16Vec4 { #[inline] fn mul_assign(&mut self, rhs: &u16) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&U16Vec4> for u16 { type Output = U16Vec4; #[inline] fn mul(self, rhs: &U16Vec4) -> U16Vec4 { self.mul(*rhs) } } impl Mul<&U16Vec4> for &u16 { type Output = U16Vec4; #[inline] fn mul(self, rhs: &U16Vec4) -> U16Vec4 { (*self).mul(*rhs) } } impl Mul for &u16 { type Output = U16Vec4; #[inline] fn mul(self, rhs: U16Vec4) -> U16Vec4 { (*self).mul(rhs) } } impl Add 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 Add<&U16Vec4> for U16Vec4 { type Output = U16Vec4; #[inline] fn add(self, rhs: &U16Vec4) -> U16Vec4 { self.add(*rhs) } } impl Add<&U16Vec4> for &U16Vec4 { type Output = U16Vec4; #[inline] fn add(self, rhs: &U16Vec4) -> U16Vec4 { (*self).add(*rhs) } } impl Add for &U16Vec4 { type Output = U16Vec4; #[inline] fn add(self, rhs: U16Vec4) -> U16Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&U16Vec4> for U16Vec4 { #[inline] fn add_assign(&mut self, rhs: &U16Vec4) { self.add_assign(*rhs) } } impl Add 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 Add<&u16> for U16Vec4 { type Output = U16Vec4; #[inline] fn add(self, rhs: &u16) -> U16Vec4 { self.add(*rhs) } } impl Add<&u16> for &U16Vec4 { type Output = U16Vec4; #[inline] fn add(self, rhs: &u16) -> U16Vec4 { (*self).add(*rhs) } } impl Add for &U16Vec4 { type Output = U16Vec4; #[inline] fn add(self, rhs: u16) -> U16Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&u16> for U16Vec4 { #[inline] fn add_assign(&mut self, rhs: &u16) { self.add_assign(*rhs) } } impl Add 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 Add<&U16Vec4> for u16 { type Output = U16Vec4; #[inline] fn add(self, rhs: &U16Vec4) -> U16Vec4 { self.add(*rhs) } } impl Add<&U16Vec4> for &u16 { type Output = U16Vec4; #[inline] fn add(self, rhs: &U16Vec4) -> U16Vec4 { (*self).add(*rhs) } } impl Add for &u16 { type Output = U16Vec4; #[inline] fn add(self, rhs: U16Vec4) -> U16Vec4 { (*self).add(rhs) } } impl Sub 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 Sub<&U16Vec4> for U16Vec4 { type Output = U16Vec4; #[inline] fn sub(self, rhs: &U16Vec4) -> U16Vec4 { self.sub(*rhs) } } impl Sub<&U16Vec4> for &U16Vec4 { type Output = U16Vec4; #[inline] fn sub(self, rhs: &U16Vec4) -> U16Vec4 { (*self).sub(*rhs) } } impl Sub for &U16Vec4 { type Output = U16Vec4; #[inline] fn sub(self, rhs: U16Vec4) -> U16Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&U16Vec4> for U16Vec4 { #[inline] fn sub_assign(&mut self, rhs: &U16Vec4) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&u16> for U16Vec4 { type Output = U16Vec4; #[inline] fn sub(self, rhs: &u16) -> U16Vec4 { self.sub(*rhs) } } impl Sub<&u16> for &U16Vec4 { type Output = U16Vec4; #[inline] fn sub(self, rhs: &u16) -> U16Vec4 { (*self).sub(*rhs) } } impl Sub for &U16Vec4 { type Output = U16Vec4; #[inline] fn sub(self, rhs: u16) -> U16Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&u16> for U16Vec4 { #[inline] fn sub_assign(&mut self, rhs: &u16) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&U16Vec4> for u16 { type Output = U16Vec4; #[inline] fn sub(self, rhs: &U16Vec4) -> U16Vec4 { self.sub(*rhs) } } impl Sub<&U16Vec4> for &u16 { type Output = U16Vec4; #[inline] fn sub(self, rhs: &U16Vec4) -> U16Vec4 { (*self).sub(*rhs) } } impl Sub for &u16 { type Output = U16Vec4; #[inline] fn sub(self, rhs: U16Vec4) -> U16Vec4 { (*self).sub(rhs) } } impl Rem 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 Rem<&U16Vec4> for U16Vec4 { type Output = U16Vec4; #[inline] fn rem(self, rhs: &U16Vec4) -> U16Vec4 { self.rem(*rhs) } } impl Rem<&U16Vec4> for &U16Vec4 { type Output = U16Vec4; #[inline] fn rem(self, rhs: &U16Vec4) -> U16Vec4 { (*self).rem(*rhs) } } impl Rem for &U16Vec4 { type Output = U16Vec4; #[inline] fn rem(self, rhs: U16Vec4) -> U16Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&U16Vec4> for U16Vec4 { #[inline] fn rem_assign(&mut self, rhs: &U16Vec4) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&u16> for U16Vec4 { type Output = U16Vec4; #[inline] fn rem(self, rhs: &u16) -> U16Vec4 { self.rem(*rhs) } } impl Rem<&u16> for &U16Vec4 { type Output = U16Vec4; #[inline] fn rem(self, rhs: &u16) -> U16Vec4 { (*self).rem(*rhs) } } impl Rem for &U16Vec4 { type Output = U16Vec4; #[inline] fn rem(self, rhs: u16) -> U16Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&u16> for U16Vec4 { #[inline] fn rem_assign(&mut self, rhs: &u16) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&U16Vec4> for u16 { type Output = U16Vec4; #[inline] fn rem(self, rhs: &U16Vec4) -> U16Vec4 { self.rem(*rhs) } } impl Rem<&U16Vec4> for &u16 { type Output = U16Vec4; #[inline] fn rem(self, rhs: &U16Vec4) -> U16Vec4 { (*self).rem(*rhs) } } impl Rem for &u16 { type Output = U16Vec4; #[inline] fn rem(self, rhs: U16Vec4) -> U16Vec4 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U16Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U16Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U16Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for U16Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } 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 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 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 From for U16Vec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( u16::from(v.x), u16::from(v.y), u16::from(v.z), u16::from(v.w), ) } } impl TryFrom for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec4) -> Result { 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 for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec4) -> Result { 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 for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { 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 for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec4) -> Result { 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 for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { 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 for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { 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 for U16Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( u16::try_from(v.x)?, u16::try_from(v.y)?, u16::try_from(v.z)?, u16::try_from(v.w)?, )) } } impl From for U16Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( u16::from(v.x), u16::from(v.y), u16::from(v.z), u16::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for U16Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( u16::from(bool_array[0]), u16::from(bool_array[1]), u16::from(bool_array[2]), u16::from(bool_array[3]), ) } } glam-0.30.1/src/u16.rs000064400000000000000000000022721046102023000124000ustar 00000000000000mod 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::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(4, core::mem::align_of::()); } mod const_test_u16vec3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(6, core::mem::size_of::()); } mod const_test_u16vec4 { const_assert_eq!(8, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(8, core::mem::align_of::()); } } glam-0.30.1/src/u32/uvec2.rs000064400000000000000000001215671046102023000134330ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec3}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn uvec2(x: u32, y: u32) -> UVec2 { UVec2::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(8)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct UVec2 { pub x: u32, pub y: u32, } impl UVec2 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// 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 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u32) -> u32, { Self::new(f(self.x), f(self.y)) } /// 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: [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] } /// 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: &[u32]) -> Self { assert!(slice.len() >= 2); 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 [u32]) { slice[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u32) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u32) -> Self { self.y = y; self } /// 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)) } /// 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 [`u32::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) -> u32 { 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) -> u32 { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u32 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u32 { self.x * 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) -> u32 { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u32::MAX`]. /// /// See also [`checked_manhattan_distance`][UVec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u32 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u32::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u32 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: IVec2) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: IVec2) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: IVec2) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), } } } impl Default for UVec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for UVec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&UVec2> for UVec2 { type Output = UVec2; #[inline] fn div(self, rhs: &UVec2) -> UVec2 { self.div(*rhs) } } impl Div<&UVec2> for &UVec2 { type Output = UVec2; #[inline] fn div(self, rhs: &UVec2) -> UVec2 { (*self).div(*rhs) } } impl Div for &UVec2 { type Output = UVec2; #[inline] fn div(self, rhs: UVec2) -> UVec2 { (*self).div(rhs) } } impl DivAssign for UVec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&UVec2> for UVec2 { #[inline] fn div_assign(&mut self, rhs: &UVec2) { self.div_assign(*rhs) } } impl Div for UVec2 { type Output = Self; #[inline] fn div(self, rhs: u32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&u32> for UVec2 { type Output = UVec2; #[inline] fn div(self, rhs: &u32) -> UVec2 { self.div(*rhs) } } impl Div<&u32> for &UVec2 { type Output = UVec2; #[inline] fn div(self, rhs: &u32) -> UVec2 { (*self).div(*rhs) } } impl Div for &UVec2 { type Output = UVec2; #[inline] fn div(self, rhs: u32) -> UVec2 { (*self).div(rhs) } } impl DivAssign for UVec2 { #[inline] fn div_assign(&mut self, rhs: u32) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&u32> for UVec2 { #[inline] fn div_assign(&mut self, rhs: &u32) { self.div_assign(*rhs) } } impl Div for u32 { type Output = UVec2; #[inline] fn div(self, rhs: UVec2) -> UVec2 { UVec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&UVec2> for u32 { type Output = UVec2; #[inline] fn div(self, rhs: &UVec2) -> UVec2 { self.div(*rhs) } } impl Div<&UVec2> for &u32 { type Output = UVec2; #[inline] fn div(self, rhs: &UVec2) -> UVec2 { (*self).div(*rhs) } } impl Div for &u32 { type Output = UVec2; #[inline] fn div(self, rhs: UVec2) -> UVec2 { (*self).div(rhs) } } impl Mul for UVec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&UVec2> for UVec2 { type Output = UVec2; #[inline] fn mul(self, rhs: &UVec2) -> UVec2 { self.mul(*rhs) } } impl Mul<&UVec2> for &UVec2 { type Output = UVec2; #[inline] fn mul(self, rhs: &UVec2) -> UVec2 { (*self).mul(*rhs) } } impl Mul for &UVec2 { type Output = UVec2; #[inline] fn mul(self, rhs: UVec2) -> UVec2 { (*self).mul(rhs) } } impl MulAssign for UVec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&UVec2> for UVec2 { #[inline] fn mul_assign(&mut self, rhs: &UVec2) { self.mul_assign(*rhs) } } impl Mul for UVec2 { type Output = Self; #[inline] fn mul(self, rhs: u32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&u32> for UVec2 { type Output = UVec2; #[inline] fn mul(self, rhs: &u32) -> UVec2 { self.mul(*rhs) } } impl Mul<&u32> for &UVec2 { type Output = UVec2; #[inline] fn mul(self, rhs: &u32) -> UVec2 { (*self).mul(*rhs) } } impl Mul for &UVec2 { type Output = UVec2; #[inline] fn mul(self, rhs: u32) -> UVec2 { (*self).mul(rhs) } } impl MulAssign for UVec2 { #[inline] fn mul_assign(&mut self, rhs: u32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&u32> for UVec2 { #[inline] fn mul_assign(&mut self, rhs: &u32) { self.mul_assign(*rhs) } } impl Mul for u32 { type Output = UVec2; #[inline] fn mul(self, rhs: UVec2) -> UVec2 { UVec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&UVec2> for u32 { type Output = UVec2; #[inline] fn mul(self, rhs: &UVec2) -> UVec2 { self.mul(*rhs) } } impl Mul<&UVec2> for &u32 { type Output = UVec2; #[inline] fn mul(self, rhs: &UVec2) -> UVec2 { (*self).mul(*rhs) } } impl Mul for &u32 { type Output = UVec2; #[inline] fn mul(self, rhs: UVec2) -> UVec2 { (*self).mul(rhs) } } impl Add for UVec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&UVec2> for UVec2 { type Output = UVec2; #[inline] fn add(self, rhs: &UVec2) -> UVec2 { self.add(*rhs) } } impl Add<&UVec2> for &UVec2 { type Output = UVec2; #[inline] fn add(self, rhs: &UVec2) -> UVec2 { (*self).add(*rhs) } } impl Add for &UVec2 { type Output = UVec2; #[inline] fn add(self, rhs: UVec2) -> UVec2 { (*self).add(rhs) } } impl AddAssign for UVec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&UVec2> for UVec2 { #[inline] fn add_assign(&mut self, rhs: &UVec2) { self.add_assign(*rhs) } } impl Add for UVec2 { type Output = Self; #[inline] fn add(self, rhs: u32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&u32> for UVec2 { type Output = UVec2; #[inline] fn add(self, rhs: &u32) -> UVec2 { self.add(*rhs) } } impl Add<&u32> for &UVec2 { type Output = UVec2; #[inline] fn add(self, rhs: &u32) -> UVec2 { (*self).add(*rhs) } } impl Add for &UVec2 { type Output = UVec2; #[inline] fn add(self, rhs: u32) -> UVec2 { (*self).add(rhs) } } impl AddAssign for UVec2 { #[inline] fn add_assign(&mut self, rhs: u32) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&u32> for UVec2 { #[inline] fn add_assign(&mut self, rhs: &u32) { self.add_assign(*rhs) } } impl Add for u32 { type Output = UVec2; #[inline] fn add(self, rhs: UVec2) -> UVec2 { UVec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&UVec2> for u32 { type Output = UVec2; #[inline] fn add(self, rhs: &UVec2) -> UVec2 { self.add(*rhs) } } impl Add<&UVec2> for &u32 { type Output = UVec2; #[inline] fn add(self, rhs: &UVec2) -> UVec2 { (*self).add(*rhs) } } impl Add for &u32 { type Output = UVec2; #[inline] fn add(self, rhs: UVec2) -> UVec2 { (*self).add(rhs) } } impl Sub for UVec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&UVec2> for UVec2 { type Output = UVec2; #[inline] fn sub(self, rhs: &UVec2) -> UVec2 { self.sub(*rhs) } } impl Sub<&UVec2> for &UVec2 { type Output = UVec2; #[inline] fn sub(self, rhs: &UVec2) -> UVec2 { (*self).sub(*rhs) } } impl Sub for &UVec2 { type Output = UVec2; #[inline] fn sub(self, rhs: UVec2) -> UVec2 { (*self).sub(rhs) } } impl SubAssign for UVec2 { #[inline] fn sub_assign(&mut self, rhs: UVec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&UVec2> for UVec2 { #[inline] fn sub_assign(&mut self, rhs: &UVec2) { self.sub_assign(*rhs) } } impl Sub for UVec2 { type Output = Self; #[inline] fn sub(self, rhs: u32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&u32> for UVec2 { type Output = UVec2; #[inline] fn sub(self, rhs: &u32) -> UVec2 { self.sub(*rhs) } } impl Sub<&u32> for &UVec2 { type Output = UVec2; #[inline] fn sub(self, rhs: &u32) -> UVec2 { (*self).sub(*rhs) } } impl Sub for &UVec2 { type Output = UVec2; #[inline] fn sub(self, rhs: u32) -> UVec2 { (*self).sub(rhs) } } impl SubAssign for UVec2 { #[inline] fn sub_assign(&mut self, rhs: u32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&u32> for UVec2 { #[inline] fn sub_assign(&mut self, rhs: &u32) { self.sub_assign(*rhs) } } impl Sub for u32 { type Output = UVec2; #[inline] fn sub(self, rhs: UVec2) -> UVec2 { UVec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&UVec2> for u32 { type Output = UVec2; #[inline] fn sub(self, rhs: &UVec2) -> UVec2 { self.sub(*rhs) } } impl Sub<&UVec2> for &u32 { type Output = UVec2; #[inline] fn sub(self, rhs: &UVec2) -> UVec2 { (*self).sub(*rhs) } } impl Sub for &u32 { type Output = UVec2; #[inline] fn sub(self, rhs: UVec2) -> UVec2 { (*self).sub(rhs) } } impl Rem for UVec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&UVec2> for UVec2 { type Output = UVec2; #[inline] fn rem(self, rhs: &UVec2) -> UVec2 { self.rem(*rhs) } } impl Rem<&UVec2> for &UVec2 { type Output = UVec2; #[inline] fn rem(self, rhs: &UVec2) -> UVec2 { (*self).rem(*rhs) } } impl Rem for &UVec2 { type Output = UVec2; #[inline] fn rem(self, rhs: UVec2) -> UVec2 { (*self).rem(rhs) } } impl RemAssign for UVec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&UVec2> for UVec2 { #[inline] fn rem_assign(&mut self, rhs: &UVec2) { self.rem_assign(*rhs) } } impl Rem for UVec2 { type Output = Self; #[inline] fn rem(self, rhs: u32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&u32> for UVec2 { type Output = UVec2; #[inline] fn rem(self, rhs: &u32) -> UVec2 { self.rem(*rhs) } } impl Rem<&u32> for &UVec2 { type Output = UVec2; #[inline] fn rem(self, rhs: &u32) -> UVec2 { (*self).rem(*rhs) } } impl Rem for &UVec2 { type Output = UVec2; #[inline] fn rem(self, rhs: u32) -> UVec2 { (*self).rem(rhs) } } impl RemAssign for UVec2 { #[inline] fn rem_assign(&mut self, rhs: u32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&u32> for UVec2 { #[inline] fn rem_assign(&mut self, rhs: &u32) { self.rem_assign(*rhs) } } impl Rem for u32 { type Output = UVec2; #[inline] fn rem(self, rhs: UVec2) -> UVec2 { UVec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&UVec2> for u32 { type Output = UVec2; #[inline] fn rem(self, rhs: &UVec2) -> UVec2 { self.rem(*rhs) } } impl Rem<&UVec2> for &u32 { type Output = UVec2; #[inline] fn rem(self, rhs: &UVec2) -> UVec2 { (*self).rem(*rhs) } } impl Rem for &u32 { type Output = UVec2; #[inline] fn rem(self, rhs: UVec2) -> UVec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[u32; 2]> for UVec2 { #[inline] fn as_ref(&self) -> &[u32; 2] { unsafe { &*(self as *const UVec2 as *const [u32; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[u32; 2]> for UVec2 { #[inline] fn as_mut(&mut self) -> &mut [u32; 2] { unsafe { &mut *(self as *mut UVec2 as *mut [u32; 2]) } } } impl Sum for UVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for UVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for UVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for UVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for UVec2 { type Output = Self; #[inline] fn not(self) -> Self::Output { Self { x: self.x.not(), y: self.y.not(), } } } impl BitAnd for UVec2 { 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 UVec2 { 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 UVec2 { 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 for UVec2 { type Output = Self; #[inline] fn bitand(self, rhs: u32) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), } } } impl BitOr for UVec2 { type Output = Self; #[inline] fn bitor(self, rhs: u32) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), } } } impl BitXor for UVec2 { type Output = Self; #[inline] fn bitxor(self, rhs: u32) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), } } } impl Shl for UVec2 { type Output = Self; #[inline] fn shl(self, rhs: i8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for UVec2 { type Output = Self; #[inline] fn shr(self, rhs: i8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for UVec2 { type Output = Self; #[inline] fn shl(self, rhs: i16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for UVec2 { type Output = Self; #[inline] fn shr(self, rhs: i16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for UVec2 { type Output = Self; #[inline] fn shl(self, rhs: i32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for UVec2 { type Output = Self; #[inline] fn shr(self, rhs: i32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl 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 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 for UVec2 { type Output = Self; #[inline] fn shl(self, rhs: u8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for UVec2 { type Output = Self; #[inline] fn shr(self, rhs: u8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for UVec2 { type Output = Self; #[inline] fn shl(self, rhs: u16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for UVec2 { type Output = Self; #[inline] fn shr(self, rhs: u16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for UVec2 { type Output = Self; #[inline] fn shl(self, rhs: u32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for UVec2 { type Output = Self; #[inline] fn shr(self, rhs: u32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl 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 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 for UVec2 { 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 for UVec2 { 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 for UVec2 { 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 for UVec2 { 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 for UVec2 { type Output = u32; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for UVec2 { #[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"), } } } impl fmt::Display for UVec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } impl fmt::Debug for UVec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(UVec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[u32; 2]> for UVec2 { #[inline] fn from(a: [u32; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [u32; 2] { #[inline] fn from(v: UVec2) -> Self { [v.x, v.y] } } impl From<(u32, u32)> for UVec2 { #[inline] fn from(t: (u32, u32)) -> Self { Self::new(t.0, t.1) } } impl From for (u32, u32) { #[inline] fn from(v: UVec2) -> Self { (v.x, v.y) } } impl From for UVec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(u32::from(v.x), u32::from(v.y)) } } impl From for UVec2 { #[inline] fn from(v: U16Vec2) -> Self { Self::new(u32::from(v.x), u32::from(v.y)) } } impl TryFrom for UVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec2) -> Result { Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?)) } } impl TryFrom for UVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec2) -> Result { Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?)) } } impl TryFrom for UVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?)) } } impl TryFrom for UVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?)) } } impl TryFrom for UVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?)) } } impl TryFrom for UVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(u32::try_from(v.x)?, u32::try_from(v.y)?)) } } impl From for UVec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(u32::from(v.x), u32::from(v.y)) } } glam-0.30.1/src/u32/uvec3.rs000064400000000000000000001355501046102023000134310ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec2, UVec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// 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 UVec3 { pub x: u32, pub y: u32, pub z: u32, } impl UVec3 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// 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 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: 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u32) -> u32, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [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] } /// 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: &[u32]) -> Self { assert!(slice.len() >= 3); 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 [u32]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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, 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: 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()`][crate::swizzles::Vec3Swizzles::xy()]. #[inline] #[must_use] pub fn truncate(self) -> UVec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u32) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u32) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u32) -> Self { self.z = z; self } /// 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, 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 [`u32::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) -> u32 { 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) -> u32 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u32 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u32 { self.x * self.y * 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) -> u32 { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u32::MAX`]. /// /// See also [`checked_manhattan_distance`][UVec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u32 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u32::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u32 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: IVec3) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: IVec3) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: IVec3) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), } } } impl Default for UVec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for UVec3 { 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 Div<&UVec3> for UVec3 { type Output = UVec3; #[inline] fn div(self, rhs: &UVec3) -> UVec3 { self.div(*rhs) } } impl Div<&UVec3> for &UVec3 { type Output = UVec3; #[inline] fn div(self, rhs: &UVec3) -> UVec3 { (*self).div(*rhs) } } impl Div for &UVec3 { type Output = UVec3; #[inline] fn div(self, rhs: UVec3) -> UVec3 { (*self).div(rhs) } } impl DivAssign for UVec3 { #[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 DivAssign<&UVec3> for UVec3 { #[inline] fn div_assign(&mut self, rhs: &UVec3) { self.div_assign(*rhs) } } impl Div for UVec3 { type Output = Self; #[inline] fn div(self, rhs: u32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&u32> for UVec3 { type Output = UVec3; #[inline] fn div(self, rhs: &u32) -> UVec3 { self.div(*rhs) } } impl Div<&u32> for &UVec3 { type Output = UVec3; #[inline] fn div(self, rhs: &u32) -> UVec3 { (*self).div(*rhs) } } impl Div for &UVec3 { type Output = UVec3; #[inline] fn div(self, rhs: u32) -> UVec3 { (*self).div(rhs) } } impl DivAssign for UVec3 { #[inline] fn div_assign(&mut self, rhs: u32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&u32> for UVec3 { #[inline] fn div_assign(&mut self, rhs: &u32) { self.div_assign(*rhs) } } impl Div for u32 { type Output = UVec3; #[inline] fn div(self, rhs: UVec3) -> UVec3 { UVec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&UVec3> for u32 { type Output = UVec3; #[inline] fn div(self, rhs: &UVec3) -> UVec3 { self.div(*rhs) } } impl Div<&UVec3> for &u32 { type Output = UVec3; #[inline] fn div(self, rhs: &UVec3) -> UVec3 { (*self).div(*rhs) } } impl Div for &u32 { type Output = UVec3; #[inline] fn div(self, rhs: UVec3) -> UVec3 { (*self).div(rhs) } } impl Mul for UVec3 { 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 Mul<&UVec3> for UVec3 { type Output = UVec3; #[inline] fn mul(self, rhs: &UVec3) -> UVec3 { self.mul(*rhs) } } impl Mul<&UVec3> for &UVec3 { type Output = UVec3; #[inline] fn mul(self, rhs: &UVec3) -> UVec3 { (*self).mul(*rhs) } } impl Mul for &UVec3 { type Output = UVec3; #[inline] fn mul(self, rhs: UVec3) -> UVec3 { (*self).mul(rhs) } } impl MulAssign for UVec3 { #[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 MulAssign<&UVec3> for UVec3 { #[inline] fn mul_assign(&mut self, rhs: &UVec3) { self.mul_assign(*rhs) } } impl Mul for UVec3 { type Output = Self; #[inline] fn mul(self, rhs: u32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&u32> for UVec3 { type Output = UVec3; #[inline] fn mul(self, rhs: &u32) -> UVec3 { self.mul(*rhs) } } impl Mul<&u32> for &UVec3 { type Output = UVec3; #[inline] fn mul(self, rhs: &u32) -> UVec3 { (*self).mul(*rhs) } } impl Mul for &UVec3 { type Output = UVec3; #[inline] fn mul(self, rhs: u32) -> UVec3 { (*self).mul(rhs) } } impl MulAssign for UVec3 { #[inline] fn mul_assign(&mut self, rhs: u32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&u32> for UVec3 { #[inline] fn mul_assign(&mut self, rhs: &u32) { self.mul_assign(*rhs) } } impl Mul for u32 { type Output = UVec3; #[inline] fn mul(self, rhs: UVec3) -> UVec3 { UVec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&UVec3> for u32 { type Output = UVec3; #[inline] fn mul(self, rhs: &UVec3) -> UVec3 { self.mul(*rhs) } } impl Mul<&UVec3> for &u32 { type Output = UVec3; #[inline] fn mul(self, rhs: &UVec3) -> UVec3 { (*self).mul(*rhs) } } impl Mul for &u32 { type Output = UVec3; #[inline] fn mul(self, rhs: UVec3) -> UVec3 { (*self).mul(rhs) } } impl Add for UVec3 { 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 Add<&UVec3> for UVec3 { type Output = UVec3; #[inline] fn add(self, rhs: &UVec3) -> UVec3 { self.add(*rhs) } } impl Add<&UVec3> for &UVec3 { type Output = UVec3; #[inline] fn add(self, rhs: &UVec3) -> UVec3 { (*self).add(*rhs) } } impl Add for &UVec3 { type Output = UVec3; #[inline] fn add(self, rhs: UVec3) -> UVec3 { (*self).add(rhs) } } impl AddAssign for UVec3 { #[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 AddAssign<&UVec3> for UVec3 { #[inline] fn add_assign(&mut self, rhs: &UVec3) { self.add_assign(*rhs) } } impl Add for UVec3 { type Output = Self; #[inline] fn add(self, rhs: u32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&u32> for UVec3 { type Output = UVec3; #[inline] fn add(self, rhs: &u32) -> UVec3 { self.add(*rhs) } } impl Add<&u32> for &UVec3 { type Output = UVec3; #[inline] fn add(self, rhs: &u32) -> UVec3 { (*self).add(*rhs) } } impl Add for &UVec3 { type Output = UVec3; #[inline] fn add(self, rhs: u32) -> UVec3 { (*self).add(rhs) } } impl AddAssign for UVec3 { #[inline] fn add_assign(&mut self, rhs: u32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&u32> for UVec3 { #[inline] fn add_assign(&mut self, rhs: &u32) { self.add_assign(*rhs) } } impl Add for u32 { type Output = UVec3; #[inline] fn add(self, rhs: UVec3) -> UVec3 { UVec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&UVec3> for u32 { type Output = UVec3; #[inline] fn add(self, rhs: &UVec3) -> UVec3 { self.add(*rhs) } } impl Add<&UVec3> for &u32 { type Output = UVec3; #[inline] fn add(self, rhs: &UVec3) -> UVec3 { (*self).add(*rhs) } } impl Add for &u32 { type Output = UVec3; #[inline] fn add(self, rhs: UVec3) -> UVec3 { (*self).add(rhs) } } impl Sub for UVec3 { 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 Sub<&UVec3> for UVec3 { type Output = UVec3; #[inline] fn sub(self, rhs: &UVec3) -> UVec3 { self.sub(*rhs) } } impl Sub<&UVec3> for &UVec3 { type Output = UVec3; #[inline] fn sub(self, rhs: &UVec3) -> UVec3 { (*self).sub(*rhs) } } impl Sub for &UVec3 { type Output = UVec3; #[inline] fn sub(self, rhs: UVec3) -> UVec3 { (*self).sub(rhs) } } impl SubAssign for UVec3 { #[inline] fn sub_assign(&mut self, rhs: UVec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&UVec3> for UVec3 { #[inline] fn sub_assign(&mut self, rhs: &UVec3) { self.sub_assign(*rhs) } } impl Sub for UVec3 { type Output = Self; #[inline] fn sub(self, rhs: u32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&u32> for UVec3 { type Output = UVec3; #[inline] fn sub(self, rhs: &u32) -> UVec3 { self.sub(*rhs) } } impl Sub<&u32> for &UVec3 { type Output = UVec3; #[inline] fn sub(self, rhs: &u32) -> UVec3 { (*self).sub(*rhs) } } impl Sub for &UVec3 { type Output = UVec3; #[inline] fn sub(self, rhs: u32) -> UVec3 { (*self).sub(rhs) } } impl SubAssign for UVec3 { #[inline] fn sub_assign(&mut self, rhs: u32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&u32> for UVec3 { #[inline] fn sub_assign(&mut self, rhs: &u32) { self.sub_assign(*rhs) } } impl Sub for u32 { type Output = UVec3; #[inline] fn sub(self, rhs: UVec3) -> UVec3 { UVec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&UVec3> for u32 { type Output = UVec3; #[inline] fn sub(self, rhs: &UVec3) -> UVec3 { self.sub(*rhs) } } impl Sub<&UVec3> for &u32 { type Output = UVec3; #[inline] fn sub(self, rhs: &UVec3) -> UVec3 { (*self).sub(*rhs) } } impl Sub for &u32 { type Output = UVec3; #[inline] fn sub(self, rhs: UVec3) -> UVec3 { (*self).sub(rhs) } } impl Rem for UVec3 { 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 Rem<&UVec3> for UVec3 { type Output = UVec3; #[inline] fn rem(self, rhs: &UVec3) -> UVec3 { self.rem(*rhs) } } impl Rem<&UVec3> for &UVec3 { type Output = UVec3; #[inline] fn rem(self, rhs: &UVec3) -> UVec3 { (*self).rem(*rhs) } } impl Rem for &UVec3 { type Output = UVec3; #[inline] fn rem(self, rhs: UVec3) -> UVec3 { (*self).rem(rhs) } } impl RemAssign for UVec3 { #[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 RemAssign<&UVec3> for UVec3 { #[inline] fn rem_assign(&mut self, rhs: &UVec3) { self.rem_assign(*rhs) } } impl Rem for UVec3 { type Output = Self; #[inline] fn rem(self, rhs: u32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&u32> for UVec3 { type Output = UVec3; #[inline] fn rem(self, rhs: &u32) -> UVec3 { self.rem(*rhs) } } impl Rem<&u32> for &UVec3 { type Output = UVec3; #[inline] fn rem(self, rhs: &u32) -> UVec3 { (*self).rem(*rhs) } } impl Rem for &UVec3 { type Output = UVec3; #[inline] fn rem(self, rhs: u32) -> UVec3 { (*self).rem(rhs) } } impl RemAssign for UVec3 { #[inline] fn rem_assign(&mut self, rhs: u32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&u32> for UVec3 { #[inline] fn rem_assign(&mut self, rhs: &u32) { self.rem_assign(*rhs) } } impl Rem for u32 { type Output = UVec3; #[inline] fn rem(self, rhs: UVec3) -> UVec3 { UVec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&UVec3> for u32 { type Output = UVec3; #[inline] fn rem(self, rhs: &UVec3) -> UVec3 { self.rem(*rhs) } } impl Rem<&UVec3> for &u32 { type Output = UVec3; #[inline] fn rem(self, rhs: &UVec3) -> UVec3 { (*self).rem(*rhs) } } impl Rem for &u32 { type Output = UVec3; #[inline] fn rem(self, rhs: UVec3) -> UVec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[u32; 3]> for UVec3 { #[inline] fn as_ref(&self) -> &[u32; 3] { unsafe { &*(self as *const UVec3 as *const [u32; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[u32; 3]> for UVec3 { #[inline] fn as_mut(&mut self) -> &mut [u32; 3] { unsafe { &mut *(self as *mut UVec3 as *mut [u32; 3]) } } } impl Sum for UVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for UVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for UVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for UVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for UVec3 { 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 UVec3 { 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 UVec3 { 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 UVec3 { 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 for UVec3 { type Output = Self; #[inline] fn bitand(self, rhs: u32) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), z: self.z.bitand(rhs), } } } impl BitOr for UVec3 { type Output = Self; #[inline] fn bitor(self, rhs: u32) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), z: self.z.bitor(rhs), } } } impl BitXor for UVec3 { type Output = Self; #[inline] fn bitxor(self, rhs: u32) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), z: self.z.bitxor(rhs), } } } impl Shl for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 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 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 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 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { 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 for UVec3 { type Output = u32; #[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 for UVec3 { #[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"), } } } impl fmt::Display for UVec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } impl fmt::Debug for UVec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(UVec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[u32; 3]> for UVec3 { #[inline] fn from(a: [u32; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [u32; 3] { #[inline] fn from(v: UVec3) -> Self { [v.x, v.y, v.z] } } impl From<(u32, u32, u32)> for UVec3 { #[inline] fn from(t: (u32, u32, u32)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (u32, u32, u32) { #[inline] fn from(v: UVec3) -> Self { (v.x, v.y, v.z) } } impl From<(UVec2, u32)> for UVec3 { #[inline] fn from((v, z): (UVec2, u32)) -> Self { Self::new(v.x, v.y, z) } } impl From for UVec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(u32::from(v.x), u32::from(v.y), u32::from(v.z)) } } impl From for UVec3 { #[inline] fn from(v: U16Vec3) -> Self { Self::new(u32::from(v.x), u32::from(v.y), u32::from(v.z)) } } impl TryFrom for UVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec3) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, )) } } impl TryFrom for UVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec3) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, )) } } impl TryFrom for UVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, )) } } impl TryFrom for UVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, )) } } impl TryFrom for UVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, )) } } impl TryFrom for UVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, )) } } impl From for UVec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(u32::from(v.x), u32::from(v.y), u32::from(v.z)) } } impl From for UVec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( u32::from(bool_array[0]), u32::from(bool_array[1]), u32::from(bool_array[2]), ) } } glam-0.30.1/src/u32/uvec4.rs000064400000000000000000001466161046102023000134370ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec2, UVec3, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// 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) } /// 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 UVec4 { pub x: u32, pub y: u32, pub z: u32, pub w: u32, } impl UVec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// 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 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: 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, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u32) -> u32, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: [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] } /// 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: &[u32]) -> Self { assert!(slice.len() >= 4); 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 [u32]) { slice[..4].copy_from_slice(&self.to_array()); } /// 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()`][crate::swizzles::Vec4Swizzles::xyz()]. #[inline] #[must_use] pub fn truncate(self) -> UVec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u32) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u32) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u32) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: u32) -> Self { self.w = w; self } /// 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)) } /// 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 [`u32::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) -> u32 { 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) -> u32 { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u32 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u32 { self.x * self.y * self.z * 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) -> u32 { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u32::MAX`]. /// /// See also [`checked_manhattan_distance`][UVec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u32 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u32::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u32 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: IVec4) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_signed(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: IVec4) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), w: self.w.wrapping_add_signed(rhs.w), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: IVec4) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), w: self.w.saturating_add_signed(rhs.w), } } } impl Default for UVec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for UVec4 { 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 Div<&UVec4> for UVec4 { type Output = UVec4; #[inline] fn div(self, rhs: &UVec4) -> UVec4 { self.div(*rhs) } } impl Div<&UVec4> for &UVec4 { type Output = UVec4; #[inline] fn div(self, rhs: &UVec4) -> UVec4 { (*self).div(*rhs) } } impl Div for &UVec4 { type Output = UVec4; #[inline] fn div(self, rhs: UVec4) -> UVec4 { (*self).div(rhs) } } impl DivAssign for UVec4 { #[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 DivAssign<&UVec4> for UVec4 { #[inline] fn div_assign(&mut self, rhs: &UVec4) { self.div_assign(*rhs) } } impl Div for UVec4 { type Output = Self; #[inline] fn div(self, rhs: u32) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&u32> for UVec4 { type Output = UVec4; #[inline] fn div(self, rhs: &u32) -> UVec4 { self.div(*rhs) } } impl Div<&u32> for &UVec4 { type Output = UVec4; #[inline] fn div(self, rhs: &u32) -> UVec4 { (*self).div(*rhs) } } impl Div for &UVec4 { type Output = UVec4; #[inline] fn div(self, rhs: u32) -> UVec4 { (*self).div(rhs) } } impl DivAssign for UVec4 { #[inline] fn div_assign(&mut self, rhs: u32) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&u32> for UVec4 { #[inline] fn div_assign(&mut self, rhs: &u32) { self.div_assign(*rhs) } } impl Div for u32 { type Output = UVec4; #[inline] fn div(self, rhs: UVec4) -> UVec4 { UVec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&UVec4> for u32 { type Output = UVec4; #[inline] fn div(self, rhs: &UVec4) -> UVec4 { self.div(*rhs) } } impl Div<&UVec4> for &u32 { type Output = UVec4; #[inline] fn div(self, rhs: &UVec4) -> UVec4 { (*self).div(*rhs) } } impl Div for &u32 { type Output = UVec4; #[inline] fn div(self, rhs: UVec4) -> UVec4 { (*self).div(rhs) } } impl Mul for UVec4 { 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 Mul<&UVec4> for UVec4 { type Output = UVec4; #[inline] fn mul(self, rhs: &UVec4) -> UVec4 { self.mul(*rhs) } } impl Mul<&UVec4> for &UVec4 { type Output = UVec4; #[inline] fn mul(self, rhs: &UVec4) -> UVec4 { (*self).mul(*rhs) } } impl Mul for &UVec4 { type Output = UVec4; #[inline] fn mul(self, rhs: UVec4) -> UVec4 { (*self).mul(rhs) } } impl MulAssign for UVec4 { #[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 MulAssign<&UVec4> for UVec4 { #[inline] fn mul_assign(&mut self, rhs: &UVec4) { self.mul_assign(*rhs) } } impl Mul for UVec4 { type Output = Self; #[inline] fn mul(self, rhs: u32) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&u32> for UVec4 { type Output = UVec4; #[inline] fn mul(self, rhs: &u32) -> UVec4 { self.mul(*rhs) } } impl Mul<&u32> for &UVec4 { type Output = UVec4; #[inline] fn mul(self, rhs: &u32) -> UVec4 { (*self).mul(*rhs) } } impl Mul for &UVec4 { type Output = UVec4; #[inline] fn mul(self, rhs: u32) -> UVec4 { (*self).mul(rhs) } } impl MulAssign for UVec4 { #[inline] fn mul_assign(&mut self, rhs: u32) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&u32> for UVec4 { #[inline] fn mul_assign(&mut self, rhs: &u32) { self.mul_assign(*rhs) } } impl Mul for u32 { type Output = UVec4; #[inline] fn mul(self, rhs: UVec4) -> UVec4 { UVec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&UVec4> for u32 { type Output = UVec4; #[inline] fn mul(self, rhs: &UVec4) -> UVec4 { self.mul(*rhs) } } impl Mul<&UVec4> for &u32 { type Output = UVec4; #[inline] fn mul(self, rhs: &UVec4) -> UVec4 { (*self).mul(*rhs) } } impl Mul for &u32 { type Output = UVec4; #[inline] fn mul(self, rhs: UVec4) -> UVec4 { (*self).mul(rhs) } } impl Add for UVec4 { 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 Add<&UVec4> for UVec4 { type Output = UVec4; #[inline] fn add(self, rhs: &UVec4) -> UVec4 { self.add(*rhs) } } impl Add<&UVec4> for &UVec4 { type Output = UVec4; #[inline] fn add(self, rhs: &UVec4) -> UVec4 { (*self).add(*rhs) } } impl Add for &UVec4 { type Output = UVec4; #[inline] fn add(self, rhs: UVec4) -> UVec4 { (*self).add(rhs) } } impl AddAssign for UVec4 { #[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 AddAssign<&UVec4> for UVec4 { #[inline] fn add_assign(&mut self, rhs: &UVec4) { self.add_assign(*rhs) } } impl Add for UVec4 { type Output = Self; #[inline] fn add(self, rhs: u32) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&u32> for UVec4 { type Output = UVec4; #[inline] fn add(self, rhs: &u32) -> UVec4 { self.add(*rhs) } } impl Add<&u32> for &UVec4 { type Output = UVec4; #[inline] fn add(self, rhs: &u32) -> UVec4 { (*self).add(*rhs) } } impl Add for &UVec4 { type Output = UVec4; #[inline] fn add(self, rhs: u32) -> UVec4 { (*self).add(rhs) } } impl AddAssign for UVec4 { #[inline] fn add_assign(&mut self, rhs: u32) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&u32> for UVec4 { #[inline] fn add_assign(&mut self, rhs: &u32) { self.add_assign(*rhs) } } impl Add for u32 { type Output = UVec4; #[inline] fn add(self, rhs: UVec4) -> UVec4 { UVec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&UVec4> for u32 { type Output = UVec4; #[inline] fn add(self, rhs: &UVec4) -> UVec4 { self.add(*rhs) } } impl Add<&UVec4> for &u32 { type Output = UVec4; #[inline] fn add(self, rhs: &UVec4) -> UVec4 { (*self).add(*rhs) } } impl Add for &u32 { type Output = UVec4; #[inline] fn add(self, rhs: UVec4) -> UVec4 { (*self).add(rhs) } } impl Sub for UVec4 { 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 Sub<&UVec4> for UVec4 { type Output = UVec4; #[inline] fn sub(self, rhs: &UVec4) -> UVec4 { self.sub(*rhs) } } impl Sub<&UVec4> for &UVec4 { type Output = UVec4; #[inline] fn sub(self, rhs: &UVec4) -> UVec4 { (*self).sub(*rhs) } } impl Sub for &UVec4 { type Output = UVec4; #[inline] fn sub(self, rhs: UVec4) -> UVec4 { (*self).sub(rhs) } } impl SubAssign for UVec4 { #[inline] fn sub_assign(&mut self, rhs: UVec4) { 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 SubAssign<&UVec4> for UVec4 { #[inline] fn sub_assign(&mut self, rhs: &UVec4) { self.sub_assign(*rhs) } } impl Sub for UVec4 { type Output = Self; #[inline] fn sub(self, rhs: u32) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&u32> for UVec4 { type Output = UVec4; #[inline] fn sub(self, rhs: &u32) -> UVec4 { self.sub(*rhs) } } impl Sub<&u32> for &UVec4 { type Output = UVec4; #[inline] fn sub(self, rhs: &u32) -> UVec4 { (*self).sub(*rhs) } } impl Sub for &UVec4 { type Output = UVec4; #[inline] fn sub(self, rhs: u32) -> UVec4 { (*self).sub(rhs) } } impl SubAssign for UVec4 { #[inline] fn sub_assign(&mut self, rhs: u32) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&u32> for UVec4 { #[inline] fn sub_assign(&mut self, rhs: &u32) { self.sub_assign(*rhs) } } impl Sub for u32 { type Output = UVec4; #[inline] fn sub(self, rhs: UVec4) -> UVec4 { UVec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&UVec4> for u32 { type Output = UVec4; #[inline] fn sub(self, rhs: &UVec4) -> UVec4 { self.sub(*rhs) } } impl Sub<&UVec4> for &u32 { type Output = UVec4; #[inline] fn sub(self, rhs: &UVec4) -> UVec4 { (*self).sub(*rhs) } } impl Sub for &u32 { type Output = UVec4; #[inline] fn sub(self, rhs: UVec4) -> UVec4 { (*self).sub(rhs) } } impl Rem for UVec4 { 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 Rem<&UVec4> for UVec4 { type Output = UVec4; #[inline] fn rem(self, rhs: &UVec4) -> UVec4 { self.rem(*rhs) } } impl Rem<&UVec4> for &UVec4 { type Output = UVec4; #[inline] fn rem(self, rhs: &UVec4) -> UVec4 { (*self).rem(*rhs) } } impl Rem for &UVec4 { type Output = UVec4; #[inline] fn rem(self, rhs: UVec4) -> UVec4 { (*self).rem(rhs) } } impl RemAssign for UVec4 { #[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 RemAssign<&UVec4> for UVec4 { #[inline] fn rem_assign(&mut self, rhs: &UVec4) { self.rem_assign(*rhs) } } impl Rem for UVec4 { type Output = Self; #[inline] fn rem(self, rhs: u32) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&u32> for UVec4 { type Output = UVec4; #[inline] fn rem(self, rhs: &u32) -> UVec4 { self.rem(*rhs) } } impl Rem<&u32> for &UVec4 { type Output = UVec4; #[inline] fn rem(self, rhs: &u32) -> UVec4 { (*self).rem(*rhs) } } impl Rem for &UVec4 { type Output = UVec4; #[inline] fn rem(self, rhs: u32) -> UVec4 { (*self).rem(rhs) } } impl RemAssign for UVec4 { #[inline] fn rem_assign(&mut self, rhs: u32) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&u32> for UVec4 { #[inline] fn rem_assign(&mut self, rhs: &u32) { self.rem_assign(*rhs) } } impl Rem for u32 { type Output = UVec4; #[inline] fn rem(self, rhs: UVec4) -> UVec4 { UVec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&UVec4> for u32 { type Output = UVec4; #[inline] fn rem(self, rhs: &UVec4) -> UVec4 { self.rem(*rhs) } } impl Rem<&UVec4> for &u32 { type Output = UVec4; #[inline] fn rem(self, rhs: &UVec4) -> UVec4 { (*self).rem(*rhs) } } impl Rem for &u32 { type Output = UVec4; #[inline] fn rem(self, rhs: UVec4) -> UVec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[u32; 4]> for UVec4 { #[inline] fn as_ref(&self) -> &[u32; 4] { unsafe { &*(self as *const UVec4 as *const [u32; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[u32; 4]> for UVec4 { #[inline] fn as_mut(&mut self) -> &mut [u32; 4] { unsafe { &mut *(self as *mut UVec4 as *mut [u32; 4]) } } } impl Sum for UVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for UVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for UVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for UVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for UVec4 { 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 UVec4 { 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 UVec4 { 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 UVec4 { 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 for UVec4 { type Output = Self; #[inline] fn bitand(self, rhs: u32) -> 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 for UVec4 { type Output = Self; #[inline] fn bitor(self, rhs: u32) -> 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 for UVec4 { type Output = Self; #[inline] fn bitxor(self, rhs: u32) -> 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 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 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 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 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { 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 for UVec4 { type Output = u32; #[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 for UVec4 { #[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"), } } } impl fmt::Display for UVec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } impl fmt::Debug for UVec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(UVec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[u32; 4]> for UVec4 { #[inline] fn from(a: [u32; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [u32; 4] { #[inline] fn from(v: UVec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(u32, u32, u32, u32)> for UVec4 { #[inline] fn from(t: (u32, u32, u32, u32)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (u32, u32, u32, u32) { #[inline] fn from(v: UVec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(UVec3, u32)> for UVec4 { #[inline] fn from((v, w): (UVec3, u32)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(u32, UVec3)> for UVec4 { #[inline] fn from((x, v): (u32, UVec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(UVec2, u32, u32)> for UVec4 { #[inline] fn from((v, z, w): (UVec2, u32, u32)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(UVec2, UVec2)> for UVec4 { #[inline] fn from((v, u): (UVec2, UVec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl From for UVec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( u32::from(v.x), u32::from(v.y), u32::from(v.z), u32::from(v.w), ) } } impl From 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 for UVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec4) -> Result { 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 for UVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec4) -> Result { 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 for UVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { 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 for UVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { 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 for UVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { 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 for UVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( u32::try_from(v.x)?, u32::try_from(v.y)?, u32::try_from(v.z)?, u32::try_from(v.w)?, )) } } impl From for UVec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( u32::from(v.x), u32::from(v.y), u32::from(v.z), u32::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for UVec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( u32::from(bool_array[0]), u32::from(bool_array[1]), u32::from(bool_array[2]), u32::from(bool_array[3]), ) } } glam-0.30.1/src/u32.rs000064400000000000000000000022171046102023000123750ustar 00000000000000mod uvec2; mod uvec3; mod uvec4; pub use uvec2::{uvec2, UVec2}; pub use uvec3::{uvec3, UVec3}; pub use uvec4::{uvec4, UVec4}; #[cfg(not(target_arch = "spirv"))] mod test { use super::*; mod const_test_uvec2 { const_assert_eq!(8, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(8, core::mem::align_of::()); } mod const_test_uvec3 { const_assert_eq!(12, core::mem::size_of::()); const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); } mod const_test_uvec4 { const_assert_eq!(16, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } } glam-0.30.1/src/u64/u64vec2.rs000064400000000000000000001226341046102023000136060ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec3, U8Vec2, USizeVec2, UVec2}; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u64) -> u64, { Self::new(f(self.x), f(self.y)) } /// 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 { assert!(slice.len() >= 2); 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[..2].copy_from_slice(&self.to_array()); } /// 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) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u64) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u64) -> Self { self.y = y; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u64 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u64 { self.x * 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) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u64::MAX`]. /// /// See also [`checked_manhattan_distance`][U64Vec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u64 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u64::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u64 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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 `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I64Vec2) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I64Vec2) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I64Vec2) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), } } } impl Default for U64Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&U64Vec2> for U64Vec2 { type Output = U64Vec2; #[inline] fn div(self, rhs: &U64Vec2) -> U64Vec2 { self.div(*rhs) } } impl Div<&U64Vec2> for &U64Vec2 { type Output = U64Vec2; #[inline] fn div(self, rhs: &U64Vec2) -> U64Vec2 { (*self).div(*rhs) } } impl Div for &U64Vec2 { type Output = U64Vec2; #[inline] fn div(self, rhs: U64Vec2) -> U64Vec2 { (*self).div(rhs) } } impl DivAssign for U64Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&U64Vec2> for U64Vec2 { #[inline] fn div_assign(&mut self, rhs: &U64Vec2) { self.div_assign(*rhs) } } impl Div for U64Vec2 { type Output = Self; #[inline] fn div(self, rhs: u64) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&u64> for U64Vec2 { type Output = U64Vec2; #[inline] fn div(self, rhs: &u64) -> U64Vec2 { self.div(*rhs) } } impl Div<&u64> for &U64Vec2 { type Output = U64Vec2; #[inline] fn div(self, rhs: &u64) -> U64Vec2 { (*self).div(*rhs) } } impl Div for &U64Vec2 { type Output = U64Vec2; #[inline] fn div(self, rhs: u64) -> U64Vec2 { (*self).div(rhs) } } impl DivAssign for U64Vec2 { #[inline] fn div_assign(&mut self, rhs: u64) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&u64> for U64Vec2 { #[inline] fn div_assign(&mut self, rhs: &u64) { self.div_assign(*rhs) } } impl Div for u64 { type Output = U64Vec2; #[inline] fn div(self, rhs: U64Vec2) -> U64Vec2 { U64Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&U64Vec2> for u64 { type Output = U64Vec2; #[inline] fn div(self, rhs: &U64Vec2) -> U64Vec2 { self.div(*rhs) } } impl Div<&U64Vec2> for &u64 { type Output = U64Vec2; #[inline] fn div(self, rhs: &U64Vec2) -> U64Vec2 { (*self).div(*rhs) } } impl Div for &u64 { type Output = U64Vec2; #[inline] fn div(self, rhs: U64Vec2) -> U64Vec2 { (*self).div(rhs) } } impl Mul 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 Mul<&U64Vec2> for U64Vec2 { type Output = U64Vec2; #[inline] fn mul(self, rhs: &U64Vec2) -> U64Vec2 { self.mul(*rhs) } } impl Mul<&U64Vec2> for &U64Vec2 { type Output = U64Vec2; #[inline] fn mul(self, rhs: &U64Vec2) -> U64Vec2 { (*self).mul(*rhs) } } impl Mul for &U64Vec2 { type Output = U64Vec2; #[inline] fn mul(self, rhs: U64Vec2) -> U64Vec2 { (*self).mul(rhs) } } impl MulAssign for U64Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&U64Vec2> for U64Vec2 { #[inline] fn mul_assign(&mut self, rhs: &U64Vec2) { self.mul_assign(*rhs) } } impl Mul for U64Vec2 { type Output = Self; #[inline] fn mul(self, rhs: u64) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&u64> for U64Vec2 { type Output = U64Vec2; #[inline] fn mul(self, rhs: &u64) -> U64Vec2 { self.mul(*rhs) } } impl Mul<&u64> for &U64Vec2 { type Output = U64Vec2; #[inline] fn mul(self, rhs: &u64) -> U64Vec2 { (*self).mul(*rhs) } } impl Mul for &U64Vec2 { type Output = U64Vec2; #[inline] fn mul(self, rhs: u64) -> U64Vec2 { (*self).mul(rhs) } } impl MulAssign for U64Vec2 { #[inline] fn mul_assign(&mut self, rhs: u64) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&u64> for U64Vec2 { #[inline] fn mul_assign(&mut self, rhs: &u64) { self.mul_assign(*rhs) } } impl Mul for u64 { type Output = U64Vec2; #[inline] fn mul(self, rhs: U64Vec2) -> U64Vec2 { U64Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&U64Vec2> for u64 { type Output = U64Vec2; #[inline] fn mul(self, rhs: &U64Vec2) -> U64Vec2 { self.mul(*rhs) } } impl Mul<&U64Vec2> for &u64 { type Output = U64Vec2; #[inline] fn mul(self, rhs: &U64Vec2) -> U64Vec2 { (*self).mul(*rhs) } } impl Mul for &u64 { type Output = U64Vec2; #[inline] fn mul(self, rhs: U64Vec2) -> U64Vec2 { (*self).mul(rhs) } } impl Add 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 Add<&U64Vec2> for U64Vec2 { type Output = U64Vec2; #[inline] fn add(self, rhs: &U64Vec2) -> U64Vec2 { self.add(*rhs) } } impl Add<&U64Vec2> for &U64Vec2 { type Output = U64Vec2; #[inline] fn add(self, rhs: &U64Vec2) -> U64Vec2 { (*self).add(*rhs) } } impl Add for &U64Vec2 { type Output = U64Vec2; #[inline] fn add(self, rhs: U64Vec2) -> U64Vec2 { (*self).add(rhs) } } impl AddAssign for U64Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&U64Vec2> for U64Vec2 { #[inline] fn add_assign(&mut self, rhs: &U64Vec2) { self.add_assign(*rhs) } } impl Add for U64Vec2 { type Output = Self; #[inline] fn add(self, rhs: u64) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&u64> for U64Vec2 { type Output = U64Vec2; #[inline] fn add(self, rhs: &u64) -> U64Vec2 { self.add(*rhs) } } impl Add<&u64> for &U64Vec2 { type Output = U64Vec2; #[inline] fn add(self, rhs: &u64) -> U64Vec2 { (*self).add(*rhs) } } impl Add for &U64Vec2 { type Output = U64Vec2; #[inline] fn add(self, rhs: u64) -> U64Vec2 { (*self).add(rhs) } } impl AddAssign for U64Vec2 { #[inline] fn add_assign(&mut self, rhs: u64) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&u64> for U64Vec2 { #[inline] fn add_assign(&mut self, rhs: &u64) { self.add_assign(*rhs) } } impl Add for u64 { type Output = U64Vec2; #[inline] fn add(self, rhs: U64Vec2) -> U64Vec2 { U64Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&U64Vec2> for u64 { type Output = U64Vec2; #[inline] fn add(self, rhs: &U64Vec2) -> U64Vec2 { self.add(*rhs) } } impl Add<&U64Vec2> for &u64 { type Output = U64Vec2; #[inline] fn add(self, rhs: &U64Vec2) -> U64Vec2 { (*self).add(*rhs) } } impl Add for &u64 { type Output = U64Vec2; #[inline] fn add(self, rhs: U64Vec2) -> U64Vec2 { (*self).add(rhs) } } impl Sub 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 Sub<&U64Vec2> for U64Vec2 { type Output = U64Vec2; #[inline] fn sub(self, rhs: &U64Vec2) -> U64Vec2 { self.sub(*rhs) } } impl Sub<&U64Vec2> for &U64Vec2 { type Output = U64Vec2; #[inline] fn sub(self, rhs: &U64Vec2) -> U64Vec2 { (*self).sub(*rhs) } } impl Sub for &U64Vec2 { type Output = U64Vec2; #[inline] fn sub(self, rhs: U64Vec2) -> U64Vec2 { (*self).sub(rhs) } } impl SubAssign for U64Vec2 { #[inline] fn sub_assign(&mut self, rhs: U64Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&U64Vec2> for U64Vec2 { #[inline] fn sub_assign(&mut self, rhs: &U64Vec2) { self.sub_assign(*rhs) } } impl Sub for U64Vec2 { type Output = Self; #[inline] fn sub(self, rhs: u64) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&u64> for U64Vec2 { type Output = U64Vec2; #[inline] fn sub(self, rhs: &u64) -> U64Vec2 { self.sub(*rhs) } } impl Sub<&u64> for &U64Vec2 { type Output = U64Vec2; #[inline] fn sub(self, rhs: &u64) -> U64Vec2 { (*self).sub(*rhs) } } impl Sub for &U64Vec2 { type Output = U64Vec2; #[inline] fn sub(self, rhs: u64) -> U64Vec2 { (*self).sub(rhs) } } impl SubAssign for U64Vec2 { #[inline] fn sub_assign(&mut self, rhs: u64) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&u64> for U64Vec2 { #[inline] fn sub_assign(&mut self, rhs: &u64) { self.sub_assign(*rhs) } } impl Sub for u64 { type Output = U64Vec2; #[inline] fn sub(self, rhs: U64Vec2) -> U64Vec2 { U64Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&U64Vec2> for u64 { type Output = U64Vec2; #[inline] fn sub(self, rhs: &U64Vec2) -> U64Vec2 { self.sub(*rhs) } } impl Sub<&U64Vec2> for &u64 { type Output = U64Vec2; #[inline] fn sub(self, rhs: &U64Vec2) -> U64Vec2 { (*self).sub(*rhs) } } impl Sub for &u64 { type Output = U64Vec2; #[inline] fn sub(self, rhs: U64Vec2) -> U64Vec2 { (*self).sub(rhs) } } impl Rem 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 Rem<&U64Vec2> for U64Vec2 { type Output = U64Vec2; #[inline] fn rem(self, rhs: &U64Vec2) -> U64Vec2 { self.rem(*rhs) } } impl Rem<&U64Vec2> for &U64Vec2 { type Output = U64Vec2; #[inline] fn rem(self, rhs: &U64Vec2) -> U64Vec2 { (*self).rem(*rhs) } } impl Rem for &U64Vec2 { type Output = U64Vec2; #[inline] fn rem(self, rhs: U64Vec2) -> U64Vec2 { (*self).rem(rhs) } } impl RemAssign for U64Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&U64Vec2> for U64Vec2 { #[inline] fn rem_assign(&mut self, rhs: &U64Vec2) { self.rem_assign(*rhs) } } impl Rem for U64Vec2 { type Output = Self; #[inline] fn rem(self, rhs: u64) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&u64> for U64Vec2 { type Output = U64Vec2; #[inline] fn rem(self, rhs: &u64) -> U64Vec2 { self.rem(*rhs) } } impl Rem<&u64> for &U64Vec2 { type Output = U64Vec2; #[inline] fn rem(self, rhs: &u64) -> U64Vec2 { (*self).rem(*rhs) } } impl Rem for &U64Vec2 { type Output = U64Vec2; #[inline] fn rem(self, rhs: u64) -> U64Vec2 { (*self).rem(rhs) } } impl RemAssign for U64Vec2 { #[inline] fn rem_assign(&mut self, rhs: u64) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&u64> for U64Vec2 { #[inline] fn rem_assign(&mut self, rhs: &u64) { self.rem_assign(*rhs) } } impl Rem for u64 { type Output = U64Vec2; #[inline] fn rem(self, rhs: U64Vec2) -> U64Vec2 { U64Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&U64Vec2> for u64 { type Output = U64Vec2; #[inline] fn rem(self, rhs: &U64Vec2) -> U64Vec2 { self.rem(*rhs) } } impl Rem<&U64Vec2> for &u64 { type Output = U64Vec2; #[inline] fn rem(self, rhs: &U64Vec2) -> U64Vec2 { (*self).rem(*rhs) } } impl Rem for &u64 { type Output = U64Vec2; #[inline] fn rem(self, rhs: U64Vec2) -> U64Vec2 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U64Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U64Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U64Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for U64Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } 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 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 for (u64, u64) { #[inline] fn from(v: U64Vec2) -> Self { (v.x, v.y) } } impl From for U64Vec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(u64::from(v.x), u64::from(v.y)) } } impl From for U64Vec2 { #[inline] fn from(v: U16Vec2) -> Self { Self::new(u64::from(v.x), u64::from(v.y)) } } impl From for U64Vec2 { #[inline] fn from(v: UVec2) -> Self { Self::new(u64::from(v.x), u64::from(v.y)) } } impl TryFrom for U64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec2) -> Result { Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?)) } } impl TryFrom for U64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec2) -> Result { Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?)) } } impl TryFrom for U64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?)) } } impl TryFrom for U64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?)) } } impl TryFrom for U64Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(u64::try_from(v.x)?, u64::try_from(v.y)?)) } } impl From for U64Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(u64::from(v.x), u64::from(v.y)) } } glam-0.30.1/src/u64/u64vec3.rs000064400000000000000000001365461046102023000136160ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec2, U64Vec4, U8Vec3, USizeVec3, UVec3, }; 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 } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u64) -> u64, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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 { assert!(slice.len() >= 3); 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[..3].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u64) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u64) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u64) -> Self { self.z = z; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u64 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u64 { self.x * self.y * 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) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u64::MAX`]. /// /// See also [`checked_manhattan_distance`][U64Vec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u64 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u64::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u64 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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 `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I64Vec3) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I64Vec3) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I64Vec3) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), } } } impl Default for U64Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&U64Vec3> for U64Vec3 { type Output = U64Vec3; #[inline] fn div(self, rhs: &U64Vec3) -> U64Vec3 { self.div(*rhs) } } impl Div<&U64Vec3> for &U64Vec3 { type Output = U64Vec3; #[inline] fn div(self, rhs: &U64Vec3) -> U64Vec3 { (*self).div(*rhs) } } impl Div for &U64Vec3 { type Output = U64Vec3; #[inline] fn div(self, rhs: U64Vec3) -> U64Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&U64Vec3> for U64Vec3 { #[inline] fn div_assign(&mut self, rhs: &U64Vec3) { self.div_assign(*rhs) } } impl Div 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 Div<&u64> for U64Vec3 { type Output = U64Vec3; #[inline] fn div(self, rhs: &u64) -> U64Vec3 { self.div(*rhs) } } impl Div<&u64> for &U64Vec3 { type Output = U64Vec3; #[inline] fn div(self, rhs: &u64) -> U64Vec3 { (*self).div(*rhs) } } impl Div for &U64Vec3 { type Output = U64Vec3; #[inline] fn div(self, rhs: u64) -> U64Vec3 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&u64> for U64Vec3 { #[inline] fn div_assign(&mut self, rhs: &u64) { self.div_assign(*rhs) } } impl Div 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 Div<&U64Vec3> for u64 { type Output = U64Vec3; #[inline] fn div(self, rhs: &U64Vec3) -> U64Vec3 { self.div(*rhs) } } impl Div<&U64Vec3> for &u64 { type Output = U64Vec3; #[inline] fn div(self, rhs: &U64Vec3) -> U64Vec3 { (*self).div(*rhs) } } impl Div for &u64 { type Output = U64Vec3; #[inline] fn div(self, rhs: U64Vec3) -> U64Vec3 { (*self).div(rhs) } } impl Mul 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 Mul<&U64Vec3> for U64Vec3 { type Output = U64Vec3; #[inline] fn mul(self, rhs: &U64Vec3) -> U64Vec3 { self.mul(*rhs) } } impl Mul<&U64Vec3> for &U64Vec3 { type Output = U64Vec3; #[inline] fn mul(self, rhs: &U64Vec3) -> U64Vec3 { (*self).mul(*rhs) } } impl Mul for &U64Vec3 { type Output = U64Vec3; #[inline] fn mul(self, rhs: U64Vec3) -> U64Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&U64Vec3> for U64Vec3 { #[inline] fn mul_assign(&mut self, rhs: &U64Vec3) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&u64> for U64Vec3 { type Output = U64Vec3; #[inline] fn mul(self, rhs: &u64) -> U64Vec3 { self.mul(*rhs) } } impl Mul<&u64> for &U64Vec3 { type Output = U64Vec3; #[inline] fn mul(self, rhs: &u64) -> U64Vec3 { (*self).mul(*rhs) } } impl Mul for &U64Vec3 { type Output = U64Vec3; #[inline] fn mul(self, rhs: u64) -> U64Vec3 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&u64> for U64Vec3 { #[inline] fn mul_assign(&mut self, rhs: &u64) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&U64Vec3> for u64 { type Output = U64Vec3; #[inline] fn mul(self, rhs: &U64Vec3) -> U64Vec3 { self.mul(*rhs) } } impl Mul<&U64Vec3> for &u64 { type Output = U64Vec3; #[inline] fn mul(self, rhs: &U64Vec3) -> U64Vec3 { (*self).mul(*rhs) } } impl Mul for &u64 { type Output = U64Vec3; #[inline] fn mul(self, rhs: U64Vec3) -> U64Vec3 { (*self).mul(rhs) } } impl Add 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 Add<&U64Vec3> for U64Vec3 { type Output = U64Vec3; #[inline] fn add(self, rhs: &U64Vec3) -> U64Vec3 { self.add(*rhs) } } impl Add<&U64Vec3> for &U64Vec3 { type Output = U64Vec3; #[inline] fn add(self, rhs: &U64Vec3) -> U64Vec3 { (*self).add(*rhs) } } impl Add for &U64Vec3 { type Output = U64Vec3; #[inline] fn add(self, rhs: U64Vec3) -> U64Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&U64Vec3> for U64Vec3 { #[inline] fn add_assign(&mut self, rhs: &U64Vec3) { self.add_assign(*rhs) } } impl Add 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 Add<&u64> for U64Vec3 { type Output = U64Vec3; #[inline] fn add(self, rhs: &u64) -> U64Vec3 { self.add(*rhs) } } impl Add<&u64> for &U64Vec3 { type Output = U64Vec3; #[inline] fn add(self, rhs: &u64) -> U64Vec3 { (*self).add(*rhs) } } impl Add for &U64Vec3 { type Output = U64Vec3; #[inline] fn add(self, rhs: u64) -> U64Vec3 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&u64> for U64Vec3 { #[inline] fn add_assign(&mut self, rhs: &u64) { self.add_assign(*rhs) } } impl Add 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 Add<&U64Vec3> for u64 { type Output = U64Vec3; #[inline] fn add(self, rhs: &U64Vec3) -> U64Vec3 { self.add(*rhs) } } impl Add<&U64Vec3> for &u64 { type Output = U64Vec3; #[inline] fn add(self, rhs: &U64Vec3) -> U64Vec3 { (*self).add(*rhs) } } impl Add for &u64 { type Output = U64Vec3; #[inline] fn add(self, rhs: U64Vec3) -> U64Vec3 { (*self).add(rhs) } } impl Sub 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 Sub<&U64Vec3> for U64Vec3 { type Output = U64Vec3; #[inline] fn sub(self, rhs: &U64Vec3) -> U64Vec3 { self.sub(*rhs) } } impl Sub<&U64Vec3> for &U64Vec3 { type Output = U64Vec3; #[inline] fn sub(self, rhs: &U64Vec3) -> U64Vec3 { (*self).sub(*rhs) } } impl Sub for &U64Vec3 { type Output = U64Vec3; #[inline] fn sub(self, rhs: U64Vec3) -> U64Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&U64Vec3> for U64Vec3 { #[inline] fn sub_assign(&mut self, rhs: &U64Vec3) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&u64> for U64Vec3 { type Output = U64Vec3; #[inline] fn sub(self, rhs: &u64) -> U64Vec3 { self.sub(*rhs) } } impl Sub<&u64> for &U64Vec3 { type Output = U64Vec3; #[inline] fn sub(self, rhs: &u64) -> U64Vec3 { (*self).sub(*rhs) } } impl Sub for &U64Vec3 { type Output = U64Vec3; #[inline] fn sub(self, rhs: u64) -> U64Vec3 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&u64> for U64Vec3 { #[inline] fn sub_assign(&mut self, rhs: &u64) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&U64Vec3> for u64 { type Output = U64Vec3; #[inline] fn sub(self, rhs: &U64Vec3) -> U64Vec3 { self.sub(*rhs) } } impl Sub<&U64Vec3> for &u64 { type Output = U64Vec3; #[inline] fn sub(self, rhs: &U64Vec3) -> U64Vec3 { (*self).sub(*rhs) } } impl Sub for &u64 { type Output = U64Vec3; #[inline] fn sub(self, rhs: U64Vec3) -> U64Vec3 { (*self).sub(rhs) } } impl Rem 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 Rem<&U64Vec3> for U64Vec3 { type Output = U64Vec3; #[inline] fn rem(self, rhs: &U64Vec3) -> U64Vec3 { self.rem(*rhs) } } impl Rem<&U64Vec3> for &U64Vec3 { type Output = U64Vec3; #[inline] fn rem(self, rhs: &U64Vec3) -> U64Vec3 { (*self).rem(*rhs) } } impl Rem for &U64Vec3 { type Output = U64Vec3; #[inline] fn rem(self, rhs: U64Vec3) -> U64Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&U64Vec3> for U64Vec3 { #[inline] fn rem_assign(&mut self, rhs: &U64Vec3) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&u64> for U64Vec3 { type Output = U64Vec3; #[inline] fn rem(self, rhs: &u64) -> U64Vec3 { self.rem(*rhs) } } impl Rem<&u64> for &U64Vec3 { type Output = U64Vec3; #[inline] fn rem(self, rhs: &u64) -> U64Vec3 { (*self).rem(*rhs) } } impl Rem for &U64Vec3 { type Output = U64Vec3; #[inline] fn rem(self, rhs: u64) -> U64Vec3 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&u64> for U64Vec3 { #[inline] fn rem_assign(&mut self, rhs: &u64) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&U64Vec3> for u64 { type Output = U64Vec3; #[inline] fn rem(self, rhs: &U64Vec3) -> U64Vec3 { self.rem(*rhs) } } impl Rem<&U64Vec3> for &u64 { type Output = U64Vec3; #[inline] fn rem(self, rhs: &U64Vec3) -> U64Vec3 { (*self).rem(*rhs) } } impl Rem for &u64 { type Output = U64Vec3; #[inline] fn rem(self, rhs: U64Vec3) -> U64Vec3 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U64Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U64Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U64Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for U64Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } 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 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 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 for U64Vec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z)) } } impl From for U64Vec3 { #[inline] fn from(v: U16Vec3) -> Self { Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z)) } } impl From for U64Vec3 { #[inline] fn from(v: UVec3) -> Self { Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z)) } } impl TryFrom for U64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec3) -> Result { Ok(Self::new( u64::try_from(v.x)?, u64::try_from(v.y)?, u64::try_from(v.z)?, )) } } impl TryFrom for U64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec3) -> Result { Ok(Self::new( u64::try_from(v.x)?, u64::try_from(v.y)?, u64::try_from(v.z)?, )) } } impl TryFrom for U64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( u64::try_from(v.x)?, u64::try_from(v.y)?, u64::try_from(v.z)?, )) } } impl TryFrom for U64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( u64::try_from(v.x)?, u64::try_from(v.y)?, u64::try_from(v.z)?, )) } } impl TryFrom for U64Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( u64::try_from(v.x)?, u64::try_from(v.y)?, u64::try_from(v.z)?, )) } } impl From for U64Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(u64::from(v.x), u64::from(v.y), u64::from(v.z)) } } impl From for U64Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( u64::from(bool_array[0]), u64::from(bool_array[1]), u64::from(bool_array[2]), ) } } glam-0.30.1/src/u64/u64vec4.rs000064400000000000000000001477101046102023000136120ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec2, U64Vec3, U8Vec4, USizeVec4, UVec4, }; 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, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u64) -> u64, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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 { assert!(slice.len() >= 4); 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[..4].copy_from_slice(&self.to_array()); } /// 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() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u64) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u64) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u64) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: u64) -> Self { self.w = w; self } /// 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 the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u64 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u64 { self.x * self.y * self.z * 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) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u64::MAX`]. /// /// See also [`checked_manhattan_distance`][U64Vec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u64 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u64::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u64 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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 `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I64Vec4) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_signed(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I64Vec4) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), w: self.w.wrapping_add_signed(rhs.w), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I64Vec4) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), w: self.w.saturating_add_signed(rhs.w), } } } impl Default for U64Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div 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 Div<&U64Vec4> for U64Vec4 { type Output = U64Vec4; #[inline] fn div(self, rhs: &U64Vec4) -> U64Vec4 { self.div(*rhs) } } impl Div<&U64Vec4> for &U64Vec4 { type Output = U64Vec4; #[inline] fn div(self, rhs: &U64Vec4) -> U64Vec4 { (*self).div(*rhs) } } impl Div for &U64Vec4 { type Output = U64Vec4; #[inline] fn div(self, rhs: U64Vec4) -> U64Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&U64Vec4> for U64Vec4 { #[inline] fn div_assign(&mut self, rhs: &U64Vec4) { self.div_assign(*rhs) } } impl Div 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 Div<&u64> for U64Vec4 { type Output = U64Vec4; #[inline] fn div(self, rhs: &u64) -> U64Vec4 { self.div(*rhs) } } impl Div<&u64> for &U64Vec4 { type Output = U64Vec4; #[inline] fn div(self, rhs: &u64) -> U64Vec4 { (*self).div(*rhs) } } impl Div for &U64Vec4 { type Output = U64Vec4; #[inline] fn div(self, rhs: u64) -> U64Vec4 { (*self).div(rhs) } } impl DivAssign 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 DivAssign<&u64> for U64Vec4 { #[inline] fn div_assign(&mut self, rhs: &u64) { self.div_assign(*rhs) } } impl Div 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 Div<&U64Vec4> for u64 { type Output = U64Vec4; #[inline] fn div(self, rhs: &U64Vec4) -> U64Vec4 { self.div(*rhs) } } impl Div<&U64Vec4> for &u64 { type Output = U64Vec4; #[inline] fn div(self, rhs: &U64Vec4) -> U64Vec4 { (*self).div(*rhs) } } impl Div for &u64 { type Output = U64Vec4; #[inline] fn div(self, rhs: U64Vec4) -> U64Vec4 { (*self).div(rhs) } } impl Mul 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 Mul<&U64Vec4> for U64Vec4 { type Output = U64Vec4; #[inline] fn mul(self, rhs: &U64Vec4) -> U64Vec4 { self.mul(*rhs) } } impl Mul<&U64Vec4> for &U64Vec4 { type Output = U64Vec4; #[inline] fn mul(self, rhs: &U64Vec4) -> U64Vec4 { (*self).mul(*rhs) } } impl Mul for &U64Vec4 { type Output = U64Vec4; #[inline] fn mul(self, rhs: U64Vec4) -> U64Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&U64Vec4> for U64Vec4 { #[inline] fn mul_assign(&mut self, rhs: &U64Vec4) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&u64> for U64Vec4 { type Output = U64Vec4; #[inline] fn mul(self, rhs: &u64) -> U64Vec4 { self.mul(*rhs) } } impl Mul<&u64> for &U64Vec4 { type Output = U64Vec4; #[inline] fn mul(self, rhs: &u64) -> U64Vec4 { (*self).mul(*rhs) } } impl Mul for &U64Vec4 { type Output = U64Vec4; #[inline] fn mul(self, rhs: u64) -> U64Vec4 { (*self).mul(rhs) } } impl MulAssign 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 MulAssign<&u64> for U64Vec4 { #[inline] fn mul_assign(&mut self, rhs: &u64) { self.mul_assign(*rhs) } } impl Mul 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 Mul<&U64Vec4> for u64 { type Output = U64Vec4; #[inline] fn mul(self, rhs: &U64Vec4) -> U64Vec4 { self.mul(*rhs) } } impl Mul<&U64Vec4> for &u64 { type Output = U64Vec4; #[inline] fn mul(self, rhs: &U64Vec4) -> U64Vec4 { (*self).mul(*rhs) } } impl Mul for &u64 { type Output = U64Vec4; #[inline] fn mul(self, rhs: U64Vec4) -> U64Vec4 { (*self).mul(rhs) } } impl Add 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 Add<&U64Vec4> for U64Vec4 { type Output = U64Vec4; #[inline] fn add(self, rhs: &U64Vec4) -> U64Vec4 { self.add(*rhs) } } impl Add<&U64Vec4> for &U64Vec4 { type Output = U64Vec4; #[inline] fn add(self, rhs: &U64Vec4) -> U64Vec4 { (*self).add(*rhs) } } impl Add for &U64Vec4 { type Output = U64Vec4; #[inline] fn add(self, rhs: U64Vec4) -> U64Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&U64Vec4> for U64Vec4 { #[inline] fn add_assign(&mut self, rhs: &U64Vec4) { self.add_assign(*rhs) } } impl Add 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 Add<&u64> for U64Vec4 { type Output = U64Vec4; #[inline] fn add(self, rhs: &u64) -> U64Vec4 { self.add(*rhs) } } impl Add<&u64> for &U64Vec4 { type Output = U64Vec4; #[inline] fn add(self, rhs: &u64) -> U64Vec4 { (*self).add(*rhs) } } impl Add for &U64Vec4 { type Output = U64Vec4; #[inline] fn add(self, rhs: u64) -> U64Vec4 { (*self).add(rhs) } } impl AddAssign 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 AddAssign<&u64> for U64Vec4 { #[inline] fn add_assign(&mut self, rhs: &u64) { self.add_assign(*rhs) } } impl Add 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 Add<&U64Vec4> for u64 { type Output = U64Vec4; #[inline] fn add(self, rhs: &U64Vec4) -> U64Vec4 { self.add(*rhs) } } impl Add<&U64Vec4> for &u64 { type Output = U64Vec4; #[inline] fn add(self, rhs: &U64Vec4) -> U64Vec4 { (*self).add(*rhs) } } impl Add for &u64 { type Output = U64Vec4; #[inline] fn add(self, rhs: U64Vec4) -> U64Vec4 { (*self).add(rhs) } } impl Sub 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 Sub<&U64Vec4> for U64Vec4 { type Output = U64Vec4; #[inline] fn sub(self, rhs: &U64Vec4) -> U64Vec4 { self.sub(*rhs) } } impl Sub<&U64Vec4> for &U64Vec4 { type Output = U64Vec4; #[inline] fn sub(self, rhs: &U64Vec4) -> U64Vec4 { (*self).sub(*rhs) } } impl Sub for &U64Vec4 { type Output = U64Vec4; #[inline] fn sub(self, rhs: U64Vec4) -> U64Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&U64Vec4> for U64Vec4 { #[inline] fn sub_assign(&mut self, rhs: &U64Vec4) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&u64> for U64Vec4 { type Output = U64Vec4; #[inline] fn sub(self, rhs: &u64) -> U64Vec4 { self.sub(*rhs) } } impl Sub<&u64> for &U64Vec4 { type Output = U64Vec4; #[inline] fn sub(self, rhs: &u64) -> U64Vec4 { (*self).sub(*rhs) } } impl Sub for &U64Vec4 { type Output = U64Vec4; #[inline] fn sub(self, rhs: u64) -> U64Vec4 { (*self).sub(rhs) } } impl SubAssign 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 SubAssign<&u64> for U64Vec4 { #[inline] fn sub_assign(&mut self, rhs: &u64) { self.sub_assign(*rhs) } } impl Sub 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 Sub<&U64Vec4> for u64 { type Output = U64Vec4; #[inline] fn sub(self, rhs: &U64Vec4) -> U64Vec4 { self.sub(*rhs) } } impl Sub<&U64Vec4> for &u64 { type Output = U64Vec4; #[inline] fn sub(self, rhs: &U64Vec4) -> U64Vec4 { (*self).sub(*rhs) } } impl Sub for &u64 { type Output = U64Vec4; #[inline] fn sub(self, rhs: U64Vec4) -> U64Vec4 { (*self).sub(rhs) } } impl Rem 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 Rem<&U64Vec4> for U64Vec4 { type Output = U64Vec4; #[inline] fn rem(self, rhs: &U64Vec4) -> U64Vec4 { self.rem(*rhs) } } impl Rem<&U64Vec4> for &U64Vec4 { type Output = U64Vec4; #[inline] fn rem(self, rhs: &U64Vec4) -> U64Vec4 { (*self).rem(*rhs) } } impl Rem for &U64Vec4 { type Output = U64Vec4; #[inline] fn rem(self, rhs: U64Vec4) -> U64Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&U64Vec4> for U64Vec4 { #[inline] fn rem_assign(&mut self, rhs: &U64Vec4) { self.rem_assign(*rhs) } } impl Rem 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 Rem<&u64> for U64Vec4 { type Output = U64Vec4; #[inline] fn rem(self, rhs: &u64) -> U64Vec4 { self.rem(*rhs) } } impl Rem<&u64> for &U64Vec4 { type Output = U64Vec4; #[inline] fn rem(self, rhs: &u64) -> U64Vec4 { (*self).rem(*rhs) } } impl Rem for &U64Vec4 { type Output = U64Vec4; #[inline] fn rem(self, rhs: u64) -> U64Vec4 { (*self).rem(rhs) } } impl RemAssign 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 RemAssign<&u64> for U64Vec4 { #[inline] fn rem_assign(&mut self, rhs: &u64) { self.rem_assign(*rhs) } } impl Rem 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), } } } impl Rem<&U64Vec4> for u64 { type Output = U64Vec4; #[inline] fn rem(self, rhs: &U64Vec4) -> U64Vec4 { self.rem(*rhs) } } impl Rem<&U64Vec4> for &u64 { type Output = U64Vec4; #[inline] fn rem(self, rhs: &U64Vec4) -> U64Vec4 { (*self).rem(*rhs) } } impl Rem for &u64 { type Output = U64Vec4; #[inline] fn rem(self, rhs: U64Vec4) -> U64Vec4 { (*self).rem(rhs) } } #[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(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U64Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U64Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U64Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"), } } } impl fmt::Display for U64Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } 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 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 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 for U64Vec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( u64::from(v.x), u64::from(v.y), u64::from(v.z), u64::from(v.w), ) } } impl From 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 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 for U64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec4) -> Result { 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 for U64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec4) -> Result { 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 for U64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { 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 for U64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { 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 for U64Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( u64::try_from(v.x)?, u64::try_from(v.y)?, u64::try_from(v.z)?, u64::try_from(v.w)?, )) } } impl From for U64Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( u64::from(v.x), u64::from(v.y), u64::from(v.z), u64::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for U64Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( u64::from(bool_array[0]), u64::from(bool_array[1]), u64::from(bool_array[2]), u64::from(bool_array[3]), ) } } glam-0.30.1/src/u64.rs000064400000000000000000000022771046102023000124100ustar 00000000000000mod 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::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } mod const_test_u64vec3 { const_assert_eq!(24, core::mem::size_of::()); const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); } mod const_test_u64vec4 { const_assert_eq!(32, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } } glam-0.30.1/src/u8/u8vec2.rs000064400000000000000000001223201046102023000134320ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec3, USizeVec2, UVec2}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn u8vec2(x: u8, y: u8) -> U8Vec2 { U8Vec2::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(2)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct U8Vec2 { pub x: u8, pub y: u8, } impl U8Vec2 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// All `u8::MIN`. pub const MIN: Self = Self::splat(u8::MIN); /// All `u8::MAX`. pub const MAX: Self = Self::splat(u8::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: u8, y: u8) -> Self { Self { x, y } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: u8) -> Self { Self { x: v, y: v } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u8) -> u8, { Self::new(f(self.x), f(self.y)) } /// 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: [u8; 2]) -> Self { Self::new(a[0], a[1]) } /// `[x, y]` #[inline] #[must_use] pub const fn to_array(&self) -> [u8; 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: &[u8]) -> Self { assert!(slice.len() >= 2); 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 [u8]) { slice[..2].copy_from_slice(&self.to_array()); } /// Creates a 3D vector from `self` and the given `z` value. #[inline] #[must_use] pub const fn extend(self, z: u8) -> U8Vec3 { U8Vec3::new(self.x, self.y, z) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u8) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u8) -> Self { self.y = y; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> u8 { (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 [`u8::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) -> u8 { 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) -> u8 { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u8 { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u8 { self.x * 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) -> u8 { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u8::MAX`]. /// /// See also [`checked_manhattan_distance`][U8Vec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u8 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u8::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u8 { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I8Vec2) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I8Vec2) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I8Vec2) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), } } } impl Default for U8Vec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for U8Vec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&U8Vec2> for U8Vec2 { type Output = U8Vec2; #[inline] fn div(self, rhs: &U8Vec2) -> U8Vec2 { self.div(*rhs) } } impl Div<&U8Vec2> for &U8Vec2 { type Output = U8Vec2; #[inline] fn div(self, rhs: &U8Vec2) -> U8Vec2 { (*self).div(*rhs) } } impl Div for &U8Vec2 { type Output = U8Vec2; #[inline] fn div(self, rhs: U8Vec2) -> U8Vec2 { (*self).div(rhs) } } impl DivAssign for U8Vec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&U8Vec2> for U8Vec2 { #[inline] fn div_assign(&mut self, rhs: &U8Vec2) { self.div_assign(*rhs) } } impl Div for U8Vec2 { type Output = Self; #[inline] fn div(self, rhs: u8) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&u8> for U8Vec2 { type Output = U8Vec2; #[inline] fn div(self, rhs: &u8) -> U8Vec2 { self.div(*rhs) } } impl Div<&u8> for &U8Vec2 { type Output = U8Vec2; #[inline] fn div(self, rhs: &u8) -> U8Vec2 { (*self).div(*rhs) } } impl Div for &U8Vec2 { type Output = U8Vec2; #[inline] fn div(self, rhs: u8) -> U8Vec2 { (*self).div(rhs) } } impl DivAssign for U8Vec2 { #[inline] fn div_assign(&mut self, rhs: u8) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&u8> for U8Vec2 { #[inline] fn div_assign(&mut self, rhs: &u8) { self.div_assign(*rhs) } } impl Div for u8 { type Output = U8Vec2; #[inline] fn div(self, rhs: U8Vec2) -> U8Vec2 { U8Vec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&U8Vec2> for u8 { type Output = U8Vec2; #[inline] fn div(self, rhs: &U8Vec2) -> U8Vec2 { self.div(*rhs) } } impl Div<&U8Vec2> for &u8 { type Output = U8Vec2; #[inline] fn div(self, rhs: &U8Vec2) -> U8Vec2 { (*self).div(*rhs) } } impl Div for &u8 { type Output = U8Vec2; #[inline] fn div(self, rhs: U8Vec2) -> U8Vec2 { (*self).div(rhs) } } impl Mul for U8Vec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&U8Vec2> for U8Vec2 { type Output = U8Vec2; #[inline] fn mul(self, rhs: &U8Vec2) -> U8Vec2 { self.mul(*rhs) } } impl Mul<&U8Vec2> for &U8Vec2 { type Output = U8Vec2; #[inline] fn mul(self, rhs: &U8Vec2) -> U8Vec2 { (*self).mul(*rhs) } } impl Mul for &U8Vec2 { type Output = U8Vec2; #[inline] fn mul(self, rhs: U8Vec2) -> U8Vec2 { (*self).mul(rhs) } } impl MulAssign for U8Vec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&U8Vec2> for U8Vec2 { #[inline] fn mul_assign(&mut self, rhs: &U8Vec2) { self.mul_assign(*rhs) } } impl Mul for U8Vec2 { type Output = Self; #[inline] fn mul(self, rhs: u8) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&u8> for U8Vec2 { type Output = U8Vec2; #[inline] fn mul(self, rhs: &u8) -> U8Vec2 { self.mul(*rhs) } } impl Mul<&u8> for &U8Vec2 { type Output = U8Vec2; #[inline] fn mul(self, rhs: &u8) -> U8Vec2 { (*self).mul(*rhs) } } impl Mul for &U8Vec2 { type Output = U8Vec2; #[inline] fn mul(self, rhs: u8) -> U8Vec2 { (*self).mul(rhs) } } impl MulAssign for U8Vec2 { #[inline] fn mul_assign(&mut self, rhs: u8) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&u8> for U8Vec2 { #[inline] fn mul_assign(&mut self, rhs: &u8) { self.mul_assign(*rhs) } } impl Mul for u8 { type Output = U8Vec2; #[inline] fn mul(self, rhs: U8Vec2) -> U8Vec2 { U8Vec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&U8Vec2> for u8 { type Output = U8Vec2; #[inline] fn mul(self, rhs: &U8Vec2) -> U8Vec2 { self.mul(*rhs) } } impl Mul<&U8Vec2> for &u8 { type Output = U8Vec2; #[inline] fn mul(self, rhs: &U8Vec2) -> U8Vec2 { (*self).mul(*rhs) } } impl Mul for &u8 { type Output = U8Vec2; #[inline] fn mul(self, rhs: U8Vec2) -> U8Vec2 { (*self).mul(rhs) } } impl Add for U8Vec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&U8Vec2> for U8Vec2 { type Output = U8Vec2; #[inline] fn add(self, rhs: &U8Vec2) -> U8Vec2 { self.add(*rhs) } } impl Add<&U8Vec2> for &U8Vec2 { type Output = U8Vec2; #[inline] fn add(self, rhs: &U8Vec2) -> U8Vec2 { (*self).add(*rhs) } } impl Add for &U8Vec2 { type Output = U8Vec2; #[inline] fn add(self, rhs: U8Vec2) -> U8Vec2 { (*self).add(rhs) } } impl AddAssign for U8Vec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&U8Vec2> for U8Vec2 { #[inline] fn add_assign(&mut self, rhs: &U8Vec2) { self.add_assign(*rhs) } } impl Add for U8Vec2 { type Output = Self; #[inline] fn add(self, rhs: u8) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&u8> for U8Vec2 { type Output = U8Vec2; #[inline] fn add(self, rhs: &u8) -> U8Vec2 { self.add(*rhs) } } impl Add<&u8> for &U8Vec2 { type Output = U8Vec2; #[inline] fn add(self, rhs: &u8) -> U8Vec2 { (*self).add(*rhs) } } impl Add for &U8Vec2 { type Output = U8Vec2; #[inline] fn add(self, rhs: u8) -> U8Vec2 { (*self).add(rhs) } } impl AddAssign for U8Vec2 { #[inline] fn add_assign(&mut self, rhs: u8) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&u8> for U8Vec2 { #[inline] fn add_assign(&mut self, rhs: &u8) { self.add_assign(*rhs) } } impl Add for u8 { type Output = U8Vec2; #[inline] fn add(self, rhs: U8Vec2) -> U8Vec2 { U8Vec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&U8Vec2> for u8 { type Output = U8Vec2; #[inline] fn add(self, rhs: &U8Vec2) -> U8Vec2 { self.add(*rhs) } } impl Add<&U8Vec2> for &u8 { type Output = U8Vec2; #[inline] fn add(self, rhs: &U8Vec2) -> U8Vec2 { (*self).add(*rhs) } } impl Add for &u8 { type Output = U8Vec2; #[inline] fn add(self, rhs: U8Vec2) -> U8Vec2 { (*self).add(rhs) } } impl Sub for U8Vec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&U8Vec2> for U8Vec2 { type Output = U8Vec2; #[inline] fn sub(self, rhs: &U8Vec2) -> U8Vec2 { self.sub(*rhs) } } impl Sub<&U8Vec2> for &U8Vec2 { type Output = U8Vec2; #[inline] fn sub(self, rhs: &U8Vec2) -> U8Vec2 { (*self).sub(*rhs) } } impl Sub for &U8Vec2 { type Output = U8Vec2; #[inline] fn sub(self, rhs: U8Vec2) -> U8Vec2 { (*self).sub(rhs) } } impl SubAssign for U8Vec2 { #[inline] fn sub_assign(&mut self, rhs: U8Vec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&U8Vec2> for U8Vec2 { #[inline] fn sub_assign(&mut self, rhs: &U8Vec2) { self.sub_assign(*rhs) } } impl Sub for U8Vec2 { type Output = Self; #[inline] fn sub(self, rhs: u8) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&u8> for U8Vec2 { type Output = U8Vec2; #[inline] fn sub(self, rhs: &u8) -> U8Vec2 { self.sub(*rhs) } } impl Sub<&u8> for &U8Vec2 { type Output = U8Vec2; #[inline] fn sub(self, rhs: &u8) -> U8Vec2 { (*self).sub(*rhs) } } impl Sub for &U8Vec2 { type Output = U8Vec2; #[inline] fn sub(self, rhs: u8) -> U8Vec2 { (*self).sub(rhs) } } impl SubAssign for U8Vec2 { #[inline] fn sub_assign(&mut self, rhs: u8) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&u8> for U8Vec2 { #[inline] fn sub_assign(&mut self, rhs: &u8) { self.sub_assign(*rhs) } } impl Sub for u8 { type Output = U8Vec2; #[inline] fn sub(self, rhs: U8Vec2) -> U8Vec2 { U8Vec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&U8Vec2> for u8 { type Output = U8Vec2; #[inline] fn sub(self, rhs: &U8Vec2) -> U8Vec2 { self.sub(*rhs) } } impl Sub<&U8Vec2> for &u8 { type Output = U8Vec2; #[inline] fn sub(self, rhs: &U8Vec2) -> U8Vec2 { (*self).sub(*rhs) } } impl Sub for &u8 { type Output = U8Vec2; #[inline] fn sub(self, rhs: U8Vec2) -> U8Vec2 { (*self).sub(rhs) } } impl Rem for U8Vec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&U8Vec2> for U8Vec2 { type Output = U8Vec2; #[inline] fn rem(self, rhs: &U8Vec2) -> U8Vec2 { self.rem(*rhs) } } impl Rem<&U8Vec2> for &U8Vec2 { type Output = U8Vec2; #[inline] fn rem(self, rhs: &U8Vec2) -> U8Vec2 { (*self).rem(*rhs) } } impl Rem for &U8Vec2 { type Output = U8Vec2; #[inline] fn rem(self, rhs: U8Vec2) -> U8Vec2 { (*self).rem(rhs) } } impl RemAssign for U8Vec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&U8Vec2> for U8Vec2 { #[inline] fn rem_assign(&mut self, rhs: &U8Vec2) { self.rem_assign(*rhs) } } impl Rem for U8Vec2 { type Output = Self; #[inline] fn rem(self, rhs: u8) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&u8> for U8Vec2 { type Output = U8Vec2; #[inline] fn rem(self, rhs: &u8) -> U8Vec2 { self.rem(*rhs) } } impl Rem<&u8> for &U8Vec2 { type Output = U8Vec2; #[inline] fn rem(self, rhs: &u8) -> U8Vec2 { (*self).rem(*rhs) } } impl Rem for &U8Vec2 { type Output = U8Vec2; #[inline] fn rem(self, rhs: u8) -> U8Vec2 { (*self).rem(rhs) } } impl RemAssign for U8Vec2 { #[inline] fn rem_assign(&mut self, rhs: u8) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&u8> for U8Vec2 { #[inline] fn rem_assign(&mut self, rhs: &u8) { self.rem_assign(*rhs) } } impl Rem for u8 { type Output = U8Vec2; #[inline] fn rem(self, rhs: U8Vec2) -> U8Vec2 { U8Vec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&U8Vec2> for u8 { type Output = U8Vec2; #[inline] fn rem(self, rhs: &U8Vec2) -> U8Vec2 { self.rem(*rhs) } } impl Rem<&U8Vec2> for &u8 { type Output = U8Vec2; #[inline] fn rem(self, rhs: &U8Vec2) -> U8Vec2 { (*self).rem(*rhs) } } impl Rem for &u8 { type Output = U8Vec2; #[inline] fn rem(self, rhs: U8Vec2) -> U8Vec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[u8; 2]> for U8Vec2 { #[inline] fn as_ref(&self) -> &[u8; 2] { unsafe { &*(self as *const U8Vec2 as *const [u8; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[u8; 2]> for U8Vec2 { #[inline] fn as_mut(&mut self) -> &mut [u8; 2] { unsafe { &mut *(self as *mut U8Vec2 as *mut [u8; 2]) } } } impl Sum for U8Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U8Vec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U8Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U8Vec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for U8Vec2 { type Output = Self; #[inline] fn not(self) -> Self::Output { Self { x: self.x.not(), y: self.y.not(), } } } impl BitAnd for U8Vec2 { 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 U8Vec2 { 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 U8Vec2 { 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 for U8Vec2 { type Output = Self; #[inline] fn bitand(self, rhs: u8) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), } } } impl BitOr for U8Vec2 { type Output = Self; #[inline] fn bitor(self, rhs: u8) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), } } } impl BitXor for U8Vec2 { type Output = Self; #[inline] fn bitxor(self, rhs: u8) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: i64) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: i64) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { type Output = Self; #[inline] fn shl(self, rhs: u64) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for U8Vec2 { type Output = Self; #[inline] fn shr(self, rhs: u64) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for U8Vec2 { 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 for U8Vec2 { 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 for U8Vec2 { 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 for U8Vec2 { 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 for U8Vec2 { type Output = u8; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for U8Vec2 { #[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"), } } } impl fmt::Display for U8Vec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } impl fmt::Debug for U8Vec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(U8Vec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[u8; 2]> for U8Vec2 { #[inline] fn from(a: [u8; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [u8; 2] { #[inline] fn from(v: U8Vec2) -> Self { [v.x, v.y] } } impl From<(u8, u8)> for U8Vec2 { #[inline] fn from(t: (u8, u8)) -> Self { Self::new(t.0, t.1) } } impl From for (u8, u8) { #[inline] fn from(v: U8Vec2) -> Self { (v.x, v.y) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl TryFrom for U8Vec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec2) -> Result { Ok(Self::new(u8::try_from(v.x)?, u8::try_from(v.y)?)) } } impl From for U8Vec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(u8::from(v.x), u8::from(v.y)) } } glam-0.30.1/src/u8/u8vec3.rs000064400000000000000000001364341046102023000134460ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec2, U8Vec4, USizeVec3, UVec3, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 3-dimensional vector. #[inline(always)] #[must_use] pub const fn u8vec3(x: u8, y: u8, z: u8) -> U8Vec3 { U8Vec3::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 U8Vec3 { pub x: u8, pub y: u8, pub z: u8, } impl U8Vec3 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// All `u8::MIN`. pub const MIN: Self = Self::splat(u8::MIN); /// All `u8::MAX`. pub const MAX: Self = Self::splat(u8::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: u8, y: u8, z: u8) -> Self { Self { x, y, z } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: u8) -> Self { Self { x: v, y: v, z: v } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u8) -> u8, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [u8; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// `[x, y, z]` #[inline] #[must_use] pub const fn to_array(&self) -> [u8; 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: &[u8]) -> Self { assert!(slice.len() >= 3); 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 [u8]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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: U8Vec4) -> 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: u8) -> U8Vec4 { U8Vec4::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) -> U8Vec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u8) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u8) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u8) -> Self { self.z = z; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> u8 { (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 [`u8::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) -> u8 { 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) -> u8 { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u8 { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u8 { self.x * self.y * 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) -> u8 { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u8::MAX`]. /// /// See also [`checked_manhattan_distance`][U8Vec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u8 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u8::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u8 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I8Vec3) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I8Vec3) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I8Vec3) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), } } } impl Default for U8Vec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for U8Vec3 { 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 Div<&U8Vec3> for U8Vec3 { type Output = U8Vec3; #[inline] fn div(self, rhs: &U8Vec3) -> U8Vec3 { self.div(*rhs) } } impl Div<&U8Vec3> for &U8Vec3 { type Output = U8Vec3; #[inline] fn div(self, rhs: &U8Vec3) -> U8Vec3 { (*self).div(*rhs) } } impl Div for &U8Vec3 { type Output = U8Vec3; #[inline] fn div(self, rhs: U8Vec3) -> U8Vec3 { (*self).div(rhs) } } impl DivAssign for U8Vec3 { #[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 DivAssign<&U8Vec3> for U8Vec3 { #[inline] fn div_assign(&mut self, rhs: &U8Vec3) { self.div_assign(*rhs) } } impl Div for U8Vec3 { type Output = Self; #[inline] fn div(self, rhs: u8) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&u8> for U8Vec3 { type Output = U8Vec3; #[inline] fn div(self, rhs: &u8) -> U8Vec3 { self.div(*rhs) } } impl Div<&u8> for &U8Vec3 { type Output = U8Vec3; #[inline] fn div(self, rhs: &u8) -> U8Vec3 { (*self).div(*rhs) } } impl Div for &U8Vec3 { type Output = U8Vec3; #[inline] fn div(self, rhs: u8) -> U8Vec3 { (*self).div(rhs) } } impl DivAssign for U8Vec3 { #[inline] fn div_assign(&mut self, rhs: u8) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&u8> for U8Vec3 { #[inline] fn div_assign(&mut self, rhs: &u8) { self.div_assign(*rhs) } } impl Div for u8 { type Output = U8Vec3; #[inline] fn div(self, rhs: U8Vec3) -> U8Vec3 { U8Vec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&U8Vec3> for u8 { type Output = U8Vec3; #[inline] fn div(self, rhs: &U8Vec3) -> U8Vec3 { self.div(*rhs) } } impl Div<&U8Vec3> for &u8 { type Output = U8Vec3; #[inline] fn div(self, rhs: &U8Vec3) -> U8Vec3 { (*self).div(*rhs) } } impl Div for &u8 { type Output = U8Vec3; #[inline] fn div(self, rhs: U8Vec3) -> U8Vec3 { (*self).div(rhs) } } impl Mul for U8Vec3 { 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 Mul<&U8Vec3> for U8Vec3 { type Output = U8Vec3; #[inline] fn mul(self, rhs: &U8Vec3) -> U8Vec3 { self.mul(*rhs) } } impl Mul<&U8Vec3> for &U8Vec3 { type Output = U8Vec3; #[inline] fn mul(self, rhs: &U8Vec3) -> U8Vec3 { (*self).mul(*rhs) } } impl Mul for &U8Vec3 { type Output = U8Vec3; #[inline] fn mul(self, rhs: U8Vec3) -> U8Vec3 { (*self).mul(rhs) } } impl MulAssign for U8Vec3 { #[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 MulAssign<&U8Vec3> for U8Vec3 { #[inline] fn mul_assign(&mut self, rhs: &U8Vec3) { self.mul_assign(*rhs) } } impl Mul for U8Vec3 { type Output = Self; #[inline] fn mul(self, rhs: u8) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&u8> for U8Vec3 { type Output = U8Vec3; #[inline] fn mul(self, rhs: &u8) -> U8Vec3 { self.mul(*rhs) } } impl Mul<&u8> for &U8Vec3 { type Output = U8Vec3; #[inline] fn mul(self, rhs: &u8) -> U8Vec3 { (*self).mul(*rhs) } } impl Mul for &U8Vec3 { type Output = U8Vec3; #[inline] fn mul(self, rhs: u8) -> U8Vec3 { (*self).mul(rhs) } } impl MulAssign for U8Vec3 { #[inline] fn mul_assign(&mut self, rhs: u8) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&u8> for U8Vec3 { #[inline] fn mul_assign(&mut self, rhs: &u8) { self.mul_assign(*rhs) } } impl Mul for u8 { type Output = U8Vec3; #[inline] fn mul(self, rhs: U8Vec3) -> U8Vec3 { U8Vec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&U8Vec3> for u8 { type Output = U8Vec3; #[inline] fn mul(self, rhs: &U8Vec3) -> U8Vec3 { self.mul(*rhs) } } impl Mul<&U8Vec3> for &u8 { type Output = U8Vec3; #[inline] fn mul(self, rhs: &U8Vec3) -> U8Vec3 { (*self).mul(*rhs) } } impl Mul for &u8 { type Output = U8Vec3; #[inline] fn mul(self, rhs: U8Vec3) -> U8Vec3 { (*self).mul(rhs) } } impl Add for U8Vec3 { 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 Add<&U8Vec3> for U8Vec3 { type Output = U8Vec3; #[inline] fn add(self, rhs: &U8Vec3) -> U8Vec3 { self.add(*rhs) } } impl Add<&U8Vec3> for &U8Vec3 { type Output = U8Vec3; #[inline] fn add(self, rhs: &U8Vec3) -> U8Vec3 { (*self).add(*rhs) } } impl Add for &U8Vec3 { type Output = U8Vec3; #[inline] fn add(self, rhs: U8Vec3) -> U8Vec3 { (*self).add(rhs) } } impl AddAssign for U8Vec3 { #[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 AddAssign<&U8Vec3> for U8Vec3 { #[inline] fn add_assign(&mut self, rhs: &U8Vec3) { self.add_assign(*rhs) } } impl Add for U8Vec3 { type Output = Self; #[inline] fn add(self, rhs: u8) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&u8> for U8Vec3 { type Output = U8Vec3; #[inline] fn add(self, rhs: &u8) -> U8Vec3 { self.add(*rhs) } } impl Add<&u8> for &U8Vec3 { type Output = U8Vec3; #[inline] fn add(self, rhs: &u8) -> U8Vec3 { (*self).add(*rhs) } } impl Add for &U8Vec3 { type Output = U8Vec3; #[inline] fn add(self, rhs: u8) -> U8Vec3 { (*self).add(rhs) } } impl AddAssign for U8Vec3 { #[inline] fn add_assign(&mut self, rhs: u8) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&u8> for U8Vec3 { #[inline] fn add_assign(&mut self, rhs: &u8) { self.add_assign(*rhs) } } impl Add for u8 { type Output = U8Vec3; #[inline] fn add(self, rhs: U8Vec3) -> U8Vec3 { U8Vec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&U8Vec3> for u8 { type Output = U8Vec3; #[inline] fn add(self, rhs: &U8Vec3) -> U8Vec3 { self.add(*rhs) } } impl Add<&U8Vec3> for &u8 { type Output = U8Vec3; #[inline] fn add(self, rhs: &U8Vec3) -> U8Vec3 { (*self).add(*rhs) } } impl Add for &u8 { type Output = U8Vec3; #[inline] fn add(self, rhs: U8Vec3) -> U8Vec3 { (*self).add(rhs) } } impl Sub for U8Vec3 { 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 Sub<&U8Vec3> for U8Vec3 { type Output = U8Vec3; #[inline] fn sub(self, rhs: &U8Vec3) -> U8Vec3 { self.sub(*rhs) } } impl Sub<&U8Vec3> for &U8Vec3 { type Output = U8Vec3; #[inline] fn sub(self, rhs: &U8Vec3) -> U8Vec3 { (*self).sub(*rhs) } } impl Sub for &U8Vec3 { type Output = U8Vec3; #[inline] fn sub(self, rhs: U8Vec3) -> U8Vec3 { (*self).sub(rhs) } } impl SubAssign for U8Vec3 { #[inline] fn sub_assign(&mut self, rhs: U8Vec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&U8Vec3> for U8Vec3 { #[inline] fn sub_assign(&mut self, rhs: &U8Vec3) { self.sub_assign(*rhs) } } impl Sub for U8Vec3 { type Output = Self; #[inline] fn sub(self, rhs: u8) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&u8> for U8Vec3 { type Output = U8Vec3; #[inline] fn sub(self, rhs: &u8) -> U8Vec3 { self.sub(*rhs) } } impl Sub<&u8> for &U8Vec3 { type Output = U8Vec3; #[inline] fn sub(self, rhs: &u8) -> U8Vec3 { (*self).sub(*rhs) } } impl Sub for &U8Vec3 { type Output = U8Vec3; #[inline] fn sub(self, rhs: u8) -> U8Vec3 { (*self).sub(rhs) } } impl SubAssign for U8Vec3 { #[inline] fn sub_assign(&mut self, rhs: u8) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&u8> for U8Vec3 { #[inline] fn sub_assign(&mut self, rhs: &u8) { self.sub_assign(*rhs) } } impl Sub for u8 { type Output = U8Vec3; #[inline] fn sub(self, rhs: U8Vec3) -> U8Vec3 { U8Vec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&U8Vec3> for u8 { type Output = U8Vec3; #[inline] fn sub(self, rhs: &U8Vec3) -> U8Vec3 { self.sub(*rhs) } } impl Sub<&U8Vec3> for &u8 { type Output = U8Vec3; #[inline] fn sub(self, rhs: &U8Vec3) -> U8Vec3 { (*self).sub(*rhs) } } impl Sub for &u8 { type Output = U8Vec3; #[inline] fn sub(self, rhs: U8Vec3) -> U8Vec3 { (*self).sub(rhs) } } impl Rem for U8Vec3 { 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 Rem<&U8Vec3> for U8Vec3 { type Output = U8Vec3; #[inline] fn rem(self, rhs: &U8Vec3) -> U8Vec3 { self.rem(*rhs) } } impl Rem<&U8Vec3> for &U8Vec3 { type Output = U8Vec3; #[inline] fn rem(self, rhs: &U8Vec3) -> U8Vec3 { (*self).rem(*rhs) } } impl Rem for &U8Vec3 { type Output = U8Vec3; #[inline] fn rem(self, rhs: U8Vec3) -> U8Vec3 { (*self).rem(rhs) } } impl RemAssign for U8Vec3 { #[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 RemAssign<&U8Vec3> for U8Vec3 { #[inline] fn rem_assign(&mut self, rhs: &U8Vec3) { self.rem_assign(*rhs) } } impl Rem for U8Vec3 { type Output = Self; #[inline] fn rem(self, rhs: u8) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&u8> for U8Vec3 { type Output = U8Vec3; #[inline] fn rem(self, rhs: &u8) -> U8Vec3 { self.rem(*rhs) } } impl Rem<&u8> for &U8Vec3 { type Output = U8Vec3; #[inline] fn rem(self, rhs: &u8) -> U8Vec3 { (*self).rem(*rhs) } } impl Rem for &U8Vec3 { type Output = U8Vec3; #[inline] fn rem(self, rhs: u8) -> U8Vec3 { (*self).rem(rhs) } } impl RemAssign for U8Vec3 { #[inline] fn rem_assign(&mut self, rhs: u8) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&u8> for U8Vec3 { #[inline] fn rem_assign(&mut self, rhs: &u8) { self.rem_assign(*rhs) } } impl Rem for u8 { type Output = U8Vec3; #[inline] fn rem(self, rhs: U8Vec3) -> U8Vec3 { U8Vec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&U8Vec3> for u8 { type Output = U8Vec3; #[inline] fn rem(self, rhs: &U8Vec3) -> U8Vec3 { self.rem(*rhs) } } impl Rem<&U8Vec3> for &u8 { type Output = U8Vec3; #[inline] fn rem(self, rhs: &U8Vec3) -> U8Vec3 { (*self).rem(*rhs) } } impl Rem for &u8 { type Output = U8Vec3; #[inline] fn rem(self, rhs: U8Vec3) -> U8Vec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[u8; 3]> for U8Vec3 { #[inline] fn as_ref(&self) -> &[u8; 3] { unsafe { &*(self as *const U8Vec3 as *const [u8; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[u8; 3]> for U8Vec3 { #[inline] fn as_mut(&mut self) -> &mut [u8; 3] { unsafe { &mut *(self as *mut U8Vec3 as *mut [u8; 3]) } } } impl Sum for U8Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U8Vec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U8Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U8Vec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for U8Vec3 { 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 U8Vec3 { 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 U8Vec3 { 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 U8Vec3 { 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 for U8Vec3 { type Output = Self; #[inline] fn bitand(self, rhs: u8) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), z: self.z.bitand(rhs), } } } impl BitOr for U8Vec3 { type Output = Self; #[inline] fn bitor(self, rhs: u8) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), z: self.z.bitor(rhs), } } } impl BitXor for U8Vec3 { type Output = Self; #[inline] fn bitxor(self, rhs: u8) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), z: self.z.bitxor(rhs), } } } impl Shl for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { 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 for U8Vec3 { type Output = u8; #[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 for U8Vec3 { #[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"), } } } impl fmt::Display for U8Vec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } impl fmt::Debug for U8Vec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(U8Vec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[u8; 3]> for U8Vec3 { #[inline] fn from(a: [u8; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [u8; 3] { #[inline] fn from(v: U8Vec3) -> Self { [v.x, v.y, v.z] } } impl From<(u8, u8, u8)> for U8Vec3 { #[inline] fn from(t: (u8, u8, u8)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (u8, u8, u8) { #[inline] fn from(v: U8Vec3) -> Self { (v.x, v.y, v.z) } } impl From<(U8Vec2, u8)> for U8Vec3 { #[inline] fn from((v, z): (U8Vec2, u8)) -> Self { Self::new(v.x, v.y, z) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl TryFrom for U8Vec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec3) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, )) } } impl From for U8Vec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(u8::from(v.x), u8::from(v.y), u8::from(v.z)) } } impl From for U8Vec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( u8::from(bool_array[0]), u8::from(bool_array[1]), u8::from(bool_array[2]), ) } } glam-0.30.1/src/u8/u8vec4.rs000064400000000000000000001472461046102023000134520ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec2, U8Vec3, USizeVec4, UVec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 4-dimensional vector. #[inline(always)] #[must_use] pub const fn u8vec4(x: u8, y: u8, z: u8, w: u8) -> U8Vec4 { U8Vec4::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(4)))] #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct U8Vec4 { pub x: u8, pub y: u8, pub z: u8, pub w: u8, } impl U8Vec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// All `u8::MIN`. pub const MIN: Self = Self::splat(u8::MIN); /// All `u8::MAX`. pub const MAX: Self = Self::splat(u8::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: u8, y: u8, z: u8, w: u8) -> Self { Self { x, y, z, w } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: u8) -> Self { Self { x: v, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(u8) -> u8, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: [u8; 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) -> [u8; 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: &[u8]) -> Self { assert!(slice.len() >= 4); 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 [u8]) { slice[..4].copy_from_slice(&self.to_array()); } /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`. /// /// Truncation to [`U8Vec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()]. #[inline] #[must_use] pub fn truncate(self) -> U8Vec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: u8) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: u8) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: u8) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: u8) -> Self { self.w = w; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> u8 { (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 [`u8::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) -> u8 { 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) -> u8 { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> u8 { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> u8 { self.x * self.y * self.z * 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) -> u8 { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`u8::MAX`]. /// /// See also [`checked_manhattan_distance`][U8Vec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> u8 { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`u8::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> u8 { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// 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) } /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new( self.x as usize, self.y as usize, self.z as usize, self.w as usize, ) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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), } } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: I8Vec4) -> Option { let x = match self.x.checked_add_signed(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add_signed(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add_signed(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add_signed(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: I8Vec4) -> Self { Self { x: self.x.wrapping_add_signed(rhs.x), y: self.y.wrapping_add_signed(rhs.y), z: self.z.wrapping_add_signed(rhs.z), w: self.w.wrapping_add_signed(rhs.w), } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: I8Vec4) -> Self { Self { x: self.x.saturating_add_signed(rhs.x), y: self.y.saturating_add_signed(rhs.y), z: self.z.saturating_add_signed(rhs.z), w: self.w.saturating_add_signed(rhs.w), } } } impl Default for U8Vec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for U8Vec4 { 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 Div<&U8Vec4> for U8Vec4 { type Output = U8Vec4; #[inline] fn div(self, rhs: &U8Vec4) -> U8Vec4 { self.div(*rhs) } } impl Div<&U8Vec4> for &U8Vec4 { type Output = U8Vec4; #[inline] fn div(self, rhs: &U8Vec4) -> U8Vec4 { (*self).div(*rhs) } } impl Div for &U8Vec4 { type Output = U8Vec4; #[inline] fn div(self, rhs: U8Vec4) -> U8Vec4 { (*self).div(rhs) } } impl DivAssign for U8Vec4 { #[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 DivAssign<&U8Vec4> for U8Vec4 { #[inline] fn div_assign(&mut self, rhs: &U8Vec4) { self.div_assign(*rhs) } } impl Div for U8Vec4 { type Output = Self; #[inline] fn div(self, rhs: u8) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&u8> for U8Vec4 { type Output = U8Vec4; #[inline] fn div(self, rhs: &u8) -> U8Vec4 { self.div(*rhs) } } impl Div<&u8> for &U8Vec4 { type Output = U8Vec4; #[inline] fn div(self, rhs: &u8) -> U8Vec4 { (*self).div(*rhs) } } impl Div for &U8Vec4 { type Output = U8Vec4; #[inline] fn div(self, rhs: u8) -> U8Vec4 { (*self).div(rhs) } } impl DivAssign for U8Vec4 { #[inline] fn div_assign(&mut self, rhs: u8) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&u8> for U8Vec4 { #[inline] fn div_assign(&mut self, rhs: &u8) { self.div_assign(*rhs) } } impl Div for u8 { type Output = U8Vec4; #[inline] fn div(self, rhs: U8Vec4) -> U8Vec4 { U8Vec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&U8Vec4> for u8 { type Output = U8Vec4; #[inline] fn div(self, rhs: &U8Vec4) -> U8Vec4 { self.div(*rhs) } } impl Div<&U8Vec4> for &u8 { type Output = U8Vec4; #[inline] fn div(self, rhs: &U8Vec4) -> U8Vec4 { (*self).div(*rhs) } } impl Div for &u8 { type Output = U8Vec4; #[inline] fn div(self, rhs: U8Vec4) -> U8Vec4 { (*self).div(rhs) } } impl Mul for U8Vec4 { 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 Mul<&U8Vec4> for U8Vec4 { type Output = U8Vec4; #[inline] fn mul(self, rhs: &U8Vec4) -> U8Vec4 { self.mul(*rhs) } } impl Mul<&U8Vec4> for &U8Vec4 { type Output = U8Vec4; #[inline] fn mul(self, rhs: &U8Vec4) -> U8Vec4 { (*self).mul(*rhs) } } impl Mul for &U8Vec4 { type Output = U8Vec4; #[inline] fn mul(self, rhs: U8Vec4) -> U8Vec4 { (*self).mul(rhs) } } impl MulAssign for U8Vec4 { #[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 MulAssign<&U8Vec4> for U8Vec4 { #[inline] fn mul_assign(&mut self, rhs: &U8Vec4) { self.mul_assign(*rhs) } } impl Mul for U8Vec4 { type Output = Self; #[inline] fn mul(self, rhs: u8) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&u8> for U8Vec4 { type Output = U8Vec4; #[inline] fn mul(self, rhs: &u8) -> U8Vec4 { self.mul(*rhs) } } impl Mul<&u8> for &U8Vec4 { type Output = U8Vec4; #[inline] fn mul(self, rhs: &u8) -> U8Vec4 { (*self).mul(*rhs) } } impl Mul for &U8Vec4 { type Output = U8Vec4; #[inline] fn mul(self, rhs: u8) -> U8Vec4 { (*self).mul(rhs) } } impl MulAssign for U8Vec4 { #[inline] fn mul_assign(&mut self, rhs: u8) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&u8> for U8Vec4 { #[inline] fn mul_assign(&mut self, rhs: &u8) { self.mul_assign(*rhs) } } impl Mul for u8 { type Output = U8Vec4; #[inline] fn mul(self, rhs: U8Vec4) -> U8Vec4 { U8Vec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&U8Vec4> for u8 { type Output = U8Vec4; #[inline] fn mul(self, rhs: &U8Vec4) -> U8Vec4 { self.mul(*rhs) } } impl Mul<&U8Vec4> for &u8 { type Output = U8Vec4; #[inline] fn mul(self, rhs: &U8Vec4) -> U8Vec4 { (*self).mul(*rhs) } } impl Mul for &u8 { type Output = U8Vec4; #[inline] fn mul(self, rhs: U8Vec4) -> U8Vec4 { (*self).mul(rhs) } } impl Add for U8Vec4 { 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 Add<&U8Vec4> for U8Vec4 { type Output = U8Vec4; #[inline] fn add(self, rhs: &U8Vec4) -> U8Vec4 { self.add(*rhs) } } impl Add<&U8Vec4> for &U8Vec4 { type Output = U8Vec4; #[inline] fn add(self, rhs: &U8Vec4) -> U8Vec4 { (*self).add(*rhs) } } impl Add for &U8Vec4 { type Output = U8Vec4; #[inline] fn add(self, rhs: U8Vec4) -> U8Vec4 { (*self).add(rhs) } } impl AddAssign for U8Vec4 { #[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 AddAssign<&U8Vec4> for U8Vec4 { #[inline] fn add_assign(&mut self, rhs: &U8Vec4) { self.add_assign(*rhs) } } impl Add for U8Vec4 { type Output = Self; #[inline] fn add(self, rhs: u8) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&u8> for U8Vec4 { type Output = U8Vec4; #[inline] fn add(self, rhs: &u8) -> U8Vec4 { self.add(*rhs) } } impl Add<&u8> for &U8Vec4 { type Output = U8Vec4; #[inline] fn add(self, rhs: &u8) -> U8Vec4 { (*self).add(*rhs) } } impl Add for &U8Vec4 { type Output = U8Vec4; #[inline] fn add(self, rhs: u8) -> U8Vec4 { (*self).add(rhs) } } impl AddAssign for U8Vec4 { #[inline] fn add_assign(&mut self, rhs: u8) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&u8> for U8Vec4 { #[inline] fn add_assign(&mut self, rhs: &u8) { self.add_assign(*rhs) } } impl Add for u8 { type Output = U8Vec4; #[inline] fn add(self, rhs: U8Vec4) -> U8Vec4 { U8Vec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&U8Vec4> for u8 { type Output = U8Vec4; #[inline] fn add(self, rhs: &U8Vec4) -> U8Vec4 { self.add(*rhs) } } impl Add<&U8Vec4> for &u8 { type Output = U8Vec4; #[inline] fn add(self, rhs: &U8Vec4) -> U8Vec4 { (*self).add(*rhs) } } impl Add for &u8 { type Output = U8Vec4; #[inline] fn add(self, rhs: U8Vec4) -> U8Vec4 { (*self).add(rhs) } } impl Sub for U8Vec4 { 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 Sub<&U8Vec4> for U8Vec4 { type Output = U8Vec4; #[inline] fn sub(self, rhs: &U8Vec4) -> U8Vec4 { self.sub(*rhs) } } impl Sub<&U8Vec4> for &U8Vec4 { type Output = U8Vec4; #[inline] fn sub(self, rhs: &U8Vec4) -> U8Vec4 { (*self).sub(*rhs) } } impl Sub for &U8Vec4 { type Output = U8Vec4; #[inline] fn sub(self, rhs: U8Vec4) -> U8Vec4 { (*self).sub(rhs) } } impl SubAssign for U8Vec4 { #[inline] fn sub_assign(&mut self, rhs: U8Vec4) { 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 SubAssign<&U8Vec4> for U8Vec4 { #[inline] fn sub_assign(&mut self, rhs: &U8Vec4) { self.sub_assign(*rhs) } } impl Sub for U8Vec4 { type Output = Self; #[inline] fn sub(self, rhs: u8) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&u8> for U8Vec4 { type Output = U8Vec4; #[inline] fn sub(self, rhs: &u8) -> U8Vec4 { self.sub(*rhs) } } impl Sub<&u8> for &U8Vec4 { type Output = U8Vec4; #[inline] fn sub(self, rhs: &u8) -> U8Vec4 { (*self).sub(*rhs) } } impl Sub for &U8Vec4 { type Output = U8Vec4; #[inline] fn sub(self, rhs: u8) -> U8Vec4 { (*self).sub(rhs) } } impl SubAssign for U8Vec4 { #[inline] fn sub_assign(&mut self, rhs: u8) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&u8> for U8Vec4 { #[inline] fn sub_assign(&mut self, rhs: &u8) { self.sub_assign(*rhs) } } impl Sub for u8 { type Output = U8Vec4; #[inline] fn sub(self, rhs: U8Vec4) -> U8Vec4 { U8Vec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&U8Vec4> for u8 { type Output = U8Vec4; #[inline] fn sub(self, rhs: &U8Vec4) -> U8Vec4 { self.sub(*rhs) } } impl Sub<&U8Vec4> for &u8 { type Output = U8Vec4; #[inline] fn sub(self, rhs: &U8Vec4) -> U8Vec4 { (*self).sub(*rhs) } } impl Sub for &u8 { type Output = U8Vec4; #[inline] fn sub(self, rhs: U8Vec4) -> U8Vec4 { (*self).sub(rhs) } } impl Rem for U8Vec4 { 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 Rem<&U8Vec4> for U8Vec4 { type Output = U8Vec4; #[inline] fn rem(self, rhs: &U8Vec4) -> U8Vec4 { self.rem(*rhs) } } impl Rem<&U8Vec4> for &U8Vec4 { type Output = U8Vec4; #[inline] fn rem(self, rhs: &U8Vec4) -> U8Vec4 { (*self).rem(*rhs) } } impl Rem for &U8Vec4 { type Output = U8Vec4; #[inline] fn rem(self, rhs: U8Vec4) -> U8Vec4 { (*self).rem(rhs) } } impl RemAssign for U8Vec4 { #[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 RemAssign<&U8Vec4> for U8Vec4 { #[inline] fn rem_assign(&mut self, rhs: &U8Vec4) { self.rem_assign(*rhs) } } impl Rem for U8Vec4 { type Output = Self; #[inline] fn rem(self, rhs: u8) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&u8> for U8Vec4 { type Output = U8Vec4; #[inline] fn rem(self, rhs: &u8) -> U8Vec4 { self.rem(*rhs) } } impl Rem<&u8> for &U8Vec4 { type Output = U8Vec4; #[inline] fn rem(self, rhs: &u8) -> U8Vec4 { (*self).rem(*rhs) } } impl Rem for &U8Vec4 { type Output = U8Vec4; #[inline] fn rem(self, rhs: u8) -> U8Vec4 { (*self).rem(rhs) } } impl RemAssign for U8Vec4 { #[inline] fn rem_assign(&mut self, rhs: u8) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&u8> for U8Vec4 { #[inline] fn rem_assign(&mut self, rhs: &u8) { self.rem_assign(*rhs) } } impl Rem for u8 { type Output = U8Vec4; #[inline] fn rem(self, rhs: U8Vec4) -> U8Vec4 { U8Vec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&U8Vec4> for u8 { type Output = U8Vec4; #[inline] fn rem(self, rhs: &U8Vec4) -> U8Vec4 { self.rem(*rhs) } } impl Rem<&U8Vec4> for &u8 { type Output = U8Vec4; #[inline] fn rem(self, rhs: &U8Vec4) -> U8Vec4 { (*self).rem(*rhs) } } impl Rem for &u8 { type Output = U8Vec4; #[inline] fn rem(self, rhs: U8Vec4) -> U8Vec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[u8; 4]> for U8Vec4 { #[inline] fn as_ref(&self) -> &[u8; 4] { unsafe { &*(self as *const U8Vec4 as *const [u8; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[u8; 4]> for U8Vec4 { #[inline] fn as_mut(&mut self) -> &mut [u8; 4] { unsafe { &mut *(self as *mut U8Vec4 as *mut [u8; 4]) } } } impl Sum for U8Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for U8Vec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for U8Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for U8Vec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for U8Vec4 { 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 U8Vec4 { 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 U8Vec4 { 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 U8Vec4 { 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 for U8Vec4 { type Output = Self; #[inline] fn bitand(self, rhs: u8) -> 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 for U8Vec4 { type Output = Self; #[inline] fn bitor(self, rhs: u8) -> 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 for U8Vec4 { type Output = Self; #[inline] fn bitxor(self, rhs: u8) -> 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { 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 for U8Vec4 { type Output = u8; #[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 for U8Vec4 { #[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"), } } } impl fmt::Display for U8Vec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } impl fmt::Debug for U8Vec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(U8Vec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[u8; 4]> for U8Vec4 { #[inline] fn from(a: [u8; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [u8; 4] { #[inline] fn from(v: U8Vec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(u8, u8, u8, u8)> for U8Vec4 { #[inline] fn from(t: (u8, u8, u8, u8)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (u8, u8, u8, u8) { #[inline] fn from(v: U8Vec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(U8Vec3, u8)> for U8Vec4 { #[inline] fn from((v, w): (U8Vec3, u8)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(u8, U8Vec3)> for U8Vec4 { #[inline] fn from((x, v): (u8, U8Vec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(U8Vec2, u8, u8)> for U8Vec4 { #[inline] fn from((v, z, w): (U8Vec2, u8, u8)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(U8Vec2, U8Vec2)> for U8Vec4 { #[inline] fn from((v, u): (U8Vec2, U8Vec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U16Vec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl TryFrom for U8Vec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: USizeVec4) -> Result { Ok(Self::new( u8::try_from(v.x)?, u8::try_from(v.y)?, u8::try_from(v.z)?, u8::try_from(v.w)?, )) } } impl From for U8Vec4 { #[inline] fn from(v: BVec4) -> Self { Self::new(u8::from(v.x), u8::from(v.y), u8::from(v.z), u8::from(v.w)) } } #[cfg(not(feature = "scalar-math"))] impl From for U8Vec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( u8::from(bool_array[0]), u8::from(bool_array[1]), u8::from(bool_array[2]), u8::from(bool_array[3]), ) } } glam-0.30.1/src/u8.rs000064400000000000000000000022401046102023000123140ustar 00000000000000mod u8vec2; mod u8vec3; mod u8vec4; pub use u8vec2::{u8vec2, U8Vec2}; pub use u8vec3::{u8vec3, U8Vec3}; pub use u8vec4::{u8vec4, U8Vec4}; #[cfg(not(target_arch = "spirv"))] mod test { use super::*; mod const_test_u8vec2 { const_assert_eq!(2, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(2, core::mem::align_of::()); } mod const_test_u8vec3 { const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); const_assert_eq!(3, core::mem::size_of::()); } mod const_test_u8vec4 { const_assert_eq!(4, core::mem::size_of::()); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(4, core::mem::align_of::()); } } glam-0.30.1/src/usize/usizevec2.rs000064400000000000000000001216511046102023000150460ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec3, UVec2}; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 2-dimensional vector. #[inline(always)] #[must_use] pub const fn usizevec2(x: usize, y: usize) -> USizeVec2 { USizeVec2::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 USizeVec2 { pub x: usize, pub y: usize, } impl USizeVec2 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// All `usize::MIN`. pub const MIN: Self = Self::splat(usize::MIN); /// All `usize::MAX`. pub const MAX: Self = Self::splat(usize::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: usize, y: usize) -> Self { Self { x, y } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: usize) -> Self { Self { x: v, y: v } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(usize) -> usize, { Self::new(f(self.x), f(self.y)) } /// 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: [usize; 2]) -> Self { Self::new(a[0], a[1]) } /// `[x, y]` #[inline] #[must_use] pub const fn to_array(&self) -> [usize; 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: &[usize]) -> Self { assert!(slice.len() >= 2); 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 [usize]) { slice[..2].copy_from_slice(&self.to_array()); } /// Creates a 3D vector from `self` and the given `z` value. #[inline] #[must_use] pub const fn extend(self, z: usize) -> USizeVec3 { USizeVec3::new(self.x, self.y, z) } /// Creates a 2D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: usize) -> Self { self.x = x; self } /// Creates a 2D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: usize) -> Self { self.y = y; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> usize { (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 [`usize::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) -> usize { 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) -> usize { self.x.max(self.y) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { if self.x <= self.y { 0 } else { 1 } } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { if self.x >= self.y { 0 } else { 1 } } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> usize { self.x + self.y } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> usize { self.x * 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) -> usize { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`usize::MAX`]. /// /// See also [`checked_manhattan_distance`][USizeVec2::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> usize { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`usize::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); d.checked_add(self.y.abs_diff(other.y)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> usize { // Note: the compiler will eventually optimize out the loop [self.x.abs_diff(other.x), self.y.abs_diff(other.y)] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } /// 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) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; Some(Self { x, y }) } /// 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 USizeVec2 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for USizeVec2 { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { Self { x: self.x.div(rhs.x), y: self.y.div(rhs.y), } } } impl Div<&USizeVec2> for USizeVec2 { type Output = USizeVec2; #[inline] fn div(self, rhs: &USizeVec2) -> USizeVec2 { self.div(*rhs) } } impl Div<&USizeVec2> for &USizeVec2 { type Output = USizeVec2; #[inline] fn div(self, rhs: &USizeVec2) -> USizeVec2 { (*self).div(*rhs) } } impl Div for &USizeVec2 { type Output = USizeVec2; #[inline] fn div(self, rhs: USizeVec2) -> USizeVec2 { (*self).div(rhs) } } impl DivAssign for USizeVec2 { #[inline] fn div_assign(&mut self, rhs: Self) { self.x.div_assign(rhs.x); self.y.div_assign(rhs.y); } } impl DivAssign<&USizeVec2> for USizeVec2 { #[inline] fn div_assign(&mut self, rhs: &USizeVec2) { self.div_assign(*rhs) } } impl Div for USizeVec2 { type Output = Self; #[inline] fn div(self, rhs: usize) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), } } } impl Div<&usize> for USizeVec2 { type Output = USizeVec2; #[inline] fn div(self, rhs: &usize) -> USizeVec2 { self.div(*rhs) } } impl Div<&usize> for &USizeVec2 { type Output = USizeVec2; #[inline] fn div(self, rhs: &usize) -> USizeVec2 { (*self).div(*rhs) } } impl Div for &USizeVec2 { type Output = USizeVec2; #[inline] fn div(self, rhs: usize) -> USizeVec2 { (*self).div(rhs) } } impl DivAssign for USizeVec2 { #[inline] fn div_assign(&mut self, rhs: usize) { self.x.div_assign(rhs); self.y.div_assign(rhs); } } impl DivAssign<&usize> for USizeVec2 { #[inline] fn div_assign(&mut self, rhs: &usize) { self.div_assign(*rhs) } } impl Div for usize { type Output = USizeVec2; #[inline] fn div(self, rhs: USizeVec2) -> USizeVec2 { USizeVec2 { x: self.div(rhs.x), y: self.div(rhs.y), } } } impl Div<&USizeVec2> for usize { type Output = USizeVec2; #[inline] fn div(self, rhs: &USizeVec2) -> USizeVec2 { self.div(*rhs) } } impl Div<&USizeVec2> for &usize { type Output = USizeVec2; #[inline] fn div(self, rhs: &USizeVec2) -> USizeVec2 { (*self).div(*rhs) } } impl Div for &usize { type Output = USizeVec2; #[inline] fn div(self, rhs: USizeVec2) -> USizeVec2 { (*self).div(rhs) } } impl Mul for USizeVec2 { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { Self { x: self.x.mul(rhs.x), y: self.y.mul(rhs.y), } } } impl Mul<&USizeVec2> for USizeVec2 { type Output = USizeVec2; #[inline] fn mul(self, rhs: &USizeVec2) -> USizeVec2 { self.mul(*rhs) } } impl Mul<&USizeVec2> for &USizeVec2 { type Output = USizeVec2; #[inline] fn mul(self, rhs: &USizeVec2) -> USizeVec2 { (*self).mul(*rhs) } } impl Mul for &USizeVec2 { type Output = USizeVec2; #[inline] fn mul(self, rhs: USizeVec2) -> USizeVec2 { (*self).mul(rhs) } } impl MulAssign for USizeVec2 { #[inline] fn mul_assign(&mut self, rhs: Self) { self.x.mul_assign(rhs.x); self.y.mul_assign(rhs.y); } } impl MulAssign<&USizeVec2> for USizeVec2 { #[inline] fn mul_assign(&mut self, rhs: &USizeVec2) { self.mul_assign(*rhs) } } impl Mul for USizeVec2 { type Output = Self; #[inline] fn mul(self, rhs: usize) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), } } } impl Mul<&usize> for USizeVec2 { type Output = USizeVec2; #[inline] fn mul(self, rhs: &usize) -> USizeVec2 { self.mul(*rhs) } } impl Mul<&usize> for &USizeVec2 { type Output = USizeVec2; #[inline] fn mul(self, rhs: &usize) -> USizeVec2 { (*self).mul(*rhs) } } impl Mul for &USizeVec2 { type Output = USizeVec2; #[inline] fn mul(self, rhs: usize) -> USizeVec2 { (*self).mul(rhs) } } impl MulAssign for USizeVec2 { #[inline] fn mul_assign(&mut self, rhs: usize) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); } } impl MulAssign<&usize> for USizeVec2 { #[inline] fn mul_assign(&mut self, rhs: &usize) { self.mul_assign(*rhs) } } impl Mul for usize { type Output = USizeVec2; #[inline] fn mul(self, rhs: USizeVec2) -> USizeVec2 { USizeVec2 { x: self.mul(rhs.x), y: self.mul(rhs.y), } } } impl Mul<&USizeVec2> for usize { type Output = USizeVec2; #[inline] fn mul(self, rhs: &USizeVec2) -> USizeVec2 { self.mul(*rhs) } } impl Mul<&USizeVec2> for &usize { type Output = USizeVec2; #[inline] fn mul(self, rhs: &USizeVec2) -> USizeVec2 { (*self).mul(*rhs) } } impl Mul for &usize { type Output = USizeVec2; #[inline] fn mul(self, rhs: USizeVec2) -> USizeVec2 { (*self).mul(rhs) } } impl Add for USizeVec2 { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { Self { x: self.x.add(rhs.x), y: self.y.add(rhs.y), } } } impl Add<&USizeVec2> for USizeVec2 { type Output = USizeVec2; #[inline] fn add(self, rhs: &USizeVec2) -> USizeVec2 { self.add(*rhs) } } impl Add<&USizeVec2> for &USizeVec2 { type Output = USizeVec2; #[inline] fn add(self, rhs: &USizeVec2) -> USizeVec2 { (*self).add(*rhs) } } impl Add for &USizeVec2 { type Output = USizeVec2; #[inline] fn add(self, rhs: USizeVec2) -> USizeVec2 { (*self).add(rhs) } } impl AddAssign for USizeVec2 { #[inline] fn add_assign(&mut self, rhs: Self) { self.x.add_assign(rhs.x); self.y.add_assign(rhs.y); } } impl AddAssign<&USizeVec2> for USizeVec2 { #[inline] fn add_assign(&mut self, rhs: &USizeVec2) { self.add_assign(*rhs) } } impl Add for USizeVec2 { type Output = Self; #[inline] fn add(self, rhs: usize) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), } } } impl Add<&usize> for USizeVec2 { type Output = USizeVec2; #[inline] fn add(self, rhs: &usize) -> USizeVec2 { self.add(*rhs) } } impl Add<&usize> for &USizeVec2 { type Output = USizeVec2; #[inline] fn add(self, rhs: &usize) -> USizeVec2 { (*self).add(*rhs) } } impl Add for &USizeVec2 { type Output = USizeVec2; #[inline] fn add(self, rhs: usize) -> USizeVec2 { (*self).add(rhs) } } impl AddAssign for USizeVec2 { #[inline] fn add_assign(&mut self, rhs: usize) { self.x.add_assign(rhs); self.y.add_assign(rhs); } } impl AddAssign<&usize> for USizeVec2 { #[inline] fn add_assign(&mut self, rhs: &usize) { self.add_assign(*rhs) } } impl Add for usize { type Output = USizeVec2; #[inline] fn add(self, rhs: USizeVec2) -> USizeVec2 { USizeVec2 { x: self.add(rhs.x), y: self.add(rhs.y), } } } impl Add<&USizeVec2> for usize { type Output = USizeVec2; #[inline] fn add(self, rhs: &USizeVec2) -> USizeVec2 { self.add(*rhs) } } impl Add<&USizeVec2> for &usize { type Output = USizeVec2; #[inline] fn add(self, rhs: &USizeVec2) -> USizeVec2 { (*self).add(*rhs) } } impl Add for &usize { type Output = USizeVec2; #[inline] fn add(self, rhs: USizeVec2) -> USizeVec2 { (*self).add(rhs) } } impl Sub for USizeVec2 { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { Self { x: self.x.sub(rhs.x), y: self.y.sub(rhs.y), } } } impl Sub<&USizeVec2> for USizeVec2 { type Output = USizeVec2; #[inline] fn sub(self, rhs: &USizeVec2) -> USizeVec2 { self.sub(*rhs) } } impl Sub<&USizeVec2> for &USizeVec2 { type Output = USizeVec2; #[inline] fn sub(self, rhs: &USizeVec2) -> USizeVec2 { (*self).sub(*rhs) } } impl Sub for &USizeVec2 { type Output = USizeVec2; #[inline] fn sub(self, rhs: USizeVec2) -> USizeVec2 { (*self).sub(rhs) } } impl SubAssign for USizeVec2 { #[inline] fn sub_assign(&mut self, rhs: USizeVec2) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); } } impl SubAssign<&USizeVec2> for USizeVec2 { #[inline] fn sub_assign(&mut self, rhs: &USizeVec2) { self.sub_assign(*rhs) } } impl Sub for USizeVec2 { type Output = Self; #[inline] fn sub(self, rhs: usize) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), } } } impl Sub<&usize> for USizeVec2 { type Output = USizeVec2; #[inline] fn sub(self, rhs: &usize) -> USizeVec2 { self.sub(*rhs) } } impl Sub<&usize> for &USizeVec2 { type Output = USizeVec2; #[inline] fn sub(self, rhs: &usize) -> USizeVec2 { (*self).sub(*rhs) } } impl Sub for &USizeVec2 { type Output = USizeVec2; #[inline] fn sub(self, rhs: usize) -> USizeVec2 { (*self).sub(rhs) } } impl SubAssign for USizeVec2 { #[inline] fn sub_assign(&mut self, rhs: usize) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); } } impl SubAssign<&usize> for USizeVec2 { #[inline] fn sub_assign(&mut self, rhs: &usize) { self.sub_assign(*rhs) } } impl Sub for usize { type Output = USizeVec2; #[inline] fn sub(self, rhs: USizeVec2) -> USizeVec2 { USizeVec2 { x: self.sub(rhs.x), y: self.sub(rhs.y), } } } impl Sub<&USizeVec2> for usize { type Output = USizeVec2; #[inline] fn sub(self, rhs: &USizeVec2) -> USizeVec2 { self.sub(*rhs) } } impl Sub<&USizeVec2> for &usize { type Output = USizeVec2; #[inline] fn sub(self, rhs: &USizeVec2) -> USizeVec2 { (*self).sub(*rhs) } } impl Sub for &usize { type Output = USizeVec2; #[inline] fn sub(self, rhs: USizeVec2) -> USizeVec2 { (*self).sub(rhs) } } impl Rem for USizeVec2 { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { Self { x: self.x.rem(rhs.x), y: self.y.rem(rhs.y), } } } impl Rem<&USizeVec2> for USizeVec2 { type Output = USizeVec2; #[inline] fn rem(self, rhs: &USizeVec2) -> USizeVec2 { self.rem(*rhs) } } impl Rem<&USizeVec2> for &USizeVec2 { type Output = USizeVec2; #[inline] fn rem(self, rhs: &USizeVec2) -> USizeVec2 { (*self).rem(*rhs) } } impl Rem for &USizeVec2 { type Output = USizeVec2; #[inline] fn rem(self, rhs: USizeVec2) -> USizeVec2 { (*self).rem(rhs) } } impl RemAssign for USizeVec2 { #[inline] fn rem_assign(&mut self, rhs: Self) { self.x.rem_assign(rhs.x); self.y.rem_assign(rhs.y); } } impl RemAssign<&USizeVec2> for USizeVec2 { #[inline] fn rem_assign(&mut self, rhs: &USizeVec2) { self.rem_assign(*rhs) } } impl Rem for USizeVec2 { type Output = Self; #[inline] fn rem(self, rhs: usize) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), } } } impl Rem<&usize> for USizeVec2 { type Output = USizeVec2; #[inline] fn rem(self, rhs: &usize) -> USizeVec2 { self.rem(*rhs) } } impl Rem<&usize> for &USizeVec2 { type Output = USizeVec2; #[inline] fn rem(self, rhs: &usize) -> USizeVec2 { (*self).rem(*rhs) } } impl Rem for &USizeVec2 { type Output = USizeVec2; #[inline] fn rem(self, rhs: usize) -> USizeVec2 { (*self).rem(rhs) } } impl RemAssign for USizeVec2 { #[inline] fn rem_assign(&mut self, rhs: usize) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); } } impl RemAssign<&usize> for USizeVec2 { #[inline] fn rem_assign(&mut self, rhs: &usize) { self.rem_assign(*rhs) } } impl Rem for usize { type Output = USizeVec2; #[inline] fn rem(self, rhs: USizeVec2) -> USizeVec2 { USizeVec2 { x: self.rem(rhs.x), y: self.rem(rhs.y), } } } impl Rem<&USizeVec2> for usize { type Output = USizeVec2; #[inline] fn rem(self, rhs: &USizeVec2) -> USizeVec2 { self.rem(*rhs) } } impl Rem<&USizeVec2> for &usize { type Output = USizeVec2; #[inline] fn rem(self, rhs: &USizeVec2) -> USizeVec2 { (*self).rem(*rhs) } } impl Rem for &usize { type Output = USizeVec2; #[inline] fn rem(self, rhs: USizeVec2) -> USizeVec2 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[usize; 2]> for USizeVec2 { #[inline] fn as_ref(&self) -> &[usize; 2] { unsafe { &*(self as *const USizeVec2 as *const [usize; 2]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[usize; 2]> for USizeVec2 { #[inline] fn as_mut(&mut self) -> &mut [usize; 2] { unsafe { &mut *(self as *mut USizeVec2 as *mut [usize; 2]) } } } impl Sum for USizeVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for USizeVec2 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for USizeVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for USizeVec2 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for USizeVec2 { type Output = Self; #[inline] fn not(self) -> Self::Output { Self { x: self.x.not(), y: self.y.not(), } } } impl BitAnd for USizeVec2 { 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 USizeVec2 { 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 USizeVec2 { 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 for USizeVec2 { type Output = Self; #[inline] fn bitand(self, rhs: usize) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), } } } impl BitOr for USizeVec2 { type Output = Self; #[inline] fn bitor(self, rhs: usize) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), } } } impl BitXor for USizeVec2 { type Output = Self; #[inline] fn bitxor(self, rhs: usize) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: i8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: i8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: i16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: i16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: i32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: i32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: i64) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: i64) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: u8) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: u8) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: u16) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: u16) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: u32) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: u32) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { type Output = Self; #[inline] fn shl(self, rhs: u64) -> Self::Output { Self { x: self.x.shl(rhs), y: self.y.shl(rhs), } } } impl Shr for USizeVec2 { type Output = Self; #[inline] fn shr(self, rhs: u64) -> Self::Output { Self { x: self.x.shr(rhs), y: self.y.shr(rhs), } } } impl Shl for USizeVec2 { 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 for USizeVec2 { 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 for USizeVec2 { 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 for USizeVec2 { 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 for USizeVec2 { type Output = usize; #[inline] fn index(&self, index: usize) -> &Self::Output { match index { 0 => &self.x, 1 => &self.y, _ => panic!("index out of bounds"), } } } impl IndexMut for USizeVec2 { #[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"), } } } impl fmt::Display for USizeVec2 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}]", self.x, self.y) } } impl fmt::Debug for USizeVec2 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(USizeVec2)) .field(&self.x) .field(&self.y) .finish() } } impl From<[usize; 2]> for USizeVec2 { #[inline] fn from(a: [usize; 2]) -> Self { Self::new(a[0], a[1]) } } impl From for [usize; 2] { #[inline] fn from(v: USizeVec2) -> Self { [v.x, v.y] } } impl From<(usize, usize)> for USizeVec2 { #[inline] fn from(t: (usize, usize)) -> Self { Self::new(t.0, t.1) } } impl From for (usize, usize) { #[inline] fn from(v: USizeVec2) -> Self { (v.x, v.y) } } impl From for USizeVec2 { #[inline] fn from(v: U8Vec2) -> Self { Self::new(usize::from(v.x), usize::from(v.y)) } } impl From for USizeVec2 { #[inline] fn from(v: U16Vec2) -> Self { Self::new(usize::from(v.x), usize::from(v.y)) } } impl TryFrom for USizeVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec2) -> Result { Ok(Self::new(usize::try_from(v.x)?, usize::try_from(v.y)?)) } } impl TryFrom for USizeVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec2) -> Result { Ok(Self::new(usize::try_from(v.x)?, usize::try_from(v.y)?)) } } impl TryFrom for USizeVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec2) -> Result { Ok(Self::new(usize::try_from(v.x)?, usize::try_from(v.y)?)) } } impl TryFrom for USizeVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec2) -> Result { Ok(Self::new(usize::try_from(v.x)?, usize::try_from(v.y)?)) } } impl TryFrom for USizeVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec2) -> Result { Ok(Self::new(usize::try_from(v.x)?, usize::try_from(v.y)?)) } } impl TryFrom for USizeVec2 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec2) -> Result { Ok(Self::new(usize::try_from(v.x)?, usize::try_from(v.y)?)) } } impl From for USizeVec2 { #[inline] fn from(v: BVec2) -> Self { Self::new(usize::from(v.x), usize::from(v.y)) } } glam-0.30.1/src/usize/usizevec3.rs000064400000000000000000001353651046102023000150560ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. use crate::{ BVec3, BVec3A, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec2, USizeVec4, UVec3, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 3-dimensional vector. #[inline(always)] #[must_use] pub const fn usizevec3(x: usize, y: usize, z: usize) -> USizeVec3 { USizeVec3::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 USizeVec3 { pub x: usize, pub y: usize, pub z: usize, } impl USizeVec3 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// All `usize::MIN`. pub const MIN: Self = Self::splat(usize::MIN); /// All `usize::MAX`. pub const MAX: Self = Self::splat(usize::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: usize, y: usize, z: usize) -> Self { Self { x, y, z } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: usize) -> Self { Self { x: v, y: v, z: v } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(usize) -> usize, { Self::new(f(self.x), f(self.y), f(self.z)) } /// 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: [usize; 3]) -> Self { Self::new(a[0], a[1], a[2]) } /// `[x, y, z]` #[inline] #[must_use] pub const fn to_array(&self) -> [usize; 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: &[usize]) -> Self { assert!(slice.len() >= 3); 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 [usize]) { slice[..3].copy_from_slice(&self.to_array()); } /// 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: USizeVec4) -> 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: usize) -> USizeVec4 { USizeVec4::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) -> USizeVec2 { use crate::swizzles::Vec3Swizzles; self.xy() } /// Creates a 3D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: usize) -> Self { self.x = x; self } /// Creates a 3D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: usize) -> Self { self.y = y; self } /// Creates a 3D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: usize) -> Self { self.z = z; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> usize { (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 [`usize::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) -> usize { 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) -> usize { self.x.max(self.y.max(self.z)) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> usize { self.x + self.y + self.z } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> usize { self.x * self.y * 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) -> usize { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`usize::MAX`]. /// /// See also [`checked_manhattan_distance`][USizeVec3::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> usize { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`usize::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; d.checked_add(self.z.abs_diff(other.z)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> usize { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } /// 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) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; Some(Self { x, y, z }) } /// 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 USizeVec3 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for USizeVec3 { 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 Div<&USizeVec3> for USizeVec3 { type Output = USizeVec3; #[inline] fn div(self, rhs: &USizeVec3) -> USizeVec3 { self.div(*rhs) } } impl Div<&USizeVec3> for &USizeVec3 { type Output = USizeVec3; #[inline] fn div(self, rhs: &USizeVec3) -> USizeVec3 { (*self).div(*rhs) } } impl Div for &USizeVec3 { type Output = USizeVec3; #[inline] fn div(self, rhs: USizeVec3) -> USizeVec3 { (*self).div(rhs) } } impl DivAssign for USizeVec3 { #[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 DivAssign<&USizeVec3> for USizeVec3 { #[inline] fn div_assign(&mut self, rhs: &USizeVec3) { self.div_assign(*rhs) } } impl Div for USizeVec3 { type Output = Self; #[inline] fn div(self, rhs: usize) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), } } } impl Div<&usize> for USizeVec3 { type Output = USizeVec3; #[inline] fn div(self, rhs: &usize) -> USizeVec3 { self.div(*rhs) } } impl Div<&usize> for &USizeVec3 { type Output = USizeVec3; #[inline] fn div(self, rhs: &usize) -> USizeVec3 { (*self).div(*rhs) } } impl Div for &USizeVec3 { type Output = USizeVec3; #[inline] fn div(self, rhs: usize) -> USizeVec3 { (*self).div(rhs) } } impl DivAssign for USizeVec3 { #[inline] fn div_assign(&mut self, rhs: usize) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); } } impl DivAssign<&usize> for USizeVec3 { #[inline] fn div_assign(&mut self, rhs: &usize) { self.div_assign(*rhs) } } impl Div for usize { type Output = USizeVec3; #[inline] fn div(self, rhs: USizeVec3) -> USizeVec3 { USizeVec3 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), } } } impl Div<&USizeVec3> for usize { type Output = USizeVec3; #[inline] fn div(self, rhs: &USizeVec3) -> USizeVec3 { self.div(*rhs) } } impl Div<&USizeVec3> for &usize { type Output = USizeVec3; #[inline] fn div(self, rhs: &USizeVec3) -> USizeVec3 { (*self).div(*rhs) } } impl Div for &usize { type Output = USizeVec3; #[inline] fn div(self, rhs: USizeVec3) -> USizeVec3 { (*self).div(rhs) } } impl Mul for USizeVec3 { 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 Mul<&USizeVec3> for USizeVec3 { type Output = USizeVec3; #[inline] fn mul(self, rhs: &USizeVec3) -> USizeVec3 { self.mul(*rhs) } } impl Mul<&USizeVec3> for &USizeVec3 { type Output = USizeVec3; #[inline] fn mul(self, rhs: &USizeVec3) -> USizeVec3 { (*self).mul(*rhs) } } impl Mul for &USizeVec3 { type Output = USizeVec3; #[inline] fn mul(self, rhs: USizeVec3) -> USizeVec3 { (*self).mul(rhs) } } impl MulAssign for USizeVec3 { #[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 MulAssign<&USizeVec3> for USizeVec3 { #[inline] fn mul_assign(&mut self, rhs: &USizeVec3) { self.mul_assign(*rhs) } } impl Mul for USizeVec3 { type Output = Self; #[inline] fn mul(self, rhs: usize) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), } } } impl Mul<&usize> for USizeVec3 { type Output = USizeVec3; #[inline] fn mul(self, rhs: &usize) -> USizeVec3 { self.mul(*rhs) } } impl Mul<&usize> for &USizeVec3 { type Output = USizeVec3; #[inline] fn mul(self, rhs: &usize) -> USizeVec3 { (*self).mul(*rhs) } } impl Mul for &USizeVec3 { type Output = USizeVec3; #[inline] fn mul(self, rhs: usize) -> USizeVec3 { (*self).mul(rhs) } } impl MulAssign for USizeVec3 { #[inline] fn mul_assign(&mut self, rhs: usize) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); } } impl MulAssign<&usize> for USizeVec3 { #[inline] fn mul_assign(&mut self, rhs: &usize) { self.mul_assign(*rhs) } } impl Mul for usize { type Output = USizeVec3; #[inline] fn mul(self, rhs: USizeVec3) -> USizeVec3 { USizeVec3 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), } } } impl Mul<&USizeVec3> for usize { type Output = USizeVec3; #[inline] fn mul(self, rhs: &USizeVec3) -> USizeVec3 { self.mul(*rhs) } } impl Mul<&USizeVec3> for &usize { type Output = USizeVec3; #[inline] fn mul(self, rhs: &USizeVec3) -> USizeVec3 { (*self).mul(*rhs) } } impl Mul for &usize { type Output = USizeVec3; #[inline] fn mul(self, rhs: USizeVec3) -> USizeVec3 { (*self).mul(rhs) } } impl Add for USizeVec3 { 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 Add<&USizeVec3> for USizeVec3 { type Output = USizeVec3; #[inline] fn add(self, rhs: &USizeVec3) -> USizeVec3 { self.add(*rhs) } } impl Add<&USizeVec3> for &USizeVec3 { type Output = USizeVec3; #[inline] fn add(self, rhs: &USizeVec3) -> USizeVec3 { (*self).add(*rhs) } } impl Add for &USizeVec3 { type Output = USizeVec3; #[inline] fn add(self, rhs: USizeVec3) -> USizeVec3 { (*self).add(rhs) } } impl AddAssign for USizeVec3 { #[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 AddAssign<&USizeVec3> for USizeVec3 { #[inline] fn add_assign(&mut self, rhs: &USizeVec3) { self.add_assign(*rhs) } } impl Add for USizeVec3 { type Output = Self; #[inline] fn add(self, rhs: usize) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), } } } impl Add<&usize> for USizeVec3 { type Output = USizeVec3; #[inline] fn add(self, rhs: &usize) -> USizeVec3 { self.add(*rhs) } } impl Add<&usize> for &USizeVec3 { type Output = USizeVec3; #[inline] fn add(self, rhs: &usize) -> USizeVec3 { (*self).add(*rhs) } } impl Add for &USizeVec3 { type Output = USizeVec3; #[inline] fn add(self, rhs: usize) -> USizeVec3 { (*self).add(rhs) } } impl AddAssign for USizeVec3 { #[inline] fn add_assign(&mut self, rhs: usize) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); } } impl AddAssign<&usize> for USizeVec3 { #[inline] fn add_assign(&mut self, rhs: &usize) { self.add_assign(*rhs) } } impl Add for usize { type Output = USizeVec3; #[inline] fn add(self, rhs: USizeVec3) -> USizeVec3 { USizeVec3 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), } } } impl Add<&USizeVec3> for usize { type Output = USizeVec3; #[inline] fn add(self, rhs: &USizeVec3) -> USizeVec3 { self.add(*rhs) } } impl Add<&USizeVec3> for &usize { type Output = USizeVec3; #[inline] fn add(self, rhs: &USizeVec3) -> USizeVec3 { (*self).add(*rhs) } } impl Add for &usize { type Output = USizeVec3; #[inline] fn add(self, rhs: USizeVec3) -> USizeVec3 { (*self).add(rhs) } } impl Sub for USizeVec3 { 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 Sub<&USizeVec3> for USizeVec3 { type Output = USizeVec3; #[inline] fn sub(self, rhs: &USizeVec3) -> USizeVec3 { self.sub(*rhs) } } impl Sub<&USizeVec3> for &USizeVec3 { type Output = USizeVec3; #[inline] fn sub(self, rhs: &USizeVec3) -> USizeVec3 { (*self).sub(*rhs) } } impl Sub for &USizeVec3 { type Output = USizeVec3; #[inline] fn sub(self, rhs: USizeVec3) -> USizeVec3 { (*self).sub(rhs) } } impl SubAssign for USizeVec3 { #[inline] fn sub_assign(&mut self, rhs: USizeVec3) { self.x.sub_assign(rhs.x); self.y.sub_assign(rhs.y); self.z.sub_assign(rhs.z); } } impl SubAssign<&USizeVec3> for USizeVec3 { #[inline] fn sub_assign(&mut self, rhs: &USizeVec3) { self.sub_assign(*rhs) } } impl Sub for USizeVec3 { type Output = Self; #[inline] fn sub(self, rhs: usize) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), } } } impl Sub<&usize> for USizeVec3 { type Output = USizeVec3; #[inline] fn sub(self, rhs: &usize) -> USizeVec3 { self.sub(*rhs) } } impl Sub<&usize> for &USizeVec3 { type Output = USizeVec3; #[inline] fn sub(self, rhs: &usize) -> USizeVec3 { (*self).sub(*rhs) } } impl Sub for &USizeVec3 { type Output = USizeVec3; #[inline] fn sub(self, rhs: usize) -> USizeVec3 { (*self).sub(rhs) } } impl SubAssign for USizeVec3 { #[inline] fn sub_assign(&mut self, rhs: usize) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); } } impl SubAssign<&usize> for USizeVec3 { #[inline] fn sub_assign(&mut self, rhs: &usize) { self.sub_assign(*rhs) } } impl Sub for usize { type Output = USizeVec3; #[inline] fn sub(self, rhs: USizeVec3) -> USizeVec3 { USizeVec3 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), } } } impl Sub<&USizeVec3> for usize { type Output = USizeVec3; #[inline] fn sub(self, rhs: &USizeVec3) -> USizeVec3 { self.sub(*rhs) } } impl Sub<&USizeVec3> for &usize { type Output = USizeVec3; #[inline] fn sub(self, rhs: &USizeVec3) -> USizeVec3 { (*self).sub(*rhs) } } impl Sub for &usize { type Output = USizeVec3; #[inline] fn sub(self, rhs: USizeVec3) -> USizeVec3 { (*self).sub(rhs) } } impl Rem for USizeVec3 { 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 Rem<&USizeVec3> for USizeVec3 { type Output = USizeVec3; #[inline] fn rem(self, rhs: &USizeVec3) -> USizeVec3 { self.rem(*rhs) } } impl Rem<&USizeVec3> for &USizeVec3 { type Output = USizeVec3; #[inline] fn rem(self, rhs: &USizeVec3) -> USizeVec3 { (*self).rem(*rhs) } } impl Rem for &USizeVec3 { type Output = USizeVec3; #[inline] fn rem(self, rhs: USizeVec3) -> USizeVec3 { (*self).rem(rhs) } } impl RemAssign for USizeVec3 { #[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 RemAssign<&USizeVec3> for USizeVec3 { #[inline] fn rem_assign(&mut self, rhs: &USizeVec3) { self.rem_assign(*rhs) } } impl Rem for USizeVec3 { type Output = Self; #[inline] fn rem(self, rhs: usize) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), } } } impl Rem<&usize> for USizeVec3 { type Output = USizeVec3; #[inline] fn rem(self, rhs: &usize) -> USizeVec3 { self.rem(*rhs) } } impl Rem<&usize> for &USizeVec3 { type Output = USizeVec3; #[inline] fn rem(self, rhs: &usize) -> USizeVec3 { (*self).rem(*rhs) } } impl Rem for &USizeVec3 { type Output = USizeVec3; #[inline] fn rem(self, rhs: usize) -> USizeVec3 { (*self).rem(rhs) } } impl RemAssign for USizeVec3 { #[inline] fn rem_assign(&mut self, rhs: usize) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); } } impl RemAssign<&usize> for USizeVec3 { #[inline] fn rem_assign(&mut self, rhs: &usize) { self.rem_assign(*rhs) } } impl Rem for usize { type Output = USizeVec3; #[inline] fn rem(self, rhs: USizeVec3) -> USizeVec3 { USizeVec3 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), } } } impl Rem<&USizeVec3> for usize { type Output = USizeVec3; #[inline] fn rem(self, rhs: &USizeVec3) -> USizeVec3 { self.rem(*rhs) } } impl Rem<&USizeVec3> for &usize { type Output = USizeVec3; #[inline] fn rem(self, rhs: &USizeVec3) -> USizeVec3 { (*self).rem(*rhs) } } impl Rem for &usize { type Output = USizeVec3; #[inline] fn rem(self, rhs: USizeVec3) -> USizeVec3 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[usize; 3]> for USizeVec3 { #[inline] fn as_ref(&self) -> &[usize; 3] { unsafe { &*(self as *const USizeVec3 as *const [usize; 3]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[usize; 3]> for USizeVec3 { #[inline] fn as_mut(&mut self) -> &mut [usize; 3] { unsafe { &mut *(self as *mut USizeVec3 as *mut [usize; 3]) } } } impl Sum for USizeVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for USizeVec3 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for USizeVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for USizeVec3 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for USizeVec3 { 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 USizeVec3 { 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 USizeVec3 { 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 USizeVec3 { 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 for USizeVec3 { type Output = Self; #[inline] fn bitand(self, rhs: usize) -> Self::Output { Self { x: self.x.bitand(rhs), y: self.y.bitand(rhs), z: self.z.bitand(rhs), } } } impl BitOr for USizeVec3 { type Output = Self; #[inline] fn bitor(self, rhs: usize) -> Self::Output { Self { x: self.x.bitor(rhs), y: self.y.bitor(rhs), z: self.z.bitor(rhs), } } } impl BitXor for USizeVec3 { type Output = Self; #[inline] fn bitxor(self, rhs: usize) -> Self::Output { Self { x: self.x.bitxor(rhs), y: self.y.bitxor(rhs), z: self.z.bitxor(rhs), } } } impl Shl for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { 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 for USizeVec3 { type Output = usize; #[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 for USizeVec3 { #[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"), } } } impl fmt::Display for USizeVec3 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}]", self.x, self.y, self.z) } } impl fmt::Debug for USizeVec3 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(USizeVec3)) .field(&self.x) .field(&self.y) .field(&self.z) .finish() } } impl From<[usize; 3]> for USizeVec3 { #[inline] fn from(a: [usize; 3]) -> Self { Self::new(a[0], a[1], a[2]) } } impl From for [usize; 3] { #[inline] fn from(v: USizeVec3) -> Self { [v.x, v.y, v.z] } } impl From<(usize, usize, usize)> for USizeVec3 { #[inline] fn from(t: (usize, usize, usize)) -> Self { Self::new(t.0, t.1, t.2) } } impl From for (usize, usize, usize) { #[inline] fn from(v: USizeVec3) -> Self { (v.x, v.y, v.z) } } impl From<(USizeVec2, usize)> for USizeVec3 { #[inline] fn from((v, z): (USizeVec2, usize)) -> Self { Self::new(v.x, v.y, z) } } impl From for USizeVec3 { #[inline] fn from(v: U8Vec3) -> Self { Self::new(usize::from(v.x), usize::from(v.y), usize::from(v.z)) } } impl From for USizeVec3 { #[inline] fn from(v: U16Vec3) -> Self { Self::new(usize::from(v.x), usize::from(v.y), usize::from(v.z)) } } impl TryFrom for USizeVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec3) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, )) } } impl TryFrom for USizeVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec3) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, )) } } impl TryFrom for USizeVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec3) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, )) } } impl TryFrom for USizeVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec3) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, )) } } impl TryFrom for USizeVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec3) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, )) } } impl TryFrom for USizeVec3 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec3) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, )) } } impl From for USizeVec3 { #[inline] fn from(v: BVec3) -> Self { Self::new(usize::from(v.x), usize::from(v.y), usize::from(v.z)) } } impl From for USizeVec3 { #[inline] fn from(v: BVec3A) -> Self { let bool_array: [bool; 3] = v.into(); Self::new( usize::from(bool_array[0]), usize::from(bool_array[1]), usize::from(bool_array[2]), ) } } glam-0.30.1/src/usize/usizevec4.rs000064400000000000000000001461061046102023000150520ustar 00000000000000// Generated from vec.rs.tera template. Edit the template, not the generated file. #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec2, USizeVec3, UVec4, }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; /// Creates a 4-dimensional vector. #[inline(always)] #[must_use] pub const fn usizevec4(x: usize, y: usize, z: usize, w: usize) -> USizeVec4 { USizeVec4::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 USizeVec4 { pub x: usize, pub y: usize, pub z: usize, pub w: usize, } impl USizeVec4 { /// All zeroes. pub const ZERO: Self = Self::splat(0); /// All ones. pub const ONE: Self = Self::splat(1); /// All `usize::MIN`. pub const MIN: Self = Self::splat(usize::MIN); /// All `usize::MAX`. pub const MAX: Self = Self::splat(usize::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: usize, y: usize, z: usize, w: usize) -> Self { Self { x, y, z, w } } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: usize) -> Self { Self { x: v, y: v, z: v, w: v, } } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn(usize) -> usize, { Self::new(f(self.x), f(self.y), f(self.z), f(self.w)) } /// 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: [usize; 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) -> [usize; 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: &[usize]) -> Self { assert!(slice.len() >= 4); 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 [usize]) { slice[..4].copy_from_slice(&self.to_array()); } /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`. /// /// Truncation to [`USizeVec3`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()]. #[inline] #[must_use] pub fn truncate(self) -> USizeVec3 { use crate::swizzles::Vec4Swizzles; self.xyz() } /// Creates a 4D vector from `self` with the given value of `x`. #[inline] #[must_use] pub fn with_x(mut self, x: usize) -> Self { self.x = x; self } /// Creates a 4D vector from `self` with the given value of `y`. #[inline] #[must_use] pub fn with_y(mut self, y: usize) -> Self { self.y = y; self } /// Creates a 4D vector from `self` with the given value of `z`. #[inline] #[must_use] pub fn with_z(mut self, z: usize) -> Self { self.z = z; self } /// Creates a 4D vector from `self` with the given value of `w`. #[inline] #[must_use] pub fn with_w(mut self, w: usize) -> Self { self.w = w; self } /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> usize { (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 [`usize::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) -> usize { 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) -> usize { self.x.max(self.y.max(self.z.max(self.w))) } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> usize { self.x + self.y + self.z + self.w } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> usize { self.x * self.y * self.z * 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) -> usize { self.dot(self) } /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`usize::MAX`]. /// /// See also [`checked_manhattan_distance`][USizeVec4::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> usize { self.x.abs_diff(other.x) + self.y.abs_diff(other.y) + self.z.abs_diff(other.z) + self.w.abs_diff(other.w) } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`usize::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option { let d = self.x.abs_diff(other.x); let d = d.checked_add(self.y.abs_diff(other.y))?; let d = d.checked_add(self.z.abs_diff(other.z))?; d.checked_add(self.w.abs_diff(other.w)) } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> usize { // Note: the compiler will eventually optimize out the loop [ self.x.abs_diff(other.x), self.y.abs_diff(other.y), self.z.abs_diff(other.z), self.w.abs_diff(other.w), ] .into_iter() .max() .unwrap() } /// 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 `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } /// 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) } /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { let x = match self.x.checked_add(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_add(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_add(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_add(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { let x = match self.x.checked_sub(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_sub(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_sub(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_sub(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { let x = match self.x.checked_mul(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_mul(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_mul(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_mul(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { let x = match self.x.checked_div(rhs.x) { Some(v) => v, None => return None, }; let y = match self.y.checked_div(rhs.y) { Some(v) => v, None => return None, }; let z = match self.z.checked_div(rhs.z) { Some(v) => v, None => return None, }; let w = match self.w.checked_div(rhs.w) { Some(v) => v, None => return None, }; Some(Self { x, y, z, w }) } /// 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 USizeVec4 { #[inline(always)] fn default() -> Self { Self::ZERO } } impl Div for USizeVec4 { 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 Div<&USizeVec4> for USizeVec4 { type Output = USizeVec4; #[inline] fn div(self, rhs: &USizeVec4) -> USizeVec4 { self.div(*rhs) } } impl Div<&USizeVec4> for &USizeVec4 { type Output = USizeVec4; #[inline] fn div(self, rhs: &USizeVec4) -> USizeVec4 { (*self).div(*rhs) } } impl Div for &USizeVec4 { type Output = USizeVec4; #[inline] fn div(self, rhs: USizeVec4) -> USizeVec4 { (*self).div(rhs) } } impl DivAssign for USizeVec4 { #[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 DivAssign<&USizeVec4> for USizeVec4 { #[inline] fn div_assign(&mut self, rhs: &USizeVec4) { self.div_assign(*rhs) } } impl Div for USizeVec4 { type Output = Self; #[inline] fn div(self, rhs: usize) -> Self { Self { x: self.x.div(rhs), y: self.y.div(rhs), z: self.z.div(rhs), w: self.w.div(rhs), } } } impl Div<&usize> for USizeVec4 { type Output = USizeVec4; #[inline] fn div(self, rhs: &usize) -> USizeVec4 { self.div(*rhs) } } impl Div<&usize> for &USizeVec4 { type Output = USizeVec4; #[inline] fn div(self, rhs: &usize) -> USizeVec4 { (*self).div(*rhs) } } impl Div for &USizeVec4 { type Output = USizeVec4; #[inline] fn div(self, rhs: usize) -> USizeVec4 { (*self).div(rhs) } } impl DivAssign for USizeVec4 { #[inline] fn div_assign(&mut self, rhs: usize) { self.x.div_assign(rhs); self.y.div_assign(rhs); self.z.div_assign(rhs); self.w.div_assign(rhs); } } impl DivAssign<&usize> for USizeVec4 { #[inline] fn div_assign(&mut self, rhs: &usize) { self.div_assign(*rhs) } } impl Div for usize { type Output = USizeVec4; #[inline] fn div(self, rhs: USizeVec4) -> USizeVec4 { USizeVec4 { x: self.div(rhs.x), y: self.div(rhs.y), z: self.div(rhs.z), w: self.div(rhs.w), } } } impl Div<&USizeVec4> for usize { type Output = USizeVec4; #[inline] fn div(self, rhs: &USizeVec4) -> USizeVec4 { self.div(*rhs) } } impl Div<&USizeVec4> for &usize { type Output = USizeVec4; #[inline] fn div(self, rhs: &USizeVec4) -> USizeVec4 { (*self).div(*rhs) } } impl Div for &usize { type Output = USizeVec4; #[inline] fn div(self, rhs: USizeVec4) -> USizeVec4 { (*self).div(rhs) } } impl Mul for USizeVec4 { 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 Mul<&USizeVec4> for USizeVec4 { type Output = USizeVec4; #[inline] fn mul(self, rhs: &USizeVec4) -> USizeVec4 { self.mul(*rhs) } } impl Mul<&USizeVec4> for &USizeVec4 { type Output = USizeVec4; #[inline] fn mul(self, rhs: &USizeVec4) -> USizeVec4 { (*self).mul(*rhs) } } impl Mul for &USizeVec4 { type Output = USizeVec4; #[inline] fn mul(self, rhs: USizeVec4) -> USizeVec4 { (*self).mul(rhs) } } impl MulAssign for USizeVec4 { #[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 MulAssign<&USizeVec4> for USizeVec4 { #[inline] fn mul_assign(&mut self, rhs: &USizeVec4) { self.mul_assign(*rhs) } } impl Mul for USizeVec4 { type Output = Self; #[inline] fn mul(self, rhs: usize) -> Self { Self { x: self.x.mul(rhs), y: self.y.mul(rhs), z: self.z.mul(rhs), w: self.w.mul(rhs), } } } impl Mul<&usize> for USizeVec4 { type Output = USizeVec4; #[inline] fn mul(self, rhs: &usize) -> USizeVec4 { self.mul(*rhs) } } impl Mul<&usize> for &USizeVec4 { type Output = USizeVec4; #[inline] fn mul(self, rhs: &usize) -> USizeVec4 { (*self).mul(*rhs) } } impl Mul for &USizeVec4 { type Output = USizeVec4; #[inline] fn mul(self, rhs: usize) -> USizeVec4 { (*self).mul(rhs) } } impl MulAssign for USizeVec4 { #[inline] fn mul_assign(&mut self, rhs: usize) { self.x.mul_assign(rhs); self.y.mul_assign(rhs); self.z.mul_assign(rhs); self.w.mul_assign(rhs); } } impl MulAssign<&usize> for USizeVec4 { #[inline] fn mul_assign(&mut self, rhs: &usize) { self.mul_assign(*rhs) } } impl Mul for usize { type Output = USizeVec4; #[inline] fn mul(self, rhs: USizeVec4) -> USizeVec4 { USizeVec4 { x: self.mul(rhs.x), y: self.mul(rhs.y), z: self.mul(rhs.z), w: self.mul(rhs.w), } } } impl Mul<&USizeVec4> for usize { type Output = USizeVec4; #[inline] fn mul(self, rhs: &USizeVec4) -> USizeVec4 { self.mul(*rhs) } } impl Mul<&USizeVec4> for &usize { type Output = USizeVec4; #[inline] fn mul(self, rhs: &USizeVec4) -> USizeVec4 { (*self).mul(*rhs) } } impl Mul for &usize { type Output = USizeVec4; #[inline] fn mul(self, rhs: USizeVec4) -> USizeVec4 { (*self).mul(rhs) } } impl Add for USizeVec4 { 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 Add<&USizeVec4> for USizeVec4 { type Output = USizeVec4; #[inline] fn add(self, rhs: &USizeVec4) -> USizeVec4 { self.add(*rhs) } } impl Add<&USizeVec4> for &USizeVec4 { type Output = USizeVec4; #[inline] fn add(self, rhs: &USizeVec4) -> USizeVec4 { (*self).add(*rhs) } } impl Add for &USizeVec4 { type Output = USizeVec4; #[inline] fn add(self, rhs: USizeVec4) -> USizeVec4 { (*self).add(rhs) } } impl AddAssign for USizeVec4 { #[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 AddAssign<&USizeVec4> for USizeVec4 { #[inline] fn add_assign(&mut self, rhs: &USizeVec4) { self.add_assign(*rhs) } } impl Add for USizeVec4 { type Output = Self; #[inline] fn add(self, rhs: usize) -> Self { Self { x: self.x.add(rhs), y: self.y.add(rhs), z: self.z.add(rhs), w: self.w.add(rhs), } } } impl Add<&usize> for USizeVec4 { type Output = USizeVec4; #[inline] fn add(self, rhs: &usize) -> USizeVec4 { self.add(*rhs) } } impl Add<&usize> for &USizeVec4 { type Output = USizeVec4; #[inline] fn add(self, rhs: &usize) -> USizeVec4 { (*self).add(*rhs) } } impl Add for &USizeVec4 { type Output = USizeVec4; #[inline] fn add(self, rhs: usize) -> USizeVec4 { (*self).add(rhs) } } impl AddAssign for USizeVec4 { #[inline] fn add_assign(&mut self, rhs: usize) { self.x.add_assign(rhs); self.y.add_assign(rhs); self.z.add_assign(rhs); self.w.add_assign(rhs); } } impl AddAssign<&usize> for USizeVec4 { #[inline] fn add_assign(&mut self, rhs: &usize) { self.add_assign(*rhs) } } impl Add for usize { type Output = USizeVec4; #[inline] fn add(self, rhs: USizeVec4) -> USizeVec4 { USizeVec4 { x: self.add(rhs.x), y: self.add(rhs.y), z: self.add(rhs.z), w: self.add(rhs.w), } } } impl Add<&USizeVec4> for usize { type Output = USizeVec4; #[inline] fn add(self, rhs: &USizeVec4) -> USizeVec4 { self.add(*rhs) } } impl Add<&USizeVec4> for &usize { type Output = USizeVec4; #[inline] fn add(self, rhs: &USizeVec4) -> USizeVec4 { (*self).add(*rhs) } } impl Add for &usize { type Output = USizeVec4; #[inline] fn add(self, rhs: USizeVec4) -> USizeVec4 { (*self).add(rhs) } } impl Sub for USizeVec4 { 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 Sub<&USizeVec4> for USizeVec4 { type Output = USizeVec4; #[inline] fn sub(self, rhs: &USizeVec4) -> USizeVec4 { self.sub(*rhs) } } impl Sub<&USizeVec4> for &USizeVec4 { type Output = USizeVec4; #[inline] fn sub(self, rhs: &USizeVec4) -> USizeVec4 { (*self).sub(*rhs) } } impl Sub for &USizeVec4 { type Output = USizeVec4; #[inline] fn sub(self, rhs: USizeVec4) -> USizeVec4 { (*self).sub(rhs) } } impl SubAssign for USizeVec4 { #[inline] fn sub_assign(&mut self, rhs: USizeVec4) { 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 SubAssign<&USizeVec4> for USizeVec4 { #[inline] fn sub_assign(&mut self, rhs: &USizeVec4) { self.sub_assign(*rhs) } } impl Sub for USizeVec4 { type Output = Self; #[inline] fn sub(self, rhs: usize) -> Self { Self { x: self.x.sub(rhs), y: self.y.sub(rhs), z: self.z.sub(rhs), w: self.w.sub(rhs), } } } impl Sub<&usize> for USizeVec4 { type Output = USizeVec4; #[inline] fn sub(self, rhs: &usize) -> USizeVec4 { self.sub(*rhs) } } impl Sub<&usize> for &USizeVec4 { type Output = USizeVec4; #[inline] fn sub(self, rhs: &usize) -> USizeVec4 { (*self).sub(*rhs) } } impl Sub for &USizeVec4 { type Output = USizeVec4; #[inline] fn sub(self, rhs: usize) -> USizeVec4 { (*self).sub(rhs) } } impl SubAssign for USizeVec4 { #[inline] fn sub_assign(&mut self, rhs: usize) { self.x.sub_assign(rhs); self.y.sub_assign(rhs); self.z.sub_assign(rhs); self.w.sub_assign(rhs); } } impl SubAssign<&usize> for USizeVec4 { #[inline] fn sub_assign(&mut self, rhs: &usize) { self.sub_assign(*rhs) } } impl Sub for usize { type Output = USizeVec4; #[inline] fn sub(self, rhs: USizeVec4) -> USizeVec4 { USizeVec4 { x: self.sub(rhs.x), y: self.sub(rhs.y), z: self.sub(rhs.z), w: self.sub(rhs.w), } } } impl Sub<&USizeVec4> for usize { type Output = USizeVec4; #[inline] fn sub(self, rhs: &USizeVec4) -> USizeVec4 { self.sub(*rhs) } } impl Sub<&USizeVec4> for &usize { type Output = USizeVec4; #[inline] fn sub(self, rhs: &USizeVec4) -> USizeVec4 { (*self).sub(*rhs) } } impl Sub for &usize { type Output = USizeVec4; #[inline] fn sub(self, rhs: USizeVec4) -> USizeVec4 { (*self).sub(rhs) } } impl Rem for USizeVec4 { 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 Rem<&USizeVec4> for USizeVec4 { type Output = USizeVec4; #[inline] fn rem(self, rhs: &USizeVec4) -> USizeVec4 { self.rem(*rhs) } } impl Rem<&USizeVec4> for &USizeVec4 { type Output = USizeVec4; #[inline] fn rem(self, rhs: &USizeVec4) -> USizeVec4 { (*self).rem(*rhs) } } impl Rem for &USizeVec4 { type Output = USizeVec4; #[inline] fn rem(self, rhs: USizeVec4) -> USizeVec4 { (*self).rem(rhs) } } impl RemAssign for USizeVec4 { #[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 RemAssign<&USizeVec4> for USizeVec4 { #[inline] fn rem_assign(&mut self, rhs: &USizeVec4) { self.rem_assign(*rhs) } } impl Rem for USizeVec4 { type Output = Self; #[inline] fn rem(self, rhs: usize) -> Self { Self { x: self.x.rem(rhs), y: self.y.rem(rhs), z: self.z.rem(rhs), w: self.w.rem(rhs), } } } impl Rem<&usize> for USizeVec4 { type Output = USizeVec4; #[inline] fn rem(self, rhs: &usize) -> USizeVec4 { self.rem(*rhs) } } impl Rem<&usize> for &USizeVec4 { type Output = USizeVec4; #[inline] fn rem(self, rhs: &usize) -> USizeVec4 { (*self).rem(*rhs) } } impl Rem for &USizeVec4 { type Output = USizeVec4; #[inline] fn rem(self, rhs: usize) -> USizeVec4 { (*self).rem(rhs) } } impl RemAssign for USizeVec4 { #[inline] fn rem_assign(&mut self, rhs: usize) { self.x.rem_assign(rhs); self.y.rem_assign(rhs); self.z.rem_assign(rhs); self.w.rem_assign(rhs); } } impl RemAssign<&usize> for USizeVec4 { #[inline] fn rem_assign(&mut self, rhs: &usize) { self.rem_assign(*rhs) } } impl Rem for usize { type Output = USizeVec4; #[inline] fn rem(self, rhs: USizeVec4) -> USizeVec4 { USizeVec4 { x: self.rem(rhs.x), y: self.rem(rhs.y), z: self.rem(rhs.z), w: self.rem(rhs.w), } } } impl Rem<&USizeVec4> for usize { type Output = USizeVec4; #[inline] fn rem(self, rhs: &USizeVec4) -> USizeVec4 { self.rem(*rhs) } } impl Rem<&USizeVec4> for &usize { type Output = USizeVec4; #[inline] fn rem(self, rhs: &USizeVec4) -> USizeVec4 { (*self).rem(*rhs) } } impl Rem for &usize { type Output = USizeVec4; #[inline] fn rem(self, rhs: USizeVec4) -> USizeVec4 { (*self).rem(rhs) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[usize; 4]> for USizeVec4 { #[inline] fn as_ref(&self) -> &[usize; 4] { unsafe { &*(self as *const USizeVec4 as *const [usize; 4]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[usize; 4]> for USizeVec4 { #[inline] fn as_mut(&mut self) -> &mut [usize; 4] { unsafe { &mut *(self as *mut USizeVec4 as *mut [usize; 4]) } } } impl Sum for USizeVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for USizeVec4 { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for USizeVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for USizeVec4 { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } impl Not for USizeVec4 { 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 USizeVec4 { 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 USizeVec4 { 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 USizeVec4 { 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 for USizeVec4 { type Output = Self; #[inline] fn bitand(self, rhs: usize) -> 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 for USizeVec4 { type Output = Self; #[inline] fn bitor(self, rhs: usize) -> 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 for USizeVec4 { type Output = Self; #[inline] fn bitxor(self, rhs: usize) -> 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { 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 for USizeVec4 { type Output = usize; #[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 for USizeVec4 { #[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"), } } } impl fmt::Display for USizeVec4 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } impl fmt::Debug for USizeVec4 { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!(USizeVec4)) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl From<[usize; 4]> for USizeVec4 { #[inline] fn from(a: [usize; 4]) -> Self { Self::new(a[0], a[1], a[2], a[3]) } } impl From for [usize; 4] { #[inline] fn from(v: USizeVec4) -> Self { [v.x, v.y, v.z, v.w] } } impl From<(usize, usize, usize, usize)> for USizeVec4 { #[inline] fn from(t: (usize, usize, usize, usize)) -> Self { Self::new(t.0, t.1, t.2, t.3) } } impl From for (usize, usize, usize, usize) { #[inline] fn from(v: USizeVec4) -> Self { (v.x, v.y, v.z, v.w) } } impl From<(USizeVec3, usize)> for USizeVec4 { #[inline] fn from((v, w): (USizeVec3, usize)) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<(usize, USizeVec3)> for USizeVec4 { #[inline] fn from((x, v): (usize, USizeVec3)) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<(USizeVec2, usize, usize)> for USizeVec4 { #[inline] fn from((v, z, w): (USizeVec2, usize, usize)) -> Self { Self::new(v.x, v.y, z, w) } } impl From<(USizeVec2, USizeVec2)> for USizeVec4 { #[inline] fn from((v, u): (USizeVec2, USizeVec2)) -> Self { Self::new(v.x, v.y, u.x, u.y) } } impl From for USizeVec4 { #[inline] fn from(v: U8Vec4) -> Self { Self::new( usize::from(v.x), usize::from(v.y), usize::from(v.z), usize::from(v.w), ) } } impl From for USizeVec4 { #[inline] fn from(v: U16Vec4) -> Self { Self::new( usize::from(v.x), usize::from(v.y), usize::from(v.z), usize::from(v.w), ) } } impl TryFrom for USizeVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I8Vec4) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, usize::try_from(v.w)?, )) } } impl TryFrom for USizeVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I16Vec4) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, usize::try_from(v.w)?, )) } } impl TryFrom for USizeVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: IVec4) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, usize::try_from(v.w)?, )) } } impl TryFrom for USizeVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: I64Vec4) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, usize::try_from(v.w)?, )) } } impl TryFrom for USizeVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: UVec4) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, usize::try_from(v.w)?, )) } } impl TryFrom for USizeVec4 { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: U64Vec4) -> Result { Ok(Self::new( usize::try_from(v.x)?, usize::try_from(v.y)?, usize::try_from(v.z)?, usize::try_from(v.w)?, )) } } impl From for USizeVec4 { #[inline] fn from(v: BVec4) -> Self { Self::new( usize::from(v.x), usize::from(v.y), usize::from(v.z), usize::from(v.w), ) } } #[cfg(not(feature = "scalar-math"))] impl From for USizeVec4 { #[inline] fn from(v: BVec4A) -> Self { let bool_array: [bool; 4] = v.into(); Self::new( usize::from(bool_array[0]), usize::from(bool_array[1]), usize::from(bool_array[2]), usize::from(bool_array[3]), ) } } glam-0.30.1/src/usize.rs000064400000000000000000000026661046102023000131330ustar 00000000000000mod usizevec2; mod usizevec3; mod usizevec4; pub use usizevec2::{usizevec2, USizeVec2}; pub use usizevec3::{usizevec3, USizeVec3}; pub use usizevec4::{usizevec4, USizeVec4}; #[cfg(not(target_arch = "spirv"))] mod test { use super::*; mod const_test_usizevec2 { const_assert_eq!( core::mem::size_of::() * 2, core::mem::size_of::() ); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } mod const_test_usizevec3 { const_assert_eq!( core::mem::size_of::() * 3, core::mem::size_of::() ); const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); } mod const_test_usizevec4 { const_assert_eq!( core::mem::size_of::() * 4, core::mem::size_of::() ); #[cfg(not(feature = "cuda"))] const_assert_eq!( core::mem::align_of::(), core::mem::align_of::() ); #[cfg(feature = "cuda")] const_assert_eq!(16, core::mem::align_of::()); } } glam-0.30.1/src/wasm32.rs000064400000000000000000000030321046102023000130740ustar 00000000000000use core::arch::wasm32::*; pub const fn v128_from_f32x4(a: [f32; 4]) -> v128 { f32x4(a[0], a[1], a[2], a[3]) } /// Calculates the vector 3 dot product and returns answer in x lane of v128. #[inline(always)] pub(crate) fn dot3_in_x(lhs: v128, rhs: v128) -> v128 { let x2_y2_z2_w2 = f32x4_mul(lhs, rhs); let y2_0_0_0 = i32x4_shuffle::<1, 0, 0, 0>(x2_y2_z2_w2, x2_y2_z2_w2); let z2_0_0_0 = i32x4_shuffle::<2, 0, 0, 0>(x2_y2_z2_w2, x2_y2_z2_w2); let x2y2_0_0_0 = f32x4_add(x2_y2_z2_w2, y2_0_0_0); f32x4_add(x2y2_0_0_0, z2_0_0_0) } /// Calculates the vector 4 dot product and returns answer in x lane of v128. #[inline(always)] pub(crate) fn dot4_in_x(lhs: v128, rhs: v128) -> v128 { let x2_y2_z2_w2 = f32x4_mul(lhs, rhs); let z2_w2_0_0 = i32x4_shuffle::<2, 3, 0, 0>(x2_y2_z2_w2, x2_y2_z2_w2); let x2z2_y2w2_0_0 = f32x4_add(x2_y2_z2_w2, z2_w2_0_0); let y2w2_0_0_0 = i32x4_shuffle::<1, 0, 0, 0>(x2z2_y2w2_0_0, x2z2_y2w2_0_0); f32x4_add(x2z2_y2w2_0_0, y2w2_0_0_0) } #[inline] pub(crate) fn dot3(lhs: v128, rhs: v128) -> f32 { f32x4_extract_lane::<0>(dot3_in_x(lhs, rhs)) } #[inline] pub(crate) fn dot3_into_v128(lhs: v128, rhs: v128) -> v128 { let dot_in_x = dot3_in_x(lhs, rhs); i32x4_shuffle::<0, 0, 0, 0>(dot_in_x, dot_in_x) } #[inline] pub(crate) fn dot4(lhs: v128, rhs: v128) -> f32 { f32x4_extract_lane::<0>(dot4_in_x(lhs, rhs)) } #[inline] pub(crate) fn dot4_into_v128(lhs: v128, rhs: v128) -> v128 { let dot_in_x = dot4_in_x(lhs, rhs); i32x4_shuffle::<0, 0, 0, 0>(dot_in_x, dot_in_x) } glam-0.30.1/templates/affine.rs.tera000064400000000000000000000664401046102023000153650ustar 00000000000000// Generated from {{template_path}} template. Edit the template, not the generated file. {% if scalar_t == "f32" %} {% if dim == 3 %} {% set self_t = "Affine3A" %} {% set col_t = "Vec3A" %} {% set mat_t = "Mat3A" %} {% else %} {% set self_t = "Affine" ~ dim %} {% set col_t = "Vec" ~ dim %} {% set mat_t = "Mat" ~ dim %} {% endif %} {% set quat_t = "Quat" %} {% set vec2_t = "Vec2" %} {% set vec3_t = "Vec3" %} {% set mat3_t = "Mat3" %} {% set mat4_t = "Mat4" %} {% elif scalar_t == "f64" %} {% set self_t = "DAffine" ~ dim %} {% set col_t = "DVec" ~ dim %} {% set mat_t = "DMat" ~ dim %} {% set quat_t = "DQuat" %} {% set vec2_t = "DVec2" %} {% set vec3_t = "DVec3" %} {% set mat3_t = "DMat3" %} {% set mat4_t = "DMat4" %} {% endif %} {% if dim == 2 %} {% set size = 6 %} {% set mat_size = 4 %} {% set vec_size = 2 %} {% elif dim == 3 %} {% set size = 12 %} {% set mat_size = 9 %} {% set vec_size = 3 %} {% endif %} {% set components = ["x", "y", "z", "w"] | slice(end = dim + 1) %} {% set axes = ["x_axis", "y_axis", "z_axis", "w_axis"] | slice(end = dim + 1) %} use crate::{ {% if self_t == "Affine2" %} Mat3A, Vec3A, {% elif self_t == "Affine3A" %} Vec3, Mat3, {% endif %} {% if dim == 2 %} {{ mat_t }}, {{ col_t }}, {{ mat3_t }}, {% elif dim == 3 %} {{ mat_t }}, {{ col_t}}, {{ mat4_t }}, {{ quat_t }}, {% endif %} }; use core::ops::{Deref, DerefMut, Mul, MulAssign}; /// A {{ dim }}D affine transform, which can represent translation, rotation, scaling and shear. {%- if is_align %} /// /// This type is 16 byte aligned. {%- endif %} #[derive(Copy, Clone)] #[repr(C)] pub struct {{ self_t }} { pub matrix{{ dim }}: {{ mat_t }}, pub translation: {{ col_t }}, } impl {{ self_t }} { /// The degenerate zero transform. /// /// This transforms any finite vector and point to zero. /// The zero transform is non-invertible. pub const ZERO: Self = Self { matrix{{ dim }}: {{ mat_t }}::ZERO, translation: {{ col_t }}::ZERO, }; /// The identity transform. /// /// Multiplying a vector with this returns the same vector. pub const IDENTITY: Self = Self { matrix{{ dim }}: {{ mat_t }}::IDENTITY, translation: {{ col_t }}::ZERO, }; /// All NAN:s. pub const NAN: Self = Self { matrix{{ dim }}: {{ mat_t }}::NAN, translation: {{ col_t }}::NAN, }; /// Creates an affine transform from three column vectors. #[inline(always)] #[must_use] pub const fn from_cols( {% for axis in axes %} {{ axis }}: {{ col_t }}, {% endfor %} ) -> Self { Self { matrix{{ dim }}: {{ mat_t }}::from_cols( {% for axis in axes | slice(end = dim) %} {{ axis }}, {% endfor %} ), translation: {{ axes[dim] }}, } } /// Creates an affine transform from a `[{{ scalar_t }}; {{ size }}]` array stored in column major order. #[inline] #[must_use] pub fn from_cols_array(m: &[{{ scalar_t }}; {{ size }}]) -> Self { Self { matrix{{ dim }}: {{ mat_t }}::from_cols_array(&[ {% for i in range(end = mat_size) %} m[{{ i }}], {%- endfor %} ]), translation: {{ col_t }}::from_array([ {% for i in range(start = mat_size, end = mat_size + vec_size) %} m[{{ i }}], {%- endfor %} ]), } } /// Creates a `[{{ scalar_t }}; {{ size }}]` array storing data in column major order. #[inline] #[must_use] pub fn to_cols_array(&self) -> [{{ scalar_t }}; {{ size }}] { {% for i in range(end = dim) %} let {{ components[i] }} = &self.matrix{{ dim }}.{{ axes[i] }}; {%- endfor %} let {{ components[dim] }} = &self.translation; [ {% for i in range(end = dim + 1) %} {% for j in range(end = dim) %} {{ components[i] }}.{{ components[j] }}, {% endfor %} {% endfor %} ] } /// Creates an affine transform from a `[[{{ scalar_t }}; {{ dim }}]; {{ dim + 1 }}]` /// {{ dim }}D array stored in column major order. /// 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: &[[{{ scalar_t }}; {{ dim }}]; {{ dim + 1 }}]) -> Self { Self { matrix{{ dim }}: {{ mat_t }}::from_cols( {% for i in range(end = dim) %} m[{{ i }}].into(), {% endfor %} ), translation: m[{{ dim }}].into(), } } /// Creates a `[[{{ scalar_t }}; {{ dim }}]; {{ dim + 1 }}]` {{ dim }}D array storing data in /// 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) -> [[{{ scalar_t }}; {{ dim }}]; {{ dim + 1 }}] { [ {% for i in range(end = dim) %} self.matrix{{ dim }}.{{ axes[i] }}.into(), {% endfor %} self.translation.into(), ] } /// Creates an affine transform from the first {{ size }} values in `slice`. /// /// # Panics /// /// Panics if `slice` is less than {{ size }} elements long. #[inline] #[must_use] pub fn from_cols_slice(slice: &[{{ scalar_t }}]) -> Self { Self { matrix{{ dim }}: {{ mat_t }}::from_cols_slice(&slice[0..{{ dim * dim }}]), translation: {{ col_t }}::from_slice(&slice[{{ dim * dim }}..{{ size }}]), } } /// Writes the columns of `self` to the first {{ size }} elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than {{ size }} elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [{{ scalar_t }}]) { self.matrix{{ dim }}.write_cols_to_slice(&mut slice[0..{{ dim * dim }}]); self.translation.write_to_slice(&mut slice[{{ dim * dim }}..{{ size }}]); } {% if dim == 2 %} /// 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_t }}) -> Self { Self { matrix{{ dim }}: {{ mat_t }}::from_diagonal(scale), translation: {{ col_t }}::ZERO, } } /// Creates an affine transform from the given rotation `angle`. #[inline] #[must_use] pub fn from_angle(angle: {{ scalar_t }}) -> Self { Self { matrix2: {{ mat_t }}::from_angle(angle), translation: {{ col_t }}::ZERO, } } /// Creates an affine transformation from the given 2D `translation`. #[inline] #[must_use] pub fn from_translation(translation: {{ vec2_t }}) -> Self { Self { matrix2: {{ mat_t }}::IDENTITY, translation, } } /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) #[inline] #[must_use] pub fn from_mat2(matrix2: {{ mat_t }}) -> Self { Self { matrix2, translation: {{ col_t }}::ZERO, } } /// Creates an affine transform from a 2x2 matrix (expressing scale, shear and rotation) and a /// translation vector. /// /// Equivalent to /// `{{ self_t }}::from_translation(translation) * {{ self_t }}::from_mat{{ dim }}(mat{{ dim }})` #[inline] #[must_use] pub fn from_mat2_translation(matrix2: {{ mat_t }}, translation: {{ vec2_t }}) -> Self { Self { matrix2, translation, } } /// Creates an affine transform from the given 2D `scale`, rotation `angle` (in radians) and /// `translation`. /// /// Equivalent to `{{ self_t }}::from_translation(translation) * /// {{ self_t }}::from_angle(angle) * {{ self_t }}::from_scale(scale)` #[inline] #[must_use] pub fn from_scale_angle_translation( scale: {{ vec2_t }}, angle: {{ scalar_t }}, translation: {{ vec2_t }}, ) -> Self { let rotation = {{ mat_t }}::from_angle(angle); Self { matrix2: {{ mat_t }}::from_cols( rotation.x_axis * scale.x, rotation.y_axis * scale.y, ), translation, } } /// Creates an affine transform from the given 2D rotation `angle` (in radians) and /// `translation`. /// /// Equivalent to `{{ self_t }}::from_translation(translation) * {{ self_t }}::from_angle(angle)` #[inline] #[must_use] pub fn from_angle_translation(angle: {{ scalar_t }}, translation: {{ vec2_t }}) -> Self { Self { matrix2: {{ mat_t }}::from_angle(angle), translation, } } /// The given `{{ mat3_t }}` must be an affine transform, #[inline] #[must_use] pub fn from_mat3(m: {{ mat3_t }}) -> Self { use crate::swizzles::Vec3Swizzles; Self { matrix2: {{ mat_t }}::from_cols(m.x_axis.xy(), m.y_axis.xy()), translation: m.z_axis.xy(), } } {% if scalar_t == "f32" %} /// The given [`Mat3A`] must be an affine transform, #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { use crate::swizzles::Vec3Swizzles; Self { matrix2: Mat2::from_cols(m.x_axis.xy(), m.y_axis.xy()), translation: m.z_axis.xy(), } } {% endif %} /// 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_t }}, {{ scalar_t }}, {{ vec2_t }}) { use crate::{{ scalar_t }}::math; let det = self.matrix2.determinant(); glam_assert!(det != 0.0); let scale = {{ col_t }}::new( self.matrix2.x_axis.length() * math::signum(det), self.matrix2.y_axis.length(), ); glam_assert!(scale.cmpne({{ col_t }}::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_t }}) -> {{ vec2_t }} { self.matrix2 * rhs + self.translation } /// Transforms the given 2D vector, applying shear, scale and rotation (but NOT /// translation). /// /// To also apply translation, use [`Self::transform_point2()`] instead. #[inline] pub fn transform_vector2(&self, rhs: {{ vec2_t }}) -> {{ vec2_t }} { self.matrix2 * rhs } {% elif dim == 3 %} /// 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_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_diagonal(scale), translation: {{ col_t }}::ZERO, } } /// Creates an affine transform from the given `rotation` quaternion. #[inline] #[must_use] pub fn from_quat(rotation: {{ quat_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_quat(rotation), translation: {{ col_t }}::ZERO, } } /// 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_t }}, angle: {{ scalar_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_axis_angle(axis, angle), translation: {{ col_t }}::ZERO, } } /// 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: {{ scalar_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_rotation_x(angle), translation: {{ col_t }}::ZERO, } } /// 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: {{ scalar_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_rotation_y(angle), translation: {{ col_t }}::ZERO, } } /// 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: {{ scalar_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_rotation_z(angle), translation: {{ col_t }}::ZERO, } } /// Creates an affine transformation from the given 3D `translation`. #[inline] #[must_use] pub fn from_translation(translation: {{ vec3_t }}) -> Self { #[allow(clippy::useless_conversion)] Self { matrix3: {{ mat_t }}::IDENTITY, translation: translation.into(), } } /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and /// rotation) #[inline] #[must_use] pub fn from_mat3(mat3: {{ mat3_t }}) -> Self { #[allow(clippy::useless_conversion)] Self { matrix3: mat3.into(), translation: {{ col_t }}::ZERO, } } /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation) /// and a translation vector. /// /// Equivalent to `{{ self_t }}::from_translation(translation) * {{ self_t }}::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: {{ mat3_t }}, translation: {{ vec3_t }}) -> Self { #[allow(clippy::useless_conversion)] Self { matrix3: mat3.into(), translation: translation.into(), } } /// Creates an affine transform from the given 3D `scale`, `rotation` and /// `translation`. /// /// Equivalent to `{{ self_t }}::from_translation(translation) * /// {{ self_t }}::from_quat(rotation) * {{ self_t }}::from_scale(scale)` #[inline] #[must_use] pub fn from_scale_rotation_translation( scale: {{ vec3_t }}, rotation: {{ quat_t }}, translation: {{ vec3_t }}, ) -> Self { let rotation = {{ mat_t }}::from_quat(rotation); #[allow(clippy::useless_conversion)] Self { matrix3: {{ mat_t }}::from_cols( rotation.x_axis * scale.x, rotation.y_axis * scale.y, rotation.z_axis * scale.z, ), translation: translation.into(), } } /// Creates an affine transform from the given 3D `rotation` and `translation`. /// /// Equivalent to `{{ self_t }}::from_translation(translation) * {{ self_t }}::from_quat(rotation)` #[inline] #[must_use] pub fn from_rotation_translation(rotation: {{ quat_t }}, translation: {{ vec3_t }}) -> Self { #[allow(clippy::useless_conversion)] Self { matrix3: {{ mat_t }}::from_quat(rotation), translation: translation.into(), } } /// The given `{{ mat4_t }}` must be an affine transform, /// i.e. contain no perspective transform. #[inline] #[must_use] pub fn from_mat4(m: {{ mat4_t }}) -> Self { Self { matrix3: {{ mat_t }}::from_cols( {{ col_t }}::from_vec4(m.x_axis), {{ col_t }}::from_vec4(m.y_axis), {{ col_t }}::from_vec4(m.z_axis), ), translation: {{ col_t }}::from_vec4(m.w_axis), } } /// Extracts `scale`, `rotation` 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.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_t }}, {{ quat_t }}, {{ vec3_t }}) { use crate::{{ scalar_t }}::math; let det = self.matrix3.determinant(); glam_assert!(det != 0.0); let scale = {{ vec3_t }}::new( self.matrix3.x_axis.length() * math::signum(det), self.matrix3.y_axis.length(), self.matrix3.z_axis.length(), ); glam_assert!(scale.cmpne({{ vec3_t }}::ZERO).all()); let inv_scale = scale.recip(); #[allow(clippy::useless_conversion)] let rotation = {{ quat_t }}::from_mat3(&{{ mat3_t }}::from_cols( (self.matrix3.x_axis * inv_scale.x).into(), (self.matrix3.y_axis * inv_scale.y).into(), (self.matrix3.z_axis * inv_scale.z).into(), )); #[allow(clippy::useless_conversion)] (scale, rotation, self.translation.into()) } /// Creates a left-handed view transform using a camera position, an up direction, and a facing /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. #[inline] #[must_use] pub fn look_to_lh(eye: {{ vec3_t }}, dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view transform using a camera position, an up direction, and a facing /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. #[inline] #[must_use] pub fn look_to_rh(eye: {{ vec3_t }}, dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { let f = dir.normalize(); let s = f.cross(up).normalize(); let u = s.cross(f); Self { matrix3: {{ mat_t }}::from_cols( {{ col_t }}::new(s.x, u.x, -f.x), {{ col_t }}::new(s.y, u.y, -f.y), {{ col_t }}::new(s.z, u.z, -f.z), ), translation: {{ col_t }}::new(-eye.dot(s), -eye.dot(u), eye.dot(f)), } } /// Creates a left-handed view transform using a camera position, an up direction, and a focal /// point. /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { glam_assert!(up.is_normalized()); Self::look_to_lh(eye, center - eye, up) } /// Creates a right-handed view transform using a camera position, an up direction, and a focal /// point. /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { glam_assert!(up.is_normalized()); Self::look_to_rh(eye, center - eye, up) } /// Transforms the given 3D points, applying shear, scale, rotation and translation. #[inline] pub fn transform_point3(&self, rhs: {{ vec3_t }}) -> {{ vec3_t }} { #[allow(clippy::useless_conversion)] ((self.matrix3.x_axis * rhs.x) + (self.matrix3.y_axis * rhs.y) + (self.matrix3.z_axis * rhs.z) + self.translation) .into() } /// Transforms the given 3D vector, applying shear, scale and rotation (but NOT /// translation). /// /// To also apply translation, use [`Self::transform_point3()`] instead. #[inline] #[must_use] pub fn transform_vector3(&self, rhs: {{ vec3_t }}) -> {{ vec3_t }} { #[allow(clippy::useless_conversion)] ((self.matrix3.x_axis * rhs.x) + (self.matrix3.y_axis * rhs.y) + (self.matrix3.z_axis * rhs.z)) .into() } {% endif %} {% if self_t == "Affine3A" %} /// 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 /// translation). /// /// To also apply translation, use [`Self::transform_point3a()`] instead. #[inline] #[must_use] pub fn transform_vector3a(&self, rhs: Vec3A) -> Vec3A { self.matrix3 * rhs } {% endif %} /// 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.matrix{{ dim }}.is_finite() && self.translation.is_finite() } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(&self) -> bool { self.matrix{{ dim }}.is_nan() || self.translation.is_nan() } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two 3x4 matrices contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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: {{ scalar_t }}) -> bool { self.matrix{{ dim }}.abs_diff_eq(rhs.matrix{{ dim }}, max_abs_diff) && self .translation .abs_diff_eq(rhs.translation, max_abs_diff) } /// Return the inverse of this transform. /// /// Note that if the transform is not invertible the result will be invalid. #[inline] #[must_use] pub fn inverse(&self) -> Self { let matrix{{ dim }} = self.matrix{{ dim }}.inverse(); // transform negative translation by the matrix inverse: let translation = -(matrix{{ dim }} * self.translation); Self { matrix{{ dim }}, translation, } } } impl Default for {{ self_t }} { #[inline(always)] fn default() -> Self { Self::IDENTITY } } impl Deref for {{ self_t }} { type Target = crate::deref::Cols{{ dim + 1 }}<{{ col_t }}>; #[inline(always)] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl DerefMut for {{ self_t }} { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } impl PartialEq for {{ self_t }} { #[inline] fn eq(&self, rhs: &Self) -> bool { self.matrix{{ dim }}.eq(&rhs.matrix{{ dim }}) && self.translation.eq(&rhs.translation) } } impl core::fmt::Debug for {{ self_t }} { fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fmt.debug_struct(stringify!({{ self_t }})) .field("matrix{{ dim }}", &self.matrix{{ dim }}) .field("translation", &self.translation) .finish() } } impl core::fmt::Display for {{ self_t }} { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { if let Some(p) = f.precision() { {% if dim == 2 %} write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.matrix2.x_axis, p, self.matrix2.y_axis, p, self.translation) {% elif dim == 3 %} write!(f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.matrix3.x_axis, p, self.matrix3.y_axis, p, self.matrix3.z_axis, p, self.translation) {% endif %} } else { {% if dim == 2 %} write!(f, "[{}, {}, {}]", self.matrix2.x_axis, self.matrix2.y_axis, self.translation) {% elif dim == 3 %} write!( f, "[{}, {}, {}, {}]", self.matrix3.x_axis, self.matrix3.y_axis, self.matrix3.z_axis, self.translation ) {% endif %} } } } impl<'a> core::iter::Product<&'a Self> for {{ self_t }} { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| a * b) } } impl Mul for {{ self_t }} { type Output = {{ self_t }}; #[inline] fn mul(self, rhs: {{ self_t }}) -> Self::Output { Self { matrix{{ dim }}: self.matrix{{ dim }} * rhs.matrix{{ dim }}, translation: self.matrix{{ dim }} * rhs.translation + self.translation, } } } impl MulAssign for {{ self_t }} { #[inline] fn mul_assign(&mut self, rhs: {{ self_t }}) { *self = self.mul(rhs); } } {% if dim == 2 %} impl From<{{ self_t }}> for {{ mat3_t }} { #[inline] fn from(m: {{ self_t }}) -> {{ mat3_t }} { Self::from_cols( m.matrix2.x_axis.extend(0.0), m.matrix2.y_axis.extend(0.0), m.translation.extend(1.0), ) } } impl Mul<{{ mat3_t }}> for {{ self_t }} { type Output = {{ mat3_t }}; #[inline] fn mul(self, rhs: {{ mat3_t }}) -> Self::Output { {{ mat3_t }}::from(self) * rhs } } impl Mul<{{ self_t }}> for {{ mat3_t }} { type Output = {{ mat3_t }}; #[inline] fn mul(self, rhs: {{ self_t }}) -> Self::Output { self * {{ mat3_t }}::from(rhs) } } {% elif dim == 3 %} impl From<{{ self_t }}> for {{ mat4_t }} { #[inline] fn from(m: {{ self_t }}) -> {{ mat4_t }} { {{ mat4_t }}::from_cols( m.matrix3.x_axis.extend(0.0), m.matrix3.y_axis.extend(0.0), m.matrix3.z_axis.extend(0.0), m.translation.extend(1.0), ) } } impl Mul<{{ mat4_t }}> for {{ self_t }} { type Output = {{ mat4_t }}; #[inline] fn mul(self, rhs: {{ mat4_t }}) -> Self::Output { {{ mat4_t }}::from(self) * rhs } } impl Mul<{{ self_t }}> for {{ mat4_t }} { type Output = {{ mat4_t }}; #[inline] fn mul(self, rhs: {{ self_t }}) -> Self::Output { self * {{ mat4_t }}::from(rhs) } } {% endif %} {% if self_t == "Affine2" %} impl From for Mat3A { #[inline] fn from(m: Affine2) -> Mat3A { Self::from_cols( Vec3A::from((m.matrix2.x_axis, 0.0)), Vec3A::from((m.matrix2.y_axis, 0.0)), Vec3A::from((m.translation, 1.0)), ) } } impl Mul for Affine2 { type Output = Mat3A; #[inline] fn mul(self, rhs: Mat3A) -> Self::Output { Mat3A::from(self) * rhs } } impl Mul for Mat3A { type Output = Mat3A; #[inline] fn mul(self, rhs: Affine2) -> Self::Output { self * Mat3A::from(rhs) } } {% endif %} glam-0.30.1/templates/coresimd.rs.tera000064400000000000000000000144331046102023000157350ustar 00000000000000{% macro impl_mat4_inverse() %} // 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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [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, [1, 1, 5, 5] ); let mul00 = swp00 * swp01; let mul01 = swp02 * swp03; mul00 - mul01 }; 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, [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, [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, [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, [3, 3, 7, 7] ); let vec3 = simd_swizzle!(temp3, [0, 2, 2, 2]); let mul00 = vec1 * fac0; let mul01 = vec2 * fac1; let mul02 = vec3 * fac2; let sub00 = mul00 - mul01; let add00 = sub00 + mul02; let inv0 = sign_b * add00; let mul03 = vec0 * fac0; let mul04 = vec2 * fac3; let mul05 = vec3 * fac4; let sub01 = mul03 - mul04; let add01 = sub01 + mul05; let inv1 = sign_a * add01; let mul06 = vec0 * fac1; let mul07 = vec1 * fac3; let mul08 = vec3 * fac5; let sub02 = mul06 - mul07; let add02 = sub02 + mul08; let inv2 = sign_b * add02; let mul09 = vec0 * fac2; let mul10 = vec1 * fac4; let mul11 = vec2 * fac5; let sub03 = mul09 - mul10; let add03 = sub03 + mul11; let inv3 = sign_a * add03; 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); let rcp0 = f32x4::splat(dot0.recip()); Self { x_axis: Vec4(inv0 * rcp0), y_axis: Vec4(inv1 * rcp0), z_axis: Vec4(inv2 * rcp0), w_axis: Vec4(inv3 * rcp0), } {% endmacro impl_mat4_inverse %} glam-0.30.1/templates/float.rs.tera000064400000000000000000000013121046102023000152250ustar 00000000000000// Generated from {{template_path}} template. Edit the template, not the generated file. use crate::float::FloatExt; impl FloatExt for {{ scalar_t }} { #[inline] fn lerp(self, rhs: {{ scalar_t }}, t: {{ scalar_t }}) -> {{ scalar_t }} { self + (rhs - self) * t } #[inline] fn inverse_lerp(a: {{ scalar_t }}, b: {{ scalar_t }}, v: {{ scalar_t }}) -> {{ scalar_t }} { (v - a) / (b - a) } #[inline] fn remap(self, in_start: {{ scalar_t }}, in_end: {{ scalar_t }}, out_start: {{ scalar_t }}, out_end: {{ scalar_t }}) -> {{ scalar_t }} { let t = {{ scalar_t }}::inverse_lerp(in_start, in_end, self); {{ scalar_t }}::lerp(out_start, out_end, t) } } glam-0.30.1/templates/macros.rs.tera000064400000000000000000000130371046102023000154130ustar 00000000000000{% macro make_tuple_t(t, n) %} ( {%- for i in range(end=n) -%} {{ t }}, {%- endfor -%} ) {% endmacro make_tuple_t %} {% macro impl_mat3_minor(mat3_t, align="") %} /// Creates a 2x2 matrix from the minor of the given 3x3 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 2. #[inline] #[must_use] pub fn from_mat3{{ align }}_minor(m: {{ mat3_t }}, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols(m.y_axis.yz(), m.z_axis.yz()), (0, 1) => Self::from_cols(m.y_axis.xz(), m.z_axis.xz()), (0, 2) => Self::from_cols(m.y_axis.xy(), m.z_axis.xy()), (1, 0) => Self::from_cols(m.x_axis.yz(), m.z_axis.yz()), (1, 1) => Self::from_cols(m.x_axis.xz(), m.z_axis.xz()), (1, 2) => Self::from_cols(m.x_axis.xy(), m.z_axis.xy()), (2, 0) => Self::from_cols(m.x_axis.yz(), m.y_axis.yz()), (2, 1) => Self::from_cols(m.x_axis.xz(), m.y_axis.xz()), (2, 2) => Self::from_cols(m.x_axis.xy(), m.y_axis.xy()), _ => panic!("index out of bounds"), } } {% endmacro impl_mat3_minor %} {% macro impl_mat4_minor(mat4_t, vec3_t) %} {% if vec3_t == "Vec3A" %} {% set w = "w" %} {% set b = "Vec3A::from_vec4(" %} {% set e = ")" %} {% else %} {% set w = "" %} {% set b = "" %} {% set e = "" %} {% endif %} /// Creates a 3x3 matrix from the minor of the given 4x4 matrix, discarding the `i`th column /// and `j`th row. /// /// # Panics /// /// Panics if `i` or `j` is greater than 3. #[inline] #[must_use] pub fn from_mat4_minor(m: {{ mat4_t }}, i: usize, j: usize) -> Self { match (i, j) { (0, 0) => Self::from_cols({{ b }}m.y_axis.yzw{{ w }}(){{ e }}, {{ b }}m.z_axis.yzw{{ w }}(){{ e }}, {{ b }}m.w_axis.yzw{{ w }}(){{ e }}), (0, 1) => Self::from_cols({{ b }}m.y_axis.xzw{{ w }}(){{ e }}, {{ b }}m.z_axis.xzw{{ w }}(){{ e }}, {{ b }}m.w_axis.xzw{{ w }}(){{ e }}), (0, 2) => Self::from_cols({{ b }}m.y_axis.xyw{{ w }}(){{ e }}, {{ b }}m.z_axis.xyw{{ w }}(){{ e }}, {{ b }}m.w_axis.xyw{{ w }}(){{ e }}), (0, 3) => Self::from_cols({{ b }}m.y_axis.xyz{{ w }}(){{ e }}, {{ b }}m.z_axis.xyz{{ w }}(){{ e }}, {{ b }}m.w_axis.xyz{{ w }}(){{ e }}), (1, 0) => Self::from_cols({{ b }}m.x_axis.yzw{{ w }}(){{ e }}, {{ b }}m.z_axis.yzw{{ w }}(){{ e }}, {{ b }}m.w_axis.yzw{{ w }}(){{ e }}), (1, 1) => Self::from_cols({{ b }}m.x_axis.xzw{{ w }}(){{ e }}, {{ b }}m.z_axis.xzw{{ w }}(){{ e }}, {{ b }}m.w_axis.xzw{{ w }}(){{ e }}), (1, 2) => Self::from_cols({{ b }}m.x_axis.xyw{{ w }}(){{ e }}, {{ b }}m.z_axis.xyw{{ w }}(){{ e }}, {{ b }}m.w_axis.xyw{{ w }}(){{ e }}), (1, 3) => Self::from_cols({{ b }}m.x_axis.xyz{{ w }}(){{ e }}, {{ b }}m.z_axis.xyz{{ w }}(){{ e }}, {{ b }}m.w_axis.xyz{{ w }}(){{ e }}), (2, 0) => Self::from_cols({{ b }}m.x_axis.yzw{{ w }}(){{ e }}, {{ b }}m.y_axis.yzw{{ w }}(){{ e }}, {{ b }}m.w_axis.yzw{{ w }}(){{ e }}), (2, 1) => Self::from_cols({{ b }}m.x_axis.xzw{{ w }}(){{ e }}, {{ b }}m.y_axis.xzw{{ w }}(){{ e }}, {{ b }}m.w_axis.xzw{{ w }}(){{ e }}), (2, 2) => Self::from_cols({{ b }}m.x_axis.xyw{{ w }}(){{ e }}, {{ b }}m.y_axis.xyw{{ w }}(){{ e }}, {{ b }}m.w_axis.xyw{{ w }}(){{ e }}), (2, 3) => Self::from_cols({{ b }}m.x_axis.xyz{{ w }}(){{ e }}, {{ b }}m.y_axis.xyz{{ w }}(){{ e }}, {{ b }}m.w_axis.xyz{{ w }}(){{ e }}), (3, 0) => Self::from_cols({{ b }}m.x_axis.yzw{{ w }}(){{ e }}, {{ b }}m.y_axis.yzw{{ w }}(){{ e }}, {{ b }}m.z_axis.yzw{{ w }}(){{ e }}), (3, 1) => Self::from_cols({{ b }}m.x_axis.xzw{{ w }}(){{ e }}, {{ b }}m.y_axis.xzw{{ w }}(){{ e }}, {{ b }}m.z_axis.xzw{{ w }}(){{ e }}), (3, 2) => Self::from_cols({{ b }}m.x_axis.xyw{{ w }}(){{ e }}, {{ b }}m.y_axis.xyw{{ w }}(){{ e }}, {{ b }}m.z_axis.xyw{{ w }}(){{ e }}), (3, 3) => Self::from_cols({{ b }}m.x_axis.xyz{{ w }}(){{ e }}, {{ b }}m.y_axis.xyz{{ w }}(){{ e }}, {{ b }}m.z_axis.xyz{{ w }}(){{ e }}), _ => panic!("index out of bounds"), } } {% endmacro impl_mat4_minor %} {% macro impl_op_ref_inner(op, self_t, rhs_t, output_t, self, self_ref, rhs_ref) %} {% set method = op | snake_case %} {% if rhs_ref and rhs_t %} {% set rhs = "&" ~ rhs_t %} {% elif rhs_t %} {% set rhs = rhs_t %} {% endif %} impl {{ op }}{% if rhs_t %}<{{ rhs }}>{% endif %} for {% if self_ref %}&{% endif %}{{ self_t }} { {% if output_t %} type Output = {{ output_t }}; {% endif -%} #[inline] fn {{ method }}({{ self }}{% if rhs_t %}, rhs: {{ rhs }}{% endif %}){% if output_t %} -> {{ output_t }}{% endif %}{ {% if self_ref %} (*self) {% else %} self {% endif %}.{{method}} ({% if rhs_ref %} *rhs {% elif rhs_t %} rhs {% endif %}) } } {% endmacro impl_op_ref_inner %} {% macro impl_op_ref(op, self_t, rhs_t=false, output_t=false, self="self") %} {%if rhs_t %} {{ self::impl_op_ref_inner(op=op, self_t=self_t, rhs_t=rhs_t, output_t=output_t, self=self, self_ref=false, rhs_ref=true) }} {%if output_t %} {{ self::impl_op_ref_inner(op=op, self_t=self_t, rhs_t=rhs_t, output_t=output_t, self=self, self_ref=true, rhs_ref=true) }} {% endif %} {% endif %} {%if output_t %} {{ self::impl_op_ref_inner(op=op, self_t=self_t, rhs_t=rhs_t, output_t=output_t, self=self, self_ref=true, rhs_ref=false) }} {% endif %} {% endmacro impl_op_ref %} glam-0.30.1/templates/mat.rs.tera000064400000000000000000003105551046102023000147150ustar 00000000000000{% import "macros.rs.tera" as macros %} {% import "coresimd.rs.tera" as coresimd %} {% import "neon.rs.tera" as neon %} {% import "sse2.rs.tera" as sse2 %} {% import "wasm32.rs.tera" as wasm32 %} // Generated from {{template_path}} template. Edit the template, not the generated file. {% if scalar_t == "f32" %} {% set vecn_t = "Vec" ~ dim %} {% if dim == 3 and is_align %} {% set self_t = "Mat3A" %} {% set col_t = "Vec3A" %} {% else %} {% set self_t = "Mat" ~ dim %} {% set col_t = vecn_t %} {% endif %} {% set quat_t = "Quat" %} {% set affine2_t = "Affine2" %} {% set affine3_t = "Affine3A" %} {% set vec2_t = "Vec2" %} {% set vec3_t = "Vec3" %} {% set vec4_t = "Vec4" %} {% set mat2_t = "Mat2" %} {% set mat3_t = "Mat3" %} {% set mat4_t = "Mat4" %} {% elif scalar_t == "f64" %} {% set vecn_t = "DVec" ~ dim %} {% set self_t = "DMat" ~ dim %} {% set col_t = vecn_t %} {% set quat_t = "DQuat" %} {% set affine2_t = "DAffine2" %} {% set affine3_t = "DAffine3" %} {% set vec2_t = "DVec2" %} {% set vec3_t = "DVec3" %} {% set vec4_t = "DVec4" %} {% set mat2_t = "DMat2" %} {% set mat3_t = "DMat3" %} {% set mat4_t = "DMat4" %} {% endif %} {% if self_t == "Mat2" %} {% if not is_scalar %} {% set is_simd = true %} {% if is_sse2 %} {% set simd_t = "__m128" %} {% elif is_wasm32 %} {% set simd_t = "v128" %} {% elif is_coresimd %} {% set simd_t = "f32x4" %} {% elif is_neon %} {% set simd_t = "float32x4_t" %} {% endif %} {% endif %} {% endif %} {% set size = dim * dim %} {% set nxn = dim ~ "x" ~ dim %} {% set components = ["x", "y", "z", "w"] | slice(end = dim) %} {% set axes = ["x_axis", "y_axis", "z_axis", "w_axis"] | slice(end = dim) %} {% set dimension_in_full = ["zero", "one", "two", "three", "four"] | nth(n = dim) %} use crate::{ {% if scalar_t == "f32" %} DMat{{ dim }}, {% elif scalar_t == "f64" %} Mat{{ dim }}, {% endif %} {% if dim == 2 %} {{ mat3_t }}, {{ vec2_t }}, {% if scalar_t == "f32" %} Mat3A, {% endif %} {% elif dim == 3 %} EulerRot, euler::{FromEuler, ToEuler}, {{ mat2_t }}, {{ mat4_t }}, {{ quat_t }}, {{ vec2_t }}, {{ col_t }}, {% if is_align %} {{ mat3_t }}, {{ vec3_t }}, {% elif scalar_t == "f32" %} Mat3A, Vec3A, {% endif %} {% elif dim == 4 %} EulerRot, euler::{FromEuler, ToEuler}, {{ mat3_t }}, {{ quat_t }}, {{ vec3_t }}, {{ col_t }}, {% if scalar_t == "f32" %} Mat3A, Vec3A, {% endif %} {% endif %} {% if self_t == "Mat4" %} {% if is_sse2 %} sse2::*, {% elif is_wasm32 %} wasm32::*, {% elif is_coresimd %} coresimd::*, {% elif is_neon %} neon::*, {% endif %} {% endif %} {{ scalar_t }}::math, swizzles::*, }; use core::fmt; use core::iter::{Product, Sum}; use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; {% if is_sse2 %} #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; {% elif is_wasm32 %} use core::arch::wasm32::*; {% elif is_coresimd %} use core::simd::*; {% elif is_neon %} use core::arch::aarch64::*; {% endif %} {% set is_sse2_or_neon = is_sse2 or is_neon %} {% if self_t == "Mat2" and is_sse2_or_neon %} #[repr(C)] union UnionCast { a: [f32; 4], v: {{ self_t }} } {% endif %} /// Creates a {{ nxn }} matrix from {{ dimension_in_full }} column vectors. #[inline(always)] #[must_use] pub const fn {{ self_t | lower }}( {% for axis in axes %} {{ axis }}: {{ col_t }}, {% endfor %} ) -> {{ self_t }} { {{ self_t }}::from_cols({{ axes | join(sep=",") }}) } /// A {{ nxn }} column major matrix. {%- if dim == 3 %} /// /// This 3x3 matrix type features convenience methods for creating and using linear and /// affine transformations. If you are primarily dealing with 2D affine transformations the /// [`{{ affine2_t }}`](crate::{{ affine2_t }}) type is much faster and more space efficient than /// using a 3x3 matrix. /// /// Linear transformations including 3D rotation and scale can be created using methods /// such as [`Self::from_diagonal()`], [`Self::from_quat()`], [`Self::from_axis_angle()`], /// [`Self::from_rotation_x()`], [`Self::from_rotation_y()`], or /// [`Self::from_rotation_z()`]. /// /// The resulting matrices can be use to transform 3D vectors using regular vector /// multiplication. /// /// Affine transformations including 2D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_angle()`], /// [`Self::from_scale()`] and [`Self::from_scale_angle_translation()`]. /// /// The [`Self::transform_point2()`] and [`Self::transform_vector2()`] convenience methods /// are provided for performing affine transforms on 2D vectors and points. These multiply /// 2D inputs as 3D vectors with an implicit `z` value of `1` for points and `0` for /// vectors respectively. These methods assume that `Self` contains a valid affine /// transform. {%- elif dim == 4 %} /// /// This 4x4 matrix type features convenience methods for creating and using affine transforms and /// perspective projections. If you are primarily dealing with 3D affine transformations /// considering using [`{{affine3_t}}`](crate::{{ affine3_t }}) which is faster than a 4x4 matrix /// for some affine operations. /// /// Affine transformations including 3D translation, rotation and scale can be created /// using methods such as [`Self::from_translation()`], [`Self::from_quat()`], /// [`Self::from_scale()`] and [`Self::from_scale_rotation_translation()`]. /// /// 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. /// /// The [`Self::transform_point3()`] and [`Self::transform_vector3()`] convenience methods /// are provided for performing affine transformations on 3D vectors and points. These /// multiply 3D inputs as 4D vectors with an implicit `w` value of `1` for points and `0` /// for vectors respectively. These methods assume that `Self` contains a valid affine /// transform. /// /// Perspective projections can be created using methods such as /// [`Self::perspective_lh()`], [`Self::perspective_infinite_lh()`] and /// [`Self::perspective_infinite_reverse_lh()`] for left-handed co-ordinate systems and /// [`Self::perspective_rh()`], [`Self::perspective_infinite_rh()`] and /// [`Self::perspective_infinite_reverse_rh()`] for right-handed co-ordinate systems. /// /// The resulting perspective project can be use to transform 3D vectors as points with /// perspective correction using the [`Self::project_point3()`] convenience method. {%- endif %} {%- if is_simd %} /// /// SIMD vector types are used for storage on supported platforms. /// /// This type is 16 byte aligned. {%- endif %} #[derive(Clone, Copy)] {%- if self_t == "Mat4" and is_scalar %} #[cfg_attr( any( not(any(feature = "scalar-math", target_arch = "spirv")), feature = "cuda"), repr(align(16)) )] {%- elif self_t == "Mat2" and is_scalar %} #[cfg_attr(not(any(feature = "scalar-math", target_arch = "spirv")), repr(align(16)))] #[cfg_attr(feature = "cuda", repr(align(8)))] {%- elif self_t == "DMat2" or self_t == "DMat4" %} #[cfg_attr(feature = "cuda", repr(align(16)))] {%- endif %} {%- if self_t == "Mat2" and not is_scalar %} #[repr(transparent)] pub struct {{ self_t }}(pub(crate) {{ simd_t }}); {%- else %} #[repr(C)] pub struct {{ self_t }} { {% for axis in axes %} pub {{ axis }}: {{ col_t }}, {%- endfor %} } {% endif %} impl {{ self_t }} { /// A {{ nxn }} matrix with all elements set to `0.0`. pub const ZERO: Self = Self::from_cols( {% for axis in axes %} {{ col_t }}::ZERO, {%- endfor %} ); /// A {{ nxn }} identity matrix, where all diagonal elements are `1`, and all off-diagonal elements are `0`. pub const IDENTITY: Self = Self::from_cols( {% for i in range(end = dim) %} {{ col_t }}::{{ components[i] | upper }}, {%- endfor %} ); /// All NAN:s. pub const NAN: Self = Self::from_cols( {% for axis in axes %} {{ col_t }}::NAN, {%- endfor %} ); #[allow(clippy::too_many_arguments)] #[inline(always)] #[must_use] const fn new( {% for i in range(end = dim) %} {%- for j in range(end = dim) %} m{{ i }}{{ j }}: {{ scalar_t }}, {%- endfor %} {%- endfor %} ) -> Self { {% if self_t == "Mat2" and is_sse2 %} unsafe { UnionCast { a: [m00, m01, m10, m11] }.v } {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4(m00, m01, m10, m11)) {% elif self_t == "Mat2" and is_coresimd %} Self(f32x4::from_array([m00, m01, m10, m11])) {% elif self_t == "Mat2" and is_neon %} unsafe { UnionCast { a: [m00, m01, m10, m11] }.v } {% else %} Self { {% for i in range(end = dim) %} {{ axes[i] }}: {{ col_t}}::new( {% for j in range(end = dim) %} m{{ i }}{{ j }}, {% endfor %} ), {%- endfor %} } {% endif %} } /// Creates a {{ nxn }} matrix from {{ dimension_in_full }} column vectors. #[inline(always)] #[must_use] pub const fn from_cols( {% for axis in axes %} {{ axis }}: {{ col_t }}, {% endfor %} ) -> Self { {% if self_t == "Mat2" and is_sse2 %} unsafe { UnionCast { a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y] }.v } {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4(x_axis.x, x_axis.y, y_axis.x, y_axis.y)) {% elif self_t == "Mat2" and is_coresimd %} Self(f32x4::from_array([x_axis.x, x_axis.y, y_axis.x, y_axis.y])) {% elif self_t == "Mat2" and is_neon %} unsafe { UnionCast { a: [x_axis.x, x_axis.y, y_axis.x, y_axis.y] }.v } {% else %} Self { {% for axis in axes %} {{ axis }}, {%- endfor %} } {% endif %} } /// Creates a {{ nxn }} matrix from a `[{{ scalar_t }}; {{ size }}]` array stored in column major order. /// 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: &[{{ scalar_t }}; {{ size }}]) -> Self { {% if self_t == "Mat2" and is_coresimd %} Self(f32x4::from_array(*m)) {% else %} Self::new( {% for i in range(end = size) %} m[{{ i }}], {%- endfor %} ) {% endif %} } /// Creates a `[{{ scalar_t }}; {{ size }}]` 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) -> [{{ scalar_t }}; {{ size }}] { {% if self_t == "Mat2" and not is_scalar %} unsafe { *(self as *const Self as *const [f32; 4]) } {% else %} {% if dim >= 2 and not is_scalar %} {% for axis in axes %} let [{% for c in components %} {{ axis }}_{{ c }}, {% endfor %}] = self.{{ axis }}.to_array(); {%- endfor %} {% endif %} [ {% for axis in axes %} {% for c in components %} {% if dim >= 2 and not is_scalar %} {{ axis }}_{{ c }}, {% else %} self.{{ axis }}.{{ c }}, {% endif %} {%- endfor %} {%- endfor %} ] {% endif %} } /// Creates a {{ nxn }} matrix from a `[[{{ scalar_t }}; {{ dim }}]; {{ dim }}]` {{ dim }}D array stored in column major order. /// 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: &[[{{ scalar_t }}; {{ dim }}]; {{ dim }}]) -> Self { Self::from_cols( {% for i in range(end = dim) %} {{ col_t }}::from_array(m[{{ i }}]), {%- endfor %} ) } /// Creates a `[[{{ scalar_t }}; {{ dim }}]; {{ dim }}]` {{ dim }}D 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) -> [[{{ scalar_t }}; {{ dim }}]; {{ dim }}] { {% if self_t == "Mat2" and not is_scalar %} unsafe { *(self as *const Self as *const [[f32; 2]; 2]) } {% else %} [ {% for axis in axes %} self.{{ axis }}.to_array(), {%- endfor %} ] {% endif %} } /// Creates a {{ nxn }} 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: {{ vecn_t }}) -> Self { {% if self_t == "Mat4" and not is_scalar %} // diagonal.x, diagonal.y etc can't be done in a const-context let [x, y, z, w] = diagonal.to_array(); Self::new( {% for i in range(end = dim) %} {% for j in range(end = dim) %} {% if i == j %} {{ components[i] }}, {% else %} 0.0, {% endif %} {%- endfor %} {%- endfor %} ) {% else %} Self::new( {% for i in range(end = dim) %} {% for j in range(end = dim) %} {% if i == j %} diagonal.{{ components[i] }}, {% else %} 0.0, {% endif %} {%- endfor %} {%- endfor %} ) {% endif %} } {% if dim == 2 %} /// Creates a {{ nxn }} matrix containing the combining non-uniform `scale` and rotation of /// `angle` (in radians). #[inline] #[must_use] pub fn from_scale_angle(scale: {{ col_t }}, angle: {{ scalar_t }}) -> Self { let (sin, cos) = math::sin_cos(angle); Self::new(cos * scale.x, sin * scale.x, -sin * scale.y, cos * scale.y) } /// Creates a {{ nxn }} matrix containing a rotation of `angle` (in radians). #[inline] #[must_use] pub fn from_angle(angle: {{ scalar_t }}) -> Self { let (sin, cos) = math::sin_cos(angle); Self::new(cos, sin, -sin, cos) } /// Creates a {{ nxn }} matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3(m: {{ mat3_t }}) -> Self { Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } {{ macros::impl_mat3_minor(mat3_t=mat3_t) }} {% if scalar_t == "f32" %} /// Creates a {{ nxn }} matrix from a 3x3 matrix, discarding the 2nd row and column. #[inline] #[must_use] pub fn from_mat3a(m: Mat3A) -> Self { {# TODO: SIMD optimise #} Self::from_cols(m.x_axis.xy(), m.y_axis.xy()) } {{ macros::impl_mat3_minor(mat3_t="Mat3A", align="a") }} {% endif %} {% elif dim == 3 %} /// Creates a 3x3 matrix from a 4x4 matrix, discarding the 4th row and column. #[inline] #[must_use] pub fn from_mat4(m: {{ mat4_t }}) -> Self { Self::from_cols( {{ col_t }}::from_vec4(m.x_axis), {{ col_t }}::from_vec4(m.y_axis), {{ col_t }}::from_vec4(m.z_axis), ) } {{ macros::impl_mat4_minor(mat4_t=mat4_t, vec3_t=col_t) }} /// Creates a 3D rotation matrix from the given quaternion. /// /// # Panics /// /// Will panic if `rotation` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_quat(rotation: {{ quat_t }}) -> Self { glam_assert!(rotation.is_normalized()); let x2 = rotation.x + rotation.x; let y2 = rotation.y + rotation.y; let z2 = rotation.z + rotation.z; let xx = rotation.x * x2; let xy = rotation.x * y2; let xz = rotation.x * z2; let yy = rotation.y * y2; let yz = rotation.y * z2; let zz = rotation.z * z2; let wx = rotation.w * x2; let wy = rotation.w * y2; let wz = rotation.w * z2; Self::from_cols( {{ col_t }}::new(1.0 - (yy + zz), xy + wz, xz - wy), {{ col_t }}::new(xy - wz, 1.0 - (xx + zz), yz + wx), {{ col_t }}::new(xz + wy, yz - wx, 1.0 - (xx + yy)), ) } /// Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in /// radians). /// /// # Panics /// /// Will panic if `axis` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_axis_angle(axis: {{ vec3_t }}, angle: {{ scalar_t }}) -> Self { {# TODO: make common with dim == 4 #} glam_assert!(axis.is_normalized()); 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(); let omc = 1.0 - cos; let xyomc = x * y * omc; let xzomc = x * z * omc; let yzomc = y * z * omc; Self::from_cols( {{ col_t }}::new(x2 * omc + cos, xyomc + zsin, xzomc - ysin), {{ col_t }}::new(xyomc - zsin, y2 * omc + cos, yzomc + xsin), {{ col_t }}::new(xzomc + ysin, yzomc - xsin, z2 * omc + cos), ) } /// 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: {{ scalar_t }}, b: {{ scalar_t }}, c: {{ scalar_t }}) -> Self { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the input matrix contains scales, shears, or other non-rotation transformations then /// the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> ({{ scalar_t }}, {{ scalar_t }}, {{ scalar_t }}) { glam_assert!(self.x_axis.is_normalized() && self.y_axis.is_normalized() && self.z_axis.is_normalized()); self.to_euler_angles(order) } /// Creates a 3D rotation matrix from `angle` (in radians) around the x axis. #[inline] #[must_use] pub fn from_rotation_x(angle: {{ scalar_t }}) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::X, {{ col_t }}::new(0.0, cosa, sina), {{ col_t }}::new(0.0, -sina, cosa), ) } /// Creates a 3D rotation matrix from `angle` (in radians) around the y axis. #[inline] #[must_use] pub fn from_rotation_y(angle: {{ scalar_t }}) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::new(cosa, 0.0, -sina), {{ col_t }}::Y, {{ col_t }}::new(sina, 0.0, cosa), ) } /// Creates a 3D rotation matrix from `angle` (in radians) around the z axis. #[inline] #[must_use] pub fn from_rotation_z(angle: {{ scalar_t }}) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::new(cosa, sina, 0.0), {{ col_t }}::new(-sina, cosa, 0.0), {{ col_t }}::Z, ) } /// Creates an affine transformation matrix from the given 2D `translation`. /// /// 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_t }}) -> Self { Self::from_cols( {{ col_t }}::X, {{ col_t }}::Y, {{ col_t }}::new(translation.x, translation.y, 1.0)) } /// Creates an affine transformation matrix from the given 2D rotation `angle` (in /// radians). /// /// 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: {{ scalar_t }}) -> Self { let (sin, cos) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::new(cos, sin, 0.0), {{ col_t }}::new(-sin, cos, 0.0), {{ col_t }}::Z, ) } /// Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in /// radians) and `translation`. /// /// 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_t }}, angle: {{ scalar_t }}, translation: {{ vec2_t }}) -> Self { let (sin, cos) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::new(cos * scale.x, sin * scale.x, 0.0), {{ col_t }}::new(-sin * scale.y, cos * scale.y, 0.0), {{ col_t }}::new(translation.x, translation.y, 1.0), ) } /// Creates an affine transformation matrix from the given non-uniform 2D `scale`. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. /// /// # Panics /// /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_scale(scale: {{ vec2_t }}) -> Self { // Do not panic as long as any component is non-zero glam_assert!(scale.cmpne({{ vec2_t }}::ZERO).any()); Self::from_cols( {{ col_t }}::new(scale.x, 0.0, 0.0), {{ col_t }}::new(0.0, scale.y, 0.0), {{ col_t }}::Z, ) } /// Creates an affine transformation matrix from the given 2x2 matrix. /// /// The resulting matrix can be used to transform 2D points and vectors. See /// [`Self::transform_point2()`] and [`Self::transform_vector2()`]. #[inline] pub fn from_mat2(m: {{ mat2_t }}) -> Self { Self::from_cols((m.x_axis, 0.0).into(), (m.y_axis, 0.0).into(), {{ col_t }}::Z) } {% elif dim == 4 %} #[inline] #[must_use] fn quat_to_axes(rotation: {{ quat_t }}) -> ({{ col_t }}, {{ col_t }}, {{ col_t }}) { glam_assert!(rotation.is_normalized()); let (x, y, z, w) = rotation.into(); let x2 = x + x; let y2 = y + y; let z2 = z + z; let xx = x * x2; let xy = x * y2; let xz = x * z2; let yy = y * y2; let yz = y * z2; let zz = z * z2; let wx = w * x2; let wy = w * y2; let wz = w * z2; let x_axis = {{ col_t }}::new(1.0 - (yy + zz), xy + wz, xz - wy, 0.0); let y_axis = {{ col_t }}::new(xy - wz, 1.0 - (xx + zz), yz + wx, 0.0); let z_axis = {{ col_t }}::new(xz + wy, yz - wx, 1.0 - (xx + yy), 0.0); (x_axis, y_axis, z_axis) } /// Creates an affine transformation matrix from the given 3D `scale`, `rotation` and /// `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// Will panic if `rotation` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_scale_rotation_translation( scale: {{ vec3_t }}, rotation: {{ quat_t }}, translation: {{ vec3_t }}, ) -> Self { let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation); Self::from_cols( x_axis.mul(scale.x), y_axis.mul(scale.y), z_axis.mul(scale.z), {{ col_t }}::from((translation, 1.0)), ) } /// Creates an affine transformation matrix from the given 3D `translation`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// Will panic if `rotation` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_rotation_translation(rotation: {{ quat_t }}, translation: {{ vec3_t }}) -> Self { let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation); Self::from_cols(x_axis, y_axis, z_axis, {{ col_t }}::from((translation, 1.0))) } /// Extracts `scale`, `rotation` and `translation` from `self`. The input matrix is /// expected to be a 3D affine transformation matrix otherwise the output will be invalid. /// /// # Panics /// /// 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_t }}, {{ quat_t }}, {{ vec3_t }}) { let det = self.determinant(); glam_assert!(det != 0.0); let scale = {{ vec3_t }}::new( self.x_axis.length() * math::signum(det), self.y_axis.length(), self.z_axis.length(), ); glam_assert!(scale.cmpne({{ vec3_t }}::ZERO).all()); let inv_scale = scale.recip(); let rotation = {{ quat_t }}::from_rotation_axes( self.x_axis.mul(inv_scale.x).xyz(), self.y_axis.mul(inv_scale.y).xyz(), self.z_axis.mul(inv_scale.z).xyz(), ); let translation = self.w_axis.xyz(); (scale, rotation, translation) } /// Creates an affine transformation matrix from the given `rotation` quaternion. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// Will panic if `rotation` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_quat(rotation: {{ quat_t }}) -> Self { let (x_axis, y_axis, z_axis) = Self::quat_to_axes(rotation); Self::from_cols(x_axis, y_axis, z_axis, {{ col_t }}::W) } /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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_t }}) -> Self { Self::from_cols( {{ col_t }}::from((m.x_axis, 0.0)), {{ col_t }}::from((m.y_axis, 0.0)), {{ col_t }}::from((m.z_axis, 0.0)), {{ col_t }}::W, ) } /// Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and /// rotation) and a translation vector. /// /// Equivalent to `{{ self_t }}::from_translation(translation) * {{ self_t }}::from_mat3(mat3)` #[inline] #[must_use] pub fn from_mat3_translation(mat3: {{ mat3_t }}, translation: {{ vec3_t }}) -> Self { Self::from_cols( {{ col_t }}::from((mat3.x_axis, 0.0)), {{ col_t }}::from((mat3.y_axis, 0.0)), {{ col_t }}::from((mat3.z_axis, 0.0)), {{ col_t }}::from((translation, 1.0)), ) } {% if scalar_t == "f32" %} /// Creates an affine transformation matrix from the given 3x3 linear transformation /// matrix. /// /// 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)), Vec4::from((m.y_axis, 0.0)), Vec4::from((m.z_axis, 0.0)), Vec4::W, ) } {% endif %} /// Creates an affine transformation matrix from the given 3D `translation`. /// /// 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_t }}) -> Self { Self::from_cols( {{ col_t }}::X, {{ col_t }}::Y, {{ col_t }}::Z, {{ col_t }}::new(translation.x, translation.y, translation.z, 1.0), ) } /// Creates an affine transformation matrix containing a 3D rotation around a normalized /// rotation `axis` of `angle` (in radians). /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// Will panic if `axis` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_axis_angle(axis: {{ vec3_t }}, angle: {{ scalar_t }}) -> Self { {# TODO: make common with dim == 3 #} glam_assert!(axis.is_normalized()); let (sin, cos) = math::sin_cos(angle); let axis_sin = axis.mul(sin); let axis_sq = axis.mul(axis); let omc = 1.0 - cos; let xyomc = axis.x * axis.y * omc; let xzomc = axis.x * axis.z * omc; let yzomc = axis.y * axis.z * omc; Self::from_cols( {{ col_t }}::new( axis_sq.x * omc + cos, xyomc + axis_sin.z, xzomc - axis_sin.y, 0.0, ), {{ col_t }}::new( xyomc - axis_sin.z, axis_sq.y * omc + cos, yzomc + axis_sin.x, 0.0, ), {{ col_t }}::new( xzomc + axis_sin.y, yzomc - axis_sin.x, axis_sq.z * omc + cos, 0.0, ), {{ col_t }}::W, ) } /// 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: {{ scalar_t }}, b: {{ scalar_t }}, c: {{ scalar_t }}) -> Self { Self::from_euler_angles(order, a, b, c) } /// Extract Euler angles with the given Euler rotation order. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting Euler angles will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn to_euler(&self, order: EulerRot) -> ({{ scalar_t }}, {{ scalar_t }}, {{ scalar_t }}) { glam_assert!(self.x_axis.xyz().is_normalized() && self.y_axis.xyz().is_normalized() && self.z_axis.xyz().is_normalized()); self.to_euler_angles(order) } /// Creates an affine transformation matrix containing a 3D rotation around the x axis of /// `angle` (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_rotation_x(angle: {{ scalar_t }}) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::X, {{ col_t }}::new(0.0, cosa, sina, 0.0), {{ col_t }}::new(0.0, -sina, cosa, 0.0), {{ col_t }}::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the y axis of /// `angle` (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_rotation_y(angle: {{ scalar_t }}) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::new(cosa, 0.0, -sina, 0.0), {{ col_t }}::Y, {{ col_t }}::new(sina, 0.0, cosa, 0.0), {{ col_t }}::W, ) } /// Creates an affine transformation matrix containing a 3D rotation around the z axis of /// `angle` (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_rotation_z(angle: {{ scalar_t }}) -> Self { let (sina, cosa) = math::sin_cos(angle); Self::from_cols( {{ col_t }}::new(cosa, sina, 0.0, 0.0), {{ col_t }}::new(-sina, cosa, 0.0, 0.0), {{ col_t }}::Z, {{ col_t }}::W, ) } /// Creates an affine transformation matrix containing the given 3D non-uniform `scale`. /// /// The resulting matrix can be used to transform 3D points and vectors. See /// [`Self::transform_point3()`] and [`Self::transform_vector3()`]. /// /// # Panics /// /// Will panic if all elements of `scale` are zero when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_scale(scale: {{ vec3_t }}) -> Self { // Do not panic as long as any component is non-zero glam_assert!(scale.cmpne({{ vec3_t }}::ZERO).any()); Self::from_cols( {{ col_t }}::new(scale.x, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, scale.y, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, scale.z, 0.0), {{ col_t }}::W, ) } {% endif %} /// Creates a {{ nxn }} matrix from the first {{ size }} values in `slice`. /// /// # Panics /// /// Panics if `slice` is less than {{ size }} elements long. #[inline] #[must_use] pub const fn from_cols_slice(slice: &[{{ scalar_t }}]) -> Self { Self::new( {% for i in range(end = size) %} slice[{{ i }}], {%- endfor %} ) } /// Writes the columns of `self` to the first {{ size }} elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than {{ size }} elements long. #[inline] pub fn write_cols_to_slice(self, slice: &mut [{{ scalar_t }}]) { {% for i in range(end = dim) %} {%- for j in range(end = dim) %} slice[{{ i * dim + j }}] = self.{{ axes[i] }}.{{ components[j] }}; {%- endfor %} {%- endfor %} } /// Returns the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than {{ dim - 1 }}. #[inline] #[must_use] pub fn col(&self, index: usize) -> {{ col_t }} { match index { {% for axis in axes %} {{ loop.index0 }} => self.{{ axis }}, {%- endfor %} _ => panic!("index out of bounds"), } } /// Returns a mutable reference to the matrix column for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than {{ dim - 1 }}. #[inline] pub fn col_mut(&mut self, index: usize) -> &mut {{ col_t }} { match index { {% for axis in axes %} {{ loop.index0 }} => &mut self.{{ axis }}, {%- endfor %} _ => panic!("index out of bounds"), } } /// Returns the matrix row for the given `index`. /// /// # Panics /// /// Panics if `index` is greater than {{ dim - 1 }}. #[inline] #[must_use] pub fn row(&self, index: usize) -> {{ col_t }} { match index { {% for i in range(end=dim) %} {{ i }} => {{ col_t }}::new( {% for axis in axes %} self.{{ axis }}.{{ components[i] }}, {%- endfor %} ), {%- endfor %} _ => panic!("index out of bounds"), } } /// 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 { {% for axis in axes %} self.{{ axis }}.is_finite() {% if not loop.last %} && {% endif %} {% endfor %} } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(&self) -> bool { {% for axis in axes %} self.{{ axis }}.is_nan() {% if not loop.last %} || {% endif %} {% endfor %} } /// Returns the transpose of `self`. #[inline] #[must_use] pub fn transpose(&self) -> Self { {% if self_t == "Mat2" and is_sse2 %} Self(unsafe { _mm_shuffle_ps(self.0, self.0, 0b11_01_10_00) }) {% elif self_t == "Mat2" and is_wasm32 %} Self(i32x4_shuffle::<0, 2, 5, 7>(self.0, self.0)) {% elif self_t == "Mat2" and is_coresimd %} Self(simd_swizzle!(self.0, [0, 2, 1, 3])) {% elif self_t == "Mat2" and is_neon %} Self(unsafe { vsetq_lane_f32( vgetq_lane_f32(self.0, 2), vsetq_lane_f32(vgetq_lane_f32(self.0, 1), self.0, 2), 1, ) }) {% elif self_t == "Mat3A" and is_sse2 %} unsafe { let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00); let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10); Self { x_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b00_00_10_00)), y_axis: Vec3A(_mm_shuffle_ps(tmp0, self.z_axis.0, 0b01_01_11_01)), z_axis: Vec3A(_mm_shuffle_ps(tmp1, self.z_axis.0, 0b10_10_10_00)), } } {% elif self_t == "Mat3A" and is_wasm32 %} 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); Self { x_axis: Vec3A(i32x4_shuffle::<0, 2, 4, 4>(tmp0, self.z_axis.0)), y_axis: Vec3A(i32x4_shuffle::<1, 3, 5, 5>(tmp0, self.z_axis.0)), z_axis: Vec3A(i32x4_shuffle::<0, 2, 6, 6>(tmp1, self.z_axis.0)), } {% elif self_t == "Mat3A" and is_coresimd %} 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, [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] )), } {% elif self_t == "Mat3A" and is_neon %} let x = self.x_axis.0; let y = self.y_axis.0; let z = self.z_axis.0; unsafe { let tmp0 = vreinterpretq_f32_u64(vsetq_lane_u64( vgetq_lane_u64(vreinterpretq_u64_f32(y), 0), vreinterpretq_u64_f32(x), 1, )); let tmp1 = vreinterpretq_f32_u64(vzip2q_u64( vreinterpretq_u64_f32(x), vreinterpretq_u64_f32(y), )); Mat3A::from_cols( Vec3A::from(vsetq_lane_f32(vgetq_lane_f32(z, 0), vuzp1q_f32(tmp0, z), 3)), Vec3A::from(vuzp2q_f32(tmp0, vdupq_laneq_f32(z, 1))), Vec3A::from(vsetq_lane_f32(vgetq_lane_f32(z, 2), vuzp1q_f32(tmp1, z), 2)), ) } {% elif self_t == "Mat4" and is_sse2 %} unsafe { // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose` let tmp0 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b01_00_01_00); let tmp1 = _mm_shuffle_ps(self.x_axis.0, self.y_axis.0, 0b11_10_11_10); let tmp2 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b01_00_01_00); let tmp3 = _mm_shuffle_ps(self.z_axis.0, self.w_axis.0, 0b11_10_11_10); Self { x_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b10_00_10_00)), y_axis: Vec4(_mm_shuffle_ps(tmp0, tmp2, 0b11_01_11_01)), z_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b10_00_10_00)), w_axis: Vec4(_mm_shuffle_ps(tmp1, tmp3, 0b11_01_11_01)), } } {% elif self_t == "Mat4" and is_wasm32 %} // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose` 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); let tmp2 = i32x4_shuffle::<0, 1, 4, 5>(self.z_axis.0, self.w_axis.0); let tmp3 = i32x4_shuffle::<2, 3, 6, 7>(self.z_axis.0, self.w_axis.0); Self { x_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp0, tmp2)), y_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp0, tmp2)), z_axis: Vec4(i32x4_shuffle::<0, 2, 4, 6>(tmp1, tmp3)), w_axis: Vec4(i32x4_shuffle::<1, 3, 5, 7>(tmp1, tmp3)), } {% elif self_t == "Mat4" and is_coresimd %} // Based on https://github.com/microsoft/DirectXMath `XMMatrixTranspose` 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, [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])), } {% else %} Self { {% for i in range(end = dim) %} {{ axes[i] }}: {{ col_t }}::new( {% for j in range(end = dim) %} self.{{ axes[j] }}.{{ components[i] }}, {% endfor %} ), {%- endfor %} } {% endif %} } /// Returns the determinant of `self`. {%- if dim < 4 %} #[inline] {%- endif %} #[must_use] pub fn determinant(&self) -> {{ scalar_t }} { {% if self_t == "Mat2" and is_sse2 %} unsafe { let abcd = self.0; let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11); let prod = _mm_mul_ps(abcd, dcba); let det = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01)); _mm_cvtss_f32(det) } {% elif self_t == "Mat2" and is_wasm32 %} let abcd = self.0; let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd); let prod = f32x4_mul(abcd, dcba); let det = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod)); f32x4_extract_lane::<0>(det) {% elif self_t == "Mat2" and is_coresimd %} let abcd = self.0; let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]); let prod = abcd * dcba; let det = prod - simd_swizzle!(prod, [1, 1, 1, 1]); det[0] {% elif self_t == "Mat2" and is_neon %} unsafe { let abcd = self.0; let badc = vrev64q_f32(abcd); let dcba = vextq_f32(badc, badc, 2); let prod = vmulq_f32(abcd, dcba); let det = vsubq_f32(prod, vdupq_laneq_f32(prod, 1)); vgetq_lane_f32(det, 0) } {% elif self_t == "Mat4" and is_sse2 %} unsafe { // Based on https://github.com/g-truc/glm `glm_mat4_determinant_lowp` let swp2a = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_01_01_10); let swp3a = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b11_10_11_11); let swp2b = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b11_10_11_11); let swp3b = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b00_01_01_10); let swp2c = _mm_shuffle_ps(self.z_axis.0, self.z_axis.0, 0b00_00_01_10); let swp3c = _mm_shuffle_ps(self.w_axis.0, self.w_axis.0, 0b01_10_00_00); let mula = _mm_mul_ps(swp2a, swp3a); let mulb = _mm_mul_ps(swp2b, swp3b); let mulc = _mm_mul_ps(swp2c, swp3c); let sube = _mm_sub_ps(mula, mulb); let subf = _mm_sub_ps(_mm_movehl_ps(mulc, mulc), mulc); let subfaca = _mm_shuffle_ps(sube, sube, 0b10_01_00_00); let swpfaca = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b00_00_00_01); let mulfaca = _mm_mul_ps(swpfaca, subfaca); let subtmpb = _mm_shuffle_ps(sube, subf, 0b00_00_11_01); let subfacb = _mm_shuffle_ps(subtmpb, subtmpb, 0b11_01_01_00); let swpfacb = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b01_01_10_10); let mulfacb = _mm_mul_ps(swpfacb, subfacb); let subres = _mm_sub_ps(mulfaca, mulfacb); let subtmpc = _mm_shuffle_ps(sube, subf, 0b01_00_10_10); let subfacc = _mm_shuffle_ps(subtmpc, subtmpc, 0b11_11_10_00); let swpfacc = _mm_shuffle_ps(self.y_axis.0, self.y_axis.0, 0b10_11_11_11); let mulfacc = _mm_mul_ps(swpfacc, subfacc); let addres = _mm_add_ps(subres, mulfacc); let detcof = _mm_mul_ps(addres, _mm_setr_ps(1.0, -1.0, 1.0, -1.0)); dot4(self.x_axis.0, detcof) } {% elif self_t == "Mat4" and is_wasm32 %} // 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); let swp3a = i32x4_shuffle::<3, 3, 2, 3>(self.w_axis.0, self.w_axis.0); let swp2b = i32x4_shuffle::<3, 3, 2, 3>(self.z_axis.0, self.z_axis.0); let swp3b = i32x4_shuffle::<2, 1, 1, 0>(self.w_axis.0, self.w_axis.0); let swp2c = i32x4_shuffle::<2, 1, 0, 0>(self.z_axis.0, self.z_axis.0); let swp3c = i32x4_shuffle::<0, 0, 2, 1>(self.w_axis.0, self.w_axis.0); let mula = f32x4_mul(swp2a, swp3a); let mulb = f32x4_mul(swp2b, swp3b); let mulc = f32x4_mul(swp2c, swp3c); let sube = f32x4_sub(mula, mulb); let subf = f32x4_sub(i32x4_shuffle::<6, 7, 2, 3>(mulc, mulc), mulc); let subfaca = i32x4_shuffle::<0, 0, 1, 2>(sube, sube); let swpfaca = i32x4_shuffle::<1, 0, 0, 0>(self.y_axis.0, self.y_axis.0); let mulfaca = f32x4_mul(swpfaca, subfaca); let subtmpb = i32x4_shuffle::<1, 3, 4, 4>(sube, subf); let subfacb = i32x4_shuffle::<0, 1, 1, 3>(subtmpb, subtmpb); let swpfacb = i32x4_shuffle::<2, 2, 1, 1>(self.y_axis.0, self.y_axis.0); let mulfacb = f32x4_mul(swpfacb, subfacb); let subres = f32x4_sub(mulfaca, mulfacb); let subtmpc = i32x4_shuffle::<2, 2, 4, 5>(sube, subf); let subfacc = i32x4_shuffle::<0, 2, 3, 3>(subtmpc, subtmpc); let swpfacc = i32x4_shuffle::<3, 3, 3, 2>(self.y_axis.0, self.y_axis.0); let mulfacc = f32x4_mul(swpfacc, subfacc); let addres = f32x4_add(subres, mulfacc); let detcof = f32x4_mul(addres, f32x4(1.0, -1.0, 1.0, -1.0)); dot4(self.x_axis.0, detcof) {% elif self_t == "Mat4" and is_coresimd %} // Based on https://github.com/g-truc/glm `glm_mat4_determinant` let swp2a = simd_swizzle!(self.z_axis.0, [2, 1, 1, 0]); let swp3a = simd_swizzle!(self.w_axis.0, [3, 3, 2, 3]); let swp2b = simd_swizzle!(self.z_axis.0, [3, 3, 2, 3]); let swp3b = simd_swizzle!(self.w_axis.0, [2, 1, 1, 0]); let swp2c = simd_swizzle!(self.z_axis.0, [2, 1, 0, 0]); let swp3c = simd_swizzle!(self.w_axis.0, [0, 0, 2, 1]); let mula = swp2a * swp3a; let mulb = swp2b * swp3b; let mulc = swp2c * swp3c; let sube = mula - mulb; let subf = simd_swizzle!(mulc, [2, 3, 2, 3]) - mulc; let subfaca = simd_swizzle!(sube, [0, 0, 1, 2]); let swpfaca = simd_swizzle!(self.y_axis.0, [1, 0, 0, 0]); let mulfaca = swpfaca * subfaca; 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, [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; let addres = subres + mulfacc; let detcof = addres * f32x4::from_array([1.0, -1.0, 1.0, -1.0]); dot4(self.x_axis.0, detcof) {# // neon implementation is slower than scalar // {% elif self_t == "Mat4" and is_neon %} // unsafe { // let swizz2110 = |x| { // let x = vuzp1q_f32(x, vdupq_laneq_f32(x, 1)); // vextq_f32(x, x, 1) // }; // let swizz3323 = |x| { // let xy = vgetq_lane_f32(x, 3); // vsetq_lane_f32(xy, vsetq_lane_f32(xy, x, 0), 1) // }; // let swizz2100 = |x| { // let y = vuzp1q_f32(x, x); // vuzp1q_f32(vextq_f32(x, y, 3), y) // }; // let swizz0021 = |x| vtrn1q_f32(x, vzip1q_f32(x, x)); // // let swizz6723 = |x, y| { // // vsetq_lane_f64(vgetq_lane_f64(y, 1), 0) // // }; // let swizz2323 = |x| vreinterpretq_f32_f64(vdupq_laneq_f64(vreinterpretq_f64_f32(x), 1)); // let swizz0012 = |x| vzip1q_f32(x, vuzp1q_f32(x, x)); // let swizz1000 = |x| vsetq_lane_f32(vgetq_lane_f32(x, 1), vdupq_laneq_f32(x, 0), 0); // let swizz1344 = |x, y| vuzp2q_f32(x, vdupq_laneq_f32(y, 0)); // let swizz0113 = |x| vsetq_lane_f32(vgetq_lane_f32(x, 1), x, 2); // let swizz2211 = |x| { // let x = vsetq_lane_f32(vgetq_lane_f32(x, 1), x, 3); // vzip2q_f32(x, x) // }; // let swizz2245 = |x, y| vextq_f32(vtrn1q_f32(x, x), y, 1); // let swizz0233 = |x| vuzp1q_f32(x, vdupq_laneq_f32(x, 3)); // let swizz3332 = |x| vsetq_lane_f32(vgetq_lane_f32(x, 2), vdupq_laneq_f32(x, 3), 3); // // Based on https://github.com/g-truc/glm `glm_mat4_determinant` // let swp2a = swizz2110(self.z_axis.0); // let swp3a = swizz3323(self.w_axis.0); // let swp2b = swizz3323(self.z_axis.0); // let swp3b = swizz2110(self.w_axis.0); // let swp2c = swizz2100(self.z_axis.0); // let swp3c = swizz0021(self.w_axis.0); // let mula = vmulq_f32(swp2a, swp3a); // let mulb = vmulq_f32(swp2b, swp3b); // let mulc = vmulq_f32(swp2c, swp3c); // let sube = vsubq_f32(mula, mulb); // let subf = vsubq_f32(swizz2323(mulc), mulc); // let subfaca = swizz0012(sube); // let swpfaca = swizz1000(self.y_axis.0); // let mulfaca = vmulq_f32(swpfaca, subfaca); // let subtmpb = swizz1344(sube, subf); // let subfacb = swizz0113(subtmpb); // let swpfacb = swizz2211(self.y_axis.0); // let mulfacb = vmulq_f32(swpfacb, subfacb); // let subres = vsubq_f32(mulfaca, mulfacb); // let subtmpc = swizz2245(sube, subf); // let subfacc = swizz0233(subtmpc); // let swpfacc = swizz3332(self.y_axis.0); // let mulfacc = vmulq_f32(swpfacc, subfacc); // let addres = vaddq_f32(subres, mulfacc); // const COF: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0; // let detcof = vmulq_f32(addres, COF); // dot4(self.x_axis.0, detcof) // } #} {% elif dim == 2 %} self.x_axis.x * self.y_axis.y - self.x_axis.y * self.y_axis.x {% elif dim == 3 %} self.z_axis.dot(self.x_axis.cross(self.y_axis)) {% elif dim == 4 %} let (m00, m01, m02, m03) = self.x_axis.into(); let (m10, m11, m12, m13) = self.y_axis.into(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let a2323 = m22 * m33 - m23 * m32; let a1323 = m21 * m33 - m23 * m31; let a1223 = m21 * m32 - m22 * m31; let a0323 = m20 * m33 - m23 * m30; let a0223 = m20 * m32 - m22 * m30; let a0123 = m20 * m31 - m21 * m30; m00 * (m11 * a2323 - m12 * a1323 + m13 * a1223) - m01 * (m10 * a2323 - m12 * a0323 + m13 * a0223) + m02 * (m10 * a1323 - m11 * a0323 + m13 * a0123) - m03 * (m10 * a1223 - m11 * a0223 + m12 * a0123) {% endif %} } /// Returns the inverse of `self`. /// /// If the matrix is not invertible the returned matrix will be invalid. /// /// # Panics /// /// Will panic if the determinant of `self` is zero when `glam_assert` is enabled. {%- if dim < 4 %} #[inline] {%- endif %} #[must_use] pub fn inverse(&self) -> Self { {% if self_t == "Mat2" and is_sse2 %} unsafe { const SIGN: __m128 = crate::sse2::m128_from_f32x4([1.0, -1.0, -1.0, 1.0]); let abcd = self.0; let dcba = _mm_shuffle_ps(abcd, abcd, 0b00_01_10_11); let prod = _mm_mul_ps(abcd, dcba); let sub = _mm_sub_ps(prod, _mm_shuffle_ps(prod, prod, 0b01_01_01_01)); let det = _mm_shuffle_ps(sub, sub, 0b00_00_00_00); let tmp = _mm_div_ps(SIGN, det); glam_assert!(Mat2(tmp).is_finite()); let dbca = _mm_shuffle_ps(abcd, abcd, 0b00_10_01_11); Self(_mm_mul_ps(dbca, tmp)) } {% elif self_t == "Mat2" and is_wasm32 %} const SIGN: v128 = crate::wasm32::v128_from_f32x4([1.0, -1.0, -1.0, 1.0]); let abcd = self.0; let dcba = i32x4_shuffle::<3, 2, 5, 4>(abcd, abcd); let prod = f32x4_mul(abcd, dcba); let sub = f32x4_sub(prod, i32x4_shuffle::<1, 1, 5, 5>(prod, prod)); let det = i32x4_shuffle::<0, 0, 4, 4>(sub, sub); let tmp = f32x4_div(SIGN, det); glam_assert!(Mat2(tmp).is_finite()); let dbca = i32x4_shuffle::<3, 1, 6, 4>(abcd, abcd); Self(f32x4_mul(dbca, tmp)) {% elif self_t == "Mat2" and is_coresimd %} const SIGN: f32x4 = f32x4::from_array([1.0, -1.0, -1.0, 1.0]); let abcd = self.0; let dcba = simd_swizzle!(abcd, [3, 2, 1, 0]); let prod = abcd * dcba; let sub = prod - simd_swizzle!(prod, [1, 1, 1, 1]); let det = simd_swizzle!(sub, [0, 0, 0, 0]); let tmp = SIGN / det; glam_assert!(Mat2(tmp).is_finite()); let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]); Self(dbca.mul(tmp)) {% elif self_t == "Mat2" and is_neon %} unsafe { const SIGN: float32x4_t = crate::neon::f32x4_from_array([1.0, -1.0, -1.0, 1.0]); let abcd = self.0; let badc = vrev64q_f32(abcd); let dcba = vextq_f32(badc, badc, 2); let prod = vmulq_f32(abcd, dcba); let sub = vsubq_f32(prod, vdupq_laneq_f32(prod, 1)); let det = vdupq_laneq_f32(sub, 0); let tmp = vdivq_f32(SIGN, det); glam_assert!(Mat2(tmp).is_finite()); //let dbca = simd_swizzle!(abcd, [3, 1, 2, 0]); let dbca = vsetq_lane_f32( vgetq_lane_f32(abcd, 0), vsetq_lane_f32(vgetq_lane_f32(abcd, 3), abcd, 0), 3, ); Self(vmulq_f32(dbca, tmp)) } {% elif self_t == "Mat4" and is_sse2 %} {{ sse2::impl_mat4_inverse() }} {% elif self_t == "Mat4" and is_wasm32 %} {{ wasm32::impl_mat4_inverse() }} {% elif self_t == "Mat4" and is_coresimd %} {{ coresimd::impl_mat4_inverse() }} {% elif self_t == "Mat4" and is_neon %} {{ neon::impl_mat4_inverse() }} {% elif dim == 2 %} let inv_det = { let det = self.determinant(); glam_assert!(det != 0.0); det.recip() }; Self::new( self.y_axis.y * inv_det, self.x_axis.y * -inv_det, self.y_axis.x * -inv_det, self.x_axis.x * inv_det, ) {% elif dim == 3 %} let tmp0 = self.y_axis.cross(self.z_axis); let tmp1 = self.z_axis.cross(self.x_axis); let tmp2 = self.x_axis.cross(self.y_axis); let det = self.z_axis.dot(tmp2); glam_assert!(det != 0.0); let inv_det = {{ col_t }}::splat(det.recip()); Self::from_cols(tmp0.mul(inv_det), tmp1.mul(inv_det), tmp2.mul(inv_det)).transpose() {% elif dim == 4 %} let (m00, m01, m02, m03) = self.x_axis.into(); let (m10, m11, m12, m13) = self.y_axis.into(); let (m20, m21, m22, m23) = self.z_axis.into(); let (m30, m31, m32, m33) = self.w_axis.into(); let coef00 = m22 * m33 - m32 * m23; let coef02 = m12 * m33 - m32 * m13; let coef03 = m12 * m23 - m22 * m13; let coef04 = m21 * m33 - m31 * m23; let coef06 = m11 * m33 - m31 * m13; let coef07 = m11 * m23 - m21 * m13; let coef08 = m21 * m32 - m31 * m22; let coef10 = m11 * m32 - m31 * m12; let coef11 = m11 * m22 - m21 * m12; let coef12 = m20 * m33 - m30 * m23; let coef14 = m10 * m33 - m30 * m13; let coef15 = m10 * m23 - m20 * m13; let coef16 = m20 * m32 - m30 * m22; let coef18 = m10 * m32 - m30 * m12; let coef19 = m10 * m22 - m20 * m12; let coef20 = m20 * m31 - m30 * m21; let coef22 = m10 * m31 - m30 * m11; let coef23 = m10 * m21 - m20 * m11; let fac0 = {{ col_t }}::new(coef00, coef00, coef02, coef03); let fac1 = {{ col_t }}::new(coef04, coef04, coef06, coef07); let fac2 = {{ col_t }}::new(coef08, coef08, coef10, coef11); let fac3 = {{ col_t }}::new(coef12, coef12, coef14, coef15); let fac4 = {{ col_t }}::new(coef16, coef16, coef18, coef19); let fac5 = {{ col_t }}::new(coef20, coef20, coef22, coef23); let vec0 = {{ col_t }}::new(m10, m00, m00, m00); let vec1 = {{ col_t }}::new(m11, m01, m01, m01); let vec2 = {{ col_t }}::new(m12, m02, m02, m02); let vec3 = {{ col_t }}::new(m13, m03, m03, m03); let inv0 = vec1.mul(fac0).sub(vec2.mul(fac1)).add(vec3.mul(fac2)); let inv1 = vec0.mul(fac0).sub(vec2.mul(fac3)).add(vec3.mul(fac4)); let inv2 = vec0.mul(fac1).sub(vec1.mul(fac3)).add(vec3.mul(fac5)); let inv3 = vec0.mul(fac2).sub(vec1.mul(fac4)).add(vec2.mul(fac5)); let sign_a = {{ col_t }}::new(1.0, -1.0, 1.0, -1.0); let sign_b = {{ col_t }}::new(-1.0, 1.0, -1.0, 1.0); let inverse = Self::from_cols( inv0.mul(sign_a), inv1.mul(sign_b), inv2.mul(sign_a), inv3.mul(sign_b), ); let col0 = {{ col_t }}::new( inverse.x_axis.x, inverse.y_axis.x, inverse.z_axis.x, inverse.w_axis.x, ); let dot0 = self.x_axis.mul(col0); let dot1 = dot0.x + dot0.y + dot0.z + dot0.w; glam_assert!(dot1 != 0.0); let rcp_det = dot1.recip(); inverse.mul(rcp_det) {% endif %} } {% if dim == 3 %} /// Transforms the given 2D vector as a point. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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_t }}) -> {{ vec2_t }} { glam_assert!(self.row(2).abs_diff_eq({{ col_t }}::Z, 1e-6)); {{ mat2_t }}::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs + self.z_axis.xy() } /// Rotates the given 2D vector. /// /// This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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_t }}) -> {{ vec2_t }} { glam_assert!(self.row(2).abs_diff_eq({{ col_t }}::Z, 1e-6)); {{ mat2_t }}::from_cols(self.x_axis.xy(), self.y_axis.xy()) * rhs } /// Creates a left-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(-dir, up) } /// Creates a right-handed view matrix using a facing direction and an up direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( {{ col_t }}::new(s.x, u.x, -f.x), {{ col_t }}::new(s.y, u.y, -f.y), {{ col_t }}::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } {% elif dim == 4 %} /// Creates a left-handed view matrix using a camera position, a facing direction and an up /// direction /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(eye: {{ vec3_t }}, dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(eye, -dir, up) } /// Creates a right-handed view matrix using a camera position, a facing direction, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` or `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(eye: {{ vec3_t }}, dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_cols( {{ col_t }}::new(s.x, u.x, -f.x, 0.0), {{ col_t }}::new(s.y, u.y, -f.y, 0.0), {{ col_t }}::new(s.z, u.z, -f.z, 0.0), {{ col_t }}::new(-eye.dot(s), -eye.dot(u), eye.dot(f), 1.0), ) } /// Creates a left-handed view matrix using a camera position, a focal points and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_lh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(eye, center.sub(eye).normalize(), up) } /// Creates a right-handed perspective projection matrix with `[-1,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what OpenGL expects. /// /// This is the same as the OpenGL `gluPerspective` function. /// See #[inline] #[must_use] pub fn perspective_rh_gl( fov_y_radians: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}, z_far: {{ scalar_t }}, ) -> Self { let inv_length = 1.0 / (z_near - z_far); 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; Self::from_cols( {{ col_t }}::new(a, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, f, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, b, -1.0), {{ col_t }}::new(0.0, 0.0, c, 0.0), ) } /// Creates a left-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard left-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}, z_far: {{ scalar_t }}) -> Self { glam_assert!(z_near > 0.0 && z_far > 0.0); 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); Self::from_cols( {{ col_t }}::new(w, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, h, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, r, 1.0), {{ col_t }}::new(0.0, 0.0, -r * z_near, 0.0), ) } /// Creates a right-handed perspective projection matrix with `[0,1]` depth range. /// /// Useful to map the standard right-handed coordinate system into what WebGPU/Metal/Direct3D expect. /// /// # Panics /// /// 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: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}, z_far: {{ scalar_t }}) -> Self { glam_assert!(z_near > 0.0 && z_far > 0.0); 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); Self::from_cols( {{ col_t }}::new(w, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, h, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, r, -1.0), {{ col_t }}::new(0.0, 0.0, r * z_near, 0.0), ) } /// Creates an infinite left-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_lh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_lh(fov_y_radians: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}) -> Self { glam_assert!(z_near > 0.0); 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( {{ col_t }}::new(w, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, h, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, 1.0, 1.0), {{ col_t }}::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse left-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_lh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}, ) -> Self { glam_assert!(z_near > 0.0); 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( {{ col_t }}::new(w, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, h, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, 0.0, 1.0), {{ col_t }}::new(0.0, 0.0, z_near, 0.0), ) } /// Creates an infinite right-handed perspective projection matrix with `[0,1]` depth range. /// /// Like `perspective_rh`, but with an infinite value for `z_far`. /// The result is that points near `z_near` are mapped to depth `0`, and as they move towards infinity the depth approaches `1`. /// /// # Panics /// /// 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_infinite_rh(fov_y_radians: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}) -> Self { glam_assert!(z_near > 0.0); let f = 1.0 / math::tan(0.5 * fov_y_radians); Self::from_cols( {{ col_t }}::new(f / aspect_ratio, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, f, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, -1.0, -1.0), {{ col_t }}::new(0.0, 0.0, -z_near, 0.0), ) } /// Creates an infinite reverse right-handed perspective projection matrix with `[0,1]` depth range. /// /// Similar to `perspective_infinite_rh`, but maps `Z = z_near` to a depth of `1` and `Z = infinity` to a depth of `0`. /// /// # Panics /// /// 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_rh( fov_y_radians: {{ scalar_t }}, aspect_ratio: {{ scalar_t }}, z_near: {{ scalar_t }}, ) -> Self { glam_assert!(z_near > 0.0); let f = 1.0 / math::tan(0.5 * fov_y_radians); Self::from_cols( {{ col_t }}::new(f / aspect_ratio, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, f, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, 0.0, -1.0), {{ col_t }}::new(0.0, 0.0, z_near, 0.0), ) } /// Creates a right-handed orthographic projection matrix with `[-1,1]` depth /// range. This is the same as the OpenGL `glOrtho` function in OpenGL. /// See /// /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that OpenGL expects. #[inline] #[must_use] pub fn orthographic_rh_gl( left: {{ scalar_t }}, right: {{ scalar_t }}, bottom: {{ scalar_t }}, top: {{ scalar_t }}, near: {{ scalar_t }}, far: {{ scalar_t }}, ) -> Self { let a = 2.0 / (right - left); let b = 2.0 / (top - bottom); let c = -2.0 / (far - near); let tx = -(right + left) / (right - left); let ty = -(top + bottom) / (top - bottom); let tz = -(far + near) / (far - near); Self::from_cols( {{ col_t }}::new(a, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, b, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, c, 0.0), {{ col_t }}::new(tx, ty, tz, 1.0), ) } /// Creates a left-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a left-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_lh( left: {{ scalar_t }}, right: {{ scalar_t }}, bottom: {{ scalar_t }}, top: {{ scalar_t }}, near: {{ scalar_t }}, far: {{ scalar_t }}, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (far - near); Self::from_cols( {{ col_t }}::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, rcp_height + rcp_height, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, r, 0.0), {{ col_t }}::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, -r * near, 1.0, ), ) } /// Creates a right-handed orthographic projection matrix with `[0,1]` depth range. /// /// Useful to map a right-handed coordinate system to the normalized device coordinates that WebGPU/Direct3D/Metal expect. #[inline] #[must_use] pub fn orthographic_rh( left: {{ scalar_t }}, right: {{ scalar_t }}, bottom: {{ scalar_t }}, top: {{ scalar_t }}, near: {{ scalar_t }}, far: {{ scalar_t }}, ) -> Self { let rcp_width = 1.0 / (right - left); let rcp_height = 1.0 / (top - bottom); let r = 1.0 / (near - far); Self::from_cols( {{ col_t }}::new(rcp_width + rcp_width, 0.0, 0.0, 0.0), {{ col_t }}::new(0.0, rcp_height + rcp_height, 0.0, 0.0), {{ col_t }}::new(0.0, 0.0, r, 0.0), {{ col_t }}::new( -(left + right) * rcp_width, -(top + bottom) * rcp_height, r * near, 1.0, ), ) } /// Transforms the given 3D vector as a point, applying perspective correction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3(&self, rhs: {{ vec3_t }}) -> {{ vec3_t }} { let mut res = self.x_axis.mul(rhs.x); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res = res.div(res.w); res.xyz() } /// Transforms the given 3D vector as a point. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `1.0`. /// /// This method assumes that `self` contains a valid affine transform. It does not perform /// a perspective divide, if `self` contains a perspective transform, or if you are unsure, /// the [`Self::project_point3()`] method should be used instead. /// /// # Panics /// /// 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_t }}) -> {{ vec3_t }} { glam_assert!(self.row(3).abs_diff_eq({{ vec4_t }}::W, 1e-6)); let mut res = self.x_axis.mul(rhs.x); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res = self.w_axis.add(res); res.xyz() } /// Transforms the give 3D vector as a direction. /// /// This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is /// `0.0`. /// /// This method assumes that `self` contains a valid affine transform. /// /// # Panics /// /// 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_t }}) -> {{ vec3_t }} { glam_assert!(self.row(3).abs_diff_eq({{ vec4_t }}::W, 1e-6)); let mut res = self.x_axis.mul(rhs.x); res = self.y_axis.mul(rhs.y).add(res); res = self.z_axis.mul(rhs.z).add(res); res.xyz() } {% endif %} {% if self_t == "Mat4" %} /// Transforms the given [`Vec3A`] as a 3D point, applying perspective correction. /// /// This is the equivalent of multiplying the [`Vec3A`] as a 4D vector where `w` is `1.0`. /// The perspective divide is performed meaning the resulting 3D vector is divided by `w`. /// /// This method assumes that `self` contains a projective transform. #[inline] #[must_use] pub fn project_point3a(&self, rhs: Vec3A) -> Vec3A { {% if is_scalar %} self.project_point3(rhs.into()).into() {% else %} let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); res = res.div(res.wwww()); Vec3A::from_vec4(res) {% endif %} } /// Transforms the given [`Vec3A`] as 3D point. /// /// 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 { {% if is_scalar %} self.transform_point3(rhs.into()).into() {% else %} glam_assert!(self.row(3).abs_diff_eq({{ vec4_t }}::W, 1e-6)); let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); res = self.w_axis.add(res); Vec3A::from_vec4(res) {% endif %} } /// Transforms the give [`Vec3A`] as 3D vector. /// /// 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 { {% if is_scalar %} self.transform_vector3(rhs.into()).into() {% else %} glam_assert!(self.row(3).abs_diff_eq({{ vec4_t }}::W, 1e-6)); let mut res = self.x_axis.mul(rhs.xxxx()); res = self.y_axis.mul(rhs.yyyy()).add(res); res = self.z_axis.mul(rhs.zzzz()).add(res); Vec3A::from_vec4(res) {% endif %} } {% endif %} /// Transforms a {{ dim }}D vector. #[inline] #[must_use] pub fn mul_vec{{ dim }}(&self, rhs: {{ vecn_t }}) -> {{ vecn_t }} { {% if self_t == "Mat2" and is_sse2 %} unsafe { use core::mem::MaybeUninit; use crate::Align16; let abcd = self.0; let xxyy = _mm_set_ps(rhs.y, rhs.y, rhs.x, rhs.x); let axbxcydy = _mm_mul_ps(abcd, xxyy); let cydyaxbx = _mm_shuffle_ps(axbxcydy, axbxcydy, 0b01_00_11_10); let result = _mm_add_ps(axbxcydy, cydyaxbx); let mut out: MaybeUninit> = MaybeUninit::uninit(); _mm_store_ps(out.as_mut_ptr().cast(), result); out.assume_init().0 } {% elif self_t == "Mat2" and is_wasm32 %} use core::mem::MaybeUninit; let abcd = self.0; let xxyy = f32x4(rhs.x, rhs.x, rhs.y, rhs.y); let axbxcydy = f32x4_mul(abcd, xxyy); let cydyaxbx = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy, axbxcydy); let result = f32x4_add(axbxcydy, cydyaxbx); let mut out: MaybeUninit = MaybeUninit::uninit(); unsafe { v128_store(out.as_mut_ptr(), result); *(&out.assume_init() as *const v128 as *const Vec2) } {% elif self_t == "Mat2" and is_coresimd %} let abcd = self.0; let xxyy = f32x4::from_array([rhs.x, rhs.x, rhs.y, rhs.y]); let axbxcydy = abcd.mul(xxyy); let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]); let result = axbxcydy.add(cydyaxbx); unsafe { *(&result as *const f32x4 as *const Vec2) } {% elif self_t == "Mat2" and is_neon %} unsafe { let abcd = self.0; let xxyy = vld1q_f32([rhs.x, rhs.x, rhs.y, rhs.y].as_ptr()); let axbxcydy = vmulq_f32(abcd, xxyy); // let cydyaxbx = simd_swizzle!(axbxcydy, [2, 3, 0, 1]); let cydyaxbx = vextq_f32(axbxcydy, axbxcydy, 2); let result = vaddq_f32(axbxcydy, cydyaxbx); *(&result as *const float32x4_t as *const Vec2) } {% elif dim == 2 %} #[allow(clippy::suspicious_operation_groupings)] {{ col_t }}::new( (self.x_axis.x * rhs.x) + (self.y_axis.x * rhs.y), (self.x_axis.y * rhs.x) + (self.y_axis.y * rhs.y), ) {% elif self_t == "Mat3A" %} {# use the Vec3A implementation #} self.mul_vec3a(rhs.into()).into() {% elif dim == 3 %} let mut res = self.x_axis.mul(rhs.x); res = res.add(self.y_axis.mul(rhs.y)); res = res.add(self.z_axis.mul(rhs.z)); res {% elif dim == 4 %} {% if is_scalar %} let mut res = self.x_axis.mul(rhs.x); res = res.add(self.y_axis.mul(rhs.y)); res = res.add(self.z_axis.mul(rhs.z)); res = res.add(self.w_axis.mul(rhs.w)); res {% else %} {# use swizzles if simd #} let mut res = self.x_axis.mul(rhs.xxxx()); res = res.add(self.y_axis.mul(rhs.yyyy())); res = res.add(self.z_axis.mul(rhs.zzzz())); res = res.add(self.w_axis.mul(rhs.wwww())); res {% endif %} {% endif %} } {% if self_t == "Mat3" %} /// Transforms a [`Vec3A`]. #[inline] #[must_use] pub fn mul_vec3a(&self, rhs: Vec3A) -> Vec3A { self.mul_vec3(rhs.into()).into() } {% elif self_t == "Mat3A" %} /// 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())); res = res.add(self.z_axis.mul(rhs.zzz())); res } {% endif %} /// Multiplies two {{ nxn }} matrices. #[inline] #[must_use] pub fn mul_mat{{ dim }}(&self, rhs: &Self) -> Self { {% if self_t == "Mat2" and is_sse2 %} unsafe { let abcd = self.0; let rhs = rhs.0; let xxyy0 = _mm_shuffle_ps(rhs, rhs, 0b01_01_00_00); let xxyy1 = _mm_shuffle_ps(rhs, rhs, 0b11_11_10_10); let axbxcydy0 = _mm_mul_ps(abcd, xxyy0); let axbxcydy1 = _mm_mul_ps(abcd, xxyy1); let cydyaxbx0 = _mm_shuffle_ps(axbxcydy0, axbxcydy0, 0b01_00_11_10); let cydyaxbx1 = _mm_shuffle_ps(axbxcydy1, axbxcydy1, 0b01_00_11_10); let result0 = _mm_add_ps(axbxcydy0, cydyaxbx0); let result1 = _mm_add_ps(axbxcydy1, cydyaxbx1); Self(_mm_shuffle_ps(result0, result1, 0b01_00_01_00)) } {% elif self_t == "Mat2" and is_wasm32 %} let abcd = self.0; let rhs = rhs.0; let xxyy0 = i32x4_shuffle::<0, 0, 5, 5>(rhs, rhs); let xxyy1 = i32x4_shuffle::<2, 2, 7, 7>(rhs, rhs); let axbxcydy0 = f32x4_mul(abcd, xxyy0); let axbxcydy1 = f32x4_mul(abcd, xxyy1); let cydyaxbx0 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy0, axbxcydy0); let cydyaxbx1 = i32x4_shuffle::<2, 3, 4, 5>(axbxcydy1, axbxcydy1); let result0 = f32x4_add(axbxcydy0, cydyaxbx0); let result1 = f32x4_add(axbxcydy1, cydyaxbx1); Self(i32x4_shuffle::<0, 1, 4, 5>(result0, result1)) {% elif self_t == "Mat2" and is_coresimd %} let abcd = self.0; let xxyy0 = simd_swizzle!(rhs.0, [0, 0, 1, 1]); let xxyy1 = simd_swizzle!(rhs.0, [2, 2, 3, 3]); let axbxcydy0 = abcd * xxyy0; let axbxcydy1 = abcd * xxyy1; let cydyaxbx0 = simd_swizzle!(axbxcydy0, [2, 3, 0, 1]); let cydyaxbx1 = simd_swizzle!(axbxcydy1, [2, 3, 0, 1]); let result0 = axbxcydy0 + cydyaxbx0; let result1 = axbxcydy1 + cydyaxbx1; Self(simd_swizzle!(result0, result1, [0, 1, 4, 5])) {% elif self_t == "Mat2" and is_neon %} unsafe { let abcd = self.0; let xxyy0 = vzip1q_f32(rhs.0, rhs.0); let xxyy1 = vzip2q_f32(rhs.0, rhs.0); let axbxcydy0 = vmulq_f32(abcd, xxyy0); let axbxcydy1 = vmulq_f32(abcd, xxyy1); let cydyaxbx0 = vextq_f32(axbxcydy0, axbxcydy0, 2); let cydyaxbx1 = vextq_f32(axbxcydy1, axbxcydy1, 2); let result0 = vaddq_f32(axbxcydy0, cydyaxbx0); let result1 = vaddq_f32(axbxcydy1, cydyaxbx1); Self(vreinterpretq_f32_u64( vsetq_lane_u64(vgetq_lane_u64(vreinterpretq_u64_f32(result1), 0), vreinterpretq_u64_f32(result0), 1))) } {% else %} Self::from_cols( {% for axis in axes %} self.mul(rhs.{{ axis }}), {%- endfor %} ) {% endif %} } /// Adds two {{ nxn }} matrices. #[inline] #[must_use] pub fn add_mat{{ dim }}(&self, rhs: &Self) -> Self { {% if self_t == "Mat2" and is_sse2 %} Self(unsafe { _mm_add_ps(self.0, rhs.0) }) {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4_add(self.0, rhs.0)) {% elif self_t == "Mat2" and is_coresimd %} Self(self.0 + rhs.0) {% elif self_t == "Mat2" and is_neon %} Self(unsafe { vaddq_f32(self.0, rhs.0) }) {% else %} Self::from_cols( {% for axis in axes %} self.{{ axis }}.add(rhs.{{ axis }}), {%- endfor %} ) {% endif %} } /// Subtracts two {{ nxn }} matrices. #[inline] #[must_use] pub fn sub_mat{{ dim }}(&self, rhs: &Self) -> Self { {% if self_t == "Mat2" and is_sse2 %} Self(unsafe { _mm_sub_ps(self.0, rhs.0) }) {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4_sub(self.0, rhs.0)) {% elif self_t == "Mat2" and is_coresimd %} Self(self.0 - rhs.0) {% elif self_t == "Mat2" and is_neon %} Self(unsafe { vsubq_f32(self.0, rhs.0) }) {% else %} Self::from_cols( {% for axis in axes %} self.{{ axis }}.sub(rhs.{{ axis }}), {%- endfor %} ) {% endif %} } /// Multiplies a {{ nxn }} matrix by a scalar. #[inline] #[must_use] pub fn mul_scalar(&self, rhs: {{ scalar_t }}) -> Self { {% if self_t == "Mat2" and is_sse2 %} Self(unsafe { _mm_mul_ps(self.0, _mm_set_ps1(rhs)) }) {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4_mul(self.0, f32x4_splat(rhs))) {% elif self_t == "Mat2" and is_coresimd %} Self(self.0 * f32x4::splat(rhs)) {% elif self_t == "Mat2" and is_neon %} Self(unsafe { vmulq_f32(self.0, vld1q_dup_f32(&rhs)) }) {% else %} Self::from_cols( {% for axis in axes %} self.{{ axis }}.mul(rhs), {%- endfor %} ) {% endif %} } /// Divides a {{ nxn }} matrix by a scalar. #[inline] #[must_use] pub fn div_scalar(&self, rhs: {{ scalar_t }}) -> Self { {% if self_t == "Mat2" and is_sse2 %} Self(unsafe { _mm_div_ps(self.0, _mm_set_ps1(rhs)) }) {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4_div(self.0, f32x4_splat(rhs))) {% elif self_t == "Mat2" and is_coresimd %} Self(self.0 / f32x4::splat(rhs)) {% elif self_t == "Mat2" and is_neon %} Self(unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }) {% else %} let rhs = {{ col_t }}::splat(rhs); Self::from_cols( {% for axis in axes %} self.{{ axis }}.div(rhs), {%- endfor %} ) {% endif %} } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two matrices contain similar elements. It works best /// when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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: {{ scalar_t }}) -> bool { {% for axis in axes %} self.{{ axis }}.abs_diff_eq(rhs.{{ axis }}, max_abs_diff) {% if not loop.last %} && {% endif %} {% endfor %} } /// Takes the absolute value of each element in `self` #[inline] #[must_use] pub fn abs(&self) -> Self { Self::from_cols( {% for axis in axes %} self.{{ axis }}.abs(), {% endfor %} ) } {% if scalar_t == "f32" %} #[inline] pub fn as_dmat{{ dim }}(&self) -> DMat{{ dim }} { DMat{{ dim }}::from_cols( {% for axis in axes %} self.{{ axis }}.as_dvec{{ dim }}(), {% endfor %} ) } {% elif scalar_t == "f64" %} #[inline] pub fn as_mat{{ dim }}(&self) -> Mat{{ dim }} { Mat{{ dim }}::from_cols( {% for axis in axes %} self.{{ axis }}.as_vec{{ dim }}(), {% endfor %} ) } {% endif %} } impl Default for {{ self_t }} { #[inline] fn default() -> Self { Self::IDENTITY } } impl Add<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self::Output { self.add_mat{{ dim }}(&rhs) } } impl AddAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn add_assign(&mut self, rhs: Self) { *self = self.add_mat{{ dim }}(&rhs); } } impl Sub<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self::Output { self.sub_mat{{ dim }}(&rhs) } } impl SubAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn sub_assign(&mut self, rhs: Self) { *self = self.sub_mat{{ dim }}(&rhs); } } impl Neg for {{ self_t }} { type Output = Self; #[inline] fn neg(self) -> Self::Output { {% if self_t == "Mat2" and is_sse2 %} Self(unsafe { _mm_xor_ps(self.0, _mm_set1_ps(-0.0)) }) {% elif self_t == "Mat2" and is_wasm32 %} Self(f32x4_neg(self.0)) {% elif self_t == "Mat2" and is_coresimd %} Self(-self.0) {% elif self_t == "Mat2" and is_neon %} Self(unsafe { vnegq_f32(self.0) }) {% else %} Self::from_cols( {% for axis in axes %} self.{{ axis }}.neg(), {%- endfor %} ) {% endif %} } } impl Mul<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self::Output { self.mul_mat{{ dim }}(&rhs) } } impl MulAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_mat{{ dim }}(&rhs); } } impl Mul<{{ col_t }}> for {{ self_t }} { type Output = {{ col_t }}; #[inline] fn mul(self, rhs: {{ col_t }}) -> Self::Output { {% if self_t == "Mat3A" %} self.mul_vec3a(rhs) {% else %} self.mul_vec{{ dim }}(rhs) {% endif %} } } impl Mul<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn mul(self, rhs: {{ self_t }}) -> Self::Output { rhs.mul_scalar(self) } } impl Mul<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn mul(self, rhs: {{ scalar_t }}) -> Self::Output { self.mul_scalar(rhs) } } impl MulAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn mul_assign(&mut self, rhs: {{ scalar_t }}) { *self = self.mul_scalar(rhs); } } impl Div<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn div(self, rhs: {{ self_t }}) -> Self::Output { rhs.div_scalar(self) } } impl Div<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn div(self, rhs: {{ scalar_t }}) -> Self::Output { self.div_scalar(rhs) } } impl DivAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn div_assign(&mut self, rhs: {{ scalar_t }}) { *self = self.div_scalar(rhs); } } {% if self_t == "Mat3" %} impl Mul for Mat3 { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Vec3A { self.mul_vec3a(rhs) } } impl From for Mat3 { #[inline] fn from(m: Mat3A) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } {% elif self_t == "Mat3A" %} impl Mul for Mat3A { type Output = Vec3; #[inline] fn mul(self, rhs: Vec3) -> Vec3 { self.mul_vec3a(rhs.into()).into() } } impl From for Mat3A { #[inline] fn from(m: Mat3) -> Self { Self { x_axis: m.x_axis.into(), y_axis: m.y_axis.into(), z_axis: m.z_axis.into(), } } } {% endif %} impl Sum for {{ self_t }} { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for {{ self_t }} { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for {{ self_t }} { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for {{ self_t }} { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } impl PartialEq for {{ self_t }} { #[inline] fn eq(&self, rhs: &Self) -> bool { {% for axis in axes %} self.{{ axis }}.eq(&rhs.{{ axis }}) {% if not loop.last %} && {% endif %} {% endfor %} } } {% if not is_align %} #[cfg(not(target_arch = "spirv"))] impl AsRef<[{{ scalar_t }}; {{ size }}]> for {{ self_t }} { #[inline] fn as_ref(&self) -> &[{{ scalar_t }}; {{ size }}] { unsafe { &*(self as *const Self as *const [{{ scalar_t }}; {{ size }}]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[{{ scalar_t }}; {{ size }}]> for {{ self_t }} { #[inline] fn as_mut(&mut self) -> &mut [{{ scalar_t }}; {{ size }}] { unsafe { &mut *(self as *mut Self as *mut [{{ scalar_t }}; {{ size }}]) } } } {% endif %} {% if self_t == "Mat2" and not is_scalar %} impl core::ops::Deref for Mat2 { type Target = crate::deref::Cols2; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self as *const Self::Target) } } } impl core::ops::DerefMut for Mat2 { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self as *mut Self::Target) } } } {% endif %} impl fmt::Debug for {{ self_t }} { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct(stringify!({{ self_t }})) {% for axis in axes %} .field("{{ axis }}", &self.{{ axis }}) {% endfor %} .finish() } } impl fmt::Display for {{ self_t }} { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { {% if dim == 2 %} write!(f, "[{:.*}, {:.*}]", p, self.x_axis, p, self.y_axis) {% elif dim == 3 %} write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis) {% elif dim == 4 %} write!(f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x_axis, p, self.y_axis, p, self.z_axis, p, self.w_axis) {% endif %} } else { {% if dim == 2 %} write!(f, "[{}, {}]", self.x_axis, self.y_axis) {% elif dim == 3 %} write!(f, "[{}, {}, {}]", self.x_axis, self.y_axis, self.z_axis) {% elif dim == 4 %} write!(f, "[{}, {}, {}, {}]", self.x_axis, self.y_axis, self.z_axis, self.w_axis) {% endif %} } } } glam-0.30.1/templates/neon.rs.tera000064400000000000000000000146511046102023000150710ustar 00000000000000{% macro impl_mat4_inverse() %} unsafe { // Based on https://github.com/g-truc/glm `glm_mat4_inverse` let swizzle3377 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp2q_f32(a, b); vtrn2q_f32(r, r) }; let swizzle2266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, b); vtrn2q_f32(r, r) }; let swizzle0046 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, a); vuzp1q_f32(r, b) }; let swizzle1155 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vzip1q_f32(a, b); vzip2q_f32(r, r) }; let swizzle0044 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, b); vtrn1q_f32(r, r) }; let swizzle0266 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { let r = vuzp1q_f32(a, b); vsetq_lane_f32(vgetq_lane_f32(b, 2), r, 2) }; let swizzle0246 = |a: float32x4_t, b: float32x4_t| -> float32x4_t { vuzp1q_f32(a, b) }; let fac0 = { let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0); let swp0b = swizzle2266(self.w_axis.0, self.z_axis.0); let swp00 = swizzle2266(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac1 = { let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0); let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0); let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac2 = { let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0); let swp0b = swizzle1155(self.w_axis.0, self.z_axis.0); let swp00 = swizzle1155(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac3 = { let swp0a = swizzle3377(self.w_axis.0, self.z_axis.0); let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0); let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle3377(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac4 = { let swp0a = swizzle2266(self.w_axis.0, self.z_axis.0); let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0); let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle2266(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; let fac5 = { let swp0a = swizzle1155(self.w_axis.0, self.z_axis.0); let swp0b = swizzle0044(self.w_axis.0, self.z_axis.0); let swp00 = swizzle0044(self.z_axis.0, self.y_axis.0); let swp01 = swizzle0046(swp0a, swp0a); let swp02 = swizzle0046(swp0b, swp0b); let swp03 = swizzle1155(self.z_axis.0, self.y_axis.0); let mul00 = vmulq_f32(swp00, swp01); let mul01 = vmulq_f32(swp02, swp03); vsubq_f32(mul00, mul01) }; const SIGN_A: float32x4_t = Vec4::new(-1.0, 1.0, -1.0, 1.0).0; const SIGN_B: float32x4_t = Vec4::new(1.0, -1.0, 1.0, -1.0).0; let temp0 = swizzle0044(self.y_axis.0, self.x_axis.0); let vec0 = swizzle0266(temp0, temp0); let temp1 = swizzle1155(self.y_axis.0, self.x_axis.0); let vec1 = swizzle0266(temp1, temp1); let temp2 = swizzle2266(self.y_axis.0, self.x_axis.0); let vec2 = swizzle0266(temp2, temp2); let temp3 = swizzle3377(self.y_axis.0, self.x_axis.0); let vec3 = swizzle0266(temp3, temp3); let mul00 = vmulq_f32(vec1, fac0); let mul01 = vmulq_f32(vec2, fac1); let mul02 = vmulq_f32(vec3, fac2); let sub00 = vsubq_f32(mul00, mul01); let add00 = vaddq_f32(sub00, mul02); let inv0 = vmulq_f32(SIGN_B, add00); let mul03 = vmulq_f32(vec0, fac0); let mul04 = vmulq_f32(vec2, fac3); let mul05 = vmulq_f32(vec3, fac4); let sub01 = vsubq_f32(mul03, mul04); let add01 = vaddq_f32(sub01, mul05); let inv1 = vmulq_f32(SIGN_A, add01); let mul06 = vmulq_f32(vec0, fac1); let mul07 = vmulq_f32(vec1, fac3); let mul08 = vmulq_f32(vec3, fac5); let sub02 = vsubq_f32(mul06, mul07); let add02 = vaddq_f32(sub02, mul08); let inv2 = vmulq_f32(SIGN_B, add02); let mul09 = vmulq_f32(vec0, fac2); let mul10 = vmulq_f32(vec1, fac4); let mul11 = vmulq_f32(vec2, fac5); let sub03 = vsubq_f32(mul09, mul10); let add03 = vaddq_f32(sub03, mul11); let inv3 = vmulq_f32(SIGN_A, add03); let row0 = swizzle0044(inv0, inv1); let row1 = swizzle0044(inv2, inv3); let row2 = swizzle0246(row0, row1); let dot0 = dot4(self.x_axis.0, row2); glam_assert!(dot0 != 0.0); let rcp0 = dot0.recip(); Self { x_axis: Vec4(vmulq_n_f32(inv0, rcp0)), y_axis: Vec4(vmulq_n_f32(inv1, rcp0)), z_axis: Vec4(vmulq_n_f32(inv2, rcp0)), w_axis: Vec4(vmulq_n_f32(inv3, rcp0)), } } {% endmacro impl_mat4_inverse %} glam-0.30.1/templates/quat.rs.tera000064400000000000000000001435321046102023000151050ustar 00000000000000// Generated from {{template_path}} template. Edit the template, not the generated file. {% if not is_scalar %} {% set is_simd = true %} {% if is_sse2 %} {% set simd_t = "__m128" %} {% elif is_wasm32 %} {% set simd_t = "v128" %} {% elif is_coresimd %} {% set simd_t = "f32x4" %} {% elif is_neon %} {% set simd_t = "float32x4_t" %} {% endif %} {% endif %} {% if scalar_t == "f32" %} {% set self_t = "Quat" %} {% set affine3_t = "Affine3A" %} {% set vec2_t = "Vec2" %} {% set vec3_t = "Vec3" %} {% set vec4_t = "Vec4" %} {% set mat3_t = "Mat3" %} {% set mat4_t = "Mat4" %} {% elif scalar_t == "f64" %} {% set self_t = "DQuat" %} {% set affine3_t = "DAffine3" %} {% set vec2_t = "DVec2" %} {% set vec3_t = "DVec3" %} {% set vec4_t = "DVec4" %} {% set mat3_t = "DMat3" %} {% set mat4_t = "DMat4" %} {% endif %} use crate::{ {{ scalar_t }}::math, euler::{EulerRot, FromEuler, ToEuler}, {% if scalar_t == "f32" %} DQuat, Mat3, Mat3A, Mat4, Vec2, Vec3, Vec3A, Vec4, {% elif scalar_t == "f64" %} DMat3, DMat4, DVec2, DVec3, DVec4, Quat, {% endif %} {% if is_sse2 %} sse2::*, {% elif is_wasm32 %} wasm32::*, {% elif is_coresimd %} coresimd::*, {% elif is_neon %} neon::*, {% endif %} }; {% if is_sse2 %} #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; {% elif is_wasm32 %} use core::arch::wasm32::*; {% elif is_coresimd %} use core::simd::*; {% elif is_neon %} use core::arch::aarch64::*; {% endif %} use core::fmt; use core::iter::{Product, Sum}; use core::ops::{ {% if not is_scalar %} Deref, DerefMut, {% endif %} Add, Div, Mul, MulAssign, Neg, Sub }; {% if is_sse2 or is_neon %} #[repr(C)] union UnionCast { a: [f32; 4], v: {{ self_t }} } {% endif %} /// Creates a quaternion from `x`, `y`, `z` and `w` values. /// /// 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 {{ self_t | lower }}(x: {{ scalar_t }}, y: {{ scalar_t }}, z: {{ scalar_t }}, w: {{ scalar_t }}) -> {{ self_t }} { {{ self_t }}::from_xyzw(x, y, z, w) } /// A quaternion representing an orientation. /// /// This quaternion is intended to be of unit length but may denormalize due to /// floating point "error creep" which can occur when successive quaternion /// operations are applied. {%- if is_simd %} /// /// SIMD vector types are used for storage on supported platforms. /// /// This type is 16 byte aligned. {%- endif %} #[derive(Clone, Copy)] {%- if is_scalar %} {%- if scalar_t == "f32" %} #[cfg_attr(not(any(feature = "scalar-math", target_arch = "spirv")), repr(align(16)))] {%- endif %} #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct {{ self_t }}{ pub x: {{ scalar_t }}, pub y: {{ scalar_t }}, pub z: {{ scalar_t }}, pub w: {{ scalar_t }}, } {%- else %} #[repr(transparent)] pub struct {{ self_t }}(pub(crate) {{ simd_t }}); {%- endif %} impl {{ self_t }} { /// All zeros. const ZERO: Self = Self::from_array([0.0; 4]); /// The identity quaternion. Corresponds to no rotation. pub const IDENTITY: Self = Self::from_xyzw(0.0, 0.0, 0.0, 1.0); /// All NANs. pub const NAN: Self = Self::from_array([{{ scalar_t }}::NAN; 4]); /// Creates a new rotation quaternion. /// /// 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`. /// /// `from_xyzw` is mostly used by unit tests and `serde` deserialization. /// /// # Preconditions /// /// 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: {{ scalar_t }}, y: {{ scalar_t }}, z: {{ scalar_t }}, w: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { x, y, z, w } {% elif is_sse2 %} unsafe { UnionCast { a: [x, y, z, w] }.v } {% elif is_wasm32 %} Self(f32x4(x, y, z, w)) {% elif is_coresimd %} Self(f32x4::from_array([x, y, z, w])) {% elif is_neon %} unsafe { UnionCast { a: [x, y, z, w] }.v } {% else %} unimplemented!() {% endif %} } /// Creates a rotation quaternion from an array. /// /// # Preconditions /// /// 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: [{{ scalar_t }}; 4]) -> Self { {% if is_coresimd %} Self(f32x4::from_array(a)) {% else %} Self::from_xyzw(a[0], a[1], a[2], a[3]) {% endif %} } /// Creates a new rotation quaternion from a 4D vector. /// /// # Preconditions /// /// 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_vec4(v: {{ vec4_t }}) -> Self { {% if is_scalar %} Self { x: v.x, y: v.y, z: v.z, w: v.w } {% else %} Self(v.0) {% endif %} } /// Creates a rotation quaternion from a slice. /// /// # Preconditions /// /// 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. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] #[must_use] pub fn from_slice(slice: &[{{ scalar_t }}]) -> Self { {% if is_sse2 %} assert!(slice.len() >= 4); Self(unsafe { _mm_loadu_ps(slice.as_ptr()) }) {% elif is_neon %} assert!(slice.len() >= 4); Self(unsafe { vld1q_f32(slice.as_ptr()) }) {% else %} Self::from_xyzw(slice[0], slice[1], slice[2], slice[3]) {% endif %} } /// Writes the quaternion to an unaligned slice. /// /// # Panics /// /// Panics if `slice` length is less than 4. #[inline] pub fn write_to_slice(self, slice: &mut [{{ scalar_t }}]) { {% if is_sse2 %} assert!(slice.len() >= 4); unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0) } {% elif is_neon %} assert!(slice.len() >= 4); unsafe { vst1q_f32(slice.as_mut_ptr(), self.0) } {% else %} slice[0] = self.x; slice[1] = self.y; slice[2] = self.z; slice[3] = self.w; {% endif %} } /// Create a quaternion for a normalized rotation `axis` and `angle` (in radians). /// /// 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_t }}, angle: {{ scalar_t }}) -> Self { glam_assert!(axis.is_normalized()); let (s, c) = math::sin_cos(angle * 0.5); let v = axis * s; Self::from_xyzw(v.x, v.y, v.z, c) } /// Create a quaternion that rotates `v.length()` radians around `v.normalize()`. /// /// `from_scaled_axis(Vec3::ZERO)` results in the identity quaternion. #[inline] #[must_use] pub fn from_scaled_axis(v: {{ vec3_t }}) -> Self { let length = v.length(); if length == 0.0 { Self::IDENTITY } else { Self::from_axis_angle(v / length, length) } } /// Creates a quaternion from the `angle` (in radians) around the x axis. #[inline] #[must_use] pub fn from_rotation_x(angle: {{ scalar_t }}) -> Self { 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: {{ scalar_t }}) -> Self { 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: {{ scalar_t }}) -> Self { let (s, c) = math::sin_cos(angle * 0.5); Self::from_xyzw(0.0, 0.0, s, c) } /// Creates a quaternion from the given Euler rotation sequence and the angles (in radians). #[inline] #[must_use] pub fn from_euler(euler: EulerRot, a: {{ scalar_t }}, b: {{ scalar_t }}, c: {{ scalar_t }}) -> Self { Self::from_euler_angles(euler, a, b, c) } /// From the columns of a 3x3 rotation matrix. /// /// Note if the input axes contain scales, shears, or other non-rotation transformations then /// the output of this function is ill-defined. /// /// # Panics /// /// Will panic if any axis is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub(crate) fn from_rotation_axes(x_axis: {{ vec3_t }}, y_axis: {{ vec3_t }}, z_axis: {{ vec3_t }}) -> Self { glam_assert!(x_axis.is_normalized() && y_axis.is_normalized() && z_axis.is_normalized()); // Based on https://github.com/microsoft/DirectXMath `XMQuaternionRotationMatrix` let (m00, m01, m02) = x_axis.into(); let (m10, m11, m12) = y_axis.into(); let (m20, m21, m22) = z_axis.into(); if m22 <= 0.0 { // x^2 + y^2 >= z^2 + w^2 let dif10 = m11 - m00; let omm22 = 1.0 - m22; if dif10 <= 0.0 { // x^2 >= y^2 let four_xsq = omm22 - dif10; let inv4x = 0.5 / math::sqrt(four_xsq); Self::from_xyzw( four_xsq * inv4x, (m01 + m10) * inv4x, (m02 + m20) * inv4x, (m12 - m21) * inv4x, ) } else { // y^2 >= x^2 let four_ysq = omm22 + dif10; let inv4y = 0.5 / math::sqrt(four_ysq); Self::from_xyzw( (m01 + m10) * inv4y, four_ysq * inv4y, (m12 + m21) * inv4y, (m20 - m02) * inv4y, ) } } else { // z^2 + w^2 >= x^2 + y^2 let sum10 = m11 + m00; let opm22 = 1.0 + m22; if sum10 <= 0.0 { // z^2 >= w^2 let four_zsq = opm22 - sum10; let inv4z = 0.5 / math::sqrt(four_zsq); Self::from_xyzw( (m02 + m20) * inv4z, (m12 + m21) * inv4z, four_zsq * inv4z, (m01 - m10) * inv4z, ) } else { // w^2 >= z^2 let four_wsq = opm22 + sum10; let inv4w = 0.5 / math::sqrt(four_wsq); Self::from_xyzw( (m12 - m21) * inv4w, (m20 - m02) * inv4w, (m01 - m10) * inv4w, four_wsq * inv4w, ) } } } /// Creates a quaternion from a 3x3 rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat3(mat: &{{ mat3_t }}) -> Self { Self::from_rotation_axes( mat.x_axis, mat.y_axis, mat.z_axis, ) } {% if scalar_t == "f32" %} /// Creates a quaternion from a 3x3 SIMD aligned rotation matrix. /// /// Note if the input matrix contain scales, shears, or other non-rotation transformations then /// the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input matrix column is not normalized when `glam_assert` is enabled. #[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(), ) } {% endif %} /// Creates a quaternion from the upper 3x3 rotation matrix inside a homogeneous 4x4 matrix. /// /// Note if the upper 3x3 matrix contain scales, shears, or other non-rotation transformations /// then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any column of the upper 3x3 rotation matrix is not normalized when /// `glam_assert` is enabled. #[inline] #[must_use] pub fn from_mat4(mat: &{{ mat4_t }}) -> Self { Self::from_rotation_axes( mat.x_axis.truncate(), mat.y_axis.truncate(), mat.z_axis.truncate(), ) } /// 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 inputs must be unit vectors. /// /// `from_rotation_arc(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # Panics /// /// Will panic if `from` or `to` are not normalized when `glam_assert` is enabled. #[must_use] pub fn from_rotation_arc(from: {{ vec3_t }}, to: {{ vec3_t }}) -> Self { glam_assert!(from.is_normalized()); glam_assert!(to.is_normalized()); const ONE_MINUS_EPS: {{ scalar_t }} = 1.0 - 2.0 * {{ scalar_t }}::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPS { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPS { // 180° singularity: from ≈ -to use core::{{ scalar_t }}::consts::PI; // half a turn = 𝛕/2 = 180° Self::from_axis_angle(from.any_orthonormal_vector(), PI) } else { let c = from.cross(to); Self::from_xyzw(c.x, c.y, c.z, 1.0 + dot).normalize() } } /// Gets the minimal rotation for transforming `from` to either `to` or `-to`. This means /// that the resulting quaternion will rotate `from` so that it is colinear with `to`. /// /// The rotation is in the plane spanned by the two vectors. Will rotate at most 90 /// degrees. /// /// The inputs must be unit vectors. /// /// `to.dot(from_rotation_arc_colinear(from, to) * from).abs() ≈ 1`. /// /// # Panics /// /// 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_t }}, to: {{ vec3_t }}) -> Self { if from.dot(to) < 0.0 { Self::from_rotation_arc(from, -to) } else { Self::from_rotation_arc(from, to) } } /// Gets the minimal rotation for transforming `from` to `to`. The resulting rotation is /// around the z axis. Will rotate at most 180 degrees. /// /// The inputs must be unit vectors. /// /// `from_rotation_arc_2d(from, to) * from ≈ to`. /// /// For near-singular cases (from≈to and from≈-to) the current implementation /// is only accurate to about 0.001 (for `f32`). /// /// # 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_t }}, to: {{ vec2_t }}) -> Self { glam_assert!(from.is_normalized()); glam_assert!(to.is_normalized()); const ONE_MINUS_EPSILON: {{ scalar_t }} = 1.0 - 2.0 * {{ scalar_t }}::EPSILON; let dot = from.dot(to); if dot > ONE_MINUS_EPSILON { // 0° singularity: from ≈ to Self::IDENTITY } else if dot < -ONE_MINUS_EPSILON { // 180° singularity: from ≈ -to const COS_FRAC_PI_2: {{ scalar_t }} = 0.0; const SIN_FRAC_PI_2: {{ scalar_t }} = 1.0; // rotation around z by PI radians Self::from_xyzw(0.0, 0.0, SIN_FRAC_PI_2, COS_FRAC_PI_2) } else { // vector3 cross where z=0 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 / math::sqrt(z * z + w * w); Self::from_xyzw(0.0, 0.0, z * len_rcp, w * len_rcp) } } /// Creates a quaterion rotation from a facing direction and an up direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_lh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(-dir, up) } /// Creates a quaterion rotation from facing direction and an up direction. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `dir` and `up` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_to_rh(dir: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { glam_assert!(dir.is_normalized()); glam_assert!(up.is_normalized()); let f = dir; let s = f.cross(up).normalize(); let u = s.cross(f); Self::from_rotation_axes( {{ vec3_t }}::new(s.x, u.x, -f.x), {{ vec3_t }}::new(s.y, u.y, -f.y), {{ vec3_t }}::new(s.z, u.z, -f.z), ) } /// Creates a left-handed view matrix using a camera position, a focal point, and an up /// direction. /// /// For a left-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn look_at_lh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_lh(center.sub(eye).normalize(), up) } /// Creates a right-handed view matrix using a camera position, an up direction, and a focal /// point. /// /// For a right-handed view coordinate system with `+X=right`, `+Y=up` and `+Z=back`. /// /// # Panics /// /// Will panic if `up` is not normalized when `glam_assert` is enabled. #[inline] pub fn look_at_rh(eye: {{ vec3_t }}, center: {{ vec3_t }}, up: {{ vec3_t }}) -> Self { Self::look_to_rh(center.sub(eye).normalize(), up) } /// Returns the rotation axis (normalized) and angle (in radians) of `self`. #[inline] #[must_use] pub fn to_axis_angle(self) -> ({{ vec3_t }}, {{ scalar_t }}) { const EPSILON: {{ scalar_t }} = 1.0e-8; let v = {{ vec3_t }}::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_t }}::X, 0.0) } } /// Returns the rotation axis scaled by the rotation in radians. #[inline] #[must_use] pub fn to_scaled_axis(self) -> {{ vec3_t }} { let (axis, angle) = self.to_axis_angle(); axis * angle } /// Returns the rotation angles for the given euler rotation sequence. #[inline] #[must_use] pub fn to_euler(self, order: EulerRot) -> ({{ scalar_t }}, {{ scalar_t }}, {{ scalar_t }}) { self.to_euler_angles(order) } /// `[x, y, z, w]` #[inline] #[must_use] pub fn to_array(&self) -> [{{ scalar_t }}; 4] { [self.x, self.y, self.z, self.w] } /// Returns the vector part of the quaternion. #[inline] #[must_use] pub fn xyz(self) -> {{ vec3_t }} { {{ vec3_t }}::new(self.x, self.y, self.z) } /// Returns the quaternion conjugate of `self`. For a unit quaternion the /// conjugate is also the inverse. #[inline] #[must_use] pub fn conjugate(self) -> Self { {% if is_scalar %} Self { x: -self.x, y: -self.y, z: -self.z, w: self.w } {% elif is_sse2 %} const SIGN: __m128 = m128_from_f32x4([-0.0, -0.0, -0.0, 0.0]); Self(unsafe { _mm_xor_ps(self.0, SIGN) }) {% elif is_wasm32 %} const SIGN: v128 = v128_from_f32x4([-1.0, -1.0, -1.0, 1.0]); Self(f32x4_mul(self.0, SIGN)) {% elif is_coresimd %} const SIGN: f32x4 = f32x4::from_array([-1.0, -1.0, -1.0, 1.0]); Self(self.0.mul(SIGN)) {% elif is_neon %} const SIGN: float32x4_t = f32x4_from_array([-1.0, -1.0, -1.0, 1.0]); Self(unsafe { vmulq_f32(self.0, SIGN) }) {% else %} unimplemented!() {% endif %} } /// Returns the inverse of a normalized quaternion. /// /// Typically quaternion inverse returns the conjugate of a normalized quaternion. /// Because `self` is assumed to already be unit length this method *does not* normalize /// before returning the conjugate. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn inverse(self) -> Self { glam_assert!(self.is_normalized()); self.conjugate() } /// 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) -> {{ scalar_t }} { {{ vec4_t }}::from(self).dot({{ vec4_t }}::from(rhs)) } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> {{ scalar_t }} { {{ vec4_t }}::from(self).length() } /// Computes the squared length of `self`. /// /// This is generally faster than `length()` as it avoids a square /// root operation. #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> {{ scalar_t }} { {{ vec4_t }}::from(self).length_squared() } /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> {{ scalar_t }} { {{ vec4_t }}::from(self).length_recip() } /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must _not_ be of length zero. /// /// Panics /// /// Will panic if `self` is zero length when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { Self::from_vec4({{ vec4_t }}::from(self).normalize()) } /// 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_t }}::from(self).is_finite() } /// Returns `true` if any elements are `NAN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { {{ vec4_t }}::from(self).is_nan() } /// Returns whether `self` of length `1.0` or not. /// /// Uses a precision threshold of `1e-6`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { {{ vec4_t }}::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; // Because of floating point precision, we cannot represent very small rotations. // The closest f32 to 1.0 that is not 1.0 itself yields: // 0.99999994.acos() * 2.0 = 0.000690533954 rad // // An error threshold of 1.e-6 is used by default. // (1.0 - 1.e-6).acos() * 2.0 = 0.00284714461 rad // (1.0 - 1.e-7).acos() * 2.0 = 0.00097656250 rad // // We don't really care about the angle value itself, only if it's close to 0. // This will happen whenever quat.w is close to 1.0. // 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 = math::acos_approx(math::abs(self.w)) * 2.0; positive_w_angle < threshold_angle } /// Returns the angle (in radians) for the minimal rotation /// for transforming this quaternion into another. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn angle_between(self, rhs: Self) -> {{ scalar_t }} { glam_assert!(self.is_normalized() && rhs.is_normalized()); math::acos_approx(math::abs(self.dot(rhs))) * 2.0 } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be equal to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. /// /// Both quaternions must be normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: {{ scalar_t }}) -> Self { glam_assert!(self.is_normalized() && rhs.is_normalized()); let angle = self.angle_between(rhs); if angle <= 1e-4 { return rhs; } let s = (max_angle / angle).clamp(-1.0, 1.0); self.slerp(rhs, s) } /// Returns true if the absolute difference of all elements between `self` and `rhs` /// is less than or equal to `max_abs_diff`. /// /// This can be used to compare if two quaternions contain similar elements. It works /// best when comparing with a known value. The `max_abs_diff` that should be used used /// depends on the values being compared against. /// /// 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: {{ scalar_t }}) -> bool { {{ vec4_t }}::from(self).abs_diff_eq({{ vec4_t }}::from(rhs), max_abs_diff) } #[inline(always)] #[must_use] fn lerp_impl(self, end: Self, s: {{ scalar_t }}) -> Self { (self * (1.0 - s) + end * s).normalize() } /// Performs a linear interpolation between `self` and `rhs` based on /// the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `rhs`. /// /// # Panics /// /// Will panic if `self` or `end` are not normalized when `glam_assert` is enabled. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, end: Self, s: {{ scalar_t }}) -> Self { glam_assert!(self.is_normalized()); glam_assert!(end.is_normalized()); {% if is_scalar %} let dot = self.dot(end); let bias = if dot >= 0.0 { 1.0 } else { -1.0 }; self.lerp_impl(end * bias, s) {% elif is_sse2 %} const NEG_ZERO: __m128 = m128_from_f32x4([-0.0; 4]); unsafe { let dot = dot4_into_m128(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = _mm_and_ps(dot, NEG_ZERO); self.lerp_impl(Self(_mm_xor_ps(end.0, bias)), s) } {% elif is_wasm32 %} const NEG_ZERO: v128 = v128_from_f32x4([-0.0; 4]); let dot = dot4_into_v128(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = v128_and(dot, NEG_ZERO); self.lerp_impl(Self(v128_xor(end.0, bias)), s) {% elif is_coresimd %} const NEG_ZERO: f32x4 = f32x4::from_array([-0.0; 4]); let dot = dot4_into_f32x4(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = f32x4_bitand(dot, NEG_ZERO); self.lerp_impl(Self(f32x4_bitxor(end.0, bias)), s) {% elif is_neon %} const NEG_ZERO: float32x4_t = f32x4_from_array([-0.0; 4]); unsafe { let dot = dot4_into_f32x4(self.0, end.0); // Calculate the bias, if the dot product is positive or zero, there is no bias // but if it is negative, we want to flip the 'end' rotation XYZW components let bias = vandq_u32(vreinterpretq_u32_f32(dot), vreinterpretq_u32_f32(NEG_ZERO)); self.lerp_impl( Self(vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(end.0), bias))), s) } {% else %} unimplemented!() {% endif %} } /// Performs a spherical linear interpolation between `self` and `end` /// based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` /// is `1.0`, the result will be equal to `end`. /// /// # Panics /// /// 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: {{ scalar_t }}) -> Self { // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/ glam_assert!(self.is_normalized()); glam_assert!(end.is_normalized()); // Note that a rotation can be represented by two quaternions: `q` and // `-q`. The slerp path between `q` and `end` will be different from the // path between `-q` and `end`. One path will take the long way around and // one will take the short way. In order to correct for this, the `dot` // product between `self` and `end` should be positive. If the `dot` // product is negative, slerp between `self` and `-end`. let mut dot = self.dot(end); if dot < 0.0 { end = -end; dot = -dot; } const DOT_THRESHOLD: {{ scalar_t }} = 1.0 - {{ scalar_t }}::EPSILON; if dot > DOT_THRESHOLD { // if above threshold perform linear interpolation to avoid divide by zero self.lerp_impl(end, s) } else { let theta = math::acos_approx(dot); {% if is_sse2 %} let x = 1.0 - s; let y = s; let z = 1.0; unsafe { let tmp = _mm_mul_ps(_mm_set_ps1(theta), _mm_set_ps(0.0, z, y, x)); let tmp = m128_sin(tmp); let scale1 = _mm_shuffle_ps(tmp, tmp, 0b00_00_00_00); let scale2 = _mm_shuffle_ps(tmp, tmp, 0b01_01_01_01); let theta_sin = _mm_shuffle_ps(tmp, tmp, 0b10_10_10_10); Self(_mm_div_ps( _mm_add_ps(_mm_mul_ps(self.0, scale1), _mm_mul_ps(end.0, scale2)), theta_sin, )) } {% else %} let scale1 = math::sin(theta * (1.0 - s)); let scale2 = math::sin(theta * s); let theta_sin = math::sin(theta); ((self * scale1) + (end * scale2)) * (1.0 / theta_sin) {% endif %} } } /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn mul_vec3(self, rhs: {{ vec3_t }}) -> {{ vec3_t }} { glam_assert!(self.is_normalized()); {% if is_scalar %} let w = self.w; let b = {{ vec3_t }}::new(self.x, self.y, self.z); let b2 = b.dot(b); rhs .mul(w * w - b2) .add(b.mul(rhs.dot(b) * 2.0)) .add(b.cross(rhs).mul(w * 2.0)) {% else %} self.mul_vec3a(rhs.into()).into() {% endif %} } /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly normalized. /// /// # Panics /// /// 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 { {% if is_scalar %} let (x0, y0, z0, w0) = self.into(); let (x1, y1, z1, w1) = rhs.into(); Self::from_xyzw( w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1, w0 * y1 - x0 * z1 + y0 * w1 + z0 * x1, w0 * z1 + x0 * y1 - y0 * x1 + z0 * w1, w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1, ) {% elif is_sse2 %} // Based on https://github.com/nfrechette/rtm `rtm::quat_mul` const CONTROL_WZYX: __m128 = m128_from_f32x4([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: __m128 = m128_from_f32x4([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: __m128 = m128_from_f32x4([-1.0, 1.0, 1.0, -1.0]); let lhs = self.0; let rhs = rhs.0; unsafe { let r_xxxx = _mm_shuffle_ps(lhs, lhs, 0b00_00_00_00); let r_yyyy = _mm_shuffle_ps(lhs, lhs, 0b01_01_01_01); let r_zzzz = _mm_shuffle_ps(lhs, lhs, 0b10_10_10_10); let r_wwww = _mm_shuffle_ps(lhs, lhs, 0b11_11_11_11); let lxrw_lyrw_lzrw_lwrw = _mm_mul_ps(r_wwww, rhs); let l_wzyx = _mm_shuffle_ps(rhs, rhs, 0b00_01_10_11); let lwrx_lzrx_lyrx_lxrx = _mm_mul_ps(r_xxxx, l_wzyx); let l_zwxy = _mm_shuffle_ps(l_wzyx, l_wzyx, 0b10_11_00_01); let lwrx_nlzrx_lyrx_nlxrx = _mm_mul_ps(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX); let lzry_lwry_lxry_lyry = _mm_mul_ps(r_yyyy, l_zwxy); let l_yxwz = _mm_shuffle_ps(l_zwxy, l_zwxy, 0b00_01_10_11); let lzry_lwry_nlxry_nlyry = _mm_mul_ps(lzry_lwry_lxry_lyry, CONTROL_ZWXY); let lyrz_lxrz_lwrz_lzrz = _mm_mul_ps(r_zzzz, l_yxwz); let result0 = _mm_add_ps(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx); let nlyrz_lxrz_lwrz_wlzrz = _mm_mul_ps(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ); let result1 = _mm_add_ps(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz); Self(_mm_add_ps(result0, result1)) } {% elif is_wasm32 %} let lhs = self.0; let rhs = rhs.0; const CONTROL_WZYX: v128 = v128_from_f32x4([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: v128 = v128_from_f32x4([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: v128 = v128_from_f32x4([-1.0, 1.0, 1.0, -1.0]); let r_xxxx = i32x4_shuffle::<0, 0, 4, 4>(lhs, lhs); let r_yyyy = i32x4_shuffle::<1, 1, 5, 5>(lhs, lhs); let r_zzzz = i32x4_shuffle::<2, 2, 6, 6>(lhs, lhs); let r_wwww = i32x4_shuffle::<3, 3, 7, 7>(lhs, lhs); let lxrw_lyrw_lzrw_lwrw = f32x4_mul(r_wwww, rhs); let l_wzyx = i32x4_shuffle::<3, 2, 5, 4>(rhs, rhs); let lwrx_lzrx_lyrx_lxrx = f32x4_mul(r_xxxx, l_wzyx); let l_zwxy = i32x4_shuffle::<1, 0, 7, 6>(l_wzyx, l_wzyx); let lwrx_nlzrx_lyrx_nlxrx = f32x4_mul(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX); let lzry_lwry_lxry_lyry = f32x4_mul(r_yyyy, l_zwxy); let l_yxwz = i32x4_shuffle::<3, 2, 5, 4>(l_zwxy, l_zwxy); let lzry_lwry_nlxry_nlyry = f32x4_mul(lzry_lwry_lxry_lyry, CONTROL_ZWXY); let lyrz_lxrz_lwrz_lzrz = f32x4_mul(r_zzzz, l_yxwz); let result0 = f32x4_add(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx); let nlyrz_lxrz_lwrz_wlzrz = f32x4_mul(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ); let result1 = f32x4_add(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz); Self(f32x4_add(result0, result1)) {% elif is_coresimd %} let lhs = self.0; let rhs = rhs.0; const CONTROL_WZYX: f32x4 = f32x4::from_array([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: f32x4 = f32x4::from_array([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: f32x4 = f32x4::from_array([-1.0, 1.0, 1.0, -1.0]); let r_xxxx = simd_swizzle!(lhs, [0, 0, 0, 0]); let r_yyyy = simd_swizzle!(lhs, [1, 1, 1, 1]); let r_zzzz = simd_swizzle!(lhs, [2, 2, 2, 2]); let r_wwww = simd_swizzle!(lhs, [3, 3, 3, 3]); let lxrw_lyrw_lzrw_lwrw = r_wwww * rhs; let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]); let lwrx_lzrx_lyrx_lxrx = r_xxxx * l_wzyx; let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]); let lwrx_nlzrx_lyrx_nlxrx = lwrx_lzrx_lyrx_lxrx * CONTROL_WZYX; let lzry_lwry_lxry_lyry = r_yyyy * l_zwxy; let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]); let lzry_lwry_nlxry_nlyry = lzry_lwry_lxry_lyry * CONTROL_ZWXY; let lyrz_lxrz_lwrz_lzrz = r_zzzz * l_yxwz; let result0 = lxrw_lyrw_lzrw_lwrw + lwrx_nlzrx_lyrx_nlxrx; let nlyrz_lxrz_lwrz_wlzrz = lyrz_lxrz_lwrz_lzrz * CONTROL_YXWZ; let result1 = lzry_lwry_nlxry_nlyry + nlyrz_lxrz_lwrz_wlzrz; Self(result0 + result1) {% elif is_neon %} unsafe { let lhs = self.0; let rhs = rhs.0; const CONTROL_WZYX: float32x4_t = f32x4_from_array([1.0, -1.0, 1.0, -1.0]); const CONTROL_ZWXY: float32x4_t = f32x4_from_array([1.0, 1.0, -1.0, -1.0]); const CONTROL_YXWZ: float32x4_t = f32x4_from_array([-1.0, 1.0, 1.0, -1.0]); let r_xxxx = vdupq_laneq_f32(lhs, 0); let r_yyyy = vdupq_laneq_f32(lhs, 1); let r_zzzz = vdupq_laneq_f32(lhs, 2); let r_wwww = vdupq_laneq_f32(lhs, 3); let lxrw_lyrw_lzrw_lwrw = vmulq_f32(r_wwww, rhs); //let l_wzyx = simd_swizzle!(rhs, [3, 2, 1, 0]); let l_wzyx = vrev64q_f32(rhs); let l_wzyx = vextq_f32(l_wzyx, l_wzyx, 2); let lwrx_lzrx_lyrx_lxrx = vmulq_f32(r_xxxx, l_wzyx); //let l_zwxy = simd_swizzle!(l_wzyx, [1, 0, 3, 2]); let l_zwxy = vrev64q_f32(l_wzyx); let lwrx_nlzrx_lyrx_nlxrx = vmulq_f32(lwrx_lzrx_lyrx_lxrx, CONTROL_WZYX); let lzry_lwry_lxry_lyry = vmulq_f32(r_yyyy, l_zwxy); // let l_yxwz = simd_swizzle!(l_zwxy, [3, 2, 1, 0]); let l_yxwz = vrev64q_f32(l_zwxy); let l_yxwz = vextq_f32(l_yxwz, l_yxwz, 2); let lzry_lwry_nlxry_nlyry = vmulq_f32(lzry_lwry_lxry_lyry, CONTROL_ZWXY); let lyrz_lxrz_lwrz_lzrz = vmulq_f32(r_zzzz, l_yxwz); let result0 = vaddq_f32(lxrw_lyrw_lzrw_lwrw, lwrx_nlzrx_lyrx_nlxrx); let nlyrz_lxrz_lwrz_wlzrz = vmulq_f32(lyrz_lxrz_lwrz_lzrz, CONTROL_YXWZ); let result1 = vaddq_f32(lzry_lwry_nlxry_nlyry, nlyrz_lxrz_lwrz_wlzrz); Self(vaddq_f32(result0, result1)) } {% else %} unimplemented!() {% endif %} } /// Creates a quaternion from a 3x3 rotation matrix inside a 3D affine transform. /// /// Note if the input affine matrix contain scales, shears, or other non-rotation /// transformations then the resulting quaternion will be ill-defined. /// /// # Panics /// /// Will panic if any input affine matrix column is not normalized when `glam_assert` is /// enabled. #[inline] #[must_use] pub fn from_affine3(a: &crate::{{ affine3_t }}) -> Self { #[allow(clippy::useless_conversion)] Self::from_rotation_axes( a.matrix3.x_axis.into(), a.matrix3.y_axis.into(), a.matrix3.z_axis.into(), ) } {% if scalar_t == "f32" %} /// Multiplies a quaternion and a 3D vector, returning the rotated vector. #[inline] #[must_use] pub fn mul_vec3a(self, rhs: Vec3A) -> Vec3A { {% if is_scalar %} self.mul_vec3(rhs.into()).into() {% elif is_sse2 %} unsafe { const TWO: __m128 = m128_from_f32x4([2.0; 4]); let w = _mm_shuffle_ps(self.0, self.0, 0b11_11_11_11); let b = self.0; let b2 = dot3_into_m128(b, b); Vec3A(_mm_add_ps( _mm_add_ps( _mm_mul_ps(rhs.0, _mm_sub_ps(_mm_mul_ps(w, w), b2)), _mm_mul_ps(b, _mm_mul_ps(dot3_into_m128(rhs.0, b), TWO)), ), _mm_mul_ps(Vec3A(b).cross(rhs).into(), _mm_mul_ps(w, TWO)), )) } {% elif is_wasm32 %} const TWO: v128 = v128_from_f32x4([2.0; 4]); let w = i32x4_shuffle::<3, 3, 7, 7>(self.0, self.0); let b = self.0; let b2 = dot3_into_v128(b, b); Vec3A(f32x4_add( f32x4_add( f32x4_mul(rhs.0, f32x4_sub(f32x4_mul(w, w), b2)), f32x4_mul(b, f32x4_mul(dot3_into_v128(rhs.0, b), TWO)), ), f32x4_mul(Vec3A(b).cross(rhs).into(), f32x4_mul(w, TWO)), )) {% elif is_coresimd %} const TWO: f32x4 = f32x4::from_array([2.0; 4]); let w = simd_swizzle!(self.0, [3, 3, 3, 3]); let b = self.0; let b2 = dot3_into_f32x4(b, b); Vec3A( rhs.0 .mul(w.mul(w).sub(b2)) .add(b.mul(dot3_into_f32x4(rhs.0, b).mul(TWO))) .add(Vec3A(b).cross(rhs).0.mul(w.mul(TWO))), ) {% elif is_neon %} unsafe { let w = self.w; let b = Vec3A::from(self.0); let b2 = b.length_squared(); Vec3A(vaddq_f32( vaddq_f32( vmulq_n_f32(rhs.0, (w * w) - b2), vmulq_n_f32(b.0, rhs.dot(b) * 2.0), ), vmulq_n_f32(b.cross(rhs).0, w * 2.0), )) } {% else %} unimplemented!() {% endif %} } #[inline] #[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) } {% elif scalar_t == "f64" %} #[inline] #[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) } {% endif %} } impl fmt::Debug for {{ self_t }} { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!({{ self_t }})) .field(&self.x) .field(&self.y) .field(&self.z) .field(&self.w) .finish() } } impl fmt::Display for {{ self_t }} { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(p) = f.precision() { write!(f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w) } else { write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) } } } impl Add<{{ self_t }}> for {{ self_t }} { type Output = Self; /// Adds two quaternions. /// /// The sum is not guaranteed to be normalized. /// /// Note that addition is not the same as combining the rotations represented by the /// two quaternions! That corresponds to multiplication. #[inline] fn add(self, rhs: Self) -> Self { Self::from_vec4({{ vec4_t }}::from(self) + {{ vec4_t }}::from(rhs)) } } impl Sub<{{ self_t }}> for {{ self_t }} { type Output = Self; /// Subtracts the `rhs` quaternion from `self`. /// /// The difference is not guaranteed to be normalized. #[inline] fn sub(self, rhs: Self) -> Self { Self::from_vec4({{ vec4_t }}::from(self) - {{ vec4_t }}::from(rhs)) } } impl Mul<{{ scalar_t }}> for {{ self_t }} { type Output = Self; /// Multiplies a quaternion by a scalar value. /// /// The product is not guaranteed to be normalized. #[inline] fn mul(self, rhs: {{ scalar_t }}) -> Self { Self::from_vec4({{ vec4_t }}::from(self) * rhs) } } impl Div<{{ scalar_t }}> for {{ self_t }} { type Output = Self; /// Divides a quaternion by a scalar value. /// The quotient is not guaranteed to be normalized. #[inline] fn div(self, rhs: {{ scalar_t }}) -> Self { Self::from_vec4({{ vec4_t }}::from(self) / rhs) } } impl Mul<{{ self_t }}> for {{ self_t }} { type Output = Self; /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: Self) -> Self { self.mul_quat(rhs) } } impl MulAssign<{{ self_t }}> for {{ self_t }} { /// Multiplies two quaternions. If they each represent a rotation, the result will /// represent the combined rotation. /// /// Note that due to floating point rounding the result may not be perfectly /// normalized. /// /// # Panics /// /// Will panic if `self` or `rhs` are not normalized when `glam_assert` is enabled. #[inline] fn mul_assign(&mut self, rhs: Self) { *self = self.mul_quat(rhs); } } impl Mul<{{ vec3_t }}> for {{ self_t }} { type Output = {{ vec3_t }}; /// Multiplies a quaternion and a 3D vector, returning the rotated vector. /// /// # Panics /// /// Will panic if `self` is not normalized when `glam_assert` is enabled. #[inline] fn mul(self, rhs: {{ vec3_t }}) -> Self::Output { self.mul_vec3(rhs) } } impl Neg for {{ self_t }} { type Output = Self; #[inline] fn neg(self) -> Self { self * -1.0 } } impl Default for {{ self_t }} { #[inline] fn default() -> Self { Self::IDENTITY } } impl PartialEq for {{ self_t }} { #[inline] fn eq(&self, rhs: &Self) -> bool { {{ vec4_t }}::from(*self).eq(&{{ vec4_t }}::from(*rhs)) } } #[cfg(not(target_arch = "spirv"))] impl AsRef<[{{ scalar_t }}; 4]> for {{ self_t }} { #[inline] fn as_ref(&self) -> &[{{ scalar_t }}; 4] { unsafe { &*(self as *const Self as *const [{{ scalar_t }}; 4]) } } } impl Sum for {{ self_t }} { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for {{ self_t }} { fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for {{ self_t }} { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, Self::mul) } } impl<'a> Product<&'a Self> for {{ self_t }} { fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::IDENTITY, |a, &b| Self::mul(a, b)) } } {% if scalar_t == "f32" %} impl Mul for Quat { type Output = Vec3A; #[inline] fn mul(self, rhs: Vec3A) -> Self::Output { self.mul_vec3a(rhs) } } {% endif %} impl From<{{ self_t }}> for {{ vec4_t }} { #[inline] fn from(q: {{ self_t }}) -> Self { {% if is_scalar %} Self::new(q.x, q.y, q.z, q.w) {% else %} Self(q.0) {% endif %} } } impl From<{{ self_t }}> for ({{ scalar_t }}, {{ scalar_t }}, {{ scalar_t }}, {{ scalar_t }}) { #[inline] fn from(q: {{ self_t }}) -> Self { {% if is_scalar %} (q.x, q.y, q.z, q.w) {% else %} {{ vec4_t }}::from(q).into() {% endif %} } } impl From<{{ self_t }}> for [{{ scalar_t }}; 4] { #[inline] fn from(q: {{ self_t }}) -> Self { {% if is_scalar %} [q.x, q.y, q.z, q.w] {% else %} {{ vec4_t }}::from(q).into() {% endif %} } } {% if not is_scalar %} impl From<{{ self_t }}> for {{ simd_t }} { #[inline] fn from(q: {{ self_t }}) -> Self { {% if is_scalar %} Self { x: q.x, y: q.y, z: q.z, w: q.w } {% else %} q.0 {% endif %} } } impl Deref for {{ self_t }} { type Target = crate::deref::Vec4<{{ scalar_t }}>; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for {{ self_t }} { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } {% endif %} glam-0.30.1/templates/sse2.rs.tera000064400000000000000000000143371046102023000150070ustar 00000000000000{% macro impl_mat4_inverse() %} unsafe { // Based on https://github.com/g-truc/glm `glm_mat4_inverse` let fac0 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac1 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac2 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac3 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b11_11_11_11); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b11_11_11_11); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac4 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b10_10_10_10); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b10_10_10_10); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let fac5 = { let swp0a = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b01_01_01_01); let swp0b = _mm_shuffle_ps(self.w_axis.0, self.z_axis.0, 0b00_00_00_00); let swp00 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b00_00_00_00); let swp01 = _mm_shuffle_ps(swp0a, swp0a, 0b10_00_00_00); let swp02 = _mm_shuffle_ps(swp0b, swp0b, 0b10_00_00_00); let swp03 = _mm_shuffle_ps(self.z_axis.0, self.y_axis.0, 0b01_01_01_01); let mul00 = _mm_mul_ps(swp00, swp01); let mul01 = _mm_mul_ps(swp02, swp03); _mm_sub_ps(mul00, mul01) }; let sign_a = _mm_set_ps(1.0, -1.0, 1.0, -1.0); let sign_b = _mm_set_ps(-1.0, 1.0, -1.0, 1.0); let temp0 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b00_00_00_00); let vec0 = _mm_shuffle_ps(temp0, temp0, 0b10_10_10_00); let temp1 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b01_01_01_01); let vec1 = _mm_shuffle_ps(temp1, temp1, 0b10_10_10_00); let temp2 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b10_10_10_10); let vec2 = _mm_shuffle_ps(temp2, temp2, 0b10_10_10_00); let temp3 = _mm_shuffle_ps(self.y_axis.0, self.x_axis.0, 0b11_11_11_11); let vec3 = _mm_shuffle_ps(temp3, temp3, 0b10_10_10_00); let mul00 = _mm_mul_ps(vec1, fac0); let mul01 = _mm_mul_ps(vec2, fac1); let mul02 = _mm_mul_ps(vec3, fac2); let sub00 = _mm_sub_ps(mul00, mul01); let add00 = _mm_add_ps(sub00, mul02); let inv0 = _mm_mul_ps(sign_b, add00); let mul03 = _mm_mul_ps(vec0, fac0); let mul04 = _mm_mul_ps(vec2, fac3); let mul05 = _mm_mul_ps(vec3, fac4); let sub01 = _mm_sub_ps(mul03, mul04); let add01 = _mm_add_ps(sub01, mul05); let inv1 = _mm_mul_ps(sign_a, add01); let mul06 = _mm_mul_ps(vec0, fac1); let mul07 = _mm_mul_ps(vec1, fac3); let mul08 = _mm_mul_ps(vec3, fac5); let sub02 = _mm_sub_ps(mul06, mul07); let add02 = _mm_add_ps(sub02, mul08); let inv2 = _mm_mul_ps(sign_b, add02); let mul09 = _mm_mul_ps(vec0, fac2); let mul10 = _mm_mul_ps(vec1, fac4); let mul11 = _mm_mul_ps(vec2, fac5); let sub03 = _mm_sub_ps(mul09, mul10); let add03 = _mm_add_ps(sub03, mul11); let inv3 = _mm_mul_ps(sign_a, add03); let row0 = _mm_shuffle_ps(inv0, inv1, 0b00_00_00_00); let row1 = _mm_shuffle_ps(inv2, inv3, 0b00_00_00_00); let row2 = _mm_shuffle_ps(row0, row1, 0b10_00_10_00); let dot0 = dot4(self.x_axis.0, row2); glam_assert!(dot0 != 0.0); let rcp0 = _mm_set1_ps(dot0.recip()); Self { x_axis: Vec4(_mm_mul_ps(inv0, rcp0)), y_axis: Vec4(_mm_mul_ps(inv1, rcp0)), z_axis: Vec4(_mm_mul_ps(inv2, rcp0)), w_axis: Vec4(_mm_mul_ps(inv3, rcp0)), } } {% endmacro impl_mat4_inverse %} glam-0.30.1/templates/swizzle_impl.rs.tera000064400000000000000000000116741046102023000166640ustar 00000000000000// Generated from {{template_path}} template. Edit the template, not the generated file. {% if not is_scalar %} #![allow(clippy::useless_conversion)] {% endif %} {# component indices #} {% set indices = [0, 1, 2, 3] %} {# vector dimensions #} {% set dimensions = [2, 3, 4] %} {# element names #} {% set e = ["x", "y", "z", "w"] %} {# shuffle bits (sse2) #} {% set b = ["00", "01", "10", "11"] %} {# low index (wasm32) #} {% set l = ["0", "1", "2", "3"] %} {# high index (wasm32) #} {% set h = ["4", "5", "6", "7"] %} use crate::{ Vec{{ dim }}Swizzles, {{vec2_t}}, {{vec3_t}}, {{vec4_t}}, }; {% if is_sse2 %} #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; {% elif is_wasm32 %} use core::arch::wasm32::*; {% elif is_coresimd %} use core::simd::*; {% endif %} impl Vec{{ dim }}Swizzles for {{ self_t }} { {% if dim != 2 %} type Vec2 = {{ vec2_t }}; {% endif %} {% if dim != 3 %} type Vec3 = {{ vec3_t }}; {% endif %} {% if dim != 4 %} type Vec4 = {{ vec4_t }}; {% endif %} {% for i in dimensions %} {% for j0 in indices | slice(end=dim) %} {% for j1 in indices | slice(end=dim) %} {% if i == 2 %} {% set skip = dim == 2 and j0 == 0 and j1 == 1 %} {% if not skip %} #[inline] #[must_use] fn {{ e[j0] }}{{ e[j1] }}(self) -> {{ vec2_t }} { {{ vec2_t }} { x: self.{{ e[j0] }}, y: self.{{ e[j1] }} } } {% endif %} {% set skip = dim == 2 or j0 == j1 %} {% if not skip %} #[inline] #[must_use] fn with_{{ e[j0] }}{{ e[j1] }}(self, rhs: {{ vec2_t }}) -> Self { Self::new( {% for l in range(start = 0, end = dim) %} {% if j0 == l %} rhs.x, {% elif j1 == l %} rhs.y, {% else %} self.{{e[l]}}, {% endif %} {% endfor %} ) } {% endif %} {% else %} {% for j2 in indices | slice(end=dim) %} {% if i == 3 %} {% set skip = dim == 3 and j0 == 0 and j1 == 1 and j2 == 2 %} {% if not skip %} #[inline] #[must_use] fn {{ e[j0] }}{{ e[j1] }}{{ e[j2] }}(self) -> {{ vec3_t }} { {% if vec3_t == "Vec3A" and is_sse2 %} {{ vec3_t }}((unsafe { _mm_shuffle_ps(self.0, self.0, 0b00_{{ b[j2] }}_{{ b[j1] }}_{{ b[j0] }}) }).into()) {% elif vec3_t == "Vec3A" and is_wasm32 %} {{ vec3_t }}(i32x4_shuffle::<{{ l[j0] }}, {{ l[j1] }}, {{ h[j2] }}, {{ h[0] }}>(self.0, self.0).into()) {% elif vec3_t == "Vec3A" and is_coresimd %} {{ vec3_t }}(simd_swizzle!(self.0, [{{ l[j0] }}, {{ l[j1] }}, {{ l[j2] }}, {{ l[0] }}]).into()) {% else %} {{ vec3_t }}::new(self.{{ e[j0] }}, self.{{ e[j1] }}, self.{{ e[j2] }}) {% endif %} } {% endif %} {% set skip = dim == 3 or j0 == j1 or j0 == j2 or j1 == j2 %} {% if not skip %} #[inline] #[must_use] fn with_{{ e[j0] }}{{ e[j1] }}{{ e[j2] }}(self, rhs: {{ vec3_t }}) -> Self { Self::new( {% for l in range(start = 0, end = dim) %} {% if j0 == l %} rhs.x, {% elif j1 == l %} rhs.y, {% elif j2 == l %} rhs.z, {% else %} self.{{e[l]}}, {% endif %} {% endfor %} ) } {% endif %} {% else %} {% for j3 in indices | slice(end=dim) %} {% set skip = dim == 4 and j0 == 0 and j1 == 1 and j2 == 2 and j3 == 3 %} {% if not skip %} #[inline] #[must_use] fn {{ e[j0] }}{{ e[j1] }}{{ e[j2] }}{{ e[j3] }}(self) -> {{ vec4_t }} { {% if is_sse2 %} {{ vec4_t }}(unsafe { _mm_shuffle_ps(self.0, self.0, 0b{{ b[j3] }}_{{ b[j2] }}_{{ b[j1] }}_{{ b[j0] }}) }) {% elif is_wasm32 %} {{ vec4_t}}(i32x4_shuffle::<{{ l[j0] }}, {{ l[j1] }}, {{ h[j2] }}, {{ h[j3] }}>(self.0, self.0)) {% elif is_coresimd %} {{ vec4_t}}(simd_swizzle!(self.0, [{{ l[j0] }}, {{ l[j1] }}, {{ l[j2] }}, {{ l[j3] }}])) {% else %} {{ vec4_t }}::new(self.{{ e[j0] }}, self.{{ e[j1] }}, self.{{ e[j2] }}, self.{{ e[j3] }}) {% endif %} } {% endif %} {% endfor %} {% endif %} {% endfor %} {% endif %} {% endfor %} {% endfor %} {% endfor %} } glam-0.30.1/templates/swizzle_traits.rs.tera000064400000000000000000000061141046102023000172220ustar 00000000000000// Generated from {{template_path}} template. Edit the template, not the generated file. {% set components = ["x", "y", "z", "w"] %} {% set dimensions = [2, 3, 4] %} {% for dim in dimensions %} {% set vec2_t = "Self::Vec2" %} {% set vec3_t = "Self::Vec3" %} {% set vec4_t = "Self::Vec4" %} {% if dim == 4 %} {% set vec4_t = "Self" %} {% elif dim == 3 %} {% set vec3_t = "Self" %} {% elif dim == 2 %} {% set vec2_t = "Self" %} {% endif %} pub trait Vec{{ dim }}Swizzles: Sized + Copy + Clone { {% if dim != 2 %} type Vec2; {% endif %} {% if dim != 3 %} type Vec3; {% endif %} {% if dim != 4 %} type Vec4; {% endif %} {% if dim == 4 %} #[inline] #[must_use] fn xyzw(self) -> Self { self } {% elif dim == 3 %} #[inline] #[must_use] fn xyz(self) -> Self { self } {% elif dim == 2 %} #[inline] #[must_use] fn xy(self) -> Self { self } {% endif %} {% for i in dimensions %} {% for e0 in components | slice(end=dim) %} {% for e1 in components | slice(end=dim) %} {% if i == 2 %} {% set skip = dim == 2 and e0 == "x" and e1 == "y" %} {% if not skip %} fn {{e0}}{{e1}}(self) -> {{ vec2_t }}; {% endif %} {% set skip = dim == 2 or e0 == e1 %} {% if not skip %} fn with_{{e0}}{{e1}}(self, rhs: {{ vec2_t }}) -> Self; {% endif %} {% else %} {% for e2 in components | slice(end=dim) %} {% if i == 3 %} {% set skip = dim == 3 and e0 == "x" and e1 == "y" and e2 == "z" %} {% if not skip %} fn {{e0}}{{e1}}{{e2}}(self) -> {{ vec3_t }}; {% endif %} {% set skip = dim == 3 or e0 == e1 or e0 == e2 or e1 == e2 %} {% if not skip %} fn with_{{e0}}{{e1}}{{e2}}(self, rhs: {{ vec3_t }}) -> Self; {% endif %} {% else %} {% for e3 in components | slice(end=dim) %} {% set skip = dim == 4 and e0 == "x" and e1 == "y" and e2 == "z" and e3 == "w" %} {% if not skip %} fn {{e0}}{{e1}}{{e2}}{{e3}}(self) -> {{ vec4_t }}; {% endif %} {% endfor %} {% endif %} {% endfor %} {% endif %} {% endfor %} {% endfor %} {% endfor %} } {% endfor %} glam-0.30.1/templates/vec.rs.tera000064400000000000000000004200371046102023000147060ustar 00000000000000{% import "macros.rs.tera" as macros %} // Generated from {{template_path}} template. Edit the template, not the generated file. {% if is_scalar and not is_align %} {% set mask_t = "BVec" ~ dim %} {% else %} {% set is_simd = true %} {% if is_sse2 %} {% set simd_t = "__m128" %} {% elif is_wasm32 %} {% set simd_t = "v128" %} {% elif is_neon %} {% set simd_t = "float32x4_t" %} {% elif is_coresimd %} {% set simd_t = "f32x4" %} {% else %} {% set is_simd = false %} {% endif %} {% set mask_t = "BVec" ~ dim ~ "A" %} {% endif %} {% if scalar_t == "f32" or scalar_t == "f64" %} {% set is_signed = true %} {% set is_float = true %} {% if scalar_t == "f32" %} {% if dim == 3 and is_align %} {% set self_t = "Vec3A" %} {% set mask_t = "BVec3A" %} {% else %} {% set self_t = "Vec" ~ dim %} {% endif %} {% set vec2_t = "Vec2" %} {% set vec3_t = "Vec3" %} {% set vec3a_t = "Vec3A" %} {% set vec4_t = "Vec4" %} {% set quat_t = "Quat" %} {% elif scalar_t == "f64" %} {% set self_t = "DVec" ~ dim %} {% set vec2_t = "DVec2" %} {% set vec3_t = "DVec3" %} {% set vec4_t = "DVec4" %} {% set from_types = ["Vec" ~ dim, "IVec" ~ dim, "UVec" ~ dim] %} {% set quat_t = "DQuat" %} {% endif %} {% elif scalar_t == "i8" %} {% set is_signed = true %} {% set is_float = false %} {% set unsigned_scalar_t = "u8" %} {% set self_t = "I8Vec" ~ dim %} {% set opposite_signedness_t = "U8Vec" ~ dim %} {% set vec2_t = "I8Vec2" %} {% set vec3_t = "I8Vec3" %} {% set vec4_t = "I8Vec4" %} {% set try_from_types = ["U8Vec" ~ dim, "I16Vec" ~ dim, "U16Vec" ~ dim, "IVec" ~ dim, "UVec" ~ dim, "I64Vec" ~ dim, "U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "u8" %} {% set is_signed = false %} {% set is_float = false %} {% set unsigned_scalar_t = "u8" %} {% set self_t = "U8Vec" ~ dim %} {% set opposite_signedness_t = "I8Vec" ~ dim %} {% set vec2_t = "U8Vec2" %} {% set vec3_t = "U8Vec3" %} {% set vec4_t = "U8Vec4" %} {% set try_from_types = ["I8Vec" ~ dim, "I16Vec" ~ dim, "U16Vec" ~ dim, "IVec" ~ dim, "UVec" ~ dim, "I64Vec" ~ dim, "U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "i16" %} {% set is_signed = true %} {% set is_float = false %} {% set unsigned_scalar_t = "u16" %} {% set self_t = "I16Vec" ~ dim %} {% set opposite_signedness_t = "U16Vec" ~ dim %} {% set vec2_t = "I16Vec2" %} {% set vec3_t = "I16Vec3" %} {% set vec4_t = "I16Vec4" %} {% set from_types = ["I8Vec" ~ dim, "U8Vec" ~ dim] %} {% set try_from_types = ["U16Vec" ~ dim, "IVec" ~ dim, "UVec" ~ dim, "I64Vec" ~ dim, "U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "u16" %} {% set is_signed = false %} {% set is_float = false %} {% set unsigned_scalar_t = "u16" %} {% set self_t = "U16Vec" ~ dim %} {% set opposite_signedness_t = "I16Vec" ~ dim %} {% set vec2_t = "U16Vec2" %} {% set vec3_t = "U16Vec3" %} {% set vec4_t = "U16Vec4" %} {% set from_types = ["U8Vec" ~ dim] %} {% set try_from_types = ["I8Vec" ~ dim, "I16Vec" ~ dim, "IVec" ~ dim, "UVec" ~ dim, "I64Vec" ~ dim, "U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "i32" %} {% set is_signed = true %} {% set is_float = false %} {% set unsigned_scalar_t = "u32" %} {% set self_t = "IVec" ~ dim %} {% set opposite_signedness_t = "UVec" ~ dim %} {% set vec2_t = "IVec2" %} {% set vec3_t = "IVec3" %} {% set vec4_t = "IVec4" %} {% set from_types = ["I8Vec" ~ dim, "U8Vec" ~ dim, "I16Vec" ~ dim, "U16Vec" ~ dim] %} {% set try_from_types = ["UVec" ~ dim, "I64Vec" ~ dim, "U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "u32" %} {% set is_signed = false %} {% set is_float = false %} {% set unsigned_scalar_t = "u32" %} {% set self_t = "UVec" ~ dim %} {% set opposite_signedness_t = "IVec" ~ dim %} {% set vec2_t = "UVec2" %} {% set vec3_t = "UVec3" %} {% set vec4_t = "UVec4" %} {% set from_types = ["U8Vec" ~ dim, "U16Vec" ~ dim] %} {% set try_from_types = ["I8Vec" ~ dim, "I16Vec" ~ dim, "IVec" ~ dim, "I64Vec" ~ dim, "U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "i64" %} {% set is_signed = true %} {% set is_float = false %} {% set unsigned_scalar_t = "u64" %} {% set self_t = "I64Vec" ~ dim %} {% set opposite_signedness_t = "U64Vec" ~ dim %} {% set vec2_t = "I64Vec2" %} {% set vec3_t = "I64Vec3" %} {% set vec4_t = "I64Vec4" %} {% set from_types = ["I8Vec" ~ dim, "U8Vec" ~ dim, "I16Vec" ~ dim, "U16Vec" ~ dim, "IVec" ~ dim, "UVec" ~ dim] %} {% set try_from_types = ["U64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "u64" %} {% set is_signed = false %} {% set is_float = false %} {% set unsigned_scalar_t = "u64" %} {% set self_t = "U64Vec" ~ dim %} {% set opposite_signedness_t = "I64Vec" ~ dim %} {% set vec2_t = "U64Vec2" %} {% set vec3_t = "U64Vec3" %} {% set vec4_t = "U64Vec4" %} {% set from_types = ["U8Vec" ~ dim, "U16Vec" ~ dim, "UVec" ~ dim] %} {% set try_from_types = ["I8Vec" ~ dim, "I16Vec" ~ dim, "IVec" ~ dim, "I64Vec" ~ dim, "USizeVec" ~ dim] %} {% elif scalar_t == "usize" %} {% set is_signed = false %} {% set is_float = false %} {% set unsigned_scalar_t = "usize" %} {% set self_t = "USizeVec" ~ dim %} {% set vec2_t = "USizeVec2" %} {% set vec3_t = "USizeVec3" %} {% set vec4_t = "USizeVec4" %} {% set from_types = ["U8Vec" ~ dim, "U16Vec" ~ dim] %} {% set try_from_types = ["I8Vec" ~ dim, "I16Vec" ~ dim, "IVec" ~ dim, "I64Vec" ~ dim, "UVec" ~ dim, "U64Vec" ~ dim] %} {% endif %} {% set bvec_from_type = "BVec" ~ dim %} {% if dim > 2 %} {% set bveca_from_type = "BVec" ~ dim ~ "A" %} {% endif %} {% if dim == 2 %} {% if scalar_t == "i8" or scalar_t == "u8" %} {% set cuda_align = 2 %} {% elif scalar_t == "i16" or scalar_t == "u16" %} {% set cuda_align = 4 %} {% elif scalar_t == "f32" or scalar_t == "i32" or scalar_t == "u32" %} {% set cuda_align = 8 %} {% elif scalar_t == "f64" or scalar_t == "i64" or scalar_t == "u64" %} {% set cuda_align = 16 %} {% elif scalar_t == "usize" %} {# assuming 64 bit here #} {% set cuda_align = 16 %} {% endif %} {% elif dim == 4 %} {% if scalar_t == "i8" or scalar_t == "u8" %} {% set cuda_align = 4 %} {% elif scalar_t == "i16" or scalar_t == "u16" %} {% set cuda_align = 8 %} {% elif scalar_t == "f32" or scalar_t == "i32" or scalar_t == "u32" %} {% set cuda_align = 16 %} {% elif scalar_t == "f64" or scalar_t == "i64" or scalar_t == "u64" %} {% set cuda_align = 16 %} {% elif scalar_t == "usize" %} {# assuming 64 bit here #} {% set cuda_align = 16 %} {% endif %} {% endif %} {% set components = ["x", "y", "z", "w"] | slice(end = dim) %} {% if is_float %} {% set one = "1.0" %} {% set neg_one = "-1.0" %} {% set zero = "0.0" %} {% else %} {% set one = "1" %} {% set neg_one = "-1" %} {% set zero = "0" %} {% endif %} {% if bveca_from_type and bveca_from_type == "BVec4A" and is_scalar %} {% if scalar_t == "f32" %} #[cfg(feature = "scalar-math")] use crate::BVec4 as BVec4A; {% endif %} #[cfg(not(feature = "scalar-math"))] use crate::BVec4A; use crate::{ {% if bveca_from_type and bveca_from_type != mask_t %} {{ mask_t }}, {% endif %} {% else %} use crate::{ {{ mask_t }}, {% if bveca_from_type and bveca_from_type != mask_t %} {{ bveca_from_type }}, {% endif %} {% endif %} {% if self_t != vec2_t %} {{ vec2_t }}, {% endif %} {% if self_t != vec3_t %} {{ vec3_t }}, {% endif %} {% if self_t == "Vec4" %} {{ vec3a_t }}, {% endif %} {% if dim > 2 and self_t != vec4_t %} {{ vec4_t }}, {% endif %} {% if is_sse2 %} sse2::*, {% elif is_wasm32 %} wasm32::*, {% elif is_neon %} neon::*, {% elif is_coresimd %} coresimd::*, {% endif %} {% if is_float %} {{ scalar_t }}::math, {% if dim == 3 %} FloatExt, {{ quat_t }}, {% endif %} {% endif %} {% if from_types %} {% for ty in from_types %} {{ ty }}, {% endfor %} {% endif %} {% if try_from_types %} {% for ty in try_from_types %} {{ ty }}, {% endfor %} {% endif %} {% if bvec_from_type != mask_t %} {{ bvec_from_type }}, {% endif %} }; use core::fmt; use core::iter::{Product, Sum}; use core::{f32, ops::*}; {% if is_sse2 %} #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; {% elif is_wasm32 %} use core::arch::wasm32::*; {% elif is_coresimd %} use core::simd::{cmp::SimdPartialEq, cmp::SimdPartialOrd, num::SimdFloat, *}; use std::simd::StdFloat; {% elif is_neon %} use core::arch::aarch64::*; {% endif %} {% if is_sse2 or is_neon %} #[repr(C)] union UnionCast { a: [f32; 4], v: {{ self_t }} } {% endif %} /// Creates a {{ dim }}-dimensional vector. #[inline(always)] #[must_use] pub const fn {{ self_t | lower }}( {% for c in components %} {{ c }}: {{ scalar_t }}, {% endfor %} ) -> {{ self_t }} { {{ self_t }}::new({{ components | join(sep=",") }}) } /// A {{ dim }}-dimensional vector. {%- if self_t == "Vec3A" %} /// /// 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`] /// or [`Into`] trait implementations. /// /// This type is 16 byte aligned. {%- elif self_t == "Vec4" and is_simd %} /// /// SIMD vector types are used for storage on supported platforms. /// /// This type is 16 byte aligned. {%- endif %} {%- if not is_float %} #[cfg_attr(not(target_arch = "spirv"), derive(Hash))] {%- endif %} #[derive( Clone, Copy, {% if is_scalar %} PartialEq, {% if not is_float %} Eq, {% endif %} {% endif %} )] {%- if self_t == "Vec3A" and is_scalar %} #[cfg_attr(not(target_arch = "spirv"), repr(align(16)))] {%- elif self_t == "Vec4" and is_scalar %} #[cfg_attr( any( not(any(feature = "scalar-math", target_arch = "spirv")), feature = "cuda"), repr(align(16)) )] {%- elif dim != 3 and is_scalar %} #[cfg_attr(feature = "cuda", repr(align({{ cuda_align }})))] {%- endif %} {%- if is_scalar %} #[cfg_attr(not(target_arch = "spirv"), repr(C))] #[cfg_attr(target_arch = "spirv", repr(simd))] pub struct {{ self_t }} { {% for c in components %} pub {{ c }}: {{ scalar_t }}, {%- endfor %} } {% else %} #[repr(transparent)] pub struct {{ self_t }}(pub(crate) {{ simd_t }}); {% endif %} impl {{ self_t }} { /// All zeroes. pub const ZERO: Self = Self::splat({{ zero }}); /// All ones. pub const ONE: Self = Self::splat({{ one }}); {% if is_signed %} /// All negative ones. pub const NEG_ONE: Self = Self::splat(-{{ one }}); {% endif %} /// All `{{ scalar_t }}::MIN`. pub const MIN: Self = Self::splat({{ scalar_t }}::MIN); /// All `{{ scalar_t }}::MAX`. pub const MAX: Self = Self::splat({{ scalar_t }}::MAX); {% if is_float %} /// All `{{ scalar_t }}::NAN`. pub const NAN: Self = Self::splat({{ scalar_t }}::NAN); /// All `{{ scalar_t }}::INFINITY`. pub const INFINITY: Self = Self::splat({{ scalar_t }}::INFINITY); /// All `{{ scalar_t }}::NEG_INFINITY`. pub const NEG_INFINITY: Self = Self::splat({{ scalar_t }}::NEG_INFINITY); {% endif %} {% for i in range(end = dim) %} {% set C = components[i] | upper %} /// A unit vector pointing along the positive {{ C }} axis. pub const {{ C }}: Self = Self::new( {% for j in range(end = dim) %} {% if i == j %} {{ one }} {% else %} {{ zero }} {% endif %}, {%- endfor %} ); {% endfor %} {% if is_signed %} {% for i in range(end = dim) %} {% set C = components[i] | upper %} /// A unit vector pointing along the negative {{ C }} axis. pub const NEG_{{ C }}: Self = Self::new( {% for j in range(end = dim) %} {% if i == j %} {{ neg_one }} {% else %} {{ zero }} {% endif %}, {%- endfor %} ); {% endfor %} {% endif %} /// The unit axes. pub const AXES: [Self; {{ dim }}] = [ {% for c in components %} Self::{{ c | upper }}, {% endfor %} ]; /// Creates a new vector. #[inline(always)] #[must_use] pub const fn new( {% for c in components %} {{ c }}: {{ scalar_t }}, {% endfor %} ) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}, {%- endfor %} } {% elif is_sse2 %} unsafe { UnionCast { a: [ {% if dim == 3 %} x, y, z, z {% elif dim == 4 %} x, y, z, w {% endif %} ] }.v } {% elif is_wasm32 %} Self(f32x4( {% if dim == 3 %} x, y, z, z {% elif dim == 4 %} x, y, z, w {% endif %} )) {% elif is_coresimd %} Self(f32x4::from_array([ x, y, z, {% if dim == 3 %} z {% elif dim == 4 %} w {% endif %} ])) {% elif is_neon %} {% if dim == 3 %} unsafe { UnionCast { a: [x, y, z, z] }.v } {% elif dim == 4 %} unsafe { UnionCast { a: [x, y, z, w] }.v } {% endif %} {% endif %} } /// Creates a vector with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: v, {% endfor %} } {% elif is_wasm32 %} Self(f32x4(v, v, v, v)) {% elif is_coresimd %} Self(Simd::from_array([v; 4])) {% else %} unsafe { UnionCast { a: [v; 4] }.v } {% endif %} } /// Returns a vector containing each element of `self` modified by a mapping function `f`. #[inline] #[must_use] pub fn map(self, f: F) -> Self where F: Fn({{ scalar_t }}) -> {{ scalar_t }}, { Self::new( {% for c in components %} f(self.{{ c }}), {%- endfor %} ) } /// 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: {{ mask_t }}, if_true: Self, if_false: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: if mask.test({{ loop.index0 }}) { if_true.{{ c }} } else { if_false.{{ c }} }, {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_or_ps(_mm_andnot_ps(mask.0, if_false.0), _mm_and_ps(if_true.0, mask.0)) }) {% elif is_wasm32 %} Self(v128_bitselect(if_true.0, if_false.0, mask.0)) {% elif is_coresimd %} Self(mask.0.select(if_true.0, if_false.0)) {% elif is_neon %} Self(unsafe { vbslq_f32(mask.0, if_true.0, if_false.0) }) {% endif %} } /// Creates a new vector from an array. #[inline] #[must_use] pub const fn from_array(a: [{{ scalar_t }}; {{ dim }}]) -> Self { Self::new( {% for c in components %} a[{{ loop.index0 }}], {%- endfor %} ) } /// `[{{ components | join(sep=", ") }}]` #[inline] #[must_use] pub const fn to_array(&self) -> [{{ scalar_t }}; {{ dim }}] { {% if is_scalar %} [ {% for c in components %} self.{{ c }}, {% endfor %} ] {% else %} unsafe { *(self as *const {{ self_t }} as *const [{{ scalar_t }}; {{ dim }}]) } {% endif %} } /// Creates a vector from the first {{ dim }} values in `slice`. /// /// # Panics /// /// Panics if `slice` is less than {{ dim }} elements long. #[inline] #[must_use] pub const fn from_slice(slice: &[{{ scalar_t }}]) -> Self { assert!(slice.len() >= {{ dim }}); Self::new( {% for c in components %} slice[{{ loop.index0 }}], {%- endfor %} ) } /// Writes the elements of `self` to the first {{ dim }} elements in `slice`. /// /// # Panics /// /// Panics if `slice` is less than {{ dim }} elements long. #[inline] pub fn write_to_slice(self, slice: &mut [{{ scalar_t }}]) { {% if self_t == "Vec4" and is_sse2 %} assert!(slice.len() >= 4); unsafe { _mm_storeu_ps(slice.as_mut_ptr(), self.0); } {% elif self_t == "Vec4" and is_neon %} assert!(slice.len() >= 4); unsafe { vst1q_f32(slice.as_mut_ptr(), self.0); } {% else %} slice[..{{ dim }}].copy_from_slice(&self.to_array()); {% endif %} } {% if dim == 2 %} /// Creates a 3D vector from `self` and the given `z` value. #[inline] #[must_use] pub const fn extend(self, z: {{ scalar_t }}) -> {{ vec3_t }} { {{ vec3_t }}::new(self.x, self.y, z) } {% elif dim == 3 %} {% if self_t == "Vec3A" %} /// 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] #[must_use] pub fn from_vec4(v: Vec4) -> Self { {% if is_scalar %} Self { x: v.x, y: v.y, z: v.z } {% else %} Self(v.0) {% endif %} } {% else %} /// 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_t }}) -> Self { {% if is_scalar %} Self { x: v.x, y: v.y, z: v.z } {% else %} Self(v.0) {% endif %} } {% endif %} /// Creates a 4D vector from `self` and the given `w` value. #[inline] #[must_use] pub fn extend(self, w: {{ scalar_t }}) -> {{ vec4_t }} { {{ vec4_t }}::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) -> {{ vec2_t }} { use crate::swizzles::Vec3Swizzles; self.xy() } {% elif dim == 4 %} /// Creates a 3D vector from the `x`, `y` and `z` elements of `self`, discarding `w`. /// /// Truncation to [`{{ vec3_t }}`] may also be performed by using [`self.xyz()`][crate::swizzles::Vec4Swizzles::xyz()]. {%- if scalar_t == "f32" %} /// /// To truncate to [`Vec3A`] use [`Vec3A::from_vec4()`]. {%- endif %} #[inline] #[must_use] pub fn truncate(self) -> {{ vec3_t }} { use crate::swizzles::Vec4Swizzles; self.xyz() } {% endif %} {% for c in components %} /// Creates a {{ dim }}D vector from `self` with the given value of `{{ c }}`. #[inline] #[must_use] pub fn with_{{ c }}(mut self, {{ c }}: {{ scalar_t }}) -> Self { self.{{ c }} = {{ c }}; self } {% endfor %} /// Computes the dot product of `self` and `rhs`. #[inline] #[must_use] pub fn dot(self, rhs: Self) -> {{ scalar_t }} { {% if is_scalar %} {% for c in components %} (self.{{ c }} * rhs.{{ c }}) {% if not loop.last %} + {% endif %} {%- endfor %} {% elif is_sse2 %} unsafe { dot{{ dim }}(self.0, rhs.0) } {% elif is_neon %} {% if dim < 4 %} // this was faster than intrinsics in testing {%- for c in components %} (self.{{ c }} * rhs.{{ c }}) {% if not loop.last %} + {% endif %} {%- endfor %} {% else %} unsafe { dot{{ dim }}(self.0, rhs.0) } {% endif %} {% else %} dot{{ dim }}(self.0, rhs.0) {% endif %} } /// 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 { {% if is_scalar %} Self::splat(self.dot(rhs)) {% elif is_sse2 %} Self(unsafe { dot{{ dim }}_into_m128(self.0, rhs.0) }) {% elif is_wasm32 %} Self(dot{{ dim }}_into_v128(self.0, rhs.0)) {% elif is_coresimd %} Self(dot{{ dim }}_into_f32x4(self.0, rhs.0)) {% elif is_neon %} Self(unsafe { dot{{ dim }}_into_f32x4(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } {% if dim == 3 %} /// Computes the cross product of `self` and `rhs`. #[inline] #[must_use] pub fn cross(self, rhs: Self) -> Self { {% if is_scalar %} 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, } {% elif is_sse2 %} unsafe { // x <- a.y*b.z - a.z*b.y // y <- a.z*b.x - a.x*b.z // z <- a.x*b.y - a.y*b.x // We can save a shuffle by grouping it in this wacky order: // (self.zxy() * rhs - self * rhs.zxy()).zxy() let lhszxy = _mm_shuffle_ps(self.0, self.0, 0b01_01_00_10); let rhszxy = _mm_shuffle_ps(rhs.0, rhs.0, 0b01_01_00_10); let lhszxy_rhs = _mm_mul_ps(lhszxy, rhs.0); let rhszxy_lhs = _mm_mul_ps(rhszxy, self.0); let sub = _mm_sub_ps(lhszxy_rhs, rhszxy_lhs); Self(_mm_shuffle_ps(sub, sub, 0b01_01_00_10)) } {% elif is_wasm32 %} let lhszxy = i32x4_shuffle::<2, 0, 1, 1>(self.0, self.0); let rhszxy = i32x4_shuffle::<2, 0, 1, 1>(rhs.0, rhs.0); let lhszxy_rhs = f32x4_mul(lhszxy, rhs.0); let rhszxy_lhs = f32x4_mul(rhszxy, self.0); let sub = f32x4_sub(lhszxy_rhs, rhszxy_lhs); Self(i32x4_shuffle::<2, 0, 1, 1>(sub, sub)) {% elif is_coresimd %} let lhszxy = simd_swizzle!(self.0, [2, 0, 1, 1]); let rhszxy = simd_swizzle!(rhs.0, [2, 0, 1, 1]); let lhszxy_rhs = lhszxy * rhs.0; let rhszxy_lhs = rhszxy * self.0; let sub = lhszxy_rhs - rhszxy_lhs; Self(simd_swizzle!(sub, [2, 0, 1, 1])) {% elif is_neon %} unsafe { // Implementation taken from Realtime Math let lhs = self.0; let rhs = rhs.0; // cross(a, b) = (a.yzx * b.zxy) - (a.zxy * b.yzx) let lhs_yzwx = vextq_f32(lhs, lhs, 1); let rhs_wxyz = vextq_f32(rhs, rhs, 3); let lhs_yzx = vsetq_lane_f32(vgetq_lane_f32(lhs, 0), lhs_yzwx, 2); let rhs_zxy = vsetq_lane_f32(vgetq_lane_f32(rhs, 2), rhs_wxyz, 0); // part_a = (a.yzx * b.zxy) let part_a = vmulq_f32(lhs_yzx, rhs_zxy); let lhs_wxyz = vextq_f32(lhs, lhs, 3); let rhs_yzwx = vextq_f32(rhs, rhs, 1); let lhs_zxy = vsetq_lane_f32(vgetq_lane_f32(lhs, 2), lhs_wxyz, 0); let rhs_yzx = vsetq_lane_f32(vgetq_lane_f32(rhs, 0), rhs_yzwx, 2); // result = part_a - (a.zxy * b.yzx) let result = vmlsq_f32(part_a, lhs_zxy, rhs_yzx); Self(result) } {% else %} unimplemented!() {% endif %} } {% endif %} /// 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 { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.min(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_min_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(f32x4_pmin(self.0, rhs.0)) {% elif is_coresimd %} Self(self.0.simd_min(rhs.0)) {% elif is_neon %} Self(unsafe { vminq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } /// 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 { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.max(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_max_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(f32x4_pmax(self.0, rhs.0)) {% elif is_coresimd %} Self(self.0.simd_max(rhs.0)) {% elif is_neon %} Self(unsafe { vmaxq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } /// Component-wise clamping of values, similar to [`{{ scalar_t }}::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) -> {{ scalar_t }} { {% if is_scalar %} {% if dim == 2 %} self.x.min(self.y) {% elif dim == 3 %} self.x.min(self.y.min(self.z)) {% elif dim == 4 %} self.x.min(self.y.min(self.z.min(self.w))) {% endif %} {% elif is_sse2 %} {% if dim == 3 %} unsafe { let v = self.0; let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b01_01_10_10)); let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } {% elif dim == 4 %} unsafe { let v = self.0; let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b00_00_11_10)); let v = _mm_min_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } {% endif %} {% elif is_wasm32 %} {% if dim == 3 %} let v = self.0; let v = f32x4_pmin(v, i32x4_shuffle::<2, 2, 1, 1>(v, v)); let v = f32x4_pmin(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% elif dim == 4 %} let v = self.0; let v = f32x4_pmin(v, i32x4_shuffle::<2, 3, 0, 0>(v, v)); let v = f32x4_pmin(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% endif %} {% elif is_coresimd %} {% if dim == 3 %} let v = self.0; let v = v.simd_min(simd_swizzle!(v, [2, 2, 1, 1])); let v = v.simd_min(simd_swizzle!(v, [1, 0, 0, 0])); v[0] {% elif dim == 4 %} self.0.reduce_min() {% endif %} {% elif is_neon %} {% if dim == 3 %} self.x.min(self.y.min(self.z)) {% elif dim == 4 %} unsafe { vminnmvq_f32(self.0) } {% endif %} {% else %} unimplemented!() {% endif %} } /// Returns the horizontal maximum of `self`. /// /// In other words this computes `max(x, y, ..)`. #[inline] #[must_use] pub fn max_element(self) -> {{ scalar_t }} { {% if is_scalar %} {% if dim == 2 %} self.x.max(self.y) {% elif dim == 3 %} self.x.max(self.y.max(self.z)) {% elif dim == 4 %} self.x.max(self.y.max(self.z.max(self.w))) {% endif %} {% elif is_sse2 %} {% if dim == 3 %} unsafe { let v = self.0; let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_10_10)); let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } {% elif dim == 4 %} unsafe { let v = self.0; let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_11_10)); let v = _mm_max_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_01)); _mm_cvtss_f32(v) } {% endif %} {% elif is_wasm32 %} {% if dim == 3 %} let v = self.0; let v = f32x4_pmax(v, i32x4_shuffle::<2, 2, 0, 0>(v, v)); let v = f32x4_pmax(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% elif dim == 4 %} let v = self.0; let v = f32x4_pmax(v, i32x4_shuffle::<2, 3, 0, 0>(v, v)); let v = f32x4_pmax(v, i32x4_shuffle::<1, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% endif %} {% elif is_coresimd %} {% if dim == 3 %} let v = self.0; let v = v.simd_max(simd_swizzle!(v, [2, 2, 0, 0])); let v = v.simd_max(simd_swizzle!(v, [1, 0, 0, 0])); v[0] {% elif dim == 4 %} self.0.reduce_max() {% endif %} {% elif is_neon %} {% if dim == 3 %} self.x.max(self.y.max(self.z)) {% elif dim == 4 %} unsafe { vmaxnmvq_f32(self.0) } {% endif %} {% else %} unimplemented!() {% endif %} } /// Returns the index of the first minimum element of `self`. #[doc(alias = "argmin")] #[inline] #[must_use] pub fn min_position(self) -> usize { {% if dim == 2 %} if self.x <= self.y { 0 } else { 1 } {% elif dim == 3 %} let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { index = 2; } index {% elif dim == 4 %} let mut min = self.x; let mut index = 0; if self.y < min { min = self.y; index = 1; } if self.z < min { min = self.z; index = 2; } if self.w < min { index = 3; } index {% endif %} } /// Returns the index of the first maximum element of `self`. #[doc(alias = "argmax")] #[inline] #[must_use] pub fn max_position(self) -> usize { {% if dim == 2 %} if self.x >= self.y { 0 } else { 1 } {% elif dim == 3 %} let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { index = 2; } index {% elif dim == 4 %} let mut max = self.x; let mut index = 0; if self.y > max { max = self.y; index = 1; } if self.z > max { max = self.z; index = 2; } if self.w > max { index = 3; } index {% endif %} } /// Returns the sum of all elements of `self`. /// /// In other words, this computes `self.x + self.y + ..`. #[inline] #[must_use] pub fn element_sum(self) -> {{ scalar_t }} { {% if is_scalar %} {% for c in components %} self.{{ c }} {% if not loop.last %} + {% endif %} {%- endfor %} {% elif is_sse2 %} {% if dim == 3 %} unsafe { let v = self.0; let v = _mm_add_ps(v, _mm_shuffle_ps(v, Self::ZERO.0, 0b00_11_00_01)); let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } {% elif dim == 4 %} unsafe { let v = self.0; let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01)); let v = _mm_add_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } {% endif %} {% elif is_wasm32 %} {% if dim == 3 %} let v = self.0; let v = f32x4_add(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ZERO.0)); let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% elif dim == 4 %} let v = self.0; let v = f32x4_add(v, i32x4_shuffle::<1, 0, 3, 0>(v, v)); let v = f32x4_add(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% endif %} {% elif is_coresimd %} {% if dim == 3 %} simd_swizzle!(self.0, Self::ZERO.0, [0, 1, 2, 4]).reduce_sum() {% elif dim == 4 %} self.0.reduce_sum() {% endif %} {% elif is_neon %} {% if dim == 3 %} unsafe { vaddvq_f32(vsetq_lane_f32(0.0, self.0, 3)) } {% elif dim == 4 %} unsafe { vaddvq_f32(self.0) } {% endif %} {% else %} unimplemented!() {% endif %} } /// Returns the product of all elements of `self`. /// /// In other words, this computes `self.x * self.y * ..`. #[inline] #[must_use] pub fn element_product(self) -> {{ scalar_t }} { {% if is_scalar %} {% for c in components %} self.{{ c }} {% if not loop.last %} * {% endif %} {%- endfor %} {% elif is_sse2 %} {% if dim == 3 %} unsafe { let v = self.0; let v = _mm_mul_ps(v, _mm_shuffle_ps(v, Self::ONE.0, 0b00_11_00_01)); let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } {% elif dim == 4 %} unsafe { let v = self.0; let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_11_00_01)); let v = _mm_mul_ps(v, _mm_shuffle_ps(v, v, 0b00_00_00_10)); _mm_cvtss_f32(v) } {% endif %} {% elif is_wasm32 %} {% if dim == 3 %} let v = self.0; let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 4, 0>(v, Self::ONE.0)); let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% elif dim == 4 %} let v = self.0; let v = f32x4_mul(v, i32x4_shuffle::<1, 0, 3, 0>(v, v)); let v = f32x4_mul(v, i32x4_shuffle::<2, 0, 0, 0>(v, v)); f32x4_extract_lane::<0>(v) {% endif %} {% elif is_coresimd %} {% if dim == 3 %} simd_swizzle!(self.0, Self::ONE.0, [0, 1, 2, 4]).reduce_product() {% elif dim == 4 %} self.0.reduce_product() {% endif %} {% elif is_neon %} {% if dim == 3 %} unsafe { let s = vmuls_laneq_f32(vgetq_lane_f32(self.0, 0), self.0, 1); vmuls_laneq_f32(s, self.0, 2) } {% elif dim == 4 %} unsafe { let s = vmuls_laneq_f32(vgetq_lane_f32(self.0, 0), self.0, 1); let s = vmuls_laneq_f32(s, self.0, 2); vmuls_laneq_f32(s, self.0, 3) } {% endif %} {% else %} unimplemented!() {% endif %} } /// 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) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.eq(&rhs.{{ c }}), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmpeq_ps(self.0, rhs.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_eq(self.0, rhs.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::simd_eq(self.0, rhs.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vceqq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } /// 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) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.ne(&rhs.{{ c }}), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmpneq_ps(self.0, rhs.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_ne(self.0, rhs.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::simd_ne(self.0, rhs.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vmvnq_u32(vceqq_f32(self.0, rhs.0)) }) {% else %} unimplemented!() {% endif %} } /// 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) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.ge(&rhs.{{ c }}), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmpge_ps(self.0, rhs.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_ge(self.0, rhs.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::simd_ge(self.0, rhs.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vcgeq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } /// 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) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.gt(&rhs.{{ c }}), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmpgt_ps(self.0, rhs.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_gt(self.0, rhs.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::simd_gt(self.0, rhs.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vcgtq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } /// 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) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.le(&rhs.{{ c }}), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmple_ps(self.0, rhs.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_le(self.0, rhs.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::simd_le(self.0, rhs.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vcleq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } /// 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) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.lt(&rhs.{{ c }}), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmplt_ps(self.0, rhs.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_lt(self.0, rhs.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::simd_lt(self.0, rhs.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vcltq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } {% if is_signed %} /// Returns a vector containing the absolute value of each element of `self`. #[inline] #[must_use] pub fn abs(self) -> Self { {% if is_scalar %} Self { {% for c in components %} {%- if is_float %} {{ c }}: math::abs(self.{{ c }}), {%- else %} {{ c }}: self.{{ c }}.abs(), {%- endif %} {%- endfor %} } {% elif is_sse2 %} Self(unsafe { crate::sse2::m128_abs(self.0) }) {% elif is_wasm32 %} Self(f32x4_abs(self.0)) {% elif is_coresimd %} Self(self.0.abs()) {% elif is_neon %} Self(unsafe { vabsq_f32(self.0) }) {% else %} unimplemented!() {% endif %} } /// Returns a vector with elements representing the sign of `self`. /// {% if is_float -%} /// - `1.0` if the number is positive, `+0.0` or `INFINITY` /// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` /// - `NAN` if the number is `NAN` {%- else -%} /// - `0` if the number is zero /// - `1` if the number is positive /// - `-1` if the number is negative {%- endif %} #[inline] #[must_use] pub fn signum(self) -> Self { {% if is_scalar %} Self { {% for c in components %} {%- if is_float %} {{ c }}: math::signum(self.{{ c }}), {%- else %} {{ c }}: self.{{ c }}.signum(), {%- endif %} {%- endfor %} } {% elif is_coresimd %} Self(self.0.signum()) {% elif is_sse2 %} let result = Self(unsafe { _mm_or_ps(_mm_and_ps(self.0, Self::NEG_ONE.0), Self::ONE.0) }); let mask = self.is_nan_mask(); Self::select(mask, self, result) {% elif is_wasm32 %} let result = Self(v128_or(v128_and(self.0, Self::NEG_ONE.0), Self::ONE.0)); let mask = self.is_nan_mask(); Self::select(mask, self, result) {% elif is_neon %} let result = Self(unsafe { vreinterpretq_f32_u32(vorrq_u32( vandq_u32( vreinterpretq_u32_f32(self.0), vreinterpretq_u32_f32(Self::NEG_ONE.0)), vreinterpretq_u32_f32(Self::ONE.0), )) }); let mask = self.is_nan_mask(); Self::select(mask, self, result) {% else %} unimplemented!() {% endif %} } {% if is_float %} /// Returns a vector with signs of `rhs` and the magnitudes of `self`. #[inline] #[must_use] pub fn copysign(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: math::copysign(self.{{ c }}, rhs.{{ c }}), {%- endfor %} } {% elif is_coresimd %} Self(self.0.copysign(rhs.0)) {% elif is_sse2 %} let mask = Self::splat(-0.0); Self(unsafe { _mm_or_ps(_mm_and_ps(rhs.0, mask.0), _mm_andnot_ps(mask.0, self.0)) }) {% elif is_wasm32 %} let mask = Self::splat(-0.0); Self(v128_or(v128_and(rhs.0, mask.0), v128_andnot(self.0, mask.0))) {% elif is_neon %} let mask = Self::splat(-0.0); Self(unsafe { vreinterpretq_f32_u32(vorrq_u32( vandq_u32(vreinterpretq_u32_f32(rhs.0), vreinterpretq_u32_f32(mask.0)), vandq_u32( vreinterpretq_u32_f32(self.0), vmvnq_u32(vreinterpretq_u32_f32(mask.0))) )) }) {% else %} unimplemented!(); {% endif %} } {% endif %} /// Returns a bitmask with the lowest {{ dim }} 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 { {% if is_scalar and is_float %} {% for c in components %} {% if loop.first %} (self.{{ c }}.is_sign_negative() as u32) | {% else %} ((self.{{ c }}.is_sign_negative() as u32) << {{ loop.index0 }}) {% if not loop.last %} | {% endif %} {% endif %} {% endfor %} {% elif is_scalar %} {% for c in components %} {% if loop.first %} (self.{{ c }}.is_negative() as u32) | {% else %} ((self.{{ c }}.is_negative() as u32) << {{ loop.index0 }}) {% if not loop.last %} | {% endif %} {% endif %} {% endfor %} {% elif is_sse2 %} {% if dim == 3 %} unsafe { (_mm_movemask_ps(self.0) as u32) & 0x7 } {% elif dim == 4 %} unsafe { _mm_movemask_ps(self.0) as u32 } {% endif %} {% elif is_wasm32 %} {% if dim == 3 %} (u32x4_bitmask(self.0) & 0x7) as u32 {% elif dim == 4 %} u32x4_bitmask(self.0) as u32 {% endif %} {% elif is_coresimd %} {% if dim == 3 %} (self.0.is_sign_negative().to_bitmask() & 0x7) as u32 {% elif dim == 4 %} self.0.is_sign_negative().to_bitmask() as u32 {% endif %} {% elif is_neon %} unsafe { let nmask = vreinterpretq_u32_f32(vdupq_n_f32(-0.0)); let m = vandq_u32(vreinterpretq_u32_f32(self.0), nmask); let x = vgetq_lane_u32(m, 0) >> 31; let y = vgetq_lane_u32(m, 1) >> 31; let z = vgetq_lane_u32(m, 2) >> 31; {% if dim == 3 %} x | y << 1 | z << 2 {% elif dim == 4 %} let w = vgetq_lane_u32(m, 3) >> 31; x | y << 1 | z << 2 | w << 3 {% endif %} } {% else %} unimplemented!() {% endif %} } {% endif %} {% if is_float %} /// 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 { {% if is_scalar %} {% for c in components %} self.{{ c }}.is_finite() {% if not loop.last %} && {% endif %} {%- endfor %} {% else %} self.is_finite_mask().all() {% endif %} } /// Performs `is_finite` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_finite(), y.is_finite(), ...]`. pub fn is_finite_mask(self) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.is_finite(), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmplt_ps(crate::sse2::m128_abs(self.0), Self::INFINITY.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_lt(f32x4_abs(self.0), Self::INFINITY.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::is_finite(self.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vcltq_f32(vabsq_f32(self.0), Self::INFINITY.0) }) {% endif %} } /// Returns `true` if any elements are `NaN`. #[inline] #[must_use] pub fn is_nan(self) -> bool { {% if is_scalar %} {% for c in components %} self.{{ c }}.is_nan() {% if not loop.last %} || {% endif %} {%- endfor %} {% else %} self.is_nan_mask().any() {% endif %} } /// Performs `is_nan` on each element of self, returning a vector mask of the results. /// /// In other words, this computes `[x.is_nan(), y.is_nan(), ...]`. #[inline] #[must_use] pub fn is_nan_mask(self) -> {{ mask_t }} { {% if is_scalar %} {{ mask_t }}::new( {% for c in components %} self.{{ c }}.is_nan(), {%- endfor %} ) {% elif is_sse2 %} {{ mask_t }}(unsafe { _mm_cmpunord_ps(self.0, self.0) }) {% elif is_wasm32 %} {{ mask_t }}(f32x4_ne(self.0, self.0)) {% elif is_coresimd %} {{ mask_t }}(f32x4::is_nan(self.0)) {% elif is_neon %} {{ mask_t }}(unsafe { vmvnq_u32(vceqq_f32(self.0, self.0)) }) {% endif %} } /// Computes the length of `self`. #[doc(alias = "magnitude")] #[inline] #[must_use] pub fn length(self) -> {{ scalar_t }} { {% if is_scalar or is_neon %} math::sqrt(self.dot(self)) {% elif is_sse2 %} unsafe { let dot = dot{{ dim }}_in_x(self.0, self.0); _mm_cvtss_f32(_mm_sqrt_ps(dot)) } {% elif is_wasm32 %} let dot = dot{{ dim }}_in_x(self.0, self.0); f32x4_extract_lane::<0>(f32x4_sqrt(dot)) {% elif is_coresimd %} let dot = dot{{ dim }}_in_x(self.0, self.0); dot.sqrt()[0] {% endif %} } {% endif %} /// Computes the squared length of `self`. {%- if is_float %} /// /// This is faster than `length()` as it avoids a square root operation. {%- endif %} #[doc(alias = "magnitude2")] #[inline] #[must_use] pub fn length_squared(self) -> {{ scalar_t }} { self.dot(self) } {% if is_float %} /// Computes `1.0 / length()`. /// /// For valid results, `self` must _not_ be of length zero. #[inline] #[must_use] pub fn length_recip(self) -> {{ scalar_t }} { {% if is_scalar or is_neon %} self.length().recip() {% elif is_sse2 %} unsafe { let dot = dot{{ dim }}_in_x(self.0, self.0); _mm_cvtss_f32(_mm_div_ps(Self::ONE.0, _mm_sqrt_ps(dot))) } {% elif is_wasm32 %} let dot = dot{{ dim }}_in_x(self.0, self.0); f32x4_extract_lane::<0>(f32x4_div(Self::ONE.0, f32x4_sqrt(dot))) {% elif is_coresimd %} let dot = dot{{ dim }}_in_x(self.0, self.0); dot.sqrt().recip()[0] {% endif %} } /// Computes the Euclidean distance between two points in space. #[inline] #[must_use] pub fn distance(self, rhs: Self) -> {{ scalar_t }} { (self - rhs).length() } {% endif %} {% if is_signed %} /// Compute the squared euclidean distance between two points in space. #[inline] #[must_use] pub fn distance_squared(self, rhs: Self) -> {{ scalar_t }} { (self - rhs).length_squared() } /// Returns the element-wise quotient of [Euclidean division] of `self` by `rhs`. {%- if not is_float%} /// /// # Panics /// This function will panic if any `rhs` element is 0 or the division results in overflow. {%- endif %} #[inline] #[must_use] pub fn div_euclid(self, rhs: Self) -> Self { Self::new( {% for c in components %} {% if is_float %} math::div_euclid(self.{{ c }}, rhs.{{ c }}), {% else %} self.{{ c }}.div_euclid(rhs.{{ c }}), {% endif %} {%- endfor %} ) } /// Returns the element-wise remainder of [Euclidean division] of `self` by `rhs`. {%- if not is_float %} /// /// # Panics /// This function will panic if any `rhs` element is 0 or the division results in overflow. {%- endif %} /// /// [Euclidean division]: {{scalar_t}}::rem_euclid #[inline] #[must_use] pub fn rem_euclid(self, rhs: Self) -> Self { Self::new( {% for c in components %} {% if is_float %} math::rem_euclid(self.{{ c }}, rhs.{{ c }}), {% else %} self.{{ c }}.rem_euclid(rhs.{{ c }}), {% endif %} {%- endfor %} ) } {% endif %} {% if is_float %} /// Returns `self` normalized to length 1.0. /// /// For valid results, `self` must be finite and _not_ of length zero, nor very close to zero. /// /// See also [`Self::try_normalize()`] and [`Self::normalize_or_zero()`]. /// /// Panics /// /// Will panic if the resulting normalized vector is not finite when `glam_assert` is enabled. #[inline] #[must_use] pub fn normalize(self) -> Self { {% if is_scalar or is_neon %} #[allow(clippy::let_and_return)] let normalized = self.mul(self.length_recip()); glam_assert!(normalized.is_finite()); normalized {% elif is_sse2 %} unsafe { let length = _mm_sqrt_ps(dot{{ dim }}_into_m128(self.0, self.0)); #[allow(clippy::let_and_return)] let normalized = Self(_mm_div_ps(self.0, length)); glam_assert!(normalized.is_finite()); normalized } {% elif is_wasm32 %} let length = f32x4_sqrt(dot{{ dim }}_into_v128(self.0, self.0)); #[allow(clippy::let_and_return)] let normalized = Self(f32x4_div(self.0, length)); glam_assert!(normalized.is_finite()); normalized {% elif is_coresimd %} let length = dot{{ dim }}_into_f32x4(self.0, self.0).sqrt(); #[allow(clippy::let_and_return)] let normalized = Self(self.0 / length); glam_assert!(normalized.is_finite()); normalized {% else %} unimplemented!() {% endif %} } /// Returns `self` normalized to length 1.0 if possible, else returns `None`. /// /// 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()`]. #[inline] #[must_use] pub fn try_normalize(self) -> Option { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { Some(self * rcp) } else { None } } /// Returns `self` normalized to length 1.0 if possible, else returns a /// fallback value. /// /// In particular, if the input is zero (or very close to zero), or non-finite, /// the result of this operation will be the fallback value. /// /// See also [`Self::try_normalize()`]. #[inline] #[must_use] pub fn normalize_or(self, fallback: Self) -> Self { let rcp = self.length_recip(); if rcp.is_finite() && rcp > 0.0 { self * rcp } else { fallback } } /// Returns `self` normalized to length 1.0 if possible, else returns zero. /// /// 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()`]. #[inline] #[must_use] pub fn normalize_or_zero(self) -> Self { self.normalize_or(Self::ZERO) } /// Returns whether `self` is length `1.0` or not. /// /// Uses a precision threshold of approximately `1e-4`. #[inline] #[must_use] pub fn is_normalized(self) -> bool { math::abs(self.length_squared() - 1.0) <= 2e-4 } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` is zero length when `glam_assert` is enabled. #[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()); rhs * self.dot(rhs) * other_len_sq_rcp } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be of non-zero length. /// /// # Panics /// /// Will panic if `rhs` has a length of zero when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from(self, rhs: Self) -> Self { self - self.project_onto(rhs) } /// Returns the vector projection of `self` onto `rhs`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn project_onto_normalized(self, rhs: Self) -> Self { glam_assert!(rhs.is_normalized()); rhs * self.dot(rhs) } /// Returns the vector rejection of `self` from `rhs`. /// /// The vector rejection is the vector perpendicular to the projection of `self` onto /// `rhs`, in rhs words the result of `self - self.project_onto(rhs)`. /// /// `rhs` must be normalized. /// /// # Panics /// /// Will panic if `rhs` is not normalized when `glam_assert` is enabled. #[doc(alias("plane"))] #[inline] #[must_use] pub fn reject_from_normalized(self, rhs: Self) -> Self { self - self.project_onto_normalized(rhs) } /// 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 { {% if is_scalar %} Self { {% for c in components %} {{ c }}: math::round(self.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { m128_round(self.0) }) {% elif is_wasm32 %} Self(f32x4_nearest(self.0)) {% elif is_coresimd %} Self(self.0.round()) {% elif is_neon %} Self(unsafe { vrndnq_f32(self.0) }) {% else %} unimplemented!() {% endif %} } /// 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 { {% if is_scalar %} Self { {% for c in components %} {{ c }}: math::floor(self.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { m128_floor(self.0) }) {% elif is_wasm32 %} Self(f32x4_floor(self.0)) {% elif is_coresimd %} Self(self.0.floor()) {% elif is_neon %} Self(unsafe { vrndmq_f32(self.0) }) {% else %} unimplemented!() {% endif %} } /// 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 { {% if is_scalar %} Self { {% for c in components %} {{ c }}: math::ceil(self.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { m128_ceil(self.0) }) {% elif is_wasm32 %} Self(f32x4_ceil(self.0)) {% elif is_coresimd %} Self(self.0.ceil()) {% elif is_neon %} Self(unsafe { vrndpq_f32(self.0) }) {% else %} unimplemented!() {% endif %} } /// 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 { {% if is_scalar %} Self { {% for c in components %} {{ c }}: math::trunc(self.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { m128_trunc(self.0) }) {% elif is_wasm32 %} Self(f32x4_trunc(self.0)) {% elif is_coresimd %} Self(self.0.trunc()) {% elif is_neon %} Self(unsafe { vrndq_f32(self.0) }) {% else %} unimplemented!() {% endif %} } /// Returns a vector containing the fractional part of the vector as `self - self.trunc()`. /// /// Note that this differs from the GLSL implementation of `fract` which returns /// `self - self.floor()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract(self) -> Self { self - self.trunc() } /// Returns a vector containing the fractional part of the vector as `self - self.floor()`. /// /// Note that this differs from the Rust implementation of `fract` which returns /// `self - self.trunc()`. /// /// Note that this is fast but not precise for large numbers. #[inline] #[must_use] pub fn fract_gl(self) -> Self { self - self.floor() } /// Returns a vector containing `e^self` (the exponential function) for each element of /// `self`. #[inline] #[must_use] pub fn exp(self) -> Self { Self::new( {% for c in components %} math::exp(self.{{ c }}), {%- endfor %} ) } /// Returns a vector containing each element of `self` raised to the power of `n`. #[inline] #[must_use] pub fn powf(self, n: {{ scalar_t }}) -> Self { Self::new( {% for c in components %} math::powf(self.{{ c }}, n), {%- endfor %} ) } /// Returns a vector containing the reciprocal `1.0/n` of each element of `self`. #[inline] #[must_use] pub fn recip(self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: 1.0 / self.{{ c }}, {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_div_ps(Self::ONE.0, self.0) }) {% elif is_wasm32 %} Self(f32x4_div(Self::ONE.0, self.0)) {% elif is_coresimd %} Self(self.0.recip()) {% elif is_neon %} Self(unsafe { vdivq_f32(Self::ONE.0, self.0) }) {% else %} unimplemented!() {% endif %} } /// Performs a linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[doc(alias = "mix")] #[inline] #[must_use] pub fn lerp(self, rhs: Self, s: {{ scalar_t }}) -> Self { self * (1.0 - s) + rhs * s } /// Moves towards `rhs` based on the value `d`. /// /// When `d` is `0.0`, the result will be equal to `self`. When `d` is equal to /// `self.distance(rhs)`, the result will be equal to `rhs`. Will not go past `rhs`. #[inline] #[must_use] pub fn move_towards(&self, rhs: Self, d: {{ scalar_t }}) -> Self { let a = rhs - *self; let len = a.length(); if len <= d || len <= 1e-4 { return rhs; } *self + a / len * d } /// Calculates the midpoint between `self` and `rhs`. /// /// The midpoint is the average of, or halfway point between, two vectors. /// `a.midpoint(b)` should yield the same result as `a.lerp(b, 0.5)` /// while being slightly cheaper to compute. #[inline] pub fn midpoint(self, rhs: Self) -> Self { (self + rhs) * 0.5 } /// Returns true if the absolute difference of all elements between `self` and `rhs` is /// less than or equal to `max_abs_diff`. /// /// This can be used to compare if two vectors contain similar elements. It works best when /// comparing with a known value. The `max_abs_diff` that should be used used depends on /// the values being compared against. /// /// 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: {{ scalar_t }}) -> bool { self.sub(rhs).abs().cmple(Self::splat(max_abs_diff)).all() } /// Returns a vector with a length no less than `min` and no more than `max`. /// /// # Panics /// /// Will panic if `min` is greater than `max`, or if either `min` or `max` is negative, when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length(self, min: {{ scalar_t }}, max: {{ scalar_t }}) -> Self { glam_assert!(0.0 <= min); glam_assert!(min <= max); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no more than `max`. /// /// # Panics /// /// Will panic if `max` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_max(self, max: {{ scalar_t }}) -> Self { glam_assert!(0.0 <= max); let length_sq = self.length_squared(); if length_sq > max * max { max * (self / math::sqrt(length_sq)) } else { self } } /// Returns a vector with a length no less than `min`. /// /// # Panics /// /// Will panic if `min` is negative when `glam_assert` is enabled. #[inline] #[must_use] pub fn clamp_length_min(self, min: {{ scalar_t }}) -> Self { glam_assert!(0.0 <= min); let length_sq = self.length_squared(); if length_sq < min * min { min * (self / math::sqrt(length_sq)) } else { self } } /// Fused multiply-add. Computes `(self * a) + b` element-wise with only one rounding /// error, yielding a more accurate result than an unfused multiply-add. /// /// Using `mul_add` *may* be more performant than an unfused multiply-add if the target /// architecture has a dedicated fma CPU instruction. However, this is not always true, /// 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 { {% if is_sse2 %} #[cfg(target_feature = "fma")] unsafe { Self(_mm_fmadd_ps(self.0, a.0, b.0)) } #[cfg(not(target_feature = "fma"))] {% endif %} {% if is_coresimd %} Self(self.0.mul_add(a.0, b.0)) {% elif is_neon %} Self(unsafe { vfmaq_f32(b.0, self.0, a.0) }) {% else %} Self::new( {% for c in components %} math::mul_add(self.{{ c }}, a.{{ c }}, b.{{ c }}), {%- endfor %} ) {% endif %} } /// Returns the reflection vector for a given incident vector `self` and surface normal /// `normal`. /// /// `normal` must be normalized. /// /// # Panics /// /// Will panic if `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn reflect(self, normal: Self) -> Self { glam_assert!(normal.is_normalized()); self - 2.0 * self.dot(normal) * normal } /// Returns the refraction direction for a given incident vector `self`, surface normal /// `normal` and ratio of indices of refraction, `eta`. When total internal reflection occurs, /// a zero vector will be returned. /// /// `self` and `normal` must be normalized. /// /// # Panics /// /// Will panic if `self` or `normal` is not normalized when `glam_assert` is enabled. #[inline] #[must_use] pub fn refract(self, normal: Self, eta: {{ scalar_t }}) -> Self { glam_assert!(self.is_normalized()); glam_assert!(normal.is_normalized()); let n_dot_i = normal.dot(self); let k = 1.0 - eta * eta * (1.0 - n_dot_i * n_dot_i); if k >= 0.0 { eta * self - (eta * n_dot_i + math::sqrt(k)) * normal } else { Self::ZERO } } {% if dim == 2 %} /// Creates a 2D vector containing `[angle.cos(), angle.sin()]`. This can be used in /// conjunction with the [`rotate()`][Self::rotate()] method, e.g. /// `{{ vec2_t }}::from_angle(PI).rotate({{ vec2_t }}::Y)` will create the vector `[-1, 0]` /// and rotate [`{{ vec2_t }}::Y`] around it returning `-{{ vec2_t }}::Y`. #[inline] #[must_use] pub fn from_angle(angle: {{ scalar_t }}) -> Self { let (sin, cos) = math::sin_cos(angle); Self { x: cos, y: sin, } } /// Returns the angle (in radians) of this vector in the range `[-π, +π]`. /// /// The input does not need to be a unit vector however it must be non-zero. #[inline] #[must_use] pub fn to_angle(self) -> {{ scalar_t }} { math::atan2(self.y, self.x) } #[inline] #[must_use] #[deprecated( since = "0.27.0", note = "Use angle_to() instead, the semantics of angle_between will change in the future." )] pub fn angle_between(self, rhs: Self) -> {{ scalar_t }} { self.angle_to(rhs) } /// Returns the angle of rotation (in radians) from `self` to `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_to(self, rhs: Self) -> {{ scalar_t }} { let angle = math::acos_approx( self.dot(rhs) / math::sqrt(self.length_squared() * rhs.length_squared())); angle * math::signum(self.perp_dot(rhs)) } {% elif dim == 3 %} /// Returns the angle (in radians) between two vectors in the range `[0, +π]`. /// /// 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) -> {{ scalar_t }} { math::acos_approx( self.dot(rhs).div( math::sqrt(self.length_squared().mul(rhs.length_squared())))) } /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(self, rhs: Self, max_angle: {{ scalar_t }}) -> Self { let angle_between = self.angle_between(rhs); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(angle_between - core::{{ scalar_t }}::consts::PI, angle_between); let axis = self .cross(rhs) .try_normalize() .unwrap_or_else(|| self.any_orthogonal_vector().normalize()); {{ quat_t }}::from_axis_angle(axis{% if self_t == "Vec3A" %}.into(){% endif%}, angle) * self } /// 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. #[inline] #[must_use] pub fn any_orthogonal_vector(&self) -> Self { // This can probably be optimized 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 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 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 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 let sign = math::signum(self.z); let a = -1.0 / (sign + self.z); let b = self.x * self.y * a; ( Self::new(1.0 + sign * self.x * self.x * a, sign * b, -sign * self.x), Self::new(b, sign + self.y * self.y * a, -self.y), ) } /// Performs a spherical linear interpolation between `self` and `rhs` based on the value `s`. /// /// When `s` is `0.0`, the result will be equal to `self`. When `s` is `1.0`, the result /// will be equal to `rhs`. When `s` is outside of range `[0, 1]`, the result is linearly /// extrapolated. #[inline] #[must_use] pub fn slerp(self, rhs: Self, s: {{ scalar_t }}) -> Self { let self_length = self.length(); let rhs_length = rhs.length(); // Cosine of the angle between the vectors [-1, 1], or NaN if either vector has a zero length let dot = self.dot(rhs) / (self_length * rhs_length); // If dot is close to 1 or -1, or is NaN the calculations for t1 and t2 break down if math::abs(dot) < 1.0 - 3e-7 { // Angle between the vectors [0, +π] let theta = math::acos_approx(dot); // Sine of the angle between vectors [0, 1] let sin_theta = math::sin(theta); let t1 = math::sin(theta * (1. - s)); let t2 = math::sin(theta * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); // Scale the vectors to the target length and interpolate them return (self * (result_length / self_length) * t1 + rhs * (result_length / rhs_length) * t2) * sin_theta.recip(); } if dot < 0.0 { // Vectors are almost parallel in opposing directions // Create a rotation from self to rhs along some axis let axis = self.any_orthogonal_vector().normalize(){% if is_align %}.into(){% endif %}; let rotation = {{ quat_t }}::from_axis_angle(axis, core::{{ scalar_t }}::consts::PI * s); // Interpolate vector lengths let result_length = self_length.lerp(rhs_length, s); rotation * self * (result_length / self_length) } else { // Vectors are almost parallel in the same direction, or dot was NaN self.lerp(rhs, s) } } {% endif %} {% endif %} {% if not is_float %} /// Computes the [manhattan distance] between two points. /// /// # Overflow /// This method may overflow if the result is greater than [`{{ unsigned_scalar_t }}::MAX`]. /// /// See also [`checked_manhattan_distance`][{{ self_t }}::checked_manhattan_distance]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn manhattan_distance(self, other: Self) -> {{ unsigned_scalar_t }} { {% for c in components %} {% if not loop.first %} + {% endif %} self.{{c}}.abs_diff(other.{{c}}) {% endfor %} } /// Computes the [manhattan distance] between two points. /// /// This will returns [`None`] if the result is greater than [`{{ unsigned_scalar_t }}::MAX`]. /// /// [manhattan distance]: https://en.wikipedia.org/wiki/Taxicab_geometry #[inline] #[must_use] pub fn checked_manhattan_distance(self, other: Self) -> Option<{{ unsigned_scalar_t }}> { {% for c in components %} {%- if loop.first -%} let d = self.{{c}}.abs_diff(other.{{c}}); {%- elif loop.last -%} d.checked_add(self.{{c}}.abs_diff(other.{{c}})) {%- else -%} let d = d.checked_add(self.{{c}}.abs_diff(other.{{c}}))?; {%- endif -%} {% endfor %} } /// Computes the [chebyshev distance] between two points. /// /// [chebyshev distance]: https://en.wikipedia.org/wiki/Chebyshev_distance #[inline] #[must_use] pub fn chebyshev_distance(self, other: Self) -> {{ unsigned_scalar_t }} { // Note: the compiler will eventually optimize out the loop [ {% for c in components %} self.{{c}}.abs_diff(other.{{c}}), {% endfor %} ].into_iter().max().unwrap() } {% endif %} {% if is_signed and dim == 2 %} /// 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) -> {{ scalar_t }} { (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, } } {% endif %} {% if is_signed and is_float and dim == 2 %} /// Rotates towards `rhs` up to `max_angle` (in radians). /// /// When `max_angle` is `0.0`, the result will be equal to `self`. When `max_angle` is equal to /// `self.angle_between(rhs)`, the result will be parallel to `rhs`. If `max_angle` is negative, /// rotates towards the exact opposite of `rhs`. Will not go past the target. #[inline] #[must_use] pub fn rotate_towards(&self, rhs: Self, max_angle: {{ scalar_t }}) -> Self { let a = self.angle_to(rhs); let abs_a = math::abs(a); // When `max_angle < 0`, rotate no further than `PI` radians away let angle = max_angle.clamp(abs_a - core::{{ scalar_t }}::consts::PI, abs_a) * math::signum(a); Self::from_angle(angle).rotate(*self) } {% endif %} {% if scalar_t != "f32" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "f64" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "i8" %} {% if dim == 2 %} /// Casts all elements of `self` to `i8`. #[inline] #[must_use] pub fn as_i8vec2(&self) -> crate::I8Vec2 { crate::I8Vec2::new(self.x as i8, self.y as i8) } {% elif dim == 3 %} /// Casts all elements of `self` to `i8`. #[inline] #[must_use] pub fn as_i8vec3(&self) -> crate::I8Vec3 { crate::I8Vec3::new(self.x as i8, self.y as i8, self.z as i8) } {% elif dim == 4 %} /// Casts all elements of `self` to `i8`. #[inline] #[must_use] pub fn as_i8vec4(&self) -> crate::I8Vec4 { crate::I8Vec4::new(self.x as i8, self.y as i8, self.z as i8, self.w as i8) } {% endif %} {% endif %} {% if scalar_t != "u8" %} {% if dim == 2 %} /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec2(&self) -> crate::U8Vec2 { crate::U8Vec2::new(self.x as u8, self.y as u8) } {% elif dim == 3 %} /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec3(&self) -> crate::U8Vec3 { crate::U8Vec3::new(self.x as u8, self.y as u8, self.z as u8) } {% elif dim == 4 %} /// Casts all elements of `self` to `u8`. #[inline] #[must_use] pub fn as_u8vec4(&self) -> crate::U8Vec4 { crate::U8Vec4::new(self.x as u8, self.y as u8, self.z as u8, self.w as u8) } {% endif %} {% endif %} {% if scalar_t != "i16" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "u16" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "i32" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "u32" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "i64" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "u64" %} {% if dim == 2 %} /// 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) } {% elif dim == 3 %} /// 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) } {% elif dim == 4 %} /// 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) } {% endif %} {% endif %} {% if scalar_t != "usize" %} {% if dim == 2 %} /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec2(&self) -> crate::USizeVec2 { crate::USizeVec2::new(self.x as usize, self.y as usize) } {% elif dim == 3 %} /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec3(&self) -> crate::USizeVec3 { crate::USizeVec3::new(self.x as usize, self.y as usize, self.z as usize) } {% elif dim == 4 %} /// Casts all elements of `self` to `usize`. #[inline] #[must_use] pub fn as_usizevec4(&self) -> crate::USizeVec4 { crate::USizeVec4::new(self.x as usize, self.y as usize, self.z as usize, self.w as usize) } {% endif %} {% endif %} {% if not is_float %} /// Returns a vector containing the wrapping addition of `self` and `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add(self, rhs: Self) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_add(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// Returns a vector containing the wrapping subtraction of `self` and `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub(self, rhs: Self) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_sub(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// Returns a vector containing the wrapping multiplication of `self` and `rhs`. /// /// In other words this computes `Some([self.x * rhs.x, self.y * rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_mul(self, rhs: Self) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_mul(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// Returns a vector containing the wrapping division of `self` and `rhs`. /// /// In other words this computes `Some([self.x / rhs.x, self.y / rhs.y, ..])` but returns `None` on any division by zero. #[inline] #[must_use] pub const fn checked_div(self, rhs: Self) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_div(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_add(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_sub(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_mul(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_div(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.saturating_add(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.saturating_sub(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.saturating_mul(rhs.{{ c }}), {%- endfor %} } } /// 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 { {% for c in components %} {{ c }}: self.{{ c }}.saturating_div(rhs.{{ c }}), {%- endfor %} } } {% if scalar_t != "usize" %} {% if is_signed %} /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_add_unsigned(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `Some([self.x - rhs.x, self.y - rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_sub_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_sub_unsigned(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// Returns a vector containing the wrapping addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_unsigned(rhs.x), self.y.wrapping_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self { Self { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_add_unsigned(rhs.{{ c }}), {%- endfor %} } } /// Returns a vector containing the wrapping subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.wrapping_sub_unsigned(rhs.x), self.y.wrapping_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_sub_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self { Self { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_sub_unsigned(rhs.{{ c }}), {%- endfor %} } } // Returns a vector containing the saturating addition of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_unsigned(rhs.x), self.y.saturating_add_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self { Self { {% for c in components %} {{ c }}: self.{{ c }}.saturating_add_unsigned(rhs.{{ c }}), {%- endfor %} } } /// Returns a vector containing the saturating subtraction of `self` and unsigned vector `rhs`. /// /// In other words this computes `[self.x.saturating_sub_unsigned(rhs.x), self.y.saturating_sub_unsigned(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_sub_unsigned(self, rhs: {{ opposite_signedness_t }}) -> Self { Self { {% for c in components %} {{ c }}: self.{{ c }}.saturating_sub_unsigned(rhs.{{ c }}), {%- endfor %} } } {% else %} /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `Some([self.x + rhs.x, self.y + rhs.y, ..])` but returns `None` on any overflow. #[inline] #[must_use] pub const fn checked_add_signed(self, rhs: {{ opposite_signedness_t }}) -> Option { {% for c in components %} let {{ c }} = match self.{{ c }}.checked_add_signed(rhs.{{ c }}) { Some(v) => v, None => {return None} }; {%- endfor %} Some(Self { {% for c in components %} {{ c }}, {%- endfor %} }) } /// Returns a vector containing the wrapping addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.wrapping_add_signed(rhs.x), self.y.wrapping_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn wrapping_add_signed(self, rhs: {{ opposite_signedness_t }}) -> Self { Self { {% for c in components %} {{ c }}: self.{{ c }}.wrapping_add_signed(rhs.{{ c }}), {%- endfor %} } } /// Returns a vector containing the saturating addition of `self` and signed vector `rhs`. /// /// In other words this computes `[self.x.saturating_add_signed(rhs.x), self.y.saturating_add_signed(rhs.y), ..]`. #[inline] #[must_use] pub const fn saturating_add_signed(self, rhs: {{ opposite_signedness_t }}) -> Self { Self { {% for c in components %} {{ c }}: self.{{ c }}.saturating_add_signed(rhs.{{ c }}), {%- endfor %} } } {% endif %} {% endif %} {% endif %} } impl Default for {{ self_t }} { #[inline(always)] fn default() -> Self { Self::ZERO } } {% if not is_scalar %} impl PartialEq for {{ self_t }} { #[inline] fn eq(&self, rhs: &Self) -> bool { self.cmpeq(*rhs).all() } } {% endif %} impl Div<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn div(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.div(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_div_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(f32x4_div(self.0, rhs.0)) {% elif is_coresimd %} Self(self.0 / rhs.0) {% elif is_neon %} Self(unsafe { vdivq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Div", self_t=self_t, rhs_t=self_t, output_t=self_t) }} impl DivAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn div_assign(&mut self, rhs: Self) { {% if is_scalar %} {% for c in components %} self.{{ c }}.div_assign(rhs.{{ c }}); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_div_ps(self.0, rhs.0) }; {% elif is_wasm32 %} self.0 = f32x4_div(self.0, rhs.0); {% elif is_coresimd %} self.0 /= rhs.0; {% elif is_neon %} self.0 = unsafe { vdivq_f32(self.0, rhs.0) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="DivAssign", self_t=self_t, rhs_t=self_t, self="&mut self") }} impl Div<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn div(self, rhs: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.div(rhs), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_div_ps(self.0, _mm_set1_ps(rhs)) }) {% elif is_wasm32 %} Self(f32x4_div(self.0, f32x4_splat(rhs))) {% elif is_coresimd %} Self(self.0 / f32x4::splat(rhs)) {% elif is_neon %} Self(unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Div", self_t=self_t, rhs_t=scalar_t, output_t=self_t) }} impl DivAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn div_assign(&mut self, rhs: {{ scalar_t }}) { {% if is_scalar %} {% for c in components %} self.{{ c }}.div_assign(rhs); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_div_ps(self.0, _mm_set1_ps(rhs)) }; {% elif is_wasm32 %} self.0 = f32x4_div(self.0, f32x4_splat(rhs)); {% elif is_coresimd %} self.0 /= f32x4::splat(rhs); {% elif is_neon %} self.0 = unsafe { vdivq_f32(self.0, vld1q_dup_f32(&rhs)) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="DivAssign", self_t=self_t, rhs_t=scalar_t, self="&mut self") }} impl Div<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn div(self, rhs: {{ self_t }}) -> {{ self_t }} { {% if is_scalar %} {{ self_t }} { {% for c in components %} {{ c }}: self.div(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} {{ self_t }}(unsafe { _mm_div_ps(_mm_set1_ps(self), rhs.0) }) {% elif is_wasm32 %} {{ self_t }}(f32x4_div(f32x4_splat(self), rhs.0)) {% elif is_coresimd %} {{ self_t }}(f32x4::splat(self) / rhs.0) {% elif is_neon %} {{ self_t }}(unsafe { vdivq_f32(vld1q_dup_f32(&self), rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Div", self_t=scalar_t, rhs_t=self_t, output_t=self_t) }} impl Mul<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn mul(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.mul(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_mul_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(f32x4_mul(self.0, rhs.0)) {% elif is_coresimd %} Self(self.0 * rhs.0) {% elif is_neon %} Self(unsafe { vmulq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Mul", self_t=self_t, rhs_t=self_t, output_t=self_t) }} impl MulAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn mul_assign(&mut self, rhs: Self) { {% if is_scalar %} {% for c in components %} self.{{ c }}.mul_assign(rhs.{{ c }}); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_mul_ps(self.0, rhs.0) }; {% elif is_wasm32 %} self.0 = f32x4_mul(self.0, rhs.0); {% elif is_coresimd %} self.0 *= rhs.0; {% elif is_neon %} self.0 = unsafe { vmulq_f32(self.0, rhs.0) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="MulAssign", self_t=self_t, rhs_t=self_t, self="&mut self") }} impl Mul<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn mul(self, rhs: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.mul(rhs), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }) {% elif is_wasm32 %} Self(f32x4_mul(self.0, f32x4_splat(rhs))) {% elif is_coresimd %} Self(self.0 * f32x4::splat(rhs)) {% elif is_neon %} Self(unsafe { vmulq_n_f32(self.0, rhs) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Mul", self_t=self_t, rhs_t=scalar_t, output_t=self_t) }} impl MulAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn mul_assign(&mut self, rhs: {{ scalar_t }}) { {% if is_scalar %} {% for c in components %} self.{{ c }}.mul_assign(rhs); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_mul_ps(self.0, _mm_set1_ps(rhs)) }; {% elif is_wasm32 %} self.0 = f32x4_mul(self.0, f32x4_splat(rhs)) {% elif is_coresimd %} self.0 *= f32x4::splat(rhs); {% elif is_neon %} self.0 = unsafe { vmulq_n_f32(self.0, rhs) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="MulAssign", self_t=self_t, rhs_t=scalar_t, self="&mut self") }} impl Mul<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn mul(self, rhs: {{ self_t }}) -> {{ self_t }} { {% if is_scalar %} {{ self_t }} { {% for c in components %} {{ c }}: self.mul(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} {{ self_t }}(unsafe { _mm_mul_ps(_mm_set1_ps(self), rhs.0) }) {% elif is_wasm32 %} {{ self_t }}(f32x4_mul(f32x4_splat(self), rhs.0)) {% elif is_coresimd %} {{ self_t }}(f32x4::splat(self) * rhs.0) {% elif is_neon %} {{ self_t }}(unsafe { vmulq_n_f32(rhs.0, self) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Mul", self_t=scalar_t, rhs_t=self_t, output_t=self_t) }} impl Add<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn add(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.add(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_add_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(f32x4_add(self.0, rhs.0)) {% elif is_coresimd %} Self(self.0 + rhs.0) {% elif is_neon %} Self(unsafe { vaddq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Add", self_t=self_t, rhs_t=self_t, output_t=self_t) }} impl AddAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn add_assign(&mut self, rhs: Self) { {% if is_scalar %} {% for c in components %} self.{{ c }}.add_assign(rhs.{{ c }}); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_add_ps(self.0, rhs.0) }; {% elif is_wasm32 %} self.0 = f32x4_add(self.0, rhs.0); {% elif is_coresimd %} self.0 += rhs.0; {% elif is_neon %} self.0 = unsafe { vaddq_f32(self.0, rhs.0) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="AddAssign", self_t=self_t, rhs_t=self_t, self="&mut self") }} impl Add<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn add(self, rhs: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.add(rhs), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }) {% elif is_wasm32 %} Self(f32x4_add(self.0, f32x4_splat(rhs))) {% elif is_coresimd %} Self(self.0 + f32x4::splat(rhs)) {% elif is_neon %} Self(unsafe { vaddq_f32(self.0, vld1q_dup_f32(&rhs)) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Add", self_t=self_t, rhs_t=scalar_t, output_t=self_t) }} impl AddAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn add_assign(&mut self, rhs: {{ scalar_t }}) { {% if is_scalar %} {% for c in components %} self.{{ c }}.add_assign(rhs); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_add_ps(self.0, _mm_set1_ps(rhs)) }; {% elif is_wasm32 %} self.0 = f32x4_add(self.0, f32x4_splat(rhs)); {% elif is_coresimd %} self.0 += f32x4::splat(rhs); {% elif is_neon %} self.0 = unsafe { vaddq_f32(self.0, vld1q_dup_f32(&rhs)) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="AddAssign", self_t=self_t, rhs_t=scalar_t, self="&mut self") }} impl Add<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn add(self, rhs: {{ self_t }}) -> {{ self_t }} { {% if is_scalar %} {{ self_t }} { {% for c in components %} {{ c }}: self.add(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} {{ self_t }}(unsafe { _mm_add_ps(_mm_set1_ps(self), rhs.0) }) {% elif is_wasm32 %} {{ self_t }}(f32x4_add(f32x4_splat(self), rhs.0)) {% elif is_coresimd %} {{ self_t }}(f32x4::splat(self) + rhs.0) {% elif is_neon %} {{ self_t }}(unsafe { vaddq_f32(vld1q_dup_f32(&self), rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Add", self_t=scalar_t, rhs_t=self_t, output_t=self_t) }} impl Sub<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn sub(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.sub(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_sub_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(f32x4_sub(self.0, rhs.0)) {% elif is_coresimd %} Self(self.0 - rhs.0) {% elif is_neon %} Self(unsafe { vsubq_f32(self.0, rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Sub", self_t=self_t, rhs_t=self_t, output_t=self_t) }} impl SubAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn sub_assign(&mut self, rhs: {{ self_t }}) { {% if is_scalar %} {% for c in components %} self.{{ c }}.sub_assign(rhs.{{ c }}); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_sub_ps(self.0, rhs.0) }; {% elif is_wasm32 %} self.0 = f32x4_sub(self.0, rhs.0); {% elif is_coresimd %} self.0 -= rhs.0; {% elif is_neon %} self.0 = unsafe { vsubq_f32(self.0, rhs.0) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="SubAssign", self_t=self_t, rhs_t=self_t, self="&mut self") }} impl Sub<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn sub(self, rhs: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.sub(rhs), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_sub_ps(self.0, _mm_set1_ps(rhs)) }) {% elif is_wasm32 %} Self(f32x4_sub(self.0, f32x4_splat(rhs))) {% elif is_coresimd %} Self(self.0 - f32x4::splat(rhs)) {% elif is_neon %} Self(unsafe { vsubq_f32(self.0, vld1q_dup_f32(&rhs)) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Sub", self_t=self_t, rhs_t=scalar_t, output_t=self_t) }} impl SubAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn sub_assign(&mut self, rhs: {{ scalar_t }}) { {% if is_scalar %} {% for c in components %} self.{{ c }}.sub_assign(rhs); {%- endfor %} {% elif is_sse2 %} self.0 = unsafe { _mm_sub_ps(self.0, _mm_set1_ps(rhs)) }; {% elif is_wasm32 %} self.0 = f32x4_sub(self.0, f32x4_splat(rhs)) {% elif is_coresimd %} self.0 -= f32x4::splat(rhs); {% elif is_neon %} self.0 = unsafe { vsubq_f32(self.0, vld1q_dup_f32(&rhs)) }; {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="SubAssign", self_t=self_t, rhs_t=scalar_t, self="&mut self") }} impl Sub<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn sub(self, rhs: {{ self_t }}) -> {{ self_t }} { {% if is_scalar %} {{ self_t }} { {% for c in components %} {{ c }}: self.sub(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} {{ self_t }}(unsafe { _mm_sub_ps(_mm_set1_ps(self), rhs.0) }) {% elif is_wasm32 %} {{ self_t }}(f32x4_sub(f32x4_splat(self), rhs.0)) {% elif is_coresimd %} {{ self_t }}(f32x4::splat(self) - rhs.0) {% elif is_neon %} {{ self_t }}(unsafe { vsubq_f32(vld1q_dup_f32(&self), rhs.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Sub", self_t=scalar_t, rhs_t=self_t, output_t=self_t) }} impl Rem<{{ self_t }}> for {{ self_t }} { type Output = Self; #[inline] fn rem(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.rem(rhs.{{ c }}), {%- endfor %} } {% elif is_sse2 %} unsafe { let n = m128_floor(_mm_div_ps(self.0, rhs.0)); Self(_mm_sub_ps(self.0, _mm_mul_ps(n, rhs.0))) } {% elif is_wasm32 %} let n = f32x4_floor(f32x4_div(self.0, rhs.0)); Self(f32x4_sub(self.0, f32x4_mul(n, rhs.0))) {% elif is_coresimd %} Self(self.0 % rhs.0) {% elif is_neon %} unsafe { let n = vrndmq_f32(vdivq_f32(self.0, rhs.0)); Self(vsubq_f32(self.0, vmulq_f32(n, rhs.0))) } {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Rem", self_t=self_t, rhs_t=self_t, output_t=self_t) }} impl RemAssign<{{ self_t }}> for {{ self_t }} { #[inline] fn rem_assign(&mut self, rhs: Self) { {% if is_scalar %} {% for c in components %} self.{{ c }}.rem_assign(rhs.{{ c }}); {%- endfor %} {% elif is_coresimd %} self.0 %= rhs.0; {% else %} *self = self.rem(rhs); {% endif %} } } {{ macros::impl_op_ref(op="RemAssign", self_t=self_t, rhs_t=self_t, self="&mut self") }} impl Rem<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn rem(self, rhs: {{ scalar_t }}) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.rem(rhs), {%- endfor %} } {% else %} self.rem(Self::splat(rhs)) {% endif %} } } {{ macros::impl_op_ref(op="Rem", self_t=self_t, rhs_t=scalar_t, output_t=self_t) }} impl RemAssign<{{ scalar_t }}> for {{ self_t }} { #[inline] fn rem_assign(&mut self, rhs: {{ scalar_t }}) { {% if is_scalar %} {% for c in components %} self.{{ c }}.rem_assign(rhs); {%- endfor %} {% elif is_coresimd %} self.0 %= f32x4::splat(rhs); {% else %} *self = self.rem(Self::splat(rhs)); {% endif %} } } {{ macros::impl_op_ref(op="RemAssign", self_t=self_t, rhs_t=scalar_t, self="&mut self") }} impl Rem<{{ self_t }}> for {{ scalar_t }} { type Output = {{ self_t }}; #[inline] fn rem(self, rhs: {{ self_t }}) -> {{ self_t }} { {% if is_scalar %} {{ self_t }} { {% for c in components %} {{ c }}: self.rem(rhs.{{ c }}), {%- endfor %} } {% else %} {{ self_t }}::splat(self).rem(rhs) {% endif %} } } {{ macros::impl_op_ref(op="Rem", self_t=scalar_t, rhs_t=self_t, output_t=self_t) }} #[cfg(not(target_arch = "spirv"))] impl AsRef<[{{ scalar_t }}; {{ dim }}]> for {{ self_t }} { #[inline] fn as_ref(&self) -> &[{{ scalar_t }}; {{ dim }}] { unsafe { &*(self as *const {{ self_t }} as *const [{{ scalar_t }}; {{ dim }}]) } } } #[cfg(not(target_arch = "spirv"))] impl AsMut<[{{ scalar_t }}; {{ dim }}]> for {{ self_t }} { #[inline] fn as_mut(&mut self) -> &mut [{{ scalar_t }}; {{ dim }}] { unsafe { &mut *(self as *mut {{ self_t }} as *mut [{{ scalar_t }}; {{ dim }}]) } } } impl Sum for {{ self_t }} { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, Self::add) } } impl<'a> Sum<&'a Self> for {{ self_t }} { #[inline] fn sum(iter: I) -> Self where I: Iterator, { iter.fold(Self::ZERO, |a, &b| Self::add(a, b)) } } impl Product for {{ self_t }} { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, Self::mul) } } impl<'a> Product<&'a Self> for {{ self_t }} { #[inline] fn product(iter: I) -> Self where I: Iterator, { iter.fold(Self::ONE, |a, &b| Self::mul(a, b)) } } {% if is_signed %} impl Neg for {{ self_t }} { type Output = Self; #[inline] fn neg(self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }}.neg(), {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_xor_ps(_mm_set1_ps(-0.0), self.0) }) {% elif is_wasm32 %} Self(f32x4_neg(self.0)) {% elif is_coresimd %} Self(-self.0) {% elif is_neon %} Self(unsafe { vnegq_f32(self.0) }) {% else %} unimplemented!() {% endif %} } } {{ macros::impl_op_ref(op="Neg", self_t=self_t, output_t=self_t) }} {% endif %} {% if not is_float %} impl Not for {{ self_t }} { type Output = Self; #[inline] fn not(self) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.not(), {%- endfor %} } } } impl BitAnd for {{ self_t }} { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.bitand(rhs.{{ c }}), {%- endfor %} } } } impl BitOr for {{ self_t }} { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.bitor(rhs.{{ c }}), {%- endfor %} } } } impl BitXor for {{ self_t }} { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.bitxor(rhs.{{ c }}), {%- endfor %} } } } impl BitAnd<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn bitand(self, rhs: {{ scalar_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.bitand(rhs), {%- endfor %} } } } impl BitOr<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn bitor(self, rhs: {{ scalar_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.bitor(rhs), {%- endfor %} } } } impl BitXor<{{ scalar_t }}> for {{ self_t }} { type Output = Self; #[inline] fn bitxor(self, rhs: {{ scalar_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.bitxor(rhs), {%- endfor %} } } } {% for rhs_t in ["i8", "i16", "i32", "i64", "u8", "u16", "u32", "u64"] %} impl Shl<{{ rhs_t }}> for {{ self_t }} { type Output = Self; #[inline] fn shl(self, rhs: {{ rhs_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.shl(rhs), {%- endfor %} } } } impl Shr<{{ rhs_t }}> for {{ self_t }} { type Output = Self; #[inline] fn shr(self, rhs: {{ rhs_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.shr(rhs), {%- endfor %} } } } {% endfor %} {% for rhs_t in ["crate::IVec" ~ dim, "crate::UVec" ~ dim] %} impl Shl<{{ rhs_t }}> for {{ self_t }} { type Output = Self; #[inline] fn shl(self, rhs: {{ rhs_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.shl(rhs.{{ c }}), {%- endfor %} } } } impl Shr<{{ rhs_t }}> for {{ self_t }} { type Output = Self; #[inline] fn shr(self, rhs: {{ rhs_t }}) -> Self::Output { Self { {% for c in components %} {{ c }}: self.{{ c }}.shr(rhs.{{ c }}), {%- endfor %} } } } {% endfor %} {% endif %} impl Index for {{ self_t }} { type Output = {{ scalar_t }}; #[inline] fn index(&self, index: usize) -> &Self::Output { {% if is_coresimd %} &self.0[index] {% else %} match index { {% for c in components %} {{ loop.index0 }} => &self.{{ c }}, {%- endfor %} _ => panic!("index out of bounds"), } {% endif %} } } impl IndexMut for {{ self_t }} { #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { {% if is_coresimd %} &mut self.0[index] {% else %} match index { {% for c in components %} {{ loop.index0 }} => &mut self.{{ c }}, {%- endfor %} _ => panic!("index out of bounds"), } {% endif %} } } impl fmt::Display for {{ self_t }} { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { {% if is_float %} if let Some(p) = f.precision() { {% if dim == 2 %} write!(f, "[{:.*}, {:.*}]", p, self.x, p, self.y) {% elif dim == 3 %} write!(f, "[{:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z) {% elif dim == 4 %} write!(f, "[{:.*}, {:.*}, {:.*}, {:.*}]", p, self.x, p, self.y, p, self.z, p, self.w) {% endif %} } else { {% endif %} {% if dim == 2 %} write!(f, "[{}, {}]", self.x, self.y) {% elif dim == 3 %} write!(f, "[{}, {}, {}]", self.x, self.y, self.z) {% elif dim == 4 %} write!(f, "[{}, {}, {}, {}]", self.x, self.y, self.z, self.w) {% endif %} {% if is_float %} } {% endif %} } } impl fmt::Debug for {{ self_t }} { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_tuple(stringify!({{ self_t }})) {% for c in components %} .field(&self.{{ c }}) {% endfor %} .finish() } } {% if not is_scalar %} impl From<{{ self_t }}> for {{ simd_t }} { #[inline(always)] fn from(t: {{ self_t }}) -> Self { t.0 } } impl From<{{ simd_t }}> for {{ self_t }} { #[inline(always)] fn from(t: {{ simd_t }}) -> Self { Self(t) } } {% endif %} impl From<[{{ scalar_t }}; {{ dim }}]> for {{ self_t }} { #[inline] fn from(a: [{{ scalar_t }}; {{ dim }}]) -> Self { {% if self_t == "Vec4" and is_sse2 %} Self(unsafe { _mm_loadu_ps(a.as_ptr()) }) {% elif self_t == "Vec4" and is_coresimd %} Self(f32x4::from_array(a)) {% elif self_t == "Vec4" and is_neon %} Self(unsafe { vld1q_f32(a.as_ptr()) }) {% else %} Self::new( {% for c in components %} a[{{ loop.index0 }}], {%- endfor %} ) {% endif %} } } impl From<{{ self_t }}> for [{{ scalar_t }}; {{ dim }}] { #[inline] fn from(v: {{ self_t }}) -> Self { {% if is_scalar %} [ {% for c in components %} v.{{ c }}, {%- endfor %} ] {% elif is_sse2 %} use core::mem::MaybeUninit; use crate::Align16; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } {% elif is_wasm32 %} unsafe { *(&v.0 as *const v128 as *const Self) } {% elif is_coresimd %} {% if dim == 3 %} unsafe { *(v.0.to_array().as_ptr() as *const Self) } {% elif dim == 4 %} v.0.to_array() {% endif %} {% elif is_neon %} use core::mem::MaybeUninit; use crate::align16::Align16; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } {% else %} unimplemented!() {% endif %} } } impl From<{{ macros::make_tuple_t(t=scalar_t, n=dim) }}> for {{ self_t }} { #[inline] fn from(t: {{ macros::make_tuple_t(t=scalar_t, n=dim) }}) -> Self { Self::new( {% for c in components %} t.{{ loop.index0 }}, {%- endfor %} ) } } impl From<{{ self_t }}> for {{ macros::make_tuple_t(t=scalar_t, n=dim) }} { #[inline] fn from(v: {{ self_t }}) -> Self { {% if is_scalar %} ( {% for c in components %} v.{{ c }}, {%- endfor %} ) {% elif is_sse2 %} use core::mem::MaybeUninit; use crate::Align16; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } {% elif is_wasm32 %} unsafe { *(&v.0 as *const v128 as *const Self) } {% elif is_coresimd %} unsafe { *(v.0.to_array().as_ptr() as *const Self) } {% elif is_neon %} use core::mem::MaybeUninit; use crate::align16::Align16; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } {% else %} unimplemented!() {% endif %} } } {% if self_t == "Vec3A" %} impl From for Vec3A { #[inline] fn from(v: Vec3) -> Self { Self::new(v.x, v.y, v.z) } } impl From for Vec3 { #[inline] fn from(v: Vec3A) -> Self { {% if is_scalar %} Self { x: v.x, y: v.y, z: v.z, } {% elif is_sse2 %} use crate::Align16; use core::mem::MaybeUninit; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { _mm_store_ps(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } {% elif is_wasm32 %} unsafe { *(&v.0 as *const v128 as *const Self) } {% elif is_coresimd %} unsafe { *(v.0.to_array().as_ptr() as *const Self) } {% elif is_neon %} use core::mem::MaybeUninit; use crate::align16::Align16; let mut out: MaybeUninit> = MaybeUninit::uninit(); unsafe { vst1q_f32(out.as_mut_ptr().cast(), v.0); out.assume_init().0 } {% else %} unimplemented!() {% endif %} } } {% elif self_t == "Vec4" %} impl From<(Vec3A, f32)> for Vec4 { #[inline] fn from((v, w): (Vec3A, f32)) -> Self { v.extend(w) } } impl From<(f32, Vec3A)> for Vec4 { #[inline] fn from((x, v): (f32, Vec3A)) -> Self { Self::new(x, v.x, v.y, v.z) } } {% endif %} {% if dim == 3 %} impl From<({{ vec2_t }}, {{ scalar_t }})> for {{ self_t }} { #[inline] fn from((v, z): ({{ vec2_t }}, {{ scalar_t }})) -> Self { Self::new(v.x, v.y, z) } } {% elif dim == 4 %} impl From<({{ vec3_t }}, {{ scalar_t }})> for {{ self_t }} { #[inline] fn from((v, w): ({{ vec3_t }}, {{ scalar_t }})) -> Self { Self::new(v.x, v.y, v.z, w) } } impl From<({{ scalar_t }}, {{ vec3_t }})> for {{ self_t }} { #[inline] fn from((x, v): ({{ scalar_t }}, {{ vec3_t }})) -> Self { Self::new(x, v.x, v.y, v.z) } } impl From<({{ vec2_t }}, {{ scalar_t }}, {{ scalar_t }})> for {{ self_t }} { #[inline] fn from((v, z, w): ({{ vec2_t }}, {{ scalar_t }}, {{ scalar_t }})) -> Self { Self::new(v.x, v.y, z, w) } } impl From<({{ vec2_t }}, {{ vec2_t }})> for {{ self_t }} { #[inline] fn from((v, u): ({{ vec2_t }}, {{ vec2_t }})) -> Self { Self::new(v.x, v.y, u.x, u.y) } } {% endif %} {% if not is_scalar %} impl Deref for {{ self_t }} { type Target = crate::deref::Vec{{ dim }}<{{ scalar_t }}>; #[inline] fn deref(&self) -> &Self::Target { unsafe { &*(self as *const Self).cast() } } } impl DerefMut for {{ self_t }} { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { unsafe { &mut *(self as *mut Self).cast() } } } {% endif %} {% if from_types %} {% for ty in from_types %} impl From<{{ ty }}> for {{ self_t }} { #[inline] fn from(v: {{ ty }}) -> Self { Self::new( {% for c in components %} {{ scalar_t }}::from(v.{{ c }}), {% endfor %} ) } } {% endfor %} {% endif %} {% if try_from_types %} {% for ty in try_from_types %} impl TryFrom<{{ ty }}> for {{ self_t }} { type Error = core::num::TryFromIntError; #[inline] fn try_from(v: {{ ty }}) -> Result { Ok(Self::new( {% for c in components %} {{ scalar_t }}::try_from(v.{{ c }})?, {% endfor %} )) } } {% endfor %} {% endif %} impl From<{{ bvec_from_type }}> for {{ self_t }} { #[inline] fn from(v: {{ bvec_from_type }}) -> Self { Self::new( {% for c in components %} {{ scalar_t }}::from(v.{{ c }}), {% endfor %} ) } } {% if bveca_from_type %} {% if bveca_from_type == "BVec4A" %} #[cfg(not(feature = "scalar-math"))] {%- endif %} impl From<{{ bveca_from_type }}> for {{ self_t }} { #[inline] fn from(v: {{ bveca_from_type }}) -> Self { let bool_array: [bool; {{ dim }}] = v.into(); Self::new( {% for c in components %} {{ scalar_t }}::from(bool_array[{{ loop.index0 }}]), {% endfor %} ) } } {% endif %} glam-0.30.1/templates/vec_mask.rs.tera000064400000000000000000000410431046102023000157150ustar 00000000000000// Generated from {{template_path}} template. Edit the template, not the generated file. {% if scalar_t == "bool" %} {% set self_t = "BVec" ~ dim %} {% set align = 1 %} {% set is_bool = true %} {% else %} {% set self_t = "BVec" ~ dim ~ "A" %} {% if dim == 4 %} {% set vec_t = "Vec4" %} {% elif dim == 3 %} {% set vec_t = "Vec3A" %} {% endif %} {% set align = 16 %} {% set is_u32 = true %} {% if is_sse2 %} {% set simd_t = "__m128" %} {% elif is_wasm32 %} {% set simd_t = "v128" %} {% elif is_neon %} {% set simd_t = "uint32x4_t" %} {% elif is_coresimd %} {% set simd_t = "mask32x4" %} {% endif %} {% endif %} {% set components = ["x", "y", "z", "w"] | slice(end = dim) %} use core::fmt; use core::ops::*; {% if is_sse2 %} #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; {% elif is_wasm32 %} use core::arch::wasm32::*; {% elif is_neon %} use core::arch::aarch64::*; {% elif is_coresimd %} use core::simd::*; {% endif %} {% if is_sse2 or is_neon or is_coresimd %} #[repr(C)] union UnionCast { a: [u32; 4], v: {{ self_t }} } {% endif %} /// Creates a {{ dim }}-dimensional `bool` vector mask. #[inline(always)] #[must_use] pub const fn {{ self_t | lower }}( {% for c in components %} {{ c }}: bool, {% endfor %} ) -> {{ self_t }} { {{ self_t }}::new({{ components | join(sep=",") }}) } {% if is_scalar and is_bool %} /// A {{ dim }}-dimensional `bool` vector mask. {%- elif is_scalar and is_u32 %} /// A {{ dim }}-dimensional `u32` vector mask. {%- else %} /// A {{ dim }}-dimensional SIMD vector mask. /// /// This type is {{ align }} byte aligned. {%- endif %} {%- if is_scalar or is_bool %} #[derive(Clone, Copy, PartialEq, Eq, Hash)] {%- else %} #[derive(Clone, Copy)] {%- endif %} {%- if is_scalar %} #[repr(C, align({{ align }}))] pub struct {{ self_t }} { {% for c in components %} pub {{ c }}: {{ scalar_t }}, {%- endfor %} } {%- else %} #[repr(transparent)] pub struct {{ self_t }}(pub(crate) {{ simd_t }}); {% endif %} const MASK: [u32; 2] = [0, 0xff_ff_ff_ff]; impl {{ self_t }} { /// All false. pub const FALSE: Self = Self::splat(false); /// All true. pub const TRUE: Self = Self::splat(true); /// Creates a new vector mask. #[inline(always)] #[must_use] pub const fn new( {% for c in components %} {{ c }}: bool, {% endfor %} ) -> Self { {% if is_scalar and is_bool %} Self { {% for c in components %} {{ c }}, {%- endfor %} } {% elif is_scalar and is_u32 %} Self { {% for c in components %} {{ c }}: MASK[{{ c }} as usize], {%- endfor %} } {% elif is_sse2 or is_neon or is_coresimd %} unsafe { UnionCast { a: [ MASK[x as usize], MASK[y as usize], MASK[z as usize], {% if dim == 3 %} 0, {% elif dim == 4 %} MASK[w as usize], {% endif %} ] }.v } {% elif is_wasm32 %} Self(u32x4( MASK[x as usize], MASK[y as usize], MASK[z as usize], {% if dim == 3 %} 0, {% elif dim == 4 %} MASK[w as usize], {% endif %} )) {% endif %} } /// Creates a vector mask with all elements set to `v`. #[inline] #[must_use] pub const fn splat(v: bool) -> Self { Self::new( {% for c in components %} v, {%- endfor %} ) } /// Creates a new vector mask from a bool array. #[inline] #[must_use] pub const fn from_array(a: [bool; {{ dim }}]) -> Self { Self::new( {% for c in components %} a[{{ loop.index0 }}], {%- endfor %} ) } /// Returns a bitmask with the lowest {{ dim }} bits set from the elements of `self`. /// /// 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 { {% if is_scalar and is_bool %} {% for c in components %} {% if loop.first %} (self.{{ c }} as u32) | {% else %} ((self.{{ c }} as u32) << {{ loop.index0 }}) {% if not loop.last %} | {% endif %} {% endif %} {% endfor %} {% elif is_scalar and is_u32 %} {% for c in components %} {% if loop.first %} (self.{{ c }} & 0x1) | {% else %} ((self.{{ c }} & 0x1) << {{ loop.index0 }}) {% if not loop.last %} | {% endif %} {% endif %} {% endfor %} {% elif is_sse2 %} {% if dim == 3 %} unsafe { (_mm_movemask_ps(self.0) as u32) & 0x7 } {% elif dim == 4 %} unsafe { _mm_movemask_ps(self.0) as u32 } {% endif %} {% elif is_wasm32 %} {% if dim == 3 %} (u32x4_bitmask(self.0) & 0x7) as u32 {% elif dim == 4 %} u32x4_bitmask(self.0) as u32 {% endif %} {% elif is_neon %} {% if dim == 3 %} let movemask = unsafe { {% elif dim == 4 %} unsafe { {% endif %} let mma = vandq_u32(self.0, vld1q_u32([1, 2, 4, 8].as_ptr())); // [0 1 2 3] let mmb = vextq_u32(mma, mma, 2); // [2 3 0 1] let mmc = vorrq_u32(mma, mmb); // [0+2 1+3 0+2 1+3] let mmd = vextq_u32(mmc, mmc, 3); // [1+3 0+2 1+3 0+2] let mme = vorrq_u32(mmc, mmd); // [0+1+2+3 ...] vgetq_lane_u32(mme, 0) {% if dim == 3 %} }; movemask & 0x7 {% elif dim == 4 %} } {% endif %} {% elif is_coresimd %} {% if dim == 3 %} (self.0.to_bitmask() & 0x7) as u32 {% elif dim == 4 %} self.0.to_bitmask() as u32 {% endif %} {% else %} unimplemented!() {% endif %} } /// Returns true if any of the elements are true, false otherwise. #[inline] #[must_use] pub fn any(self) -> bool { {% if is_scalar and is_bool %} {% for c in components %} self.{{ c }} {% if not loop.last %} || {% endif %} {%- endfor %} {% elif is_scalar and is_u32 %} (( {% for c in components %} self.{{ c }} {% if not loop.last %} | {% endif %} {%- endfor %} ) & 0x1) != 0 {% else %} self.bitmask() != 0 {% endif %} } /// Returns true if all the elements are true, false otherwise. #[inline] #[must_use] pub fn all(self) -> bool { {% if is_scalar and is_bool %} {% for c in components %} self.{{ c }} {% if not loop.last %} && {% endif %} {%- endfor %} {% elif is_scalar and is_u32 %} (( {% for c in components %} self.{{ c }} {% if not loop.last %} & {% endif %} {%- endfor %} ) & 0x1) != 0 {% else %} {% if dim == 3 %} self.bitmask() == 0x7 {% elif dim == 4 %} self.bitmask() == 0xf {% endif %} {% endif %} } /// Tests the value at `index`. /// /// Panics if `index` is greater than {{ dim - 1 }}. #[inline] #[must_use] pub fn test(&self, index: usize) -> bool { {% if is_coresimd %} self.0.test(index) {% else %} match index { {% for c in components %} {%- if is_scalar and is_bool %} {{ loop.index0 }} => self.{{ c }}, {%- elif is_scalar and is_u32 %} {{ loop.index0 }} => (self.{{ c }} & 0x1) != 0, {%- else %} {{ loop.index0 }} => (self.bitmask() & (1 << {{ loop.index0 }})) != 0, {%- endif %} {%- endfor %} _ => panic!("index out of bounds") } {% endif %} } /// Sets the element at `index`. /// /// Panics if `index` is greater than {{ dim - 1 }}. #[inline] pub fn set(&mut self, index: usize, value: bool) { {% if is_scalar %} match index { {% for c in components %} {%- if is_bool %} {{ loop.index0 }} => self.{{ c }} = value, {%- elif is_u32 %} {{ loop.index0 }} => self.{{ c }} = MASK[value as usize], {%- endif %} {%- endfor %} _ => panic!("index out of bounds") } {% elif is_coresimd %} self.0.set(index, value) {% elif is_neon %} self.0 = match index { {% for c in components %} {{ loop.index0 }} => unsafe { vsetq_lane_u32(MASK[value as usize], self.0, {{ loop.index0 }}) }, {%- endfor %} _ => panic!("index out of bounds") } {% else %} use crate::{{ vec_t }}; let mut v = {{ vec_t }}(self.0); v[index] = f32::from_bits(MASK[value as usize]); self.0 = v.0; {% endif %} } #[inline] #[must_use] fn into_bool_array(self) -> [bool; {{ dim }}] { {% if is_scalar and is_bool %} [ {% for c in components %} self.{{ c }}, {%- endfor %} ] {% elif is_scalar and is_u32 %} [ {% for c in components %} (self.{{ c }} & 0x1) != 0, {%- endfor %} ] {% else %} {% set bits = [1, 2, 4, 8] | slice(end = dim) %} let bitmask = self.bitmask(); [ {% for b in bits %} (bitmask & {{ b }}) != 0, {%- endfor %} ] {% endif %} } #[inline] #[must_use] fn into_u32_array(self) -> [u32; {{ dim }}] { {% if is_scalar and is_bool %} [ {% for c in components %} MASK[self.{{ c }} as usize], {%- endfor %} ] {% elif is_scalar and is_u32 %} [ {% for c in components %} self.{{ c }}, {%- endfor %} ] {% else %} let bitmask = self.bitmask(); [ {% for c in components %} {% if loop.first %} MASK[(bitmask & 1) as usize], {% else %} MASK[((bitmask >> {{ loop.index0 }}) & 1) as usize], {% endif %} {%- endfor %} ] {% endif %} } } impl Default for {{ self_t }} { #[inline] fn default() -> Self { Self::FALSE } } {% if not is_scalar and not is_bool %} impl PartialEq for {{ self_t }} { #[inline] fn eq(&self, rhs: &Self) -> bool { self.bitmask().eq(&rhs.bitmask()) } } impl Eq for {{ self_t }} {} impl core::hash::Hash for {{ self_t }} { #[inline] fn hash(&self, state: &mut H) { self.bitmask().hash(state); } } {%- endif %} impl BitAnd for {{ self_t }} { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }} & rhs.{{ c }}, {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_and_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(v128_and(self.0, rhs.0)) {% elif is_neon %} Self(unsafe { vandq_u32(self.0, rhs.0) }) {% elif is_coresimd %} Self(self.0 & rhs.0) {% else %} unimplemented!() {% endif %} } } impl BitAndAssign for {{ self_t }} { #[inline] fn bitand_assign(&mut self, rhs: Self) { *self = self.bitand(rhs); } } impl BitOr for {{ self_t }} { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }} | rhs.{{ c }}, {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_or_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(v128_or(self.0, rhs.0)) {% elif is_neon %} Self(unsafe { vorrq_u32(self.0, rhs.0) }) {% elif is_coresimd %} Self(self.0 | rhs.0) {% else %} unimplemented!() {% endif %} } } impl BitOrAssign for {{ self_t }} { #[inline] fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } impl BitXor for {{ self_t }} { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: self.{{ c }} ^ rhs.{{ c }}, {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_xor_ps(self.0, rhs.0) }) {% elif is_wasm32 %} Self(v128_xor(self.0, rhs.0)) {% elif is_neon %} Self(unsafe { veorq_u32(self.0, rhs.0) }) {% elif is_coresimd %} Self(self.0 ^ rhs.0) {% else %} unimplemented!() {% endif %} } } impl BitXorAssign for {{ self_t }} { #[inline] fn bitxor_assign(&mut self, rhs: Self) { *self = self.bitxor(rhs); } } impl Not for {{ self_t }} { type Output = Self; #[inline] fn not(self) -> Self { {% if is_scalar %} Self { {% for c in components %} {{ c }}: !self.{{ c }}, {%- endfor %} } {% elif is_sse2 %} Self(unsafe { _mm_andnot_ps(self.0, _mm_set_ps1(f32::from_bits(0xff_ff_ff_ff))) }) {% elif is_wasm32 %} Self(v128_not(self.0)) {% elif is_neon %} Self(unsafe { vmvnq_u32(self.0) }) {% elif is_coresimd %} Self(!self.0) {% else %} unimplemented!() {% endif %} } } {% if not is_scalar %} impl From<{{ self_t }}> for {{ simd_t }} { #[inline] fn from(t: {{ self_t }}) -> Self { t.0 } } {% endif %} impl fmt::Debug for {{ self_t }} { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_u32_array(); {%- if dim == 2 %} write!(f, "{}({:#x}, {:#x})", stringify!({{ self_t }}), arr[0], arr[1]) {% elif dim == 3 %} write!(f, "{}({:#x}, {:#x}, {:#x})", stringify!({{ self_t }}), arr[0], arr[1], arr[2]) {% elif dim == 4 %} write!(f, "{}({:#x}, {:#x}, {:#x}, {:#x})", stringify!({{ self_t }}), arr[0], arr[1], arr[2], arr[3]) {% endif %} } } impl fmt::Display for {{ self_t }} { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let arr = self.into_bool_array(); {%- if dim == 2 %} write!(f, "[{}, {}]", arr[0], arr[1]) {% elif dim == 3 %} write!(f, "[{}, {}, {}]", arr[0], arr[1], arr[2]) {% elif dim == 4 %} write!(f, "[{}, {}, {}, {}]", arr[0], arr[1], arr[2], arr[3]) {% endif %} } } impl From<[bool; {{ dim }}]> for {{ self_t }} { #[inline] fn from(a: [bool; {{ dim }}]) -> Self { Self::from_array(a) } } impl From<{{ self_t }}> for [bool; {{ dim }}] { #[inline] fn from(mask: {{ self_t }}) -> Self { mask.into_bool_array() } } impl From<{{ self_t }}> for [u32; {{ dim }}] { #[inline] fn from(mask: {{ self_t }}) -> Self { mask.into_u32_array() } } glam-0.30.1/templates/wasm32.rs.tera000064400000000000000000000131621046102023000152420ustar 00000000000000{% macro impl_mat4_inverse() %} // Based on https://github.com/g-truc/glm `glm_mat4_inverse` let fac0 = { let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac1 = { let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac2 = { let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac3 = { let swp0a = i32x4_shuffle::<3, 3, 7, 7>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<3, 3, 7, 7>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac4 = { let swp0a = i32x4_shuffle::<2, 2, 6, 6>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<2, 2, 6, 6>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let fac5 = { let swp0a = i32x4_shuffle::<1, 1, 5, 5>(self.w_axis.0, self.z_axis.0); let swp0b = i32x4_shuffle::<0, 0, 4, 4>(self.w_axis.0, self.z_axis.0); let swp00 = i32x4_shuffle::<0, 0, 4, 4>(self.z_axis.0, self.y_axis.0); let swp01 = i32x4_shuffle::<0, 0, 4, 6>(swp0a, swp0a); let swp02 = i32x4_shuffle::<0, 0, 4, 6>(swp0b, swp0b); let swp03 = i32x4_shuffle::<1, 1, 5, 5>(self.z_axis.0, self.y_axis.0); let mul00 = f32x4_mul(swp00, swp01); let mul01 = f32x4_mul(swp02, swp03); f32x4_sub(mul00, mul01) }; let sign_a = f32x4(-1.0, 1.0, -1.0, 1.0); let sign_b = f32x4(1.0, -1.0, 1.0, -1.0); let temp0 = i32x4_shuffle::<0, 0, 4, 4>(self.y_axis.0, self.x_axis.0); let vec0 = i32x4_shuffle::<0, 2, 6, 6>(temp0, temp0); let temp1 = i32x4_shuffle::<1, 1, 5, 5>(self.y_axis.0, self.x_axis.0); let vec1 = i32x4_shuffle::<0, 2, 6, 6>(temp1, temp1); let temp2 = i32x4_shuffle::<2, 2, 6, 6>(self.y_axis.0, self.x_axis.0); let vec2 = i32x4_shuffle::<0, 2, 6, 6>(temp2, temp2); let temp3 = i32x4_shuffle::<3, 3, 7, 7>(self.y_axis.0, self.x_axis.0); let vec3 = i32x4_shuffle::<0, 2, 6, 6>(temp3, temp3); let mul00 = f32x4_mul(vec1, fac0); let mul01 = f32x4_mul(vec2, fac1); let mul02 = f32x4_mul(vec3, fac2); let sub00 = f32x4_sub(mul00, mul01); let add00 = f32x4_add(sub00, mul02); let inv0 = f32x4_mul(sign_b, add00); let mul03 = f32x4_mul(vec0, fac0); let mul04 = f32x4_mul(vec2, fac3); let mul05 = f32x4_mul(vec3, fac4); let sub01 = f32x4_sub(mul03, mul04); let add01 = f32x4_add(sub01, mul05); let inv1 = f32x4_mul(sign_a, add01); let mul06 = f32x4_mul(vec0, fac1); let mul07 = f32x4_mul(vec1, fac3); let mul08 = f32x4_mul(vec3, fac5); let sub02 = f32x4_sub(mul06, mul07); let add02 = f32x4_add(sub02, mul08); let inv2 = f32x4_mul(sign_b, add02); let mul09 = f32x4_mul(vec0, fac2); let mul10 = f32x4_mul(vec1, fac4); let mul11 = f32x4_mul(vec2, fac5); let sub03 = f32x4_sub(mul09, mul10); let add03 = f32x4_add(sub03, mul11); let inv3 = f32x4_mul(sign_a, add03); let row0 = i32x4_shuffle::<0, 0, 4, 4>(inv0, inv1); let row1 = i32x4_shuffle::<0, 0, 4, 4>(inv2, inv3); let row2 = i32x4_shuffle::<0, 2, 4, 6>(row0, row1); let dot0 = dot4(self.x_axis.0, row2); glam_assert!(dot0 != 0.0); let rcp0 = f32x4_splat(dot0.recip()); Self { x_axis: Vec4(f32x4_mul(inv0, rcp0)), y_axis: Vec4(f32x4_mul(inv1, rcp0)), z_axis: Vec4(f32x4_mul(inv2, rcp0)), w_axis: Vec4(f32x4_mul(inv3, rcp0)), } {% endmacro impl_mat4_inverse %} glam-0.30.1/tests/affine2.rs000064400000000000000000000322361046102023000136550ustar 00000000000000#[macro_use] mod support; macro_rules! impl_affine2_tests { ($t:ident, $affine2:ident, $vec2:ident, $mat2:ident, $mat3:ident) => { const MATRIX1D: [$t; 6] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]; const MATRIX2D: [[$t; 2]; 3] = [[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]; glam_test!(test_affine2_identity, { assert_eq!($affine2::IDENTITY, $affine2::IDENTITY * $affine2::IDENTITY); assert_eq!($affine2::IDENTITY, $affine2::default()); }); glam_test!(test_affine2_zero, { assert_eq!( $affine2::ZERO.transform_point2($vec2::new(1., 2.)), $vec2::ZERO ); }); glam_test!(test_affine2_nan, { assert!($affine2::NAN.is_nan()); assert!(!$affine2::NAN.is_finite()); }); glam_test!(test_affine2_from_cols, { let a = $affine2::from_cols( $vec2::from_array(MATRIX2D[0]), $vec2::from_array(MATRIX2D[1]), $vec2::from_array(MATRIX2D[2]), ); assert_eq!(MATRIX2D, a.to_cols_array_2d()); let a = $affine2::from_cols_array(&MATRIX1D); assert_eq!(MATRIX1D, a.to_cols_array()); let a = $affine2::from_cols_array_2d(&MATRIX2D); assert_eq!(MATRIX2D, a.to_cols_array_2d()); }); glam_test!(test_affine2_deref, { let a = $affine2::from_cols_array_2d(&MATRIX2D); assert_eq!(MATRIX2D[0], a.x_axis.to_array()); assert_eq!(MATRIX2D[1], a.y_axis.to_array()); assert_eq!(MATRIX2D[2], a.z_axis.to_array()); let mut b = a; b.x_axis *= 0.0; b.y_axis *= 0.0; b.z_axis *= 0.0; assert_eq!($affine2::ZERO, b); }); glam_test!(test_affine2_from_mat2, { let m = $mat2::from_cols_array_2d(&[MATRIX2D[0], MATRIX2D[1]]); let a = $affine2::from_mat2(m); assert_eq!(m, a.matrix2); assert_eq!($vec2::ZERO, a.translation); let t = $vec2::from_array(MATRIX2D[2]); let a = $affine2::from_mat2_translation(m, t); assert_eq!(MATRIX2D, a.to_cols_array_2d()); }); glam_test!(test_affine2_from_mat3, { let m = $mat3::from_cols_array_2d(&[[1.0, 2.0, 0.0], [3.0, 4.0, 0.0], [5.0, 6.0, 1.0]]); let a = $affine2::from_mat3(m); assert_eq!(MATRIX2D, a.to_cols_array_2d()); assert_eq!(m, $mat3::from(a)); }); glam_test!(test_affine2_translation, { let translate = $affine2::from_translation($vec2::new(1.0, 2.0)); assert_eq!(translate.translation, $vec2::new(1.0, 2.0).into()); assert_eq!( translate.transform_point2($vec2::new(2.0, 3.0)), $vec2::new(3.0, 5.0), ); }); glam_test!(test_affine2_mul, { let m = $affine2::from_angle(deg(90.0)); let result3 = m.transform_vector2($vec2::Y); assert_approx_eq!($vec2::new(-1.0, 0.0), result3); let m = $affine2::from_angle_translation(deg(90.0), $vec2::new(1.0, 2.0)); let result3 = m.transform_vector2($vec2::Y); assert_approx_eq!($vec2::new(-1.0, 0.0), result3, 1.0e-6); let m = $affine2::from_scale_angle_translation( $vec2::new(0.5, 1.5), deg(90.0), $vec2::new(1.0, 2.0), ); let result3 = m.transform_vector2($vec2::Y); assert_approx_eq!($vec2::new(-1.5, 0.0), result3, 1.0e-6); let result3 = m.transform_point2($vec2::Y); assert_approx_eq!($vec2::new(-0.5, 2.0), result3, 1.0e-6); }); glam_test!(test_from_scale, { let m = $affine2::from_scale($vec2::new(2.0, 4.0)); assert_approx_eq!( m.transform_point2($vec2::new(1.0, 1.0)), $vec2::new(2.0, 4.0) ); }); glam_test!(test_affine2_inverse, { let inv = $affine2::IDENTITY.inverse(); assert_approx_eq!($affine2::IDENTITY, inv); let rot = $affine2::from_angle(deg(90.0)); let rot_inv = rot.inverse(); assert_approx_eq!($affine2::IDENTITY, rot * rot_inv); assert_approx_eq!($affine2::IDENTITY, rot_inv * rot); let trans = $affine2::from_translation($vec2::new(1.0, 2.0)); let trans_inv = trans.inverse(); assert_approx_eq!($affine2::IDENTITY, trans * trans_inv); assert_approx_eq!($affine2::IDENTITY, trans_inv * trans); let scale = $affine2::from_scale($vec2::new(4.0, 5.0)); let scale_inv = scale.inverse(); assert_approx_eq!($affine2::IDENTITY, scale * scale_inv); assert_approx_eq!($affine2::IDENTITY, scale_inv * scale); let m = scale * rot * trans; let m_inv = m.inverse(); assert_approx_eq!($affine2::IDENTITY, m * m_inv, 1.0e-5); assert_approx_eq!($affine2::IDENTITY, m_inv * m, 1.0e-5); assert_approx_eq!(m_inv, trans_inv * rot_inv * scale_inv, 1.0e-6); // Make sure we can invert a shear matrix: let m = $affine2::from_angle(0.5) * $affine2::from_scale($vec2::new(1.0, 0.5)) * $affine2::from_angle(-0.5); let m_inv = m.inverse(); assert_approx_eq!($affine2::IDENTITY, m * m_inv, 1.0e-5); assert_approx_eq!($affine2::IDENTITY, m_inv * m, 1.0e-5); 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); }); glam_test!(test_affine2_fmt, { let a = $affine2::from_cols_array_2d(&MATRIX2D); assert_eq!(format!("{}", a), "[[1, 2], [3, 4], [5, 6]]"); assert_eq!(format!("{:.1}", a), "[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]"); }); glam_test!(test_affine2_to_from_slice, { let m = $affine2::from_cols_slice(&MATRIX1D); assert_eq!($affine2::from_cols_array(&MATRIX1D), m); assert_eq!(MATRIX1D, m.to_cols_array()); assert_eq!(MATRIX2D, m.to_cols_array_2d()); let mut out: [$t; 6] = Default::default(); m.write_cols_to_slice(&mut out); assert_eq!(MATRIX1D, out); assert_eq!( m, $affine2::from_cols(MATRIX2D[0].into(), MATRIX2D[1].into(), MATRIX2D[2].into()) ); should_panic!({ $affine2::from_cols_slice(&[0.0; 5]) }); should_panic!({ $affine2::IDENTITY.write_cols_to_slice(&mut [0.0; 5]) }); }); glam_test!(test_product, { let ident = $affine2::IDENTITY; assert_eq!([ident, ident].iter().product::<$affine2>(), ident * ident); }); glam_test!(test_affine2_is_finite, { assert!($affine2::from_scale($vec2::new(1.0, 1.0)).is_finite()); assert!($affine2::from_scale($vec2::new(0.0, 1.0)).is_finite()); assert!(!$affine2::from_scale($vec2::new(1.0, $t::NAN)).is_finite()); assert!(!$affine2::from_scale($vec2::new(1.0, $t::NEG_INFINITY)).is_finite()); }); }; } mod affine2 { use super::support::{deg, FloatCompare}; use glam::{Affine2, Mat2, Mat3, Vec2}; impl FloatCompare for Affine2 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self { matrix2: self.matrix2.abs_diff(&other.matrix2), translation: self.translation.abs_diff(&other.translation), } } } glam_test!(test_align, { use std::mem; if cfg!(not(feature = "scalar-math")) { assert_eq!(32, mem::size_of::()); assert_eq!(16, mem::align_of::()); } else if cfg!(feature = "cuda") { assert_eq!(24, mem::size_of::()); assert_eq!(8, mem::align_of::()); } else { assert_eq!(24, mem::size_of::()); assert_eq!(4, mem::align_of::()); } }); glam_test!(test_affine2_from_mat3a, { use glam::Mat3A; let m = Mat3A::from_cols_array_2d(&[[1.0, 2.0, 0.0], [3.0, 4.0, 0.0], [5.0, 6.0, 1.0]]); let a = Affine2::from_mat3a(m); assert_eq!(MATRIX2D, a.to_cols_array_2d()); assert_eq!(m, Mat3A::from(a)); }); impl_affine2_tests!(f32, Affine2, Vec2, Mat2, Mat3); } mod daffine2 { use super::support::{deg, FloatCompare}; use glam::{DAffine2, DMat2, DMat3, DVec2}; impl FloatCompare for DAffine2 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self { matrix2: self.matrix2.abs_diff(&other.matrix2), translation: self.translation.abs_diff(&other.translation), } } } #[cfg(not(feature = "cuda"))] glam_test!(test_align, { use std::mem; assert_eq!(48, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); #[cfg(feature = "cuda")] glam_test!(test_align, { use std::mem; assert_eq!(48, mem::size_of::()); assert_eq!(16, mem::align_of::()); }); impl_affine2_tests!(f64, DAffine2, DVec2, DMat2, DMat3); } glam-0.30.1/tests/affine3.rs000064400000000000000000000412241046102023000136530ustar 00000000000000#[macro_use] mod support; macro_rules! impl_affine3_tests { ($t:ident, $affine3:ident, $quat:ident, $vec3:ident, $mat3:ident, $mat4:ident) => { const MATRIX1D: [$t; 12] = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, ]; const MATRIX2D: [[$t; 3]; 4] = [ [1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0], [10.0, 11.0, 12.0], ]; glam_test!(test_affine3_identity, { assert_eq!($affine3::IDENTITY, $affine3::IDENTITY * $affine3::IDENTITY); assert_eq!($affine3::IDENTITY, $affine3::default()); }); glam_test!(test_affine3_zero, { assert_eq!( $affine3::ZERO.transform_point3($vec3::new(1., 2., 3.)), $vec3::ZERO ); }); glam_test!(test_affine3_nan, { assert!($affine3::NAN.is_nan()); assert!(!$affine3::NAN.is_finite()); }); glam_test!(test_affine3_from_cols, { let a = $affine3::from_cols( $vec3::from_array(MATRIX2D[0]).into(), $vec3::from_array(MATRIX2D[1]).into(), $vec3::from_array(MATRIX2D[2]).into(), $vec3::from_array(MATRIX2D[3]).into(), ); assert_eq!(MATRIX2D, a.to_cols_array_2d()); let a = $affine3::from_cols_array(&MATRIX1D); assert_eq!(MATRIX1D, a.to_cols_array()); let a = $affine3::from_cols_array_2d(&MATRIX2D); assert_eq!(MATRIX2D, a.to_cols_array_2d()); }); glam_test!(test_affine3_deref, { let a = $affine3::from_cols_array_2d(&MATRIX2D); assert_eq!(MATRIX2D[0], a.x_axis.to_array()); assert_eq!(MATRIX2D[1], a.y_axis.to_array()); assert_eq!(MATRIX2D[2], a.z_axis.to_array()); assert_eq!(MATRIX2D[3], a.w_axis.to_array()); let mut b = a; b.x_axis *= 0.0; b.y_axis *= 0.0; b.z_axis *= 0.0; b.w_axis *= 0.0; assert_eq!($affine3::ZERO, b); }); glam_test!(test_affine3_from_mat3, { let m = $mat3::from_cols_array_2d(&[MATRIX2D[0], MATRIX2D[1], MATRIX2D[2]]); let a = $affine3::from_mat3(m); assert_eq!(m, a.matrix3.into()); assert_eq!($vec3::ZERO, a.translation.into()); let t = $vec3::from_array(MATRIX2D[3]); let a = $affine3::from_mat3_translation(m, t); assert_eq!(MATRIX2D, a.to_cols_array_2d()); }); glam_test!(test_affine2_from_mat4, { let m = $mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 0.0], [4.0, 5.0, 6.0, 0.0], [7.0, 8.0, 9.0, 0.0], [10.0, 11.0, 12.0, 1.0], ]); let a = $affine3::from_mat4(m); assert_eq!(MATRIX2D, a.to_cols_array_2d()); assert_eq!(m, $mat4::from(a)); }); glam_test!(test_affine3_translation, { let translate = $affine3::from_translation($vec3::new(1.0, 2.0, 3.0)); assert_eq!(translate.translation, $vec3::new(1.0, 2.0, 3.0).into()); assert_eq!( translate.transform_point3($vec3::new(2.0, 3.0, 4.0)), $vec3::new(3.0, 5.0, 7.0), ); }); glam_test!(test_from_rotation, { let eps = 2.0 * f32::EPSILON; let rot_x1 = $affine3::from_rotation_x(deg(180.0)); let rot_x2 = $affine3::from_axis_angle($vec3::X, deg(180.0)); assert_approx_eq!(rot_x1, rot_x2, eps); let rot_y1 = $affine3::from_rotation_y(deg(180.0)); let rot_y2 = $affine3::from_axis_angle($vec3::Y, deg(180.0)); assert_approx_eq!(rot_y1, rot_y2, eps); let rot_z1 = $affine3::from_rotation_z(deg(180.0)); let rot_z2 = $affine3::from_axis_angle($vec3::Z, deg(180.0)); assert_approx_eq!(rot_z1, rot_z2, eps); assert_approx_eq!( $affine3::from_rotation_x(deg(180.0)), $affine3::from_quat($quat::from_rotation_x(deg(180.0))) ); assert_approx_eq!( $quat::from_affine3(&$affine3::from_rotation_x(deg(180.0))), $quat::from_rotation_x(deg(180.0)) ); let m = $affine3::from_rotation_translation( $quat::from_rotation_x(deg(90.0)), $vec3::new(1.0, 2.0, 3.0), ); let result3 = m.transform_vector3($vec3::Y); assert_approx_eq!($vec3::new(0.0, 0.0, 1.0), result3, 1.0e-6); should_glam_assert!({ $affine3::from_axis_angle($vec3::ZERO, 0.0) }); should_glam_assert!({ $affine3::from_quat($quat::IDENTITY * 2.0) }); }); glam_test!(test_affine3_mul, { let m = $affine3::from_axis_angle($vec3::Z, deg(90.0)); let result3 = m.transform_vector3($vec3::Y); assert_approx_eq!($vec3::new(-1.0, 0.0, 0.0), result3); let m = $affine3::from_scale_rotation_translation( $vec3::new(0.5, 1.5, 2.0), $quat::from_rotation_x(deg(90.0)), $vec3::new(1.0, 2.0, 3.0), ); let result3 = m.transform_vector3($vec3::Y); assert_approx_eq!($vec3::new(0.0, 0.0, 1.5), result3, 1.0e-6); let result3 = m.transform_point3($vec3::Y); assert_approx_eq!($vec3::new(1.0, 2.0, 4.5), result3, 1.0e-6); }); glam_test!(test_from_scale, { let m = $affine3::from_scale($vec3::new(2.0, 4.0, 8.0)); assert_approx_eq!( m.transform_point3($vec3::new(1.0, 1.0, 1.0)), $vec3::new(2.0, 4.0, 8.0) ); }); glam_test!(test_affine3_inverse, { let inv = $affine3::IDENTITY.inverse(); assert_approx_eq!($affine3::IDENTITY, inv); let rotz = $affine3::from_rotation_z(deg(90.0)); let rotz_inv = rotz.inverse(); assert_approx_eq!($affine3::IDENTITY, rotz * rotz_inv); assert_approx_eq!($affine3::IDENTITY, rotz_inv * rotz); let trans = $affine3::from_translation($vec3::new(1.0, 2.0, 3.0)); let trans_inv = trans.inverse(); assert_approx_eq!($affine3::IDENTITY, trans * trans_inv); assert_approx_eq!($affine3::IDENTITY, trans_inv * trans); let scale = $affine3::from_scale($vec3::new(4.0, 5.0, 6.0)); let scale_inv = scale.inverse(); assert_approx_eq!($affine3::IDENTITY, scale * scale_inv); assert_approx_eq!($affine3::IDENTITY, scale_inv * scale); let m = scale * rotz * trans; let m_inv = m.inverse(); assert_approx_eq!($affine3::IDENTITY, m * m_inv, 1.0e-5); assert_approx_eq!($affine3::IDENTITY, m_inv * m, 1.0e-5); assert_approx_eq!(m_inv, trans_inv * rotz_inv * scale_inv, 1.0e-6); // Make sure we can invert a shear matrix: let m = $affine3::from_axis_angle($vec3::X, 0.5) * $affine3::from_scale($vec3::new(1.0, 0.5, 2.0)) * $affine3::from_axis_angle($vec3::X, -0.5); let m_inv = m.inverse(); assert_approx_eq!($affine3::IDENTITY, m * m_inv, 1.0e-5); assert_approx_eq!($affine3::IDENTITY, m_inv * m, 1.0e-5); should_glam_assert!({ $affine3::ZERO.inverse() }); }); glam_test!(test_affine3_decompose, { // identity let (out_scale, out_rotation, out_translation) = $affine3::IDENTITY.to_scale_rotation_translation(); assert_approx_eq!($vec3::ONE, out_scale); assert!(out_rotation.is_near_identity()); assert_approx_eq!($vec3::ZERO, out_translation); // no scale let in_scale = $vec3::ONE; let in_translation = $vec3::new(-2.0, 4.0, -0.125); let in_rotation = $quat::from_euler( glam::EulerRot::YXZ, $t::to_radians(-45.0), $t::to_radians(180.0), $t::to_radians(270.0), ); let in_mat = $affine3::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); assert_approx_eq!(in_scale, out_scale, 1e-6); // out_rotation is different but produces the same matrix // assert_approx_eq!(in_rotation, out_rotation); assert_approx_eq!(in_translation, out_translation); assert_approx_eq!( in_mat, $affine3::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-6 ); // positive scale let in_scale = $vec3::new(1.0, 2.0, 4.0); let in_mat = $affine3::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); assert_approx_eq!(in_scale, out_scale, 1e-6); // out_rotation is different but produces the same matrix // assert_approx_eq!(in_rotation, out_rotation); assert_approx_eq!(in_translation, out_translation); assert_approx_eq!( in_mat, $affine3::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-5 ); // negative scale let in_scale = $vec3::new(-4.0, 1.0, 2.0); let in_mat = $affine3::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); assert_approx_eq!(in_scale, out_scale, 1e-6); // out_rotation is different but produces the same matrix // assert_approx_eq!(in_rotation, out_rotation); assert_approx_eq!(in_translation, out_translation); assert_approx_eq!( in_mat, $affine3::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-5 ); // negative scale let in_scale = $vec3::new(4.0, -1.0, -2.0); let in_mat = $affine3::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_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, $affine3::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-6 ); }); glam_test!(test_affine3_look_at, { let eye = $vec3::new(0.0, 0.0, -5.0); let center = $vec3::new(0.0, 0.0, 0.0); let up = $vec3::new(1.0, 0.0, 0.0); let point = $vec3::new(1.0, 0.0, 0.0); let lh = $affine3::look_at_lh(eye, center, up); let rh = $affine3::look_at_rh(eye, center, up); assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); let dir = center - eye; let lh = $affine3::look_to_lh(eye, dir, up); let rh = $affine3::look_to_rh(eye, dir, up); assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); should_glam_assert!({ $affine3::look_at_lh($vec3::ONE, $vec3::ZERO, $vec3::ZERO) }); should_glam_assert!({ $affine3::look_at_rh($vec3::ONE, $vec3::ZERO, $vec3::ZERO) }); }); glam_test!(test_affine3_ops, { let m0 = $affine3::from_cols_array_2d(&MATRIX2D); 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); }); glam_test!(test_affine3_fmt, { let a = $affine3::from_cols_array_2d(&MATRIX2D); assert_eq!( format!("{}", a), "[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]" ); assert_eq!( format!("{:.1}", a), "[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0], [10.0, 11.0, 12.0]]" ); }); glam_test!(test_affine3_to_from_slice, { let m = $affine3::from_cols_slice(&MATRIX1D); assert_eq!($affine3::from_cols_array(&MATRIX1D), m); assert_eq!(MATRIX1D, m.to_cols_array()); assert_eq!(MATRIX2D, m.to_cols_array_2d()); let mut out: [$t; 12] = Default::default(); m.write_cols_to_slice(&mut out); assert_eq!(MATRIX1D, out); assert_eq!( m, $affine3::from_cols( MATRIX2D[0].into(), MATRIX2D[1].into(), MATRIX2D[2].into(), MATRIX2D[3].into() ) ); should_panic!({ $affine3::from_cols_slice(&[0.0; 11]) }); should_panic!({ $affine3::IDENTITY.write_cols_to_slice(&mut [0.0; 11]) }); }); glam_test!(test_product, { let ident = $affine3::IDENTITY; assert_eq!([ident, ident].iter().product::<$affine3>(), ident * ident); }); glam_test!(test_affine3_is_finite, { assert!($affine3::from_scale($vec3::new(1.0, 1.0, 1.0)).is_finite()); assert!($affine3::from_scale($vec3::new(0.0, 1.0, 1.0)).is_finite()); assert!(!$affine3::from_scale($vec3::new(1.0, $t::NAN, 1.0)).is_finite()); assert!(!$affine3::from_scale($vec3::new(1.0, 1.0, $t::NEG_INFINITY)).is_finite()); }); }; } mod affine3a { use super::support::{deg, FloatCompare}; use glam::{Affine3A, Mat3, Mat4, Quat, Vec3, Vec3A}; impl FloatCompare for Affine3A { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self { matrix3: self.matrix3.abs_diff(&other.matrix3), translation: self.translation.abs_diff(&other.translation), } } } glam_test!(test_align, { use std::mem; assert_eq!(64, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); glam_test!(test_affine3_mul_vec3a, { let m = Affine3A::from_axis_angle(Vec3::Z, deg(90.0)); let result3 = m.transform_vector3a(Vec3A::Y); assert_approx_eq!(Vec3A::new(-1.0, 0.0, 0.0), result3); let m = Affine3A::from_scale_rotation_translation( Vec3::new(0.5, 1.5, 2.0), Quat::from_rotation_x(deg(90.0)), Vec3::new(1.0, 2.0, 3.0), ); let result3 = m.transform_vector3a(Vec3A::Y); assert_approx_eq!(Vec3A::new(0.0, 0.0, 1.5), result3, 1.0e-6); let result3 = m.transform_point3a(Vec3A::Y); assert_approx_eq!(Vec3A::new(1.0, 2.0, 4.5), result3, 1.0e-6); }); impl_affine3_tests!(f32, Affine3A, Quat, Vec3, Mat3, Mat4); } mod daffine3 { use super::support::{deg, FloatCompare}; use glam::{DAffine3, DMat3, DMat4, DQuat, DVec3}; impl FloatCompare for DAffine3 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self { matrix3: self.matrix3.abs_diff(&other.matrix3), translation: self.translation.abs_diff(&other.translation), } } } glam_test!(test_align, { use std::mem; assert_eq!(96, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); impl_affine3_tests!(f64, DAffine3, DQuat, DVec3, DMat3, DMat4); } glam-0.30.1/tests/euler.rs000064400000000000000000000206661046102023000134630ustar 00000000000000#[macro_use] mod support; mod euler { use glam::*; use std::ops::RangeInclusive; /// 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) represent no rotation at all. trait CanonicalQuat: Copy { fn canonical(self) -> Self; } /// Helper to set some alternative epsilons based on the floating point type used trait EulerEpsilon { /// epsilon for comparing quaternion round-tripped through eulers (quat -> euler -> quat) const E_EPS: f32; } impl EulerEpsilon for f32 { const E_EPS: f32 = 2e-6; } impl EulerEpsilon for f64 { const E_EPS: f32 = 1e-8; } fn axis_order(order: EulerRot) -> (usize, usize, usize) { match order { EulerRot::XYZ => (0, 1, 2), EulerRot::XYX => (0, 1, 0), EulerRot::XZY => (0, 2, 1), EulerRot::XZX => (0, 2, 0), EulerRot::YZX => (1, 2, 0), EulerRot::YZY => (1, 2, 1), EulerRot::YXZ => (1, 0, 2), EulerRot::YXY => (1, 0, 1), EulerRot::ZXY => (2, 0, 1), EulerRot::ZXZ => (2, 0, 2), EulerRot::ZYX => (2, 1, 0), EulerRot::ZYZ => (2, 1, 2), EulerRot::ZYXEx => (2, 1, 0), EulerRot::XYXEx => (0, 1, 0), EulerRot::YZXEx => (1, 2, 0), EulerRot::XZXEx => (0, 2, 0), EulerRot::XZYEx => (0, 2, 1), EulerRot::YZYEx => (1, 2, 1), EulerRot::ZXYEx => (2, 0, 1), EulerRot::YXYEx => (1, 0, 1), EulerRot::YXZEx => (1, 0, 2), EulerRot::ZXZEx => (2, 0, 2), EulerRot::XYZEx => (0, 1, 2), EulerRot::ZYZEx => (2, 1, 2), } } fn is_intrinsic(order: EulerRot) -> bool { match order { EulerRot::XYZ | EulerRot::XYX | EulerRot::XZY | EulerRot::XZX | EulerRot::YZX | EulerRot::YZY | EulerRot::YXZ | EulerRot::YXY | EulerRot::ZXY | EulerRot::ZXZ | EulerRot::ZYX | EulerRot::ZYZ => true, EulerRot::ZYXEx | EulerRot::XYXEx | EulerRot::YZXEx | EulerRot::XZXEx | EulerRot::XZYEx | EulerRot::YZYEx | EulerRot::ZXYEx | EulerRot::YXYEx | EulerRot::YXZEx | EulerRot::ZXZEx | EulerRot::XYZEx | EulerRot::ZYZEx => false, } } mod f32 { pub fn deg_to_rad(a: i32, b: i32, c: i32) -> (f32, f32, f32) { ( (a as f32).to_radians(), (b as f32).to_radians(), (c as f32).to_radians(), ) } } mod f64 { pub fn deg_to_rad(a: i32, b: i32, c: i32) -> (f64, f64, f64) { ( (a as f64).to_radians(), (b as f64).to_radians(), (c as f64).to_radians(), ) } } fn test_order_angles(order: EulerRot, test: &F) { const RANGE: RangeInclusive = -180..=180; const STEP: usize = 15; for i in RANGE.step_by(STEP) { for j in RANGE.step_by(STEP) { for k in RANGE.step_by(STEP) { test(order, i, j, k); } } } } fn test_all_orders(test: &F) { test(EulerRot::XYZ); test(EulerRot::XZY); test(EulerRot::YZX); test(EulerRot::YXZ); test(EulerRot::ZXY); test(EulerRot::ZYX); test(EulerRot::XZX); test(EulerRot::XYX); test(EulerRot::YXY); test(EulerRot::YZY); test(EulerRot::ZYZ); test(EulerRot::ZXZ); test(EulerRot::XYZEx); test(EulerRot::XZYEx); test(EulerRot::YZXEx); test(EulerRot::YXZEx); test(EulerRot::ZXYEx); test(EulerRot::ZYXEx); test(EulerRot::XZXEx); test(EulerRot::XYXEx); test(EulerRot::YXYEx); test(EulerRot::YZYEx); test(EulerRot::ZYZEx); test(EulerRot::ZXZEx); } macro_rules! impl_quat_euler_test { ($quat:ident, $t:ident) => { use super::{ axis_order, is_intrinsic, test_all_orders, test_order_angles, $t::deg_to_rad, CanonicalQuat, EulerEpsilon, }; use glam::{$quat, EulerRot}; const AXIS_ANGLE: [fn($t) -> $quat; 3] = [ $quat::from_rotation_x, $quat::from_rotation_y, $quat::from_rotation_z, ]; impl CanonicalQuat for $quat { fn canonical(self) -> Self { match self { _ if self.w >= 1e-5 => self, _ if self.w <= -1e-5 => -self, _ => $quat::from_xyzw(0.0, 0.0, 0.0, 1.0), } } } fn test_euler(order: EulerRot, a: i32, b: i32, c: i32) { println!( "test_euler: {} {order:?} ({a}, {b}, {c})", stringify!($quat) ); let (a, b, c) = deg_to_rad(a, b, c); let m = $quat::from_euler(order, a, b, c); let n = { let (i, j, k) = m.to_euler(order); $quat::from_euler(order, i, j, k) }; assert_approx_eq!(m.canonical(), n.canonical(), $t::E_EPS); let o = { let (i, j, k) = axis_order(order); if is_intrinsic(order) { AXIS_ANGLE[i](a) * AXIS_ANGLE[j](b) * AXIS_ANGLE[k](c) } else { AXIS_ANGLE[k](c) * AXIS_ANGLE[j](b) * AXIS_ANGLE[i](a) } }; assert_approx_eq!(m.canonical(), o.canonical(), $t::E_EPS); } #[test] fn test_all_euler_orders() { let test = |order| test_order_angles(order, &test_euler); test_all_orders(&test); } }; } macro_rules! impl_mat_euler_test { ($mat:ident, $t:ident) => { use super::{ axis_order, is_intrinsic, test_all_orders, test_order_angles, $t::deg_to_rad, EulerEpsilon, }; use glam::{$mat, EulerRot}; const AXIS_ANGLE: [fn($t) -> $mat; 3] = [ $mat::from_rotation_x, $mat::from_rotation_y, $mat::from_rotation_z, ]; fn test_euler(order: EulerRot, a: i32, b: i32, c: i32) { println!("test_euler: {} {order:?} ({a}, {b}, {c})", stringify!($mat)); let (a, b, c) = deg_to_rad(a, b, c); let m = $mat::from_euler(order, a, b, c); let n = { let (i, j, k) = m.to_euler(order); $mat::from_euler(order, i, j, k) }; assert_approx_eq!(m, n, $t::E_EPS); let o = { let (i, j, k) = axis_order(order); if is_intrinsic(order) { AXIS_ANGLE[i](a) * AXIS_ANGLE[j](b) * AXIS_ANGLE[k](c) } else { AXIS_ANGLE[k](c) * AXIS_ANGLE[j](b) * AXIS_ANGLE[i](a) } }; assert_approx_eq!(m, o, $t::E_EPS); } #[test] fn test_all_euler_orders() { let test = |order| test_order_angles(order, &test_euler); test_all_orders(&test); } }; } #[test] fn test_euler_default() { assert_eq!(EulerRot::YXZ, EulerRot::default()); } mod quat { impl_quat_euler_test!(Quat, f32); } mod mat3 { impl_mat_euler_test!(Mat3, f32); } mod mat3a { impl_mat_euler_test!(Mat3A, f32); } mod mat4 { impl_mat_euler_test!(Mat4, f32); } mod dquat { impl_quat_euler_test!(DQuat, f64); } mod dmat3 { impl_mat_euler_test!(DMat3, f64); } mod dmat4 { impl_mat_euler_test!(DMat4, f64); } } glam-0.30.1/tests/float.rs000064400000000000000000000026261046102023000134500ustar 00000000000000#[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); } glam-0.30.1/tests/mat2.rs000064400000000000000000000265441046102023000132130ustar 00000000000000#[macro_use] mod support; macro_rules! impl_mat2_tests { ($t:ident, $newmat2:ident, $mat2:ident, $mat3:ident, $newvec2:ident, $vec2:ident) => { const IDENTITY: [[$t; 2]; 2] = [[1.0, 0.0], [0.0, 1.0]]; const ARRAY2X2: [[$t; 2]; 2] = [[1.0, 2.0], [3.0, 4.0]]; const ARRAY1X4: [$t; 4] = [1.0, 2.0, 3.0, 4.0]; const ARRAY3X3: [[$t; 3]; 3] = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]; glam_test!(test_const, { const M0: $mat2 = $mat2::from_cols($newvec2(1.0, 2.0), $newvec2(3.0, 4.0)); const M1: $mat2 = $mat2::from_cols_array(&ARRAY1X4); const M2: $mat2 = $mat2::from_cols_array_2d(&ARRAY2X2); assert_eq!(ARRAY1X4, M0.to_cols_array()); assert_eq!(ARRAY1X4, M1.to_cols_array()); assert_eq!(ARRAY1X4, M2.to_cols_array()); }); glam_test!(test_mat2_identity, { assert_eq!($mat2::IDENTITY, $mat2::from_cols_array(&[1., 0., 0., 1.])); let identity = $mat2::IDENTITY; assert_eq!(IDENTITY, identity.to_cols_array_2d()); assert_eq!($mat2::from_cols_array_2d(&IDENTITY), identity); assert_eq!(identity, identity * identity); assert_eq!(identity, $mat2::default()); assert_eq!(identity, $mat2::from_diagonal($vec2::ONE)); }); glam_test!(test_mat2_zero, { assert_eq!($mat2::ZERO, $mat2::from_cols_array(&[0., 0., 0., 0.])); }); glam_test!(test_mat2_nan, { assert!($mat2::NAN.is_nan()); assert!(!$mat2::NAN.is_finite()); }); glam_test!(test_mat2_accessors, { let mut m = $mat2::ZERO; m.x_axis = $vec2::new(1.0, 2.0); m.y_axis = $vec2::new(3.0, 4.0); assert_eq!($mat2::from_cols_array_2d(&ARRAY2X2), m); assert_eq!($vec2::new(1.0, 2.0), m.x_axis); assert_eq!($vec2::new(3.0, 4.0), m.y_axis); assert_eq!($vec2::new(1.0, 2.0), m.col(0)); assert_eq!($vec2::new(3.0, 4.0), m.col(1)); assert_eq!($newvec2(1.0, 3.0), m.row(0)); assert_eq!($newvec2(2.0, 4.0), m.row(1)); *m.col_mut(0) = m.col(0).yx(); *m.col_mut(1) = m.col(1).yx(); assert_eq!($vec2::new(2.0, 1.0), m.col(0)); assert_eq!($vec2::new(4.0, 3.0), m.col(1)); should_panic!({ $mat2::ZERO.col(2) }); should_panic!({ let mut m = $mat2::ZERO; m.col_mut(2); }); should_panic!({ $mat2::ZERO.row(2) }); }); glam_test!(test_mat2_from_axes, { let a = $mat2::from_cols_array_2d(&ARRAY2X2); assert_eq!(ARRAY2X2, a.to_cols_array_2d()); let b = $mat2::from_cols($newvec2(1.0, 2.0), $newvec2(3.0, 4.0)); assert_eq!(a, b); let c = $newmat2($newvec2(1.0, 2.0), $newvec2(3.0, 4.0)); assert_eq!(a, c); let d = b.to_cols_array(); let f = $mat2::from_cols_array(&d); assert_eq!(b, f); }); glam_test!(test_mat2_mul, { let mat_a = $mat2::from_angle(deg(90.0)); let res_a = mat_a * $vec2::Y; assert_approx_eq!($newvec2(-1.0, 0.0), res_a); let res_b = mat_a * $vec2::X; assert_approx_eq!($newvec2(0.0, 1.0), res_b); }); glam_test!(test_from_scale_angle, { let rot = $mat2::from_scale_angle($vec2::new(4.0, 2.0), deg(180.0)); assert_approx_eq!($vec2::X * -4.0, rot * $vec2::X, 1.0e-6); assert_approx_eq!($vec2::Y * -2.0, rot * $vec2::Y, 1.0e-6); }); glam_test!(test_from_diagonal, { let m = $mat2::from_diagonal($vec2::new(2 as $t, 4 as $t)); assert_eq!( $mat2::from_cols_array_2d(&[[2 as $t, 0 as $t], [0 as $t, 4 as $t]]), m ); assert_approx_eq!(m * $vec2::new(1.0, 1.0), $vec2::new(2.0, 4.0)); assert_approx_eq!($vec2::X * 2.0, m.x_axis); assert_approx_eq!($vec2::Y * 4.0, m.y_axis); }); glam_test!(test_from_mat3, { let m3 = $mat3::from_cols_array_2d(&ARRAY3X3); let m2 = $mat2::from_mat3(m3); assert_eq!($mat2::from_cols_array_2d(&[[1.0, 2.0], [4.0, 5.0]]), m2); }); glam_test!(test_from_mat3_minor, { let m3 = $mat3::from_cols_array_2d(&ARRAY3X3); for i in 0..3 { for j in 0..3 { let m2 = $mat2::from_mat3_minor(m3, i, j); test_matrix_minor!(3, m2, m3, i, j); } } should_panic!({ $mat2::from_mat3_minor(m3, 3, 0) }); should_panic!({ $mat2::from_mat3_minor(m3, 0, 3) }); }); glam_test!(test_mat2_transpose, { let m = $newmat2($newvec2(1.0, 2.0), $newvec2(3.0, 4.0)); let mt = m.transpose(); assert_eq!($newvec2(1.0, 3.0), mt.x_axis); assert_eq!($newvec2(2.0, 4.0), mt.y_axis); }); glam_test!(test_mat2_det, { assert_eq!(0.0, $mat2::ZERO.determinant()); assert_eq!(1.0, $mat2::IDENTITY.determinant()); assert_eq!(1.0, $mat2::from_angle(deg(90.0)).determinant()); assert_eq!(1.0, $mat2::from_angle(deg(180.0)).determinant()); assert_eq!(1.0, $mat2::from_angle(deg(270.0)).determinant()); assert_eq!( 2.0 * 2.0, $mat2::from_diagonal($newvec2(2.0, 2.0)).determinant() ); assert_eq!( 1.0 * 4.0 - 2.0 * 3.0, $mat2::from_cols_array(&ARRAY1X4).determinant() ); }); glam_test!(test_mat2_inverse, { let inv = $mat2::IDENTITY.inverse(); assert_approx_eq!($mat2::IDENTITY, inv); let rot = $mat2::from_angle(deg(90.0)); let rot_inv = rot.inverse(); assert_approx_eq!($mat2::IDENTITY, rot * rot_inv); assert_approx_eq!($mat2::IDENTITY, rot_inv * rot); let scale = $mat2::from_diagonal($newvec2(4.0, 5.0)); let scale_inv = scale.inverse(); assert_approx_eq!($mat2::IDENTITY, scale * scale_inv); assert_approx_eq!($mat2::IDENTITY, scale_inv * scale); let m = scale * rot; let m_inv = m.inverse(); assert_approx_eq!($mat2::IDENTITY, m * m_inv); assert_approx_eq!($mat2::IDENTITY, m_inv * m); assert_approx_eq!(m_inv, rot_inv * scale_inv); should_glam_assert!({ $mat2::ZERO.inverse() }); }); glam_test!(test_mat2_ops, { let m0 = $mat2::from_cols_array_2d(&ARRAY2X2); let m0x2 = $mat2::from_cols_array_2d(&[[2.0, 4.0], [6.0, 8.0]]); let m0_neg = $mat2::from_cols_array_2d(&[[-1.0, -2.0], [-3.0, -4.0]]); assert_eq!(m0x2, m0 * 2.0); assert_eq!(m0x2, 2.0 * m0); assert_eq!(m0, m0x2 / 2.0); assert_eq!(m0, 2.0 / m0x2); assert_eq!(m0x2, m0 + m0); assert_eq!($mat2::ZERO, m0 - m0); assert_eq!(m0_neg, -m0); assert_approx_eq!(m0, m0 * $mat2::IDENTITY); assert_approx_eq!(m0, $mat2::IDENTITY * m0); let mut m1 = m0; m1 *= 2.0; assert_eq!(m0x2, m1); let mut m1 = m0x2; m1 /= 2.0; assert_eq!(m0, m1); let mut m1 = m0; m1 += m0; assert_eq!(m0x2, m1); let mut m1 = m0; m1 -= m0; assert_eq!($mat2::ZERO, m1); let mut m1 = $mat2::IDENTITY; m1 *= m0; assert_approx_eq!(m0, m1); }); glam_test!(test_mat2_fmt, { let a = $mat2::from_cols_array_2d(&ARRAY2X2); assert_eq!(format!("{}", a), "[[1, 2], [3, 4]]"); assert_eq!(format!("{:.2}", a), "[[1.00, 2.00], [3.00, 4.00]]"); }); glam_test!(test_mat2_to_from_slice, { let m = $mat2::from_cols_slice(&ARRAY1X4); assert_eq!($mat2::from_cols_array(&ARRAY1X4), m); let mut out: [$t; 4] = Default::default(); m.write_cols_to_slice(&mut out); assert_eq!(ARRAY1X4, out); should_panic!({ $mat2::from_cols_slice(&[0.0; 3]) }); should_panic!({ $mat2::IDENTITY.write_cols_to_slice(&mut [0.0; 3]) }); }); glam_test!(test_sum, { let id = $mat2::IDENTITY; 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!([two, two].iter().product::<$mat2>(), two * two); assert_eq!([two, two].into_iter().product::<$mat2>(), two * two); }); glam_test!(test_mat2_is_finite, { assert!($mat2::IDENTITY.is_finite()); assert!(!($mat2::IDENTITY * $t::INFINITY).is_finite()); assert!(!($mat2::IDENTITY * $t::NEG_INFINITY).is_finite()); assert!(!($mat2::IDENTITY * $t::NAN).is_finite()); }); }; } macro_rules! impl_as_ref_tests { ($mat:ident) => { glam_test!(test_as_ref, { let m = $mat::from_cols_array_2d(&ARRAY2X2); assert_eq!(ARRAY1X4, *m.as_ref()); }); glam_test!(test_as_mut, { let mut m = $mat::ZERO; *m.as_mut() = ARRAY1X4; assert_eq!($mat::from_cols_array_2d(&ARRAY2X2), m); }); }; } mod mat2 { use super::support::deg; use glam::{mat2, swizzles::*, vec2, Mat2, Mat3, Mat3A, Vec2}; glam_test!(test_align, { use std::mem; assert_eq!(16, mem::size_of::()); if cfg!(feature = "scalar-math") { assert_eq!(mem::align_of::(), mem::align_of::()); } else { assert_eq!(16, mem::align_of::()); } }); glam_test!(test_from_mat3a, { let m3 = Mat3A::from_cols_array_2d(&ARRAY3X3); let m2 = Mat2::from_mat3a(m3); assert_eq!(Mat2::from_cols_array_2d(&[[1.0, 2.0], [4.0, 5.0]]), m2); }); glam_test!(test_from_mat3a_minor, { let m3 = Mat3A::from_cols_array_2d(&ARRAY3X3); for i in 0..3 { for j in 0..3 { let m2 = Mat2::from_mat3a_minor(m3, i, j); test_matrix_minor!(3, m2, m3, i, j); } } should_panic!({ Mat2::from_mat3a_minor(m3, 3, 0) }); should_panic!({ Mat2::from_mat3a_minor(m3, 0, 3) }); }); glam_test!(test_as, { use glam::DMat2; assert_eq!( DMat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]), Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]).as_dmat2() ); assert_eq!( Mat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]), DMat2::from_cols_array(&[1.0, 2.0, 3.0, 4.0]).as_mat2() ); }); impl_mat2_tests!(f32, mat2, Mat2, Mat3, vec2, Vec2); impl_as_ref_tests!(Mat2); } mod dmat2 { use super::support::deg; use glam::{dmat2, dvec2, swizzles::*, DMat2, DMat3, DVec2}; glam_test!(test_align, { use std::mem; assert_eq!(32, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); impl_mat2_tests!(f64, dmat2, DMat2, DMat3, dvec2, DVec2); impl_as_ref_tests!(DMat2); } glam-0.30.1/tests/mat3.rs000064400000000000000000000452151046102023000132100ustar 00000000000000#[macro_use] mod support; macro_rules! impl_mat3_tests { ($t:ident, $newmat3:ident, $mat3:ident, $mat2:ident, $mat4:ident, $quat:ident, $newvec3:ident, $vec3:ident, $vec2:ident) => { const IDENTITY: [[$t; 3]; 3] = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]; const ARRAY3X3: [[$t; 3]; 3] = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]; const ARRAY1X9: [$t; 9] = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]; const ARRAY4X4: [[$t; 4]; 4] = [ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0], ]; glam_test!(test_const, { const M0: $mat3 = $mat3::from_cols( $newvec3(1.0, 2.0, 3.0), $newvec3(4.0, 5.0, 6.0), $newvec3(7.0, 8.0, 9.0), ); const M1: $mat3 = $mat3::from_cols_array(&ARRAY1X9); const M2: $mat3 = $mat3::from_cols_array_2d(&ARRAY3X3); assert_eq!(ARRAY1X9, M0.to_cols_array()); assert_eq!(ARRAY1X9, M1.to_cols_array()); assert_eq!(ARRAY1X9, M2.to_cols_array()); }); glam_test!(test_mat3_identity, { assert_eq!( $mat3::IDENTITY, $mat3::from_cols_array(&[ 1., 0., 0., // 0., 1., 0., // 0., 0., 1., // ]) ); let identity = $mat3::IDENTITY; assert_eq!(IDENTITY, identity.to_cols_array_2d()); assert_eq!($mat3::from_cols_array_2d(&IDENTITY), identity); assert_eq!(identity, identity * identity); assert_eq!(identity, $mat3::default()); assert_eq!(identity, $mat3::from_diagonal($vec3::ONE)); }); glam_test!(test_mat3_zero, { assert_eq!( $mat3::ZERO, $mat3::from_cols_array(&[0., 0., 0., 0., 0., 0., 0., 0., 0.]) ); }); glam_test!(test_mat3_nan, { assert!($mat3::NAN.is_nan()); assert!(!$mat3::NAN.is_finite()); }); glam_test!(test_mat3_accessors, { let mut m = $mat3::ZERO; m.x_axis = $newvec3(1.0, 2.0, 3.0); m.y_axis = $newvec3(4.0, 5.0, 6.0); m.z_axis = $newvec3(7.0, 8.0, 9.0); assert_eq!($mat3::from_cols_array_2d(&ARRAY3X3), m); assert_eq!($newvec3(1.0, 2.0, 3.0), m.x_axis); assert_eq!($newvec3(4.0, 5.0, 6.0), m.y_axis); assert_eq!($newvec3(7.0, 8.0, 9.0), m.z_axis); assert_eq!($newvec3(1.0, 2.0, 3.0), m.col(0)); assert_eq!($newvec3(4.0, 5.0, 6.0), m.col(1)); assert_eq!($newvec3(7.0, 8.0, 9.0), m.col(2)); assert_eq!($newvec3(1.0, 4.0, 7.0), m.row(0)); assert_eq!($newvec3(2.0, 5.0, 8.0), m.row(1)); assert_eq!($newvec3(3.0, 6.0, 9.0), m.row(2)); *m.col_mut(0) = m.col(0).zyx(); *m.col_mut(1) = m.col(1).zyx(); *m.col_mut(2) = m.col(2).zyx(); assert_eq!($newvec3(3.0, 2.0, 1.0), m.col(0)); assert_eq!($newvec3(6.0, 5.0, 4.0), m.col(1)); assert_eq!($newvec3(9.0, 8.0, 7.0), m.col(2)); should_panic!({ $mat3::ZERO.col(3) }); should_panic!({ let mut m = $mat3::ZERO; m.col_mut(3); }); should_panic!({ $mat3::ZERO.row(3) }); }); glam_test!(test_mat3_from_axes, { let a = $mat3::from_cols_array_2d(&[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]); assert_eq!(ARRAY3X3, a.to_cols_array_2d()); let b = $mat3::from_cols( $newvec3(1.0, 2.0, 3.0), $newvec3(4.0, 5.0, 6.0), $newvec3(7.0, 8.0, 9.0), ); assert_eq!(a, b); let c = $newmat3( $newvec3(1.0, 2.0, 3.0), $newvec3(4.0, 5.0, 6.0), $newvec3(7.0, 8.0, 9.0), ); assert_eq!(a, c); let d = b.to_cols_array(); let f = $mat3::from_cols_array(&d); assert_eq!(b, f); }); glam_test!(test_from_rotation, { let rot_x1 = $mat3::from_rotation_x(deg(180.0)); let rot_x2 = $mat3::from_axis_angle($vec3::X, deg(180.0)); assert_approx_eq!(rot_x1, rot_x2); let rot_x3 = $mat3::from_quat($quat::from_rotation_x(deg(180.0))); assert_approx_eq!(rot_x1, rot_x3); let rot_y1 = $mat3::from_rotation_y(deg(180.0)); let rot_y2 = $mat3::from_axis_angle($vec3::Y, deg(180.0)); assert_approx_eq!(rot_y1, rot_y2); let rot_y3 = $mat3::from_quat($quat::from_rotation_y(deg(180.0))); assert_approx_eq!(rot_y1, rot_y3); let rot_z1 = $mat3::from_rotation_z(deg(180.0)); let rot_z2 = $mat3::from_axis_angle($vec3::Z, deg(180.0)); assert_approx_eq!(rot_z1, rot_z2); let rot_z3 = $mat3::from_quat($quat::from_rotation_z(deg(180.0))); assert_approx_eq!(rot_z1, rot_z3); should_glam_assert!({ $mat3::from_axis_angle($vec3::ZERO, 0.0) }); should_glam_assert!({ $mat3::from_quat($quat::from_xyzw(0.0, 0.0, 0.0, 0.0)) }); }); glam_test!(test_mat3_mul, { let mat_a = $mat3::from_axis_angle($vec3::Z, deg(90.0)); assert_approx_eq!($newvec3(-1.0, 0.0, 0.0), mat_a * $newvec3(0.0, 1.0, 0.0)); assert_approx_eq!( $vec3::new(-1.0, 0.0, 0.0), mat_a.mul_vec3($vec3::new(0.0, 1.0, 0.0)) ); }); glam_test!(test_mat3_transform2d, { let m = $mat3::from_translation($vec2::new(2.0, 4.0)); assert_eq!($vec2::ZERO, m.transform_vector2($vec2::ZERO)); assert_eq!($vec2::new(2.0, 4.0), m.transform_point2($vec2::ZERO)); assert_eq!($vec2::ZERO, m.transform_point2($vec2::new(-2.0, -4.0))); let m = $mat3::from_angle($t::to_radians(90.0)); assert_approx_eq!($vec2::Y, m.transform_vector2($vec2::X), 1e-7); assert_approx_eq!($vec2::Y, m.transform_point2($vec2::X), 1e-7); let m = $mat3::from_scale($vec2::new(2.0, 4.0)); assert_eq!($vec2::new(2.0, 0.0), m.transform_vector2($vec2::X)); assert_eq!($vec2::new(0.0, 4.0), m.transform_vector2($vec2::Y)); assert_eq!($vec2::new(2.0, 0.0), m.transform_point2($vec2::X)); assert_eq!($vec2::new(0.0, 4.0), m.transform_point2($vec2::Y)); should_glam_assert!({ $mat3::from_scale($vec2::ZERO) }); let m = $mat3::from_scale_angle_translation( $vec2::new(0.5, 1.5), $t::to_radians(90.0), $vec2::new(1.0, 2.0), ); let result2 = m.transform_vector2($vec2::Y); assert_approx_eq!($vec2::new(-1.5, 0.0), result2, 1.0e-6); assert_approx_eq!(result2, (m * $vec2::Y.extend(0.0)).truncate()); let result2 = m.transform_point2($vec2::Y); assert_approx_eq!($vec2::new(-0.5, 2.0), result2, 1.0e-6); assert_approx_eq!(result2, (m * $vec2::Y.extend(1.0)).truncate()); }); glam_test!(test_from_ypr, { use glam::EulerRot; let zero = deg(0.0); let yaw = deg(30.0); let pitch = deg(60.0); let roll = deg(90.0); let y0 = $mat3::from_rotation_y(yaw); let y1 = $mat3::from_euler(EulerRot::YXZ, yaw, zero, zero); assert_approx_eq!(y0, y1); let x0 = $mat3::from_rotation_x(pitch); let x1 = $mat3::from_euler(EulerRot::YXZ, zero, pitch, zero); assert_approx_eq!(x0, x1); let z0 = $mat3::from_rotation_z(roll); let z1 = $mat3::from_euler(EulerRot::YXZ, zero, zero, roll); assert_approx_eq!(z0, z1); let yx0 = y0 * x0; let yx1 = $mat3::from_euler(EulerRot::YXZ, yaw, pitch, zero); assert_approx_eq!(yx0, yx1, 1e-6); let yxz0 = y0 * x0 * z0; let yxz1 = $mat3::from_euler(EulerRot::YXZ, yaw, pitch, roll); assert_approx_eq!(yxz0, yxz1, 1e-6); }); glam_test!(test_from_diagonal, { let m = $mat3::from_diagonal($vec3::new(2.0, 4.0, 8.0)); assert_approx_eq!(m * $vec3::new(1.0, 1.0, 1.0), $vec3::new(2.0, 4.0, 8.0)); assert_approx_eq!($newvec3(2.0, 0.0, 0.0), m.x_axis); assert_approx_eq!($newvec3(0.0, 4.0, 0.0), m.y_axis); assert_approx_eq!($newvec3(0.0, 0.0, 8.0), m.z_axis); }); glam_test!(test_from_mat2, { let m2 = $mat2::from_cols_array_2d(&[[1.0, 2.0], [3.0, 4.0]]); let m3 = $mat3::from_mat2(m2); assert_eq!( $mat3::from_cols_array_2d(&[[1.0, 2.0, 0.0], [3.0, 4.0, 0.0], [0.0, 0.0, 1.0]]), m3 ); }); glam_test!(test_from_mat4, { let m4 = $mat4::from_cols_array_2d(&ARRAY4X4); let m3 = $mat3::from_mat4(m4); assert_eq!( $mat3::from_cols_array_2d(&[[1.0, 2.0, 3.0], [5.0, 6.0, 7.0], [9.0, 10.0, 11.0]]), m3 ); }); glam_test!(test_from_mat4_minor, { let m4 = $mat4::from_cols_array_2d(&ARRAY4X4); for i in 0..4 { for j in 0..4 { let m3 = $mat3::from_mat4_minor(m4, i, j); test_matrix_minor!(4, m3, m4, i, j); } } should_panic!({ $mat3::from_mat4_minor(m4, 4, 0) }); should_panic!({ $mat3::from_mat4_minor(m4, 0, 4) }); }); glam_test!(test_mat3_look_at, { let eye = $vec3::new(0.0, 0.0, -5.0); let center = $vec3::new(0.0, 0.0, 0.0); let up = $vec3::new(1.0, 0.0, 0.0); let point = $vec3::new(1.0, 0.0, 0.0); let lh = $mat3::look_at_lh(eye, center, up); let rh = $mat3::look_at_rh(eye, center, up); assert_approx_eq!(lh * point, $vec3::new(0.0, 1.0, 0.0)); assert_approx_eq!(rh * point, $vec3::new(0.0, 1.0, 0.0)); let dir = (center - eye).normalize(); let lh = $mat3::look_to_lh(dir, up); let rh = $mat3::look_to_rh(dir, up); assert_approx_eq!(lh * point, $vec3::new(0.0, 1.0, 0.0)); assert_approx_eq!(rh * point, $vec3::new(0.0, 1.0, 0.0)); should_glam_assert!({ $mat3::look_to_lh($vec3::ONE, $vec3::ZERO) }); should_glam_assert!({ $mat3::look_to_lh($vec3::ZERO, $vec3::ONE) }); should_glam_assert!({ $mat3::look_to_rh($vec3::ONE, $vec3::ZERO) }); should_glam_assert!({ $mat3::look_to_rh($vec3::ZERO, $vec3::ONE) }); }); glam_test!(test_mat3_transpose, { let m = $newmat3( $newvec3(1.0, 2.0, 3.0), $newvec3(4.0, 5.0, 6.0), $newvec3(7.0, 8.0, 9.0), ); let mt = m.transpose(); assert_eq!($newvec3(1.0, 4.0, 7.0), mt.x_axis); assert_eq!($newvec3(2.0, 5.0, 8.0), mt.y_axis); assert_eq!($newvec3(3.0, 6.0, 9.0), mt.z_axis); }); glam_test!(test_mat3_det, { assert_eq!(0.0, $mat3::ZERO.determinant()); assert_eq!(1.0, $mat3::IDENTITY.determinant()); assert_eq!(1.0, $mat3::from_rotation_x(deg(90.0)).determinant()); assert_eq!(1.0, $mat3::from_rotation_y(deg(180.0)).determinant()); assert_eq!(1.0, $mat3::from_rotation_z(deg(270.0)).determinant()); assert_eq!( 2.0 * 2.0 * 2.0, $mat3::from_diagonal($vec3::new(2.0, 2.0, 2.0)).determinant() ); }); glam_test!(test_mat3_inverse, { // assert_eq!(None, $mat3::ZERO.inverse()); let inv = $mat3::IDENTITY.inverse(); // assert_ne!(None, inv); assert_approx_eq!($mat3::IDENTITY, inv); let rotz = $mat3::from_rotation_z(deg(90.0)); let rotz_inv = rotz.inverse(); // assert_ne!(None, rotz_inv); // let rotz_inv = rotz_inv.unwrap(); assert_approx_eq!($mat3::IDENTITY, rotz * rotz_inv); assert_approx_eq!($mat3::IDENTITY, rotz_inv * rotz); let scale = $mat3::from_diagonal($vec3::new(4.0, 5.0, 6.0)); let scale_inv = scale.inverse(); // assert_ne!(None, scale_inv); // let scale_inv = scale_inv.unwrap(); assert_approx_eq!($mat3::IDENTITY, scale * scale_inv); assert_approx_eq!($mat3::IDENTITY, scale_inv * scale); let m = scale * rotz; let m_inv = m.inverse(); // assert_ne!(None, m_inv); // let m_inv = m_inv.unwrap(); assert_approx_eq!($mat3::IDENTITY, m * m_inv); assert_approx_eq!($mat3::IDENTITY, m_inv * m); assert_approx_eq!(m_inv, rotz_inv * scale_inv); should_glam_assert!({ $mat3::ZERO.inverse() }); }); glam_test!(test_mat3_ops, { let m0 = $mat3::from_cols_array_2d(&ARRAY3X3); let m0x2 = $mat3::from_cols_array_2d(&[ [2.0, 4.0, 6.0], [8.0, 10.0, 12.0], [14.0, 16.0, 18.0], ]); let m0_neg = $mat3::from_cols_array_2d(&[ [-1.0, -2.0, -3.0], [-4.0, -5.0, -6.0], [-7.0, -8.0, -9.0], ]); assert_eq!(m0x2, m0 * 2.0); assert_eq!(m0x2, 2.0 * m0); assert_eq!(m0, m0x2 / 2.0); assert_eq!(m0, 2.0 / m0x2); assert_eq!(m0x2, m0 + m0); assert_eq!($mat3::ZERO, m0 - m0); assert_eq!(m0_neg, -m0); assert_approx_eq!(m0, m0 * $mat3::IDENTITY); assert_approx_eq!(m0, $mat3::IDENTITY * m0); let mut m1 = m0; m1 *= 2.0; assert_eq!(m0x2, m1); let mut m1 = m0x2; m1 /= 2.0; assert_eq!(m0, m1); let mut m1 = m0; m1 += m0; assert_eq!(m0x2, m1); let mut m1 = m0; m1 -= m0; assert_eq!($mat3::ZERO, m1); let mut m1 = $mat3::IDENTITY; m1 *= m0; assert_approx_eq!(m0, m1); }); glam_test!(test_mat3_fmt, { let a = $mat3::from_cols_array_2d(&ARRAY3X3); assert_eq!(format!("{}", a), "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]"); assert_eq!( format!("{:.1}", a), "[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]" ); }); glam_test!(test_mat3_to_from_slice, { let m = $mat3::from_cols_slice(&ARRAY1X9); assert_eq!($mat3::from_cols_array(&ARRAY1X9), m); let mut out: [$t; 9] = Default::default(); m.write_cols_to_slice(&mut out); assert_eq!(ARRAY1X9, out); should_panic!({ $mat3::from_cols_slice(&[0.0; 8]) }); should_panic!({ $mat3::IDENTITY.write_cols_to_slice(&mut [0.0; 8]) }); }); glam_test!(test_sum, { let id = $mat3::IDENTITY; 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!([two, two].iter().product::<$mat3>(), two * two); assert_eq!([two, two].into_iter().product::<$mat3>(), two * two); }); glam_test!(test_mat3_is_finite, { assert!($mat3::IDENTITY.is_finite()); assert!(!($mat3::IDENTITY * $t::INFINITY).is_finite()); assert!(!($mat3::IDENTITY * $t::NEG_INFINITY).is_finite()); assert!(!($mat3::IDENTITY * $t::NAN).is_finite()); }); }; } macro_rules! impl_as_ref_tests { ($mat:ident) => { glam_test!(test_as_ref, { let m = $mat::from_cols_array_2d(&ARRAY3X3); assert_eq!(ARRAY1X9, *m.as_ref()); }); glam_test!(test_as_mut, { let mut m = $mat::ZERO; *m.as_mut() = ARRAY1X9; assert_eq!($mat::from_cols_array_2d(&ARRAY3X3), m); }); }; } mod mat3 { use super::support::deg; use glam::{mat3, swizzles::*, vec3, vec3a, Mat2, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A}; glam_test!(test_align, { use std::mem; assert_eq!(36, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); glam_test!(test_mul_vec3a, { let mat_a = Mat3::from_axis_angle(Vec3::Z, deg(90.0)); assert_approx_eq!(vec3a(-1.0, 0.0, 0.0), mat_a * Vec3A::Y); assert_approx_eq!(vec3a(-1.0, 0.0, 0.0), mat_a.mul_vec3a(Vec3A::Y)); }); glam_test!(test_as, { use glam::DMat3; assert_eq!( DMat3::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]), Mat3::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]).as_dmat3() ); assert_eq!( Mat3::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]), DMat3::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]).as_mat3() ); }); impl_mat3_tests!(f32, mat3, Mat3, Mat2, Mat4, Quat, vec3, Vec3, Vec2); impl_as_ref_tests!(Mat3); } mod mat3a { use super::support::deg; use glam::{mat3a, swizzles::*, vec3a, Mat2, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A}; glam_test!(test_align, { use std::mem; assert_eq!(48, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); glam_test!(test_mul_vec3a, { let mat_a = Mat3A::from_axis_angle(Vec3::Z, deg(90.0)); assert_approx_eq!(vec3a(-1.0, 0.0, 0.0), mat_a * Vec3A::Y); assert_approx_eq!(vec3a(-1.0, 0.0, 0.0), mat_a.mul_vec3a(Vec3A::Y)); }); glam_test!(test_as, { use glam::DMat3; assert_eq!( DMat3::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]), Mat3A::from_cols_array(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]).as_dmat3() ); }); impl_mat3_tests!(f32, mat3a, Mat3A, Mat2, Mat4, Quat, vec3a, Vec3, Vec2); } mod dmat3 { use super::support::deg; use glam::{dmat3, dvec3, swizzles::*, DMat2, DMat3, DMat4, DQuat, DVec2, DVec3}; glam_test!(test_align, { use std::mem; assert_eq!(72, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); impl_mat3_tests!(f64, dmat3, DMat3, DMat2, DMat4, DQuat, dvec3, DVec3, DVec2); impl_as_ref_tests!(DMat3); } glam-0.30.1/tests/mat4.rs000064400000000000000000001014301046102023000132010ustar 00000000000000#[macro_use] mod support; macro_rules! impl_mat4_tests { ($t:ident, $newmat4:ident, $newvec4:ident, $newvec3:ident, $mat4:ident, $mat3:ident, $quat:ident, $vec4:ident, $vec3:ident) => { const IDENTITY: [[$t; 4]; 4] = [ [1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0], ]; const ARRAY4X4: [[$t; 4]; 4] = [ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0], ]; const ARRAY1X16: [$t; 16] = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, ]; const ARRAY3X3: [[$t; 3]; 3] = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]; glam_test!(test_const, { const M0: $mat4 = $mat4::from_cols( $newvec4(1.0, 2.0, 3.0, 4.0), $newvec4(5.0, 6.0, 7.0, 8.0), $newvec4(9.0, 10.0, 11.0, 12.0), $newvec4(13.0, 14.0, 15.0, 16.0), ); const M1: $mat4 = $mat4::from_cols_array(&ARRAY1X16); const M2: $mat4 = $mat4::from_cols_array_2d(&ARRAY4X4); assert_eq!(ARRAY1X16, M0.to_cols_array()); assert_eq!(ARRAY1X16, M1.to_cols_array()); assert_eq!(ARRAY1X16, M2.to_cols_array()); }); glam_test!(test_mat4_identity, { assert_eq!( $mat4::IDENTITY, $mat4::from_cols_array(&[ 1., 0., 0., 0., // 0., 1., 0., 0., // 0., 0., 1., 0., // 0., 0., 0., 1., // ]) ); let identity = $mat4::IDENTITY; assert_eq!(IDENTITY, identity.to_cols_array_2d()); assert_eq!($mat4::from_cols_array_2d(&IDENTITY), identity); assert_eq!(identity, identity * identity); assert_eq!(identity, $mat4::default()); assert_eq!(identity, $mat4::from_diagonal($vec4::ONE)); }); glam_test!(test_mat4_zero, { assert_eq!( $mat4::ZERO, $mat4::from_cols_array(&[ 0., 0., 0., 0., // 0., 0., 0., 0., // 0., 0., 0., 0., // 0., 0., 0., 0., // ]) ); }); glam_test!(test_mat4_nan, { assert!($mat4::NAN.is_nan()); assert!(!$mat4::NAN.is_finite()); }); glam_test!(test_mat4_accessors, { let mut m = $mat4::ZERO; m.x_axis = $vec4::new(1.0, 2.0, 3.0, 4.0); m.y_axis = $vec4::new(5.0, 6.0, 7.0, 8.0); m.z_axis = $vec4::new(9.0, 10.0, 11.0, 12.0); m.w_axis = $vec4::new(13.0, 14.0, 15.0, 16.0); assert_eq!($mat4::from_cols_array_2d(&ARRAY4X4), m); assert_eq!($vec4::new(1.0, 2.0, 3.0, 4.0), m.x_axis); assert_eq!($vec4::new(5.0, 6.0, 7.0, 8.0), m.y_axis); assert_eq!($vec4::new(9.0, 10.0, 11.0, 12.0), m.z_axis); assert_eq!($vec4::new(13.0, 14.0, 15.0, 16.0), m.w_axis); assert_eq!($vec4::new(1.0, 2.0, 3.0, 4.0), m.col(0)); assert_eq!($vec4::new(5.0, 6.0, 7.0, 8.0), m.col(1)); assert_eq!($vec4::new(9.0, 10.0, 11.0, 12.0), m.col(2)); assert_eq!($vec4::new(13.0, 14.0, 15.0, 16.0), m.col(3)); assert_eq!($newvec4(1.0, 5.0, 9.0, 13.0), m.row(0)); assert_eq!($newvec4(2.0, 6.0, 10.0, 14.0), m.row(1)); assert_eq!($newvec4(3.0, 7.0, 11.0, 15.0), m.row(2)); assert_eq!($newvec4(4.0, 8.0, 12.0, 16.0), m.row(3)); *m.col_mut(0) = m.col(0).wzyx(); *m.col_mut(1) = m.col(1).wzyx(); *m.col_mut(2) = m.col(2).wzyx(); *m.col_mut(3) = m.col(3).wzyx(); assert_eq!($newvec4(4.0, 3.0, 2.0, 1.0), m.col(0)); assert_eq!($newvec4(8.0, 7.0, 6.0, 5.0), m.col(1)); assert_eq!($newvec4(12.0, 11.0, 10.0, 9.0), m.col(2)); assert_eq!($newvec4(16.0, 15.0, 14.0, 13.0), m.col(3)); should_panic!({ $mat4::ZERO.col(4) }); should_panic!({ let mut m = $mat4::ZERO; m.col_mut(4); }); should_panic!({ $mat4::ZERO.row(4) }); }); glam_test!(test_mat4_from_axes, { let a = $mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0], ]); assert_eq!(ARRAY4X4, a.to_cols_array_2d()); let b = $mat4::from_cols( $newvec4(1.0, 2.0, 3.0, 4.0), $newvec4(5.0, 6.0, 7.0, 8.0), $newvec4(9.0, 10.0, 11.0, 12.0), $newvec4(13.0, 14.0, 15.0, 16.0), ); assert_eq!(a, b); let c = $newmat4( $newvec4(1.0, 2.0, 3.0, 4.0), $newvec4(5.0, 6.0, 7.0, 8.0), $newvec4(9.0, 10.0, 11.0, 12.0), $newvec4(13.0, 14.0, 15.0, 16.0), ); assert_eq!(a, c); let d = b.to_cols_array(); let f = $mat4::from_cols_array(&d); assert_eq!(b, f); }); glam_test!(test_mat4_translation, { let translate = $mat4::from_translation($newvec3(1.0, 2.0, 3.0)); assert_eq!( $mat4::from_cols( $newvec4(1.0, 0.0, 0.0, 0.0), $newvec4(0.0, 1.0, 0.0, 0.0), $newvec4(0.0, 0.0, 1.0, 0.0), $newvec4(1.0, 2.0, 3.0, 1.0) ), translate ); }); glam_test!(test_from_rotation, { let rot_x1 = $mat4::from_rotation_x(deg(180.0)); let rot_x2 = $mat4::from_axis_angle($vec3::X, deg(180.0)); assert_approx_eq!(rot_x1, rot_x2); let rot_y1 = $mat4::from_rotation_y(deg(180.0)); let rot_y2 = $mat4::from_axis_angle($vec3::Y, deg(180.0)); assert_approx_eq!(rot_y1, rot_y2); let rot_z1 = $mat4::from_rotation_z(deg(180.0)); let rot_z2 = $mat4::from_axis_angle($vec3::Z, deg(180.0)); assert_approx_eq!(rot_z1, rot_z2); assert_approx_eq!($mat4::IDENTITY, $mat4::from_quat($quat::IDENTITY)); should_glam_assert!({ $mat4::from_axis_angle($vec3::ZERO, 0.0) }); should_glam_assert!({ $mat4::from_quat($quat::from_xyzw(0.0, 0.0, 0.0, 0.0)) }); }); glam_test!(test_from_mat3, { let m3 = $mat3::from_cols_array_2d(&ARRAY3X3); let m4 = $mat4::from_mat3(m3); assert_eq!( $mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 0.0], [4.0, 5.0, 6.0, 0.0], [7.0, 8.0, 9.0, 0.0], [0.0, 0.0, 0.0, 1.0] ]), m4 ); let t = $vec3::new(10.0, 11.0, 12.0); let m4 = $mat4::from_mat3_translation(m3, t); assert_eq!($mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 0.0], [4.0, 5.0, 6.0, 0.0], [7.0, 8.0, 9.0, 0.0], [10.0, 11.0, 12.0, 1.0] ]), m4); }); glam_test!(test_mat4_mul, { let m = $mat4::from_axis_angle($vec3::Z, deg(90.0)); let result3 = m.transform_vector3($vec3::Y); assert_approx_eq!($newvec3(-1.0, 0.0, 0.0), result3); assert_approx_eq!(result3, (m * $vec3::Y.extend(0.0)).truncate().into()); let result4 = m * $vec4::Y; assert_approx_eq!($newvec4(-1.0, 0.0, 0.0, 0.0), result4); assert_approx_eq!(result4, m * $vec4::Y); let m = $mat4::from_scale_rotation_translation( $vec3::new(0.5, 1.5, 2.0), $quat::from_rotation_x(deg(90.0)), $vec3::new(1.0, 2.0, 3.0), ); let result3 = m.transform_vector3($vec3::Y); assert_approx_eq!($newvec3(0.0, 0.0, 1.5), result3, 1.0e-6); assert_approx_eq!(result3, (m * $vec3::Y.extend(0.0)).truncate().into()); let result3 = m.transform_point3($vec3::Y); assert_approx_eq!($newvec3(1.0, 2.0, 4.5), result3, 1.0e-6); assert_approx_eq!(result3, (m * $vec3::Y.extend(1.0)).truncate().into()); let m = $mat4::from_cols( $newvec4(8.0, 0.0, 0.0, 0.0), $newvec4(0.0, 4.0, 0.0, 0.0), $newvec4(0.0, 0.0, 2.0, 2.0), $newvec4(0.0, 0.0, 0.0, 0.0), ); assert_approx_eq!( $newvec3(4.0, 2.0, 1.0), m.project_point3($newvec3(2.0, 2.0, 2.0)) ); should_glam_assert!({ $mat4::ZERO.transform_vector3($vec3::X) }); should_glam_assert!({ $mat4::ZERO.transform_point3($vec3::X) }); }); glam_test!(test_from_ypr, { use glam::EulerRot; let zero = deg(0.0); let yaw = deg(30.0); let pitch = deg(60.0); let roll = deg(90.0); let y0 = $mat4::from_rotation_y(yaw); let y1 = $mat4::from_euler(EulerRot::YXZ, yaw, zero, zero); assert_approx_eq!(y0, y1); let x0 = $mat4::from_rotation_x(pitch); let x1 = $mat4::from_euler(EulerRot::YXZ, zero, pitch, zero); assert_approx_eq!(x0, x1); let z0 = $mat4::from_rotation_z(roll); let z1 = $mat4::from_euler(EulerRot::YXZ, zero, zero, roll); assert_approx_eq!(z0, z1); let yx0 = y0 * x0; let yx1 = $mat4::from_euler(EulerRot::YXZ, yaw, pitch, zero); assert_approx_eq!(yx0, yx1, 1e-6); let yxz0 = y0 * x0 * z0; let yxz1 = $mat4::from_euler(EulerRot::YXZ, yaw, pitch, roll); assert_approx_eq!(yxz0, yxz1, 1e-6); }); glam_test!(test_from_scale, { let m = $mat4::from_scale($vec3::new(2.0, 4.0, 8.0)); assert_approx_eq!($vec4::X * 2.0, m.x_axis); assert_approx_eq!($vec4::Y * 4.0, m.y_axis); assert_approx_eq!($vec4::Z * 8.0, m.z_axis); assert_approx_eq!($vec4::W, m.w_axis); assert_approx_eq!( m.transform_point3($vec3::new(1.0, 1.0, 1.0)), $vec3::new(2.0, 4.0, 8.0) ); should_glam_assert!({ $mat4::from_scale($vec3::ZERO) }); }); glam_test!(test_mat4_transpose, { let m = $newmat4( $newvec4(1.0, 2.0, 3.0, 4.0), $newvec4(5.0, 6.0, 7.0, 8.0), $newvec4(9.0, 10.0, 11.0, 12.0), $newvec4(13.0, 14.0, 15.0, 16.0), ); let mt = m.transpose(); assert_eq!($newvec4(1.0, 5.0, 9.0, 13.0), mt.x_axis); assert_eq!($newvec4(2.0, 6.0, 10.0, 14.0), mt.y_axis); assert_eq!($newvec4(3.0, 7.0, 11.0, 15.0), mt.z_axis); assert_eq!($newvec4(4.0, 8.0, 12.0, 16.0), mt.w_axis); }); glam_test!(test_mat4_det, { assert_eq!(0.0, $mat4::ZERO.determinant()); assert_eq!(1.0, $mat4::IDENTITY.determinant()); assert_eq!(1.0, $mat4::from_rotation_x(deg(90.0)).determinant()); assert_eq!(1.0, $mat4::from_rotation_y(deg(180.0)).determinant()); assert_eq!(1.0, $mat4::from_rotation_z(deg(270.0)).determinant()); assert_eq!( 2.0 * 2.0 * 2.0, $mat4::from_scale($newvec3(2.0, 2.0, 2.0)).determinant() ); assert_eq!( 1.0, $newmat4( $newvec4(0.0, 0.0, 0.0, 1.0), $newvec4(1.0, 0.0, 0.0, 0.0), $newvec4(0.0, 0.0, 1.0, 0.0), $newvec4(0.0, 1.0, 0.0, 0.0), ) .determinant() ); }); glam_test!(test_mat4_inverse, { // assert_eq!(None, $mat4::ZERO.inverse()); let inv = $mat4::IDENTITY.inverse(); // assert_ne!(None, inv); assert_approx_eq!($mat4::IDENTITY, inv); let rotz = $mat4::from_rotation_z(deg(90.0)); let rotz_inv = rotz.inverse(); // assert_ne!(None, rotz_inv); // let rotz_inv = rotz_inv.unwrap(); assert_approx_eq!($mat4::IDENTITY, rotz * rotz_inv); assert_approx_eq!($mat4::IDENTITY, rotz_inv * rotz); let trans = $mat4::from_translation($newvec3(1.0, 2.0, 3.0)); let trans_inv = trans.inverse(); // assert_ne!(None, trans_inv); // let trans_inv = trans_inv.unwrap(); assert_approx_eq!($mat4::IDENTITY, trans * trans_inv); assert_approx_eq!($mat4::IDENTITY, trans_inv * trans); let scale = $mat4::from_scale($newvec3(4.0, 5.0, 6.0)); let scale_inv = scale.inverse(); // assert_ne!(None, scale_inv); // let scale_inv = scale_inv.unwrap(); assert_approx_eq!($mat4::IDENTITY, scale * scale_inv); assert_approx_eq!($mat4::IDENTITY, scale_inv * scale); let m = scale * rotz * trans; let m_inv = m.inverse(); // assert_ne!(None, m_inv); // let m_inv = m_inv.unwrap(); assert_approx_eq!($mat4::IDENTITY, m * m_inv, 1.0e-5); assert_approx_eq!($mat4::IDENTITY, m_inv * m, 1.0e-5); assert_approx_eq!(m_inv, trans_inv * rotz_inv * scale_inv, 1.0e-6); // Make sure we can invert a "random" matrix: let m = $mat4::from_cols( $newvec4(1.0, -0.3, 1.0, 1.0), $newvec4(0.5, 0.6, 0.7, 0.8), $newvec4(-0.9, -0.3, 0.0, 12.0), $newvec4(0.13, 0.14, 0.15, 0.16), ); let m_inv = m.inverse(); assert_approx_eq!($mat4::IDENTITY, m * m_inv, 1.0e-5); assert_approx_eq!($mat4::IDENTITY, m_inv * m, 1.0e-5); should_glam_assert!({ $mat4::ZERO.inverse() }); }); glam_test!(test_mat4_decompose, { // identity let (out_scale, out_rotation, out_translation) = $mat4::IDENTITY.to_scale_rotation_translation(); assert_approx_eq!($vec3::ONE, out_scale); assert!(out_rotation.is_near_identity()); assert_approx_eq!($vec3::ZERO, out_translation); // no scale let in_scale = $vec3::ONE; let in_translation = $vec3::new(-2.0, 4.0, -0.125); let in_rotation = $quat::from_euler( glam::EulerRot::YXZ, $t::to_radians(-45.0), $t::to_radians(180.0), $t::to_radians(270.0), ); let in_mat = $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); assert_approx_eq!(in_scale, out_scale, 1e-6); // out_rotation is different but produces the same matrix // assert_approx_eq!(in_rotation, out_rotation); assert_approx_eq!(in_translation, out_translation); assert_approx_eq!( in_mat, $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-6 ); // positive scale let in_scale = $vec3::new(1.0, 2.0, 4.0); let in_mat = $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); assert_approx_eq!(in_scale, out_scale, 1e-6); // out_rotation is different but produces the same matrix // assert_approx_eq!(in_rotation, out_rotation); assert_approx_eq!(in_translation, out_translation); assert_approx_eq!( in_mat, $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-5 ); // negative scale let in_scale = $vec3::new(-4.0, 1.0, 2.0); let in_mat = $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_translation(); assert_approx_eq!(in_scale, out_scale, 1e-6); // out_rotation is different but produces the same matrix // assert_approx_eq!(in_rotation, out_rotation); assert_approx_eq!(in_translation, out_translation); assert_approx_eq!( in_mat, $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-5 ); // negative scale let in_scale = $vec3::new(4.0, -1.0, -2.0); let in_mat = $mat4::from_scale_rotation_translation(in_scale, in_rotation, in_translation); let (out_scale, out_rotation, out_translation) = in_mat.to_scale_rotation_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, $mat4::from_scale_rotation_translation(out_scale, out_rotation, out_translation), 1e-6 ); should_glam_assert!({ $mat4::from_scale_rotation_translation( $vec3::ONE, $quat::from_xyzw(0.0, 0.0, 0.0, 0.0), $vec3::ZERO, ) }); should_glam_assert!({ $mat4::from_rotation_translation($quat::from_xyzw(0.0, 0.0, 0.0, 0.0), $vec3::ZERO) }); // TODO: should check scale // should_glam_assert!({ $mat4::from_scale_rotation_translation($vec3::ZERO, $quat::IDENTITY, $vec3::ZERO) }); should_glam_assert!({ $mat4::ZERO.to_scale_rotation_translation() }); }); glam_test!(test_mat4_look_at, { let eye = $vec3::new(0.0, 0.0, -5.0); let center = $vec3::new(0.0, 0.0, 0.0); let up = $vec3::new(1.0, 0.0, 0.0); let point = $vec3::new(1.0, 0.0, 0.0); let lh = $mat4::look_at_lh(eye, center, up); let rh = $mat4::look_at_rh(eye, center, up); assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); let dir = (center - eye).normalize(); let lh = $mat4::look_to_lh(eye, dir, up); let rh = $mat4::look_to_rh(eye, dir, up); assert_approx_eq!(lh.transform_point3(point), $vec3::new(0.0, 1.0, 5.0)); assert_approx_eq!(rh.transform_point3(point), $vec3::new(0.0, 1.0, -5.0)); should_glam_assert!({ $mat4::look_to_lh($vec3::ONE, $vec3::ONE, $vec3::ZERO) }); should_glam_assert!({ $mat4::look_to_lh($vec3::ONE, $vec3::ZERO, $vec3::ONE) }); should_glam_assert!({ $mat4::look_to_rh($vec3::ONE, $vec3::ONE, $vec3::ZERO) }); should_glam_assert!({ $mat4::look_to_rh($vec3::ONE, $vec3::ZERO, $vec3::ONE) }); }); glam_test!(test_mat4_perspective_gl_rh, { let projection = $mat4::perspective_rh_gl($t::to_radians(90.0), 2.0, 5.0, 15.0); let original = $vec3::new(5.0, 5.0, -15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 15.0, 15.0), projected); let original = $vec3::new(5.0, 5.0, -5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, -5.0, 5.0), projected); }); glam_test!(test_mat4_perspective_lh, { let projection = $mat4::perspective_lh($t::to_radians(90.0), 2.0, 5.0, 15.0); let original = $vec3::new(5.0, 5.0, 15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 15.0, 15.0), projected, 1e-6); let original = $vec3::new(5.0, 5.0, 5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 0.0, 5.0), projected, 1e-6); should_glam_assert!({ $mat4::perspective_lh(0.0, 1.0, 1.0, 0.0) }); should_glam_assert!({ $mat4::perspective_lh(0.0, 1.0, 0.0, 1.0) }); }); glam_test!(test_mat4_perspective_infinite_lh, { let projection = $mat4::perspective_infinite_lh($t::to_radians(90.0), 2.0, 5.0); let original = $vec3::new(5.0, 5.0, 15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 10.0, 15.0), projected, 1e-6); let original = $vec3::new(5.0, 5.0, 5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 0.0, 5.0), projected, 1e-6); should_glam_assert!({ $mat4::perspective_infinite_lh(0.0, 1.0, 0.0) }); }); glam_test!(test_mat4_perspective_infinite_reverse_lh, { let projection = $mat4::perspective_infinite_reverse_lh($t::to_radians(90.0), 2.0, 5.0); let original = $vec3::new(5.0, 5.0, 15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, 15.0), projected, 1e-6); let original = $vec3::new(5.0, 5.0, 5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, 5.0), projected, 1e-6); should_glam_assert!({ $mat4::perspective_infinite_reverse_lh(0.0, 1.0, 0.0) }); }); glam_test!(test_mat4_perspective_rh, { let projection = $mat4::perspective_rh($t::to_radians(90.0), 2.0, 5.0, 15.0); let original = $vec3::new(5.0, 5.0, 15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, -30.0, -15.0), projected, 1e-6); let original = $vec3::new(5.0, 5.0, 5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, -15.0, -5.0), projected, 1e-6); should_glam_assert!({ $mat4::perspective_rh(0.0, 1.0, 1.0, 0.0) }); should_glam_assert!({ $mat4::perspective_rh(0.0, 1.0, 0.0, 1.0) }); }); glam_test!(test_mat4_perspective_infinite_rh, { let projection = $mat4::perspective_infinite_rh($t::to_radians(90.0), 2.0, 5.0); let original = $vec3::new(5.0, 5.0, 15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, -20.0, -15.0), projected); let original = $vec3::new(5.0, 5.0, 5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, -10.0, -5.0), projected); should_glam_assert!({ $mat4::perspective_infinite_rh(0.0, 1.0, 0.0) }); }); glam_test!(test_mat4_perspective_infinite_reverse_rh, { let projection = $mat4::perspective_infinite_reverse_rh($t::to_radians(90.0), 2.0, 5.0); let original = $vec3::new(5.0, 5.0, 15.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, -15.0), projected); let original = $vec3::new(5.0, 5.0, 5.0); let projected = projection * original.extend(1.0); assert_approx_eq!($vec4::new(2.5, 5.0, 5.0, -5.0), projected); should_glam_assert!({ $mat4::perspective_infinite_reverse_rh(0.0, 1.0, 0.0) }); }); glam_test!(test_mat4_orthographic_gl_rh, { let projection = $mat4::orthographic_rh_gl(-10.0, 10.0, -5.0, 5.0, 0.0, -10.0); let original = $vec4::new(5.0, 5.0, -5.0, 1.0); let projected = projection.mul_vec4(original); assert_approx_eq!(projected, $vec4::new(0.5, 1.0, -2.0, 1.0)); }); glam_test!(test_mat4_orthographic_rh, { let projection = $mat4::orthographic_rh(-10.0, 10.0, -5.0, 5.0, -10.0, 10.0); let original = $vec4::new(5.0, 5.0, -5.0, 1.0); let projected = projection.mul_vec4(original); assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.75, 1.0)); let original = $vec4::new(5.0, 5.0, 5.0, 1.0); let projected = projection.mul_vec4(original); assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.25, 1.0)); }); glam_test!(test_mat4_orthographic_lh, { let projection = $mat4::orthographic_lh(-10.0, 10.0, -5.0, 5.0, -10.0, 10.0); let original = $vec4::new(5.0, 5.0, -5.0, 1.0); let projected = projection.mul_vec4(original); assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.25, 1.0)); let original = $vec4::new(5.0, 5.0, 5.0, 1.0); let projected = projection.mul_vec4(original); assert_approx_eq!(projected, $vec4::new(0.5, 1.0, 0.75, 1.0)); }); glam_test!(test_mat4_ops, { let m0 = $mat4::from_cols_array_2d(&ARRAY4X4); let m0x2 = $mat4::from_cols_array_2d(&[ [2.0, 4.0, 6.0, 8.0], [10.0, 12.0, 14.0, 16.0], [18.0, 20.0, 22.0, 24.0], [26.0, 28.0, 30.0, 32.0], ]); let m0_neg = $mat4::from_cols_array_2d(&[ [-1.0, -2.0, -3.0, -4.0], [-5.0, -6.0, -7.0, -8.0], [-9.0, -10.0, -11.0, -12.0], [-13.0, -14.0, -15.0, -16.0], ]); assert_eq!(m0x2, m0 * 2.0); assert_eq!(m0x2, 2.0 * m0); assert_eq!(m0, m0x2 / 2.0); assert_eq!(m0, 2.0 / m0x2); assert_eq!(m0x2, m0 + m0); assert_eq!($mat4::ZERO, m0 - m0); assert_eq!(m0_neg, -m0); assert_approx_eq!(m0, m0 * $mat4::IDENTITY); assert_approx_eq!(m0, $mat4::IDENTITY * m0); let mut m1 = m0; m1 *= 2.0; assert_eq!(m0x2, m1); let mut m1 = m0x2; m1 /= 2.0; assert_eq!(m0, m1); let mut m1 = m0; m1 += m0; assert_eq!(m0x2, m1); let mut m1 = m0; m1 -= m0; assert_eq!($mat4::ZERO, m1); let mut m1 = $mat4::IDENTITY; m1 *= m0; assert_approx_eq!(m0, m1); }); glam_test!(test_mat4_fmt, { let a = $mat4::from_cols_array_2d(&ARRAY4X4); assert_eq!( format!("{}", a), "[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]" ); assert_eq!( format!("{:.1}", a), "[[1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0]]" ); }); glam_test!(test_mat4_to_from_slice, { let m = $mat4::from_cols_slice(&ARRAY1X16); assert_eq!($mat4::from_cols_array(&ARRAY1X16), m); let mut out: [$t; 16] = Default::default(); m.write_cols_to_slice(&mut out); assert_eq!(ARRAY1X16, out); should_panic!({ $mat4::from_cols_slice(&[0.0; 15]) }); should_panic!({ $mat4::IDENTITY.write_cols_to_slice(&mut [0.0; 15]) }); }); glam_test!(test_sum, { let id = $mat4::IDENTITY; 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!([two, two].iter().product::<$mat4>(), two * two); assert_eq!([two, two].into_iter().product::<$mat4>(), two * two); }); glam_test!(test_mat4_is_finite, { assert!($mat4::IDENTITY.is_finite()); assert!(!($mat4::IDENTITY * $t::INFINITY).is_finite()); assert!(!($mat4::IDENTITY * $t::NEG_INFINITY).is_finite()); assert!(!($mat4::IDENTITY * $t::NAN).is_finite()); }); glam_test!(test_mat4_abs, { let neg = $mat4::IDENTITY * -1.0; assert_eq!(neg.abs(), $mat4::IDENTITY); let partial_neg = $mat4::from_cols_array_2d(&[ [1.0, -2.0, 3.0, -4.0], [-5.0, 6.0, -7.0, 8.0], [-9.0, 10.0, 11.0, -12.0], [13.0, -14.0, -15.0, 16.0], ]); assert_eq!( partial_neg.abs(), $mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0], ]) ); }); }; } macro_rules! impl_as_ref_tests { ($mat:ident) => { glam_test!(test_as_ref, { let m = $mat::from_cols_array_2d(&ARRAY4X4); assert_eq!(ARRAY1X16, *m.as_ref()); }); glam_test!(test_as_mut, { let mut m = $mat::ZERO; *m.as_mut() = ARRAY1X16; assert_eq!($mat::from_cols_array_2d(&ARRAY4X4), m); }); }; } mod mat4 { use super::support::deg; use glam::{mat4, swizzles::*, vec3, vec4, Mat3, Mat4, Quat, Vec3, Vec4}; glam_test!(test_align, { use std::mem; assert_eq!(mem::align_of::(), mem::align_of::()); assert_eq!(64, mem::size_of::()); }); glam_test!(test_from_mat3a, { use glam::Mat3A; let m3 = Mat3A::from_cols_array_2d(&ARRAY3X3); let m4 = Mat4::from_mat3a(m3); assert_eq!( Mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 0.0], [4.0, 5.0, 6.0, 0.0], [7.0, 8.0, 9.0, 0.0], [0.0, 0.0, 0.0, 1.0] ]), m4 ); }); glam_test!(test_transform_vec3a, { use glam::Vec3A; let m = Mat4::from_axis_angle(Vec3::Z, deg(90.0)); let result3 = m.transform_vector3a(Vec3A::Y); assert_approx_eq!(Vec3A::new(-1.0, 0.0, 0.0), result3); let m = Mat4::from_scale_rotation_translation( Vec3::new(0.5, 1.5, 2.0), Quat::from_rotation_x(deg(90.0)), Vec3::new(1.0, 2.0, 3.0), ); let result3 = m.transform_vector3a(Vec3A::Y); assert_approx_eq!(Vec3A::new(0.0, 0.0, 1.5), result3, 1.0e-6); let result3 = m.transform_point3a(Vec3A::Y); assert_approx_eq!(Vec3A::new(1.0, 2.0, 4.5), result3, 1.0e-6); let m = Mat4::from_cols( vec4(8.0, 0.0, 0.0, 0.0), vec4(0.0, 4.0, 0.0, 0.0), vec4(0.0, 0.0, 2.0, 2.0), vec4(0.0, 0.0, 0.0, 0.0), ); assert_approx_eq!( Vec3A::new(4.0, 2.0, 1.0), m.project_point3a(Vec3A::new(2.0, 2.0, 2.0)) ); }); glam_test!(test_as, { use glam::DMat4; assert_eq!( DMat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0] ]), Mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0] ]) .as_dmat4() ); assert_eq!( Mat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0] ]), DMat4::from_cols_array_2d(&[ [1.0, 2.0, 3.0, 4.0], [5.0, 6.0, 7.0, 8.0], [9.0, 10.0, 11.0, 12.0], [13.0, 14.0, 15.0, 16.0] ]) .as_mat4() ); }); impl_mat4_tests!(f32, mat4, vec4, vec3, Mat4, Mat3, Quat, Vec4, Vec3); impl_as_ref_tests!(Mat4); } mod dmat4 { use super::support::deg; use glam::{dmat4, dvec3, dvec4, swizzles::*, DMat3, DMat4, DQuat, DVec3, DVec4}; glam_test!(test_align, { use std::mem; assert_eq!(mem::align_of::(), mem::align_of::()); assert_eq!(128, mem::size_of::()); }); impl_mat4_tests!(f64, dmat4, dvec4, dvec3, DMat4, DMat3, DQuat, DVec4, DVec3); impl_as_ref_tests!(DMat4); } glam-0.30.1/tests/quat.rs000064400000000000000000000732061046102023000133170ustar 00000000000000#![allow(clippy::excessive_precision)] #[macro_use] mod support; macro_rules! impl_quat_tests { ($t:ident, $new:ident, $mat3:ident, $mat4:ident, $quat:ident, $vec2:ident, $vec3:ident, $vec4:ident) => { glam_test!(test_const, { const Q0: $quat = $quat::from_xyzw(1.0, 2.0, 3.0, 4.0); const Q1: $quat = $quat::from_array([1.0, 2.0, 3.0, 4.0]); assert_eq!([1.0, 2.0, 3.0, 4.0], *Q0.as_ref()); assert_eq!([1.0, 2.0, 3.0, 4.0], *Q1.as_ref()); }); glam_test!(test_nan, { assert!($quat::NAN.is_nan()); assert!(!$quat::NAN.is_finite()); }); glam_test!(test_new, { let ytheta = deg(45.0); let q0 = $quat::from_rotation_y(ytheta); let v1 = $vec4::new(0.0, (ytheta * 0.5).sin(), 0.0, (ytheta * 0.5).cos()); assert_eq!(q0, $quat::from_vec4(v1)); let q1 = $quat::from_vec4(v1); assert_eq!(v1, q1.into()); assert_eq!(q0, $new(v1.x, v1.y, v1.z, v1.w)); let a1: [$t; 4] = q1.into(); assert_eq!([v1.x, v1.y, v1.z, v1.w], a1); assert_eq!(q1, $quat::from_array(a1)); assert_eq!(a1, *q0.as_ref()); }); glam_test!(test_funcs, { let q0 = $quat::from_euler(EulerRot::YXZ, deg(45.0), deg(180.0), deg(90.0)); assert!(q0.is_normalized()); assert_approx_eq!(q0.length_squared(), 1.0); assert_approx_eq!(q0.length(), 1.0); assert_approx_eq!(q0.length_recip(), 1.0); assert_approx_eq!(q0, q0.normalize()); assert_approx_eq!(q0.dot(q0), 1.0); assert_approx_eq!(q0.dot(q0), 1.0); let q1 = $quat::from_vec4($vec4::from(q0) * 2.0); assert!(!q1.is_normalized()); assert_approx_eq!(q1.length_squared(), 4.0, 1.0e-6); assert_approx_eq!(q1.length(), 2.0); assert_approx_eq!(q1.length_recip(), 0.5); assert_approx_eq!(q0, q1.normalize()); assert_approx_eq!(q0.dot(q1), 2.0, 1.0e-6); should_glam_assert!({ ($quat::IDENTITY * 0.0).normalize() }); }); glam_test!(test_rotation, { let zero = deg(0.0); let yaw = deg(30.0); let pitch = deg(60.0); let roll = deg(90.0); let y0 = $quat::from_rotation_y(yaw); assert!(y0.is_normalized()); let (axis, angle) = y0.to_axis_angle(); assert_approx_eq!(axis, $vec3::Y, 1.0e-6); assert_approx_eq!(angle, yaw); let y1 = $quat::from_euler(EulerRot::YXZ, yaw, zero, zero); assert_approx_eq!(y0, y1); let y2 = $quat::from_axis_angle($vec3::Y, yaw); assert_approx_eq!(y0, y2); let y3 = $quat::from_mat3(&$mat3::from_rotation_y(yaw)); assert_approx_eq!(y0, y3); let y4 = $quat::from_mat3(&$mat3::from_quat(y0)); assert_approx_eq!(y0, y4); let x0 = $quat::from_rotation_x(pitch); assert!(x0.is_normalized()); let (axis, angle) = x0.to_axis_angle(); assert_approx_eq!(axis, $vec3::X); assert_approx_eq!(angle, pitch, 1e-6); let x1 = $quat::from_euler(EulerRot::YXZ, zero, pitch, zero); assert_approx_eq!(x0, x1); let x2 = $quat::from_axis_angle($vec3::X, pitch); assert_approx_eq!(x0, x2); let x3 = $quat::from_mat4(&$mat4::from_rotation_x(deg(180.0))); assert!(x3.is_normalized()); assert_approx_eq!($quat::from_rotation_x(deg(180.0)), x3); let z0 = $quat::from_rotation_z(roll); assert!(z0.is_normalized()); let (axis, angle) = z0.to_axis_angle(); assert_approx_eq!(axis, $vec3::Z); assert_approx_eq!(angle, roll); let z1 = $quat::from_euler(EulerRot::YXZ, zero, zero, roll); assert_approx_eq!(z0, z1); let z2 = $quat::from_axis_angle($vec3::Z, roll); assert_approx_eq!(z0, z2); let z3 = $quat::from_mat4(&$mat4::from_rotation_z(roll)); assert_approx_eq!(z0, z3); let yx0 = y0 * x0; assert!(yx0.is_normalized()); let yx1 = $quat::from_euler(EulerRot::YXZ, yaw, pitch, zero); assert_approx_eq!(yx0, yx1); let yxz0 = y0 * x0 * z0; assert!(yxz0.is_normalized()); let yxz1 = $quat::from_euler(EulerRot::YXZ, yaw, pitch, roll); assert_approx_eq!(yxz0, yxz1); // use the conjugate of z0 to remove the rotation from yxz0 let yx2 = yxz0 * z0.conjugate(); assert_approx_eq!(yx0, yx2); assert!((yxz0 * yxz0.conjugate()).is_near_identity()); // test inverse does the same let yx2 = yxz0 * z0.inverse(); assert_approx_eq!(yx0, yx2); assert!((yxz0 * yxz0.inverse()).is_near_identity()); let yxz2 = $quat::from_mat4(&$mat4::from_quat(yxz0)); assert_approx_eq!(yxz0, yxz2); // if near identity, just returns x axis and 0 rotation let (axis, angle) = $quat::IDENTITY.to_axis_angle(); assert_eq!(axis, $vec3::X); assert_eq!(angle, rad(0.0)); let mut x0 = $quat::from_rotation_x(pitch); x0 *= x0; assert_approx_eq!(x0, $quat::from_rotation_x(pitch * 2.0)); should_glam_assert!({ ($quat::IDENTITY * 2.0).inverse() }); should_glam_assert!({ $quat::from_axis_angle($vec3::ZERO, 0.0) }); }); glam_test!(test_from_scaled_axis, { assert_eq!($quat::from_scaled_axis($vec3::ZERO), $quat::IDENTITY); assert_eq!( $quat::from_scaled_axis($vec3::Y * 1e-10), $quat::from_axis_angle($vec3::Y, 1e-10) ); assert_eq!( $quat::from_scaled_axis($vec3::X * 1.0), $quat::from_axis_angle($vec3::X, 1.0) ); assert_eq!( $quat::from_scaled_axis($vec3::Z * 2.0), $quat::from_axis_angle($vec3::Z, 2.0) ); assert_eq!( $quat::from_scaled_axis($vec3::ZERO).to_scaled_axis(), $vec3::ZERO ); for &v in &vec3_float_test_vectors!($vec3) { if v.length() < core::$t::consts::PI { assert!(($quat::from_scaled_axis(v).to_scaled_axis() - v).length() < 1e-6,); } } }); glam_test!(test_quat_look_at, { let eye = $vec3::new(0.0, 0.0, -5.0); let center = $vec3::new(0.0, 0.0, 0.0); let up = $vec3::new(1.0, 0.0, 0.0); let point = $vec3::new(1.0, 0.0, 0.0); let lh = $quat::look_at_lh(eye, center, up); let rh = $quat::look_at_rh(eye, center, up); assert_approx_eq!(lh * point, $vec3::new(0.0, 1.0, 0.0)); assert_approx_eq!(rh * point, $vec3::new(0.0, 1.0, 0.0)); let dir = (center - eye).normalize(); let lh = $quat::look_to_lh(dir, up); let rh = $quat::look_to_rh(dir, up); assert_approx_eq!(lh * point, $vec3::new(0.0, 1.0, 0.0)); assert_approx_eq!(rh * point, $vec3::new(0.0, 1.0, 0.0)); should_glam_assert!({ $quat::look_to_lh($vec3::ONE, $vec3::ZERO) }); should_glam_assert!({ $quat::look_to_lh($vec3::ZERO, $vec3::ONE) }); should_glam_assert!({ $quat::look_to_rh($vec3::ONE, $vec3::ZERO) }); should_glam_assert!({ $quat::look_to_rh($vec3::ZERO, $vec3::ONE) }); }); glam_test!(test_mul_vec3, { let qrz = $quat::from_rotation_z(deg(90.0)); assert_approx_eq!($vec3::Y, qrz * $vec3::X); assert_approx_eq!($vec3::Y, qrz.mul_vec3($vec3::X)); assert_approx_eq!($vec3::Y, -qrz * $vec3::X); assert_approx_eq!($vec3::Y, qrz.neg().mul_vec3($vec3::X)); assert_approx_eq!(-$vec3::X, qrz * $vec3::Y); assert_approx_eq!(-$vec3::X, qrz.mul_vec3($vec3::Y)); assert_approx_eq!(-$vec3::X, -qrz * $vec3::Y); assert_approx_eq!(-$vec3::X, qrz.neg().mul_vec3($vec3::Y)); // check vec3 * mat3 is the same let mrz = $mat3::from_quat(qrz); assert_approx_eq!($vec3::Y, mrz * $vec3::X); assert_approx_eq!($vec3::Y, mrz.mul_vec3($vec3::X)); // assert_approx_eq!($vec3::Y, -mrz * $vec3::X); assert_approx_eq!(-$vec3::X, mrz * $vec3::Y); assert_approx_eq!(-$vec3::X, mrz.mul_vec3($vec3::Y)); let qrx = $quat::from_rotation_x(deg(90.0)); assert_approx_eq!($vec3::X, qrx * $vec3::X); assert_approx_eq!($vec3::X, qrx.mul_vec3($vec3::X)); assert_approx_eq!($vec3::X, -qrx * $vec3::X); assert_approx_eq!($vec3::X, qrx.neg().mul_vec3($vec3::X)); assert_approx_eq!($vec3::Z, qrx * $vec3::Y); assert_approx_eq!($vec3::Z, qrx.mul_vec3($vec3::Y)); assert_approx_eq!($vec3::Z, -qrx * $vec3::Y); assert_approx_eq!($vec3::Z, qrx.neg().mul_vec3($vec3::Y)); // check vec3 * mat3 is the same let mrx = $mat3::from_quat(qrx); assert_approx_eq!($vec3::X, mrx * $vec3::X); assert_approx_eq!($vec3::X, mrx.mul_vec3($vec3::X)); assert_approx_eq!($vec3::Z, mrx * $vec3::Y); assert_approx_eq!($vec3::Z, mrx.mul_vec3($vec3::Y)); let qrxz = qrz * qrx; assert_approx_eq!($vec3::Y, qrxz * $vec3::X); assert_approx_eq!($vec3::Y, qrxz.mul_vec3($vec3::X)); assert_approx_eq!($vec3::Z, qrxz * $vec3::Y); assert_approx_eq!($vec3::Z, qrxz.mul_vec3($vec3::Y)); let mrxz = mrz * mrx; assert_approx_eq!($vec3::Y, mrxz * $vec3::X); assert_approx_eq!($vec3::Y, mrxz.mul_vec3($vec3::X)); assert_approx_eq!($vec3::Z, mrxz * $vec3::Y); assert_approx_eq!($vec3::Z, mrxz.mul_vec3($vec3::Y)); let qrzx = qrx * qrz; assert_approx_eq!($vec3::Z, qrzx * $vec3::X); assert_approx_eq!($vec3::Z, qrzx.mul_vec3($vec3::X)); assert_approx_eq!(-$vec3::X, qrzx * $vec3::Y); assert_approx_eq!(-$vec3::X, qrzx.mul_vec3($vec3::Y)); let mrzx = qrx * qrz; assert_approx_eq!($vec3::Z, mrzx * $vec3::X); assert_approx_eq!($vec3::Z, mrzx.mul_vec3($vec3::X)); assert_approx_eq!(-$vec3::X, mrzx * $vec3::Y); assert_approx_eq!(-$vec3::X, mrzx.mul_vec3($vec3::Y)); should_glam_assert!({ ($quat::IDENTITY * 0.5).mul_vec3($vec3::X) }); should_glam_assert!({ ($quat::IDENTITY * 0.5) * $vec3::X }); }); glam_test!(test_angle_between, { const TAU: $t = 2.0 * core::$t::consts::PI; let eps = 10.0 * $t::EPSILON as f32; let q1 = $quat::from_euler(EulerRot::YXZ, 0.0, 0.0, 0.0); let q2 = $quat::from_euler(EulerRot::YXZ, TAU * 0.25, 0.0, 0.0); let q3 = $quat::from_euler(EulerRot::YXZ, TAU * 0.5, 0.0, 0.0); let q4 = $quat::from_euler(EulerRot::YXZ, 0.0, 0.0, TAU * 0.25); let q5 = $quat::from_axis_angle($vec3::new(1.0, 2.0, 3.0).normalize(), TAU * 0.3718); let q6 = $quat::from_axis_angle($vec3::new(-1.0, 5.0, 3.0).normalize(), TAU * 0.94); assert_approx_eq!(q1.angle_between(q2), TAU * 0.25, eps); assert_approx_eq!(q1.angle_between(q3), TAU * 0.5, eps); assert_approx_eq!(q3.angle_between(q3), 0.0, eps); assert_approx_eq!(q3.angle_between(-q3), 0.0, eps); assert_approx_eq!((q4 * q2 * q2).angle_between(q4 * q2), TAU * 0.25, eps); assert_approx_eq!(q1.angle_between(q5), TAU * 0.3718, eps); assert_approx_eq!( (q5 * q2 * q1).angle_between(q5 * q2 * q5), TAU * 0.3718, eps ); assert_approx_eq!((q3 * q3).angle_between(q1), 0.0, eps); assert_approx_eq!((q3 * q3 * q3).angle_between(q3), 0.0, eps); assert_approx_eq!((q3 * q3 * q3 * q3).angle_between(q1), 0.0, eps); assert_approx_eq!(q1.angle_between(q6), TAU - TAU * 0.94, eps); assert_approx_eq!((q5 * q1).angle_between(q5 * q6), TAU - TAU * 0.94, eps); assert_approx_eq!((q1 * q5).angle_between(q6 * q5), TAU - TAU * 0.94, eps); }); glam_test!(test_lerp, { let q0 = $quat::from_rotation_y(deg(0.0)); assert_approx_eq!(q0, q0.slerp(q0, 0.0)); assert_approx_eq!(q0, q0.slerp(q0, 1.0)); let q1 = $quat::from_rotation_y(deg(90.0)); assert_approx_eq!(q0, q0.lerp(q1, 0.0)); assert_approx_eq!(q1, q0.lerp(q1, 1.0)); assert_approx_eq!($quat::from_rotation_y(deg(45.0)), q0.lerp(q1, 0.5)); should_glam_assert!({ $quat::lerp($quat::IDENTITY * 2.0, $quat::IDENTITY, 1.0) }); should_glam_assert!({ $quat::lerp($quat::IDENTITY, $quat::IDENTITY * 0.5, 1.0) }); }); glam_test!(test_slerp, { let q0 = $quat::from_rotation_y(deg(0.0)); assert_approx_eq!(q0, q0.slerp(q0, 0.0)); assert_approx_eq!(q0, q0.slerp(q0, 1.0)); let q1 = $quat::from_rotation_y(deg(90.0)); assert_approx_eq!(q0, q0.slerp(q1, 0.0), 1.0e-3); assert_approx_eq!(q1, q0.slerp(q1, 1.0), 1.0e-3); assert_approx_eq!($quat::from_rotation_y(deg(45.0)), q0.slerp(q1, 0.5), 1.0e-3); should_glam_assert!({ $quat::slerp($quat::IDENTITY * 2.0, $quat::IDENTITY, 1.0) }); should_glam_assert!({ $quat::slerp($quat::IDENTITY, $quat::IDENTITY * 0.5, 1.0) }); }); glam_test!(test_slerp_constant_speed, { let step = 0.01; let mut s = 0.0; while s <= 1.0 { let q0 = $quat::from_rotation_y(deg(0.0)); let q1 = $quat::from_rotation_y(deg(90.0)); let result = q0.slerp(q1, s); assert_approx_eq!($quat::from_rotation_y(deg(s * 90.0)), result, 1.0e-3); assert!(result.is_normalized()); s += step; } }); glam_test!(test_slerp_tau, { let q1 = $quat::IDENTITY; let q2 = $quat::from_rotation_x(core::$t::consts::TAU); let s = q1.slerp(q2, 1.); assert!(s.is_finite()); assert!(s.is_normalized()); }); glam_test!(test_slerp_negative_tau, { let q1 = $quat::IDENTITY; let q2 = $quat::from_rotation_x(-core::$t::consts::TAU); let s = q1.slerp(q2, 1.); assert!(s.is_finite()); assert!(s.is_normalized()); }); glam_test!(test_slerp_pi, { let q1 = $quat::IDENTITY; let q2 = $quat::from_rotation_x(core::$t::consts::PI); let s = q1.slerp(q2, 1.); assert!(s.is_finite()); assert!(s.is_normalized()); }); glam_test!(test_slerp_negative_pi, { let q1 = $quat::IDENTITY; let q2 = $quat::from_rotation_x(-core::$t::consts::PI); let s = q1.slerp(q2, 1.); assert!(s.is_finite()); assert!(s.is_normalized()); }); glam_test!(test_rotate_towards, { use core::$t::consts::{FRAC_PI_2, FRAC_PI_4}; let eps = 10.0 * $t::EPSILON as f32; // Setup such that `q0` is `PI/2` and `-PI/2` radians away from `q1` and `q2` respectively. let q0 = $quat::from_euler(EulerRot::YXZ, 0.0, 0.0, 0.0); let q1 = $quat::from_euler(EulerRot::YXZ, FRAC_PI_2, 0.0, 0.0); let q2 = $quat::from_euler(EulerRot::YXZ, -FRAC_PI_2, 0.0, 0.0); // Positive delta assert_approx_eq!(q0, q0.rotate_towards(q1, 0.0), eps); assert_approx_eq!( $quat::from_euler(EulerRot::YXZ, FRAC_PI_4, 0.0, 0.0), q0.rotate_towards(q1, FRAC_PI_4), eps ); assert_approx_eq!(q1, q0.rotate_towards(q1, FRAC_PI_2), eps); assert_approx_eq!(q1, q0.rotate_towards(q1, FRAC_PI_2 * 1.5), eps); // Negative delta assert_approx_eq!( $quat::from_euler(EulerRot::YXZ, -FRAC_PI_4, 0.0, 0.0), q0.rotate_towards(q1, -FRAC_PI_4), eps ); assert_approx_eq!(q2, q0.rotate_towards(q1, -FRAC_PI_2), eps); assert_approx_eq!(q2, q0.rotate_towards(q1, -FRAC_PI_2 * 1.5), eps); // Small angles let q0 = $quat::from_euler(EulerRot::YXZ, 0.0, 0.0, 0.0); let q1 = $quat::from_euler(EulerRot::YXZ, 1e-4, 0.0, 0.0); assert_eq!(q1, q0.rotate_towards(q1, FRAC_PI_2)) }); glam_test!(test_fmt, { let a = $quat::IDENTITY; assert_eq!( format!("{:?}", a), format!("{}(0.0, 0.0, 0.0, 1.0)", stringify!($quat)) ); // assert_eq!( // format!("{:#?}", a), // "$quat(\n 1.0,\n 2.0,\n 3.0,\n 4.0\n)" // ); assert_eq!(format!("{}", a), "[0, 0, 0, 1]"); assert_eq!(format!("{:.2}", a), "[0.00, 0.00, 0.00, 1.00]"); }); glam_test!(test_identity, { let identity = $quat::IDENTITY; assert!(identity.is_near_identity()); assert!(identity.is_normalized()); assert_eq!(identity, $quat::from_xyzw(0.0, 0.0, 0.0, 1.0)); assert_eq!(identity, identity * identity); let q = $quat::from_euler(EulerRot::YXZ, deg(10.0), deg(-10.0), deg(45.0)); assert_eq!(q, q * identity); assert_eq!(q, identity * q); assert_eq!(identity, $quat::default()); }); glam_test!(test_slice, { let a: [$t; 4] = $quat::from_euler(EulerRot::YXZ, deg(30.0), deg(60.0), deg(90.0)).into(); let b = $quat::from_slice(&a); let c: [$t; 4] = b.into(); assert_eq!(a, c); let mut d = [0.0, 0.0, 0.0, 0.0]; b.write_to_slice(&mut d[..]); assert_eq!(a, d); should_panic!({ $quat::IDENTITY.write_to_slice(&mut [0 as $t; 3]) }); should_panic!({ $quat::from_slice(&[0 as $t; 3]) }); }); glam_test!(test_elements, { let x = 1.0; let y = 2.0; let z = 3.0; let w = 4.0; let a = $quat::from_xyzw(x, y, z, w); assert!(a.x == x); assert!(a.y == y); assert!(a.z == z); assert!(a.w == w); assert_eq!($vec3::new(1.0, 2.0, 3.0), a.xyz()); }); glam_test!(test_addition, { let a = $quat::from_xyzw(1.0, 2.0, 3.0, 4.0); let b = $quat::from_xyzw(5.0, 6.0, 7.0, -9.0); assert_eq!(a + b, $quat::from_xyzw(6.0, 8.0, 10.0, -5.0)); }); glam_test!(test_subtraction, { let a = $quat::from_xyzw(6.0, 8.0, 10.0, -5.0); let b = $quat::from_xyzw(5.0, 6.0, 7.0, -9.0); assert_eq!(a - b, $quat::from_xyzw(1.0, 2.0, 3.0, 4.0)); }); glam_test!(test_scalar_multiplication, { let a = $quat::from_xyzw(1.0, 2.0, 3.0, 4.0); assert_eq!(a * 2.0, $quat::from_xyzw(2.0, 4.0, 6.0, 8.0)); }); glam_test!(test_scalar_division, { let a = $quat::from_xyzw(2.0, 4.0, 6.0, 8.0); assert_eq!(a / 2.0, $quat::from_xyzw(1.0, 2.0, 3.0, 4.0)); }); glam_test!(test_sum, { let two = $new(2.0, 2.0, 2.0, 2.0); 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!([two, two].iter().product::<$quat>(), two * two); assert_eq!([two, two].into_iter().product::<$quat>(), two * two); }); glam_test!(test_is_finite, { assert!($quat::from_xyzw(0.0, 0.0, 0.0, 0.0).is_finite()); assert!($quat::from_xyzw(-1e-10, 1.0, 1e10, 42.0).is_finite()); assert!(!$quat::from_xyzw($t::INFINITY, 0.0, 0.0, 0.0).is_finite()); assert!(!$quat::from_xyzw(0.0, $t::NAN, 0.0, 0.0).is_finite()); assert!(!$quat::from_xyzw(0.0, 0.0, $t::NEG_INFINITY, 0.0).is_finite()); assert!(!$quat::from_xyzw(0.0, 0.0, 0.0, $t::NAN).is_finite()); }); glam_test!(test_rotation_arc, { let eps = 2.0 * $t::EPSILON.sqrt(); for &from in &vec3_float_test_vectors!($vec3) { let from = from.normalize(); { let q = $quat::from_rotation_arc(from, from); assert!(q.is_near_identity(), "from: {}, q: {}", from, q); } { let q = $quat::from_rotation_arc_colinear(from, from); assert!(q.is_near_identity(), "from: {}, q: {}", from, q); } { let to = -from; let q = $quat::from_rotation_arc(from, to); assert!(q.is_normalized()); assert!((q * from - to).length() < eps); } { let to = -from; let q = $quat::from_rotation_arc_colinear(from, to); assert!(q.is_near_identity(), "from: {}, q: {}", from, q); } for &to in &vec3_float_test_vectors!($vec3) { let to = to.normalize(); let q = $quat::from_rotation_arc(from, to); assert!(q.is_normalized()); assert!((q * from - to).length() < eps); let q = $quat::from_rotation_arc_colinear(from, to); assert!(q.is_normalized()); let transformed = q * from; assert!( (transformed - to).length() < eps || (-transformed - to).length() < eps ); } } for &from in &vec2_float_test_vectors!($vec2) { let from = from.normalize(); { let q = $quat::from_rotation_arc_2d(from, from); assert!(q.is_near_identity(), "from: {}, q: {}", from, q); } { let to = -from; let q = $quat::from_rotation_arc_2d(from, to); assert!(q.is_normalized()); assert!((q * from.extend(0.0) - to.extend(0.0)).length() < eps); } for &to in &vec2_float_test_vectors!($vec2) { let to = to.normalize(); let q = $quat::from_rotation_arc_2d(from, to); assert!(q.is_normalized()); assert!((q * from.extend(0.0) - to.extend(0.0)).length() < eps); } } should_glam_assert!({ $quat::from_rotation_arc($vec3::ZERO, $vec3::X) }); should_glam_assert!({ $quat::from_rotation_arc($vec3::X, $vec3::ZERO) }); should_glam_assert!({ $quat::from_rotation_arc_colinear($vec3::ZERO, $vec3::X) }); should_glam_assert!({ $quat::from_rotation_arc_colinear($vec3::X, $vec3::ZERO) }); should_glam_assert!({ $quat::from_rotation_arc_2d($vec2::ZERO, $vec2::X) }); should_glam_assert!({ $quat::from_rotation_arc_2d($vec2::X, $vec2::ZERO) }); }); 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); } }); }; } mod quat { use crate::support::{deg, rad}; use core::ops::Neg; use glam::{quat, EulerRot, Mat3, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4}; glam_test!(test_align, { use std::mem; assert_eq!(16, mem::size_of::()); if cfg!(feature = "scalar-math") { assert_eq!(4, mem::align_of::()); } else { assert_eq!(16, mem::align_of::()); } }); glam_test!(test_mul_vec3a, { let qrz = Quat::from_rotation_z(deg(90.0)); assert_approx_eq!(Vec3A::Y, qrz * Vec3A::X); assert_approx_eq!(Vec3A::Y, qrz.mul_vec3a(Vec3A::X)); assert_approx_eq!(Vec3A::Y, -qrz * Vec3A::X); assert_approx_eq!(Vec3A::Y, qrz.neg().mul_vec3a(Vec3A::X)); assert_approx_eq!(-Vec3A::X, qrz * Vec3A::Y); assert_approx_eq!(-Vec3A::X, qrz.mul_vec3a(Vec3A::Y)); assert_approx_eq!(-Vec3A::X, -qrz * Vec3A::Y); assert_approx_eq!(-Vec3A::X, qrz.neg().mul_vec3a(Vec3A::Y)); // check vec3 * mat3 is the same let mrz = Mat3::from_quat(qrz); assert_approx_eq!(Vec3A::Y, mrz * Vec3A::X); assert_approx_eq!(Vec3A::Y, mrz.mul_vec3a(Vec3A::X)); // assert_approx_eq!(Vec3A::Y, -mrz * Vec3A::X); assert_approx_eq!(-Vec3A::X, mrz * Vec3A::Y); assert_approx_eq!(-Vec3A::X, mrz.mul_vec3a(Vec3A::Y)); let qrx = Quat::from_rotation_x(deg(90.0)); assert_approx_eq!(Vec3A::X, qrx * Vec3A::X); assert_approx_eq!(Vec3A::X, qrx.mul_vec3a(Vec3A::X)); assert_approx_eq!(Vec3A::X, -qrx * Vec3A::X); assert_approx_eq!(Vec3A::X, qrx.neg().mul_vec3a(Vec3A::X)); assert_approx_eq!(Vec3A::Z, qrx * Vec3A::Y); assert_approx_eq!(Vec3A::Z, qrx.mul_vec3a(Vec3A::Y)); assert_approx_eq!(Vec3A::Z, -qrx * Vec3A::Y); assert_approx_eq!(Vec3A::Z, qrx.neg().mul_vec3a(Vec3A::Y)); // check vec3 * mat3 is the same let mrx = Mat3::from_quat(qrx); assert_approx_eq!(Vec3A::X, mrx * Vec3A::X); assert_approx_eq!(Vec3A::X, mrx.mul_vec3a(Vec3A::X)); assert_approx_eq!(Vec3A::Z, mrx * Vec3A::Y); assert_approx_eq!(Vec3A::Z, mrx.mul_vec3a(Vec3A::Y)); let qrxz = qrz * qrx; assert_approx_eq!(Vec3A::Y, qrxz * Vec3A::X); assert_approx_eq!(Vec3A::Y, qrxz.mul_vec3a(Vec3A::X)); assert_approx_eq!(Vec3A::Z, qrxz * Vec3A::Y); assert_approx_eq!(Vec3A::Z, qrxz.mul_vec3a(Vec3A::Y)); let mrxz = mrz * mrx; assert_approx_eq!(Vec3A::Y, mrxz * Vec3A::X); assert_approx_eq!(Vec3A::Y, mrxz.mul_vec3a(Vec3A::X)); assert_approx_eq!(Vec3A::Z, mrxz * Vec3A::Y); assert_approx_eq!(Vec3A::Z, mrxz.mul_vec3a(Vec3A::Y)); let qrzx = qrx * qrz; assert_approx_eq!(Vec3A::Z, qrzx * Vec3A::X); assert_approx_eq!(Vec3A::Z, qrzx.mul_vec3a(Vec3A::X)); assert_approx_eq!(-Vec3A::X, qrzx * Vec3A::Y); assert_approx_eq!(-Vec3A::X, qrzx.mul_vec3a(Vec3A::Y)); let mrzx = qrx * qrz; assert_approx_eq!(Vec3A::Z, mrzx * Vec3A::X); assert_approx_eq!(Vec3A::Z, mrzx.mul_vec3a(Vec3A::X)); assert_approx_eq!(-Vec3A::X, mrzx * Vec3A::Y); assert_approx_eq!(-Vec3A::X, mrzx.mul_vec3a(Vec3A::Y)); }); glam_test!(test_from_mat3a, { use glam::Mat3A; let yaw = deg(30.0); let y0 = Quat::from_rotation_y(yaw); let y1 = Quat::from_mat3a(&Mat3A::from_rotation_y(yaw)); assert_approx_eq!(y0, y1); let y2 = Quat::from_mat3a(&Mat3A::from_quat(y0)); assert_approx_eq!(y0, y2); }); glam_test!(test_as, { 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_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_quat() ); }); impl_quat_tests!(f32, quat, Mat3, Mat4, Quat, Vec2, Vec3, Vec4); } mod dquat { use crate::support::{deg, rad}; use core::ops::Neg; use glam::{dquat, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, EulerRot}; glam_test!(test_align, { use std::mem; assert_eq!(32, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); impl_quat_tests!(f64, dquat, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4); } glam-0.30.1/tests/support/macros.rs000064400000000000000000000223271046102023000153430ustar 00000000000000#[macro_export] macro_rules! glam_test { ($name:ident, $block:block) => { #[cfg_attr(not(target_arch = "wasm32"), test)] #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)] fn $name() { $block } }; } #[macro_export] macro_rules! should_panic { ($block:block) => {{ #[cfg(all(feature = "std", panic = "unwind"))] assert!(std::panic::catch_unwind(|| $block).is_err()); }}; } #[macro_export] macro_rules! should_glam_assert { ($block:block) => {{ #[cfg(any(feature = "glam-assert", feature = "debug-glam-assert"))] should_panic!($block); }}; } #[macro_export] macro_rules! assert_approx_eq { ($a:expr, $b:expr) => {{ #[allow(unused_imports)] use $crate::support::FloatCompare; let eps = f32::EPSILON; let (a, b) = (&$a, &$b); assert!( a.approx_eq(b, eps), "assertion failed: `(left !== right)` \ (left: `{:?}`, right: `{:?}`, expect diff: `{:?}`, real diff: `{:?}`)", *a, *b, eps, a.abs_diff(b) ); }}; ($a:expr, $b:expr, $eps: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: `{:?}`)", *a, *b, eps, 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 #[macro_export] macro_rules! impl_vec_float_normalize_tests { ($t:ident, $vec:ident) => { /// Works for vec2, vec3, vec4 fn from_x_y(x: $t, y: $t) -> $vec { let mut v = $vec::ZERO; v.x = x; v.y = y; v } glam_test!(test_normalize, { assert_eq!(from_x_y(-42.0, 0.0).normalize(), from_x_y(-1.0, 0.0)); assert_eq!( from_x_y($t::MAX.sqrt(), 0.0).normalize(), from_x_y(1.0, 0.0) ); // assert_eq!(from_x_y($t::MAX, 0.0).normalize(), from_x_y(1.0, 0.0)); // normalize fails for huge vectors and returns zero // We expect not to be able to normalize small numbers: should_glam_assert!({ from_x_y(0.0, 0.0).normalize() }); should_glam_assert!({ from_x_y($t::MIN_POSITIVE, 0.0).normalize() }); // We expect not to be able to normalize non-finite vectors: should_glam_assert!({ from_x_y($t::INFINITY, 0.0).normalize() }); should_glam_assert!({ from_x_y($t::NAN, 0.0).normalize() }); }); #[cfg(not(any(feature = "debug-glam-assert", feature = "glam-assert")))] glam_test!(test_normalize_no_glam_assert, { // We expect not to be able to normalize small numbers: assert!(!from_x_y(0.0, 0.0).normalize().is_finite()); assert!(!from_x_y($t::MIN_POSITIVE, 0.0).normalize().is_finite()); // We expect not to be able to normalize non-finite vectors: assert!(!from_x_y($t::INFINITY, 0.0).normalize().is_finite()); assert!(!from_x_y($t::NAN, 0.0).normalize().is_finite()); }); glam_test!(test_try_normalize, { assert_eq!( from_x_y(-42.0, 0.0).try_normalize(), Some(from_x_y(-1.0, 0.0)) ); assert_eq!( from_x_y($t::MAX.sqrt(), 0.0).try_normalize(), Some(from_x_y(1.0, 0.0)) ); // We expect `try_normalize` to return None when inputs are very small: assert_eq!(from_x_y(0.0, 0.0).try_normalize(), None); assert_eq!(from_x_y($t::MIN_POSITIVE, 0.0).try_normalize(), None); // We expect `try_normalize` to return None when inputs are non-finite: assert_eq!(from_x_y($t::INFINITY, 0.0).try_normalize(), None); assert_eq!(from_x_y($t::NAN, 0.0).try_normalize(), None); // We expect `try_normalize` to return None when inputs are very large: assert_eq!(from_x_y($t::MAX, 0.0).try_normalize(), None); assert_eq!(from_x_y($t::MAX, $t::MAX).try_normalize(), None); }); glam_test!(test_normalize_or, { assert_eq!( from_x_y(-42.0, 0.0).normalize_or($vec::Y), from_x_y(-1.0, 0.0) ); assert_eq!( from_x_y($t::MAX.sqrt(), 0.0).normalize_or($vec::Y), from_x_y(1.0, 0.0) ); // We expect `normalize_or` to return the fallback value when inputs are very small: assert_eq!(from_x_y(0.0, 0.0).normalize_or($vec::Y), $vec::Y); assert_eq!( from_x_y($t::MIN_POSITIVE, 0.0).normalize_or($vec::Y), $vec::Y ); // We expect `normalize` to return zero when inputs are non-finite: assert_eq!(from_x_y($t::INFINITY, 0.0).normalize_or($vec::Y), $vec::Y); assert_eq!(from_x_y($t::NAN, 0.0).normalize_or($vec::Y), $vec::Y); // We expect `normalize` to return zero when inputs are very large: assert_eq!(from_x_y($t::MAX, 0.0).normalize_or($vec::Y), $vec::Y); assert_eq!(from_x_y($t::MAX, $t::MAX).normalize_or($vec::Y), $vec::Y); }); glam_test!(test_normalize_or_zero, { assert_eq!( from_x_y(-42.0, 0.0).normalize_or_zero(), from_x_y(-1.0, 0.0) ); assert_eq!( from_x_y($t::MAX.sqrt(), 0.0).normalize_or_zero(), from_x_y(1.0, 0.0) ); // We expect `normalize_or_zero` to return zero when inputs are very small: assert_eq!(from_x_y(0.0, 0.0).normalize_or_zero(), $vec::ZERO); assert_eq!( from_x_y($t::MIN_POSITIVE, 0.0).normalize_or_zero(), $vec::ZERO ); // We expect `normalize_or_zero` to return zero when inputs are non-finite: assert_eq!(from_x_y($t::INFINITY, 0.0).normalize_or_zero(), $vec::ZERO); assert_eq!(from_x_y($t::NAN, 0.0).normalize_or_zero(), $vec::ZERO); // We expect `normalize_or_zero` to return zero when inputs are very large: assert_eq!(from_x_y($t::MAX, 0.0).normalize_or_zero(), $vec::ZERO); assert_eq!(from_x_y($t::MAX, $t::MAX).normalize_or_zero(), $vec::ZERO); }); }; } /// Useful test vectors #[macro_export] macro_rules! vec3_float_test_vectors { ($vec3:ident) => { [ $vec3::X, $vec3::Y, $vec3::Z, -$vec3::X, -$vec3::Y, -$vec3::Z, $vec3::new(1.0, 1e-3, 0.0), $vec3::new(1.0, 1e-4, 0.0), $vec3::new(1.0, 1e-5, 0.0), $vec3::new(1.0, 1e-6, 0.0), $vec3::new(1.0, 1e-7, 0.0), $vec3::new(1.0, 1e-14, 0.0), $vec3::new(1.0, 1e-15, 0.0), $vec3::new(1.0, 1e-16, 0.0), $vec3::new(0.1, 0.2, 0.3), $vec3::new(0.2, 0.3, 0.4), $vec3::new(4.0, -5.0, 6.0), $vec3::new(-2.0, 0.5, -1.0), // Pathological cases from : $vec3::new(0.00038527316, 0.00038460016, -0.99999988079), $vec3::new(-0.00019813581, -0.00008946839, -0.99999988079), ] }; } #[macro_export] macro_rules! vec2_float_test_vectors { ($vec2:ident) => { [ $vec2::X, $vec2::Y, -$vec2::X, -$vec2::Y, $vec2::new(1.0, 1e-3), $vec2::new(1.0, 1e-4), $vec2::new(1.0, 1e-5), $vec2::new(1.0, 1e-6), $vec2::new(1.0, 1e-7), $vec2::new(1.0, 1e-14), $vec2::new(1.0, 1e-15), $vec2::new(1.0, 1e-16), $vec2::new(0.1, 0.2), $vec2::new(0.2, 0.3), $vec2::new(4.0, -5.0), $vec2::new(-2.0, 0.5), // Pathological cases from : $vec2::new(0.00038527316, 0.00038460016), $vec2::new(-0.00019813581, -0.00008946839), ] }; } #[macro_export] macro_rules! test_matrix_minor { ($n:expr, $minor:expr, $input:expr, $i:expr, $j:expr) => { let mut yy = 0; for y in 0..$n { if y != $j { let mut xx = 0; for x in 0..$n { if x != $i { assert_eq!($minor.col(xx)[yy], $input.col(x)[y]); xx += 1; } } yy += 1; } } }; } glam-0.30.1/tests/support.rs000064400000000000000000000162231046102023000140550ustar 00000000000000#![allow(dead_code)] #[path = "support/macros.rs"] #[macro_use] mod macros; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); use glam::{ DMat2, DMat3, DMat4, DQuat, DVec2, DVec3, DVec4, Mat2, Mat3, Mat3A, Mat4, Quat, Vec2, Vec3, Vec3A, Vec4, }; pub trait Deg { fn to_radians(self) -> Self; } impl Deg for f32 { fn to_radians(self) -> f32 { f32::to_radians(self) } } impl Deg for f64 { fn to_radians(self) -> f64 { f64::to_radians(self) } } /// Helper function for migrating away from `glam::angle::deg`. #[allow(dead_code)] #[inline] pub fn deg(angle: T) -> T { angle.to_radians() } /// Helper function for migrating away from `glam::angle::rad`. #[allow(dead_code)] #[inline] pub fn rad(angle: T) -> T { angle } /// Trait used by the `assert_approx_eq` macro for floating point comparisons. pub trait FloatCompare { /// Return true if the absolute difference between `self` and `other` is /// less then or equal to `max_abs_diff`. fn approx_eq(&self, other: &Rhs, max_abs_diff: f32) -> bool; /// Returns the absolute difference of `self` and `other` which is printed /// if `assert_approx_eq` fails. fn abs_diff(&self, other: &Rhs) -> Rhs; } impl FloatCompare for f32 { #[inline] fn approx_eq(&self, other: &f32, max_abs_diff: f32) -> bool { (self - other).abs() <= max_abs_diff } #[inline] fn abs_diff(&self, other: &f32) -> f32 { (self - other).abs() } } impl FloatCompare for f64 { #[inline] fn approx_eq(&self, other: &f64, max_abs_diff: f32) -> bool { (self - other).abs() <= max_abs_diff as f64 } #[inline] fn abs_diff(&self, other: &f64) -> f64 { (self - other).abs() } } impl FloatCompare for Mat2 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), ) } } impl FloatCompare for DMat2 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), ) } } impl FloatCompare for Mat3 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), (self.z_axis - other.z_axis).abs(), ) } } impl FloatCompare for Mat3A { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), (self.z_axis - other.z_axis).abs(), ) } } impl FloatCompare for DMat3 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), (self.z_axis - other.z_axis).abs(), ) } } impl FloatCompare for DMat4 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), (self.z_axis - other.z_axis).abs(), (self.w_axis - other.w_axis).abs(), ) } } impl FloatCompare for Mat4 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { Self::from_cols( (self.x_axis - other.x_axis).abs(), (self.y_axis - other.y_axis).abs(), (self.z_axis - other.z_axis).abs(), (self.w_axis - other.w_axis).abs(), ) } } impl FloatCompare for Quat { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { let a: Vec4 = (*self).into(); let b: Vec4 = (*other).into(); Quat::from_vec4((a - b).abs()) } } impl FloatCompare for Vec2 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } impl FloatCompare for Vec3 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } impl FloatCompare for Vec3A { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } impl FloatCompare for Vec4 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } impl FloatCompare for DQuat { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { let a: DVec4 = (*self).into(); let b: DVec4 = (*other).into(); DQuat::from_vec4((a - b).abs()) } } impl FloatCompare for DVec2 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } impl FloatCompare for DVec3 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } impl FloatCompare for DVec4 { #[inline] fn approx_eq(&self, other: &Self, max_abs_diff: f32) -> bool { self.abs_diff_eq(*other, max_abs_diff as f64) } #[inline] fn abs_diff(&self, other: &Self) -> Self { (*self - *other).abs() } } glam-0.30.1/tests/swizzles_f32.rs000064400000000000000000001122061046102023000147030ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_vec4_swizzles, { let v = vec4(1_f32, 2_f32, 3_f32, 4_f32); let rhs3 = vec3(11_f32, 12_f32, 13_f32); let rhs2 = vec2(11_f32, 12_f32); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), vec4(1_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.xxxy(), vec4(1_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.xxxz(), vec4(1_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.xxxw(), vec4(1_f32, 1_f32, 1_f32, 4_f32)); assert_eq!(v.xxyx(), vec4(1_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.xxyy(), vec4(1_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.xxyz(), vec4(1_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.xxyw(), vec4(1_f32, 1_f32, 2_f32, 4_f32)); assert_eq!(v.xxzx(), vec4(1_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.xxzy(), vec4(1_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.xxzz(), vec4(1_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.xxzw(), vec4(1_f32, 1_f32, 3_f32, 4_f32)); assert_eq!(v.xxwx(), vec4(1_f32, 1_f32, 4_f32, 1_f32)); assert_eq!(v.xxwy(), vec4(1_f32, 1_f32, 4_f32, 2_f32)); assert_eq!(v.xxwz(), vec4(1_f32, 1_f32, 4_f32, 3_f32)); assert_eq!(v.xxww(), vec4(1_f32, 1_f32, 4_f32, 4_f32)); assert_eq!(v.xyxx(), vec4(1_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.xyxy(), vec4(1_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.xyxz(), vec4(1_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.xyxw(), vec4(1_f32, 2_f32, 1_f32, 4_f32)); assert_eq!(v.xyyx(), vec4(1_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.xyyy(), vec4(1_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.xyyz(), vec4(1_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.xyyw(), vec4(1_f32, 2_f32, 2_f32, 4_f32)); assert_eq!(v.xyzx(), vec4(1_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.xyzy(), vec4(1_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.xyzz(), vec4(1_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.xywx(), vec4(1_f32, 2_f32, 4_f32, 1_f32)); assert_eq!(v.xywy(), vec4(1_f32, 2_f32, 4_f32, 2_f32)); assert_eq!(v.xywz(), vec4(1_f32, 2_f32, 4_f32, 3_f32)); assert_eq!(v.xyww(), vec4(1_f32, 2_f32, 4_f32, 4_f32)); assert_eq!(v.xzxx(), vec4(1_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.xzxy(), vec4(1_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.xzxz(), vec4(1_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.xzxw(), vec4(1_f32, 3_f32, 1_f32, 4_f32)); assert_eq!(v.xzyx(), vec4(1_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.xzyy(), vec4(1_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.xzyz(), vec4(1_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.xzyw(), vec4(1_f32, 3_f32, 2_f32, 4_f32)); assert_eq!(v.xzzx(), vec4(1_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.xzzy(), vec4(1_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.xzzz(), vec4(1_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.xzzw(), vec4(1_f32, 3_f32, 3_f32, 4_f32)); assert_eq!(v.xzwx(), vec4(1_f32, 3_f32, 4_f32, 1_f32)); assert_eq!(v.xzwy(), vec4(1_f32, 3_f32, 4_f32, 2_f32)); assert_eq!(v.xzwz(), vec4(1_f32, 3_f32, 4_f32, 3_f32)); assert_eq!(v.xzww(), vec4(1_f32, 3_f32, 4_f32, 4_f32)); assert_eq!(v.xwxx(), vec4(1_f32, 4_f32, 1_f32, 1_f32)); assert_eq!(v.xwxy(), vec4(1_f32, 4_f32, 1_f32, 2_f32)); assert_eq!(v.xwxz(), vec4(1_f32, 4_f32, 1_f32, 3_f32)); assert_eq!(v.xwxw(), vec4(1_f32, 4_f32, 1_f32, 4_f32)); assert_eq!(v.xwyx(), vec4(1_f32, 4_f32, 2_f32, 1_f32)); assert_eq!(v.xwyy(), vec4(1_f32, 4_f32, 2_f32, 2_f32)); assert_eq!(v.xwyz(), vec4(1_f32, 4_f32, 2_f32, 3_f32)); assert_eq!(v.xwyw(), vec4(1_f32, 4_f32, 2_f32, 4_f32)); assert_eq!(v.xwzx(), vec4(1_f32, 4_f32, 3_f32, 1_f32)); assert_eq!(v.xwzy(), vec4(1_f32, 4_f32, 3_f32, 2_f32)); assert_eq!(v.xwzz(), vec4(1_f32, 4_f32, 3_f32, 3_f32)); assert_eq!(v.xwzw(), vec4(1_f32, 4_f32, 3_f32, 4_f32)); assert_eq!(v.xwwx(), vec4(1_f32, 4_f32, 4_f32, 1_f32)); assert_eq!(v.xwwy(), vec4(1_f32, 4_f32, 4_f32, 2_f32)); assert_eq!(v.xwwz(), vec4(1_f32, 4_f32, 4_f32, 3_f32)); assert_eq!(v.xwww(), vec4(1_f32, 4_f32, 4_f32, 4_f32)); assert_eq!(v.yxxx(), vec4(2_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.yxxy(), vec4(2_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.yxxz(), vec4(2_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.yxxw(), vec4(2_f32, 1_f32, 1_f32, 4_f32)); assert_eq!(v.yxyx(), vec4(2_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.yxyy(), vec4(2_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.yxyz(), vec4(2_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.yxyw(), vec4(2_f32, 1_f32, 2_f32, 4_f32)); assert_eq!(v.yxzx(), vec4(2_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.yxzy(), vec4(2_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.yxzz(), vec4(2_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.yxzw(), vec4(2_f32, 1_f32, 3_f32, 4_f32)); assert_eq!(v.yxwx(), vec4(2_f32, 1_f32, 4_f32, 1_f32)); assert_eq!(v.yxwy(), vec4(2_f32, 1_f32, 4_f32, 2_f32)); assert_eq!(v.yxwz(), vec4(2_f32, 1_f32, 4_f32, 3_f32)); assert_eq!(v.yxww(), vec4(2_f32, 1_f32, 4_f32, 4_f32)); assert_eq!(v.yyxx(), vec4(2_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.yyxy(), vec4(2_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.yyxz(), vec4(2_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.yyxw(), vec4(2_f32, 2_f32, 1_f32, 4_f32)); assert_eq!(v.yyyx(), vec4(2_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.yyyy(), vec4(2_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.yyyz(), vec4(2_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.yyyw(), vec4(2_f32, 2_f32, 2_f32, 4_f32)); assert_eq!(v.yyzx(), vec4(2_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.yyzy(), vec4(2_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.yyzz(), vec4(2_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.yyzw(), vec4(2_f32, 2_f32, 3_f32, 4_f32)); assert_eq!(v.yywx(), vec4(2_f32, 2_f32, 4_f32, 1_f32)); assert_eq!(v.yywy(), vec4(2_f32, 2_f32, 4_f32, 2_f32)); assert_eq!(v.yywz(), vec4(2_f32, 2_f32, 4_f32, 3_f32)); assert_eq!(v.yyww(), vec4(2_f32, 2_f32, 4_f32, 4_f32)); assert_eq!(v.yzxx(), vec4(2_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.yzxy(), vec4(2_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.yzxz(), vec4(2_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.yzxw(), vec4(2_f32, 3_f32, 1_f32, 4_f32)); assert_eq!(v.yzyx(), vec4(2_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.yzyy(), vec4(2_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.yzyz(), vec4(2_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.yzyw(), vec4(2_f32, 3_f32, 2_f32, 4_f32)); assert_eq!(v.yzzx(), vec4(2_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.yzzy(), vec4(2_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.yzzz(), vec4(2_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.yzzw(), vec4(2_f32, 3_f32, 3_f32, 4_f32)); assert_eq!(v.yzwx(), vec4(2_f32, 3_f32, 4_f32, 1_f32)); assert_eq!(v.yzwy(), vec4(2_f32, 3_f32, 4_f32, 2_f32)); assert_eq!(v.yzwz(), vec4(2_f32, 3_f32, 4_f32, 3_f32)); assert_eq!(v.yzww(), vec4(2_f32, 3_f32, 4_f32, 4_f32)); assert_eq!(v.ywxx(), vec4(2_f32, 4_f32, 1_f32, 1_f32)); assert_eq!(v.ywxy(), vec4(2_f32, 4_f32, 1_f32, 2_f32)); assert_eq!(v.ywxz(), vec4(2_f32, 4_f32, 1_f32, 3_f32)); assert_eq!(v.ywxw(), vec4(2_f32, 4_f32, 1_f32, 4_f32)); assert_eq!(v.ywyx(), vec4(2_f32, 4_f32, 2_f32, 1_f32)); assert_eq!(v.ywyy(), vec4(2_f32, 4_f32, 2_f32, 2_f32)); assert_eq!(v.ywyz(), vec4(2_f32, 4_f32, 2_f32, 3_f32)); assert_eq!(v.ywyw(), vec4(2_f32, 4_f32, 2_f32, 4_f32)); assert_eq!(v.ywzx(), vec4(2_f32, 4_f32, 3_f32, 1_f32)); assert_eq!(v.ywzy(), vec4(2_f32, 4_f32, 3_f32, 2_f32)); assert_eq!(v.ywzz(), vec4(2_f32, 4_f32, 3_f32, 3_f32)); assert_eq!(v.ywzw(), vec4(2_f32, 4_f32, 3_f32, 4_f32)); assert_eq!(v.ywwx(), vec4(2_f32, 4_f32, 4_f32, 1_f32)); assert_eq!(v.ywwy(), vec4(2_f32, 4_f32, 4_f32, 2_f32)); assert_eq!(v.ywwz(), vec4(2_f32, 4_f32, 4_f32, 3_f32)); assert_eq!(v.ywww(), vec4(2_f32, 4_f32, 4_f32, 4_f32)); assert_eq!(v.zxxx(), vec4(3_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.zxxy(), vec4(3_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.zxxz(), vec4(3_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.zxxw(), vec4(3_f32, 1_f32, 1_f32, 4_f32)); assert_eq!(v.zxyx(), vec4(3_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.zxyy(), vec4(3_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.zxyz(), vec4(3_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.zxyw(), vec4(3_f32, 1_f32, 2_f32, 4_f32)); assert_eq!(v.zxzx(), vec4(3_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.zxzy(), vec4(3_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.zxzz(), vec4(3_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.zxzw(), vec4(3_f32, 1_f32, 3_f32, 4_f32)); assert_eq!(v.zxwx(), vec4(3_f32, 1_f32, 4_f32, 1_f32)); assert_eq!(v.zxwy(), vec4(3_f32, 1_f32, 4_f32, 2_f32)); assert_eq!(v.zxwz(), vec4(3_f32, 1_f32, 4_f32, 3_f32)); assert_eq!(v.zxww(), vec4(3_f32, 1_f32, 4_f32, 4_f32)); assert_eq!(v.zyxx(), vec4(3_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.zyxy(), vec4(3_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.zyxz(), vec4(3_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.zyxw(), vec4(3_f32, 2_f32, 1_f32, 4_f32)); assert_eq!(v.zyyx(), vec4(3_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.zyyy(), vec4(3_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.zyyz(), vec4(3_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.zyyw(), vec4(3_f32, 2_f32, 2_f32, 4_f32)); assert_eq!(v.zyzx(), vec4(3_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.zyzy(), vec4(3_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.zyzz(), vec4(3_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.zyzw(), vec4(3_f32, 2_f32, 3_f32, 4_f32)); assert_eq!(v.zywx(), vec4(3_f32, 2_f32, 4_f32, 1_f32)); assert_eq!(v.zywy(), vec4(3_f32, 2_f32, 4_f32, 2_f32)); assert_eq!(v.zywz(), vec4(3_f32, 2_f32, 4_f32, 3_f32)); assert_eq!(v.zyww(), vec4(3_f32, 2_f32, 4_f32, 4_f32)); assert_eq!(v.zzxx(), vec4(3_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.zzxy(), vec4(3_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.zzxz(), vec4(3_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.zzxw(), vec4(3_f32, 3_f32, 1_f32, 4_f32)); assert_eq!(v.zzyx(), vec4(3_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.zzyy(), vec4(3_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.zzyz(), vec4(3_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.zzyw(), vec4(3_f32, 3_f32, 2_f32, 4_f32)); assert_eq!(v.zzzx(), vec4(3_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.zzzy(), vec4(3_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.zzzz(), vec4(3_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.zzzw(), vec4(3_f32, 3_f32, 3_f32, 4_f32)); assert_eq!(v.zzwx(), vec4(3_f32, 3_f32, 4_f32, 1_f32)); assert_eq!(v.zzwy(), vec4(3_f32, 3_f32, 4_f32, 2_f32)); assert_eq!(v.zzwz(), vec4(3_f32, 3_f32, 4_f32, 3_f32)); assert_eq!(v.zzww(), vec4(3_f32, 3_f32, 4_f32, 4_f32)); assert_eq!(v.zwxx(), vec4(3_f32, 4_f32, 1_f32, 1_f32)); assert_eq!(v.zwxy(), vec4(3_f32, 4_f32, 1_f32, 2_f32)); assert_eq!(v.zwxz(), vec4(3_f32, 4_f32, 1_f32, 3_f32)); assert_eq!(v.zwxw(), vec4(3_f32, 4_f32, 1_f32, 4_f32)); assert_eq!(v.zwyx(), vec4(3_f32, 4_f32, 2_f32, 1_f32)); assert_eq!(v.zwyy(), vec4(3_f32, 4_f32, 2_f32, 2_f32)); assert_eq!(v.zwyz(), vec4(3_f32, 4_f32, 2_f32, 3_f32)); assert_eq!(v.zwyw(), vec4(3_f32, 4_f32, 2_f32, 4_f32)); assert_eq!(v.zwzx(), vec4(3_f32, 4_f32, 3_f32, 1_f32)); assert_eq!(v.zwzy(), vec4(3_f32, 4_f32, 3_f32, 2_f32)); assert_eq!(v.zwzz(), vec4(3_f32, 4_f32, 3_f32, 3_f32)); assert_eq!(v.zwzw(), vec4(3_f32, 4_f32, 3_f32, 4_f32)); assert_eq!(v.zwwx(), vec4(3_f32, 4_f32, 4_f32, 1_f32)); assert_eq!(v.zwwy(), vec4(3_f32, 4_f32, 4_f32, 2_f32)); assert_eq!(v.zwwz(), vec4(3_f32, 4_f32, 4_f32, 3_f32)); assert_eq!(v.zwww(), vec4(3_f32, 4_f32, 4_f32, 4_f32)); assert_eq!(v.wxxx(), vec4(4_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.wxxy(), vec4(4_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.wxxz(), vec4(4_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.wxxw(), vec4(4_f32, 1_f32, 1_f32, 4_f32)); assert_eq!(v.wxyx(), vec4(4_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.wxyy(), vec4(4_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.wxyz(), vec4(4_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.wxyw(), vec4(4_f32, 1_f32, 2_f32, 4_f32)); assert_eq!(v.wxzx(), vec4(4_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.wxzy(), vec4(4_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.wxzz(), vec4(4_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.wxzw(), vec4(4_f32, 1_f32, 3_f32, 4_f32)); assert_eq!(v.wxwx(), vec4(4_f32, 1_f32, 4_f32, 1_f32)); assert_eq!(v.wxwy(), vec4(4_f32, 1_f32, 4_f32, 2_f32)); assert_eq!(v.wxwz(), vec4(4_f32, 1_f32, 4_f32, 3_f32)); assert_eq!(v.wxww(), vec4(4_f32, 1_f32, 4_f32, 4_f32)); assert_eq!(v.wyxx(), vec4(4_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.wyxy(), vec4(4_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.wyxz(), vec4(4_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.wyxw(), vec4(4_f32, 2_f32, 1_f32, 4_f32)); assert_eq!(v.wyyx(), vec4(4_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.wyyy(), vec4(4_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.wyyz(), vec4(4_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.wyyw(), vec4(4_f32, 2_f32, 2_f32, 4_f32)); assert_eq!(v.wyzx(), vec4(4_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.wyzy(), vec4(4_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.wyzz(), vec4(4_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.wyzw(), vec4(4_f32, 2_f32, 3_f32, 4_f32)); assert_eq!(v.wywx(), vec4(4_f32, 2_f32, 4_f32, 1_f32)); assert_eq!(v.wywy(), vec4(4_f32, 2_f32, 4_f32, 2_f32)); assert_eq!(v.wywz(), vec4(4_f32, 2_f32, 4_f32, 3_f32)); assert_eq!(v.wyww(), vec4(4_f32, 2_f32, 4_f32, 4_f32)); assert_eq!(v.wzxx(), vec4(4_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.wzxy(), vec4(4_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.wzxz(), vec4(4_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.wzxw(), vec4(4_f32, 3_f32, 1_f32, 4_f32)); assert_eq!(v.wzyx(), vec4(4_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.wzyy(), vec4(4_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.wzyz(), vec4(4_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.wzyw(), vec4(4_f32, 3_f32, 2_f32, 4_f32)); assert_eq!(v.wzzx(), vec4(4_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.wzzy(), vec4(4_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.wzzz(), vec4(4_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.wzzw(), vec4(4_f32, 3_f32, 3_f32, 4_f32)); assert_eq!(v.wzwx(), vec4(4_f32, 3_f32, 4_f32, 1_f32)); assert_eq!(v.wzwy(), vec4(4_f32, 3_f32, 4_f32, 2_f32)); assert_eq!(v.wzwz(), vec4(4_f32, 3_f32, 4_f32, 3_f32)); assert_eq!(v.wzww(), vec4(4_f32, 3_f32, 4_f32, 4_f32)); assert_eq!(v.wwxx(), vec4(4_f32, 4_f32, 1_f32, 1_f32)); assert_eq!(v.wwxy(), vec4(4_f32, 4_f32, 1_f32, 2_f32)); assert_eq!(v.wwxz(), vec4(4_f32, 4_f32, 1_f32, 3_f32)); assert_eq!(v.wwxw(), vec4(4_f32, 4_f32, 1_f32, 4_f32)); assert_eq!(v.wwyx(), vec4(4_f32, 4_f32, 2_f32, 1_f32)); assert_eq!(v.wwyy(), vec4(4_f32, 4_f32, 2_f32, 2_f32)); assert_eq!(v.wwyz(), vec4(4_f32, 4_f32, 2_f32, 3_f32)); assert_eq!(v.wwyw(), vec4(4_f32, 4_f32, 2_f32, 4_f32)); assert_eq!(v.wwzx(), vec4(4_f32, 4_f32, 3_f32, 1_f32)); assert_eq!(v.wwzy(), vec4(4_f32, 4_f32, 3_f32, 2_f32)); assert_eq!(v.wwzz(), vec4(4_f32, 4_f32, 3_f32, 3_f32)); assert_eq!(v.wwzw(), vec4(4_f32, 4_f32, 3_f32, 4_f32)); assert_eq!(v.wwwx(), vec4(4_f32, 4_f32, 4_f32, 1_f32)); assert_eq!(v.wwwy(), vec4(4_f32, 4_f32, 4_f32, 2_f32)); assert_eq!(v.wwwz(), vec4(4_f32, 4_f32, 4_f32, 3_f32)); assert_eq!(v.wwww(), vec4(4_f32, 4_f32, 4_f32, 4_f32)); assert_eq!(v.xxx(), vec3(1_f32, 1_f32, 1_f32)); assert_eq!(v.xxy(), vec3(1_f32, 1_f32, 2_f32)); assert_eq!(v.xxz(), vec3(1_f32, 1_f32, 3_f32)); assert_eq!(v.xxw(), vec3(1_f32, 1_f32, 4_f32)); assert_eq!(v.xyx(), vec3(1_f32, 2_f32, 1_f32)); assert_eq!(v.xyy(), vec3(1_f32, 2_f32, 2_f32)); assert_eq!(v.xyz(), vec3(1_f32, 2_f32, 3_f32)); assert_eq!(v.xyw(), vec3(1_f32, 2_f32, 4_f32)); assert_eq!(v.xzx(), vec3(1_f32, 3_f32, 1_f32)); assert_eq!(v.xzy(), vec3(1_f32, 3_f32, 2_f32)); assert_eq!(v.xzz(), vec3(1_f32, 3_f32, 3_f32)); assert_eq!(v.xzw(), vec3(1_f32, 3_f32, 4_f32)); assert_eq!(v.xwx(), vec3(1_f32, 4_f32, 1_f32)); assert_eq!(v.xwy(), vec3(1_f32, 4_f32, 2_f32)); assert_eq!(v.xwz(), vec3(1_f32, 4_f32, 3_f32)); assert_eq!(v.xww(), vec3(1_f32, 4_f32, 4_f32)); assert_eq!(v.yxx(), vec3(2_f32, 1_f32, 1_f32)); assert_eq!(v.yxy(), vec3(2_f32, 1_f32, 2_f32)); assert_eq!(v.yxz(), vec3(2_f32, 1_f32, 3_f32)); assert_eq!(v.yxw(), vec3(2_f32, 1_f32, 4_f32)); assert_eq!(v.yyx(), vec3(2_f32, 2_f32, 1_f32)); assert_eq!(v.yyy(), vec3(2_f32, 2_f32, 2_f32)); assert_eq!(v.yyz(), vec3(2_f32, 2_f32, 3_f32)); assert_eq!(v.yyw(), vec3(2_f32, 2_f32, 4_f32)); assert_eq!(v.yzx(), vec3(2_f32, 3_f32, 1_f32)); assert_eq!(v.yzy(), vec3(2_f32, 3_f32, 2_f32)); assert_eq!(v.yzz(), vec3(2_f32, 3_f32, 3_f32)); assert_eq!(v.yzw(), vec3(2_f32, 3_f32, 4_f32)); assert_eq!(v.ywx(), vec3(2_f32, 4_f32, 1_f32)); assert_eq!(v.ywy(), vec3(2_f32, 4_f32, 2_f32)); assert_eq!(v.ywz(), vec3(2_f32, 4_f32, 3_f32)); assert_eq!(v.yww(), vec3(2_f32, 4_f32, 4_f32)); assert_eq!(v.zxx(), vec3(3_f32, 1_f32, 1_f32)); assert_eq!(v.zxy(), vec3(3_f32, 1_f32, 2_f32)); assert_eq!(v.zxz(), vec3(3_f32, 1_f32, 3_f32)); assert_eq!(v.zxw(), vec3(3_f32, 1_f32, 4_f32)); assert_eq!(v.zyx(), vec3(3_f32, 2_f32, 1_f32)); assert_eq!(v.zyy(), vec3(3_f32, 2_f32, 2_f32)); assert_eq!(v.zyz(), vec3(3_f32, 2_f32, 3_f32)); assert_eq!(v.zyw(), vec3(3_f32, 2_f32, 4_f32)); assert_eq!(v.zzx(), vec3(3_f32, 3_f32, 1_f32)); assert_eq!(v.zzy(), vec3(3_f32, 3_f32, 2_f32)); assert_eq!(v.zzz(), vec3(3_f32, 3_f32, 3_f32)); assert_eq!(v.zzw(), vec3(3_f32, 3_f32, 4_f32)); assert_eq!(v.zwx(), vec3(3_f32, 4_f32, 1_f32)); assert_eq!(v.zwy(), vec3(3_f32, 4_f32, 2_f32)); assert_eq!(v.zwz(), vec3(3_f32, 4_f32, 3_f32)); assert_eq!(v.zww(), vec3(3_f32, 4_f32, 4_f32)); assert_eq!(v.wxx(), vec3(4_f32, 1_f32, 1_f32)); assert_eq!(v.wxy(), vec3(4_f32, 1_f32, 2_f32)); assert_eq!(v.wxz(), vec3(4_f32, 1_f32, 3_f32)); assert_eq!(v.wxw(), vec3(4_f32, 1_f32, 4_f32)); assert_eq!(v.wyx(), vec3(4_f32, 2_f32, 1_f32)); assert_eq!(v.wyy(), vec3(4_f32, 2_f32, 2_f32)); assert_eq!(v.wyz(), vec3(4_f32, 2_f32, 3_f32)); assert_eq!(v.wyw(), vec3(4_f32, 2_f32, 4_f32)); assert_eq!(v.wzx(), vec3(4_f32, 3_f32, 1_f32)); assert_eq!(v.wzy(), vec3(4_f32, 3_f32, 2_f32)); assert_eq!(v.wzz(), vec3(4_f32, 3_f32, 3_f32)); assert_eq!(v.wzw(), vec3(4_f32, 3_f32, 4_f32)); assert_eq!(v.wwx(), vec3(4_f32, 4_f32, 1_f32)); assert_eq!(v.wwy(), vec3(4_f32, 4_f32, 2_f32)); assert_eq!(v.wwz(), vec3(4_f32, 4_f32, 3_f32)); assert_eq!(v.www(), vec3(4_f32, 4_f32, 4_f32)); assert_eq!(v.with_xyz(rhs3), vec4(11_f32, 12_f32, 13_f32, 4_f32)); assert_eq!(v.with_xyw(rhs3), vec4(11_f32, 12_f32, 3_f32, 13_f32)); assert_eq!(v.with_xzy(rhs3), vec4(11_f32, 13_f32, 12_f32, 4_f32)); assert_eq!(v.with_xzw(rhs3), vec4(11_f32, 2_f32, 12_f32, 13_f32)); assert_eq!(v.with_xwy(rhs3), vec4(11_f32, 13_f32, 3_f32, 12_f32)); assert_eq!(v.with_xwz(rhs3), vec4(11_f32, 2_f32, 13_f32, 12_f32)); assert_eq!(v.with_yxz(rhs3), vec4(12_f32, 11_f32, 13_f32, 4_f32)); assert_eq!(v.with_yxw(rhs3), vec4(12_f32, 11_f32, 3_f32, 13_f32)); assert_eq!(v.with_yzx(rhs3), vec4(13_f32, 11_f32, 12_f32, 4_f32)); assert_eq!(v.with_yzw(rhs3), vec4(1_f32, 11_f32, 12_f32, 13_f32)); assert_eq!(v.with_ywx(rhs3), vec4(13_f32, 11_f32, 3_f32, 12_f32)); assert_eq!(v.with_ywz(rhs3), vec4(1_f32, 11_f32, 13_f32, 12_f32)); assert_eq!(v.with_zxy(rhs3), vec4(12_f32, 13_f32, 11_f32, 4_f32)); assert_eq!(v.with_zxw(rhs3), vec4(12_f32, 2_f32, 11_f32, 13_f32)); assert_eq!(v.with_zyx(rhs3), vec4(13_f32, 12_f32, 11_f32, 4_f32)); assert_eq!(v.with_zyw(rhs3), vec4(1_f32, 12_f32, 11_f32, 13_f32)); assert_eq!(v.with_zwx(rhs3), vec4(13_f32, 2_f32, 11_f32, 12_f32)); assert_eq!(v.with_zwy(rhs3), vec4(1_f32, 13_f32, 11_f32, 12_f32)); assert_eq!(v.with_wxy(rhs3), vec4(12_f32, 13_f32, 3_f32, 11_f32)); assert_eq!(v.with_wxz(rhs3), vec4(12_f32, 2_f32, 13_f32, 11_f32)); assert_eq!(v.with_wyx(rhs3), vec4(13_f32, 12_f32, 3_f32, 11_f32)); assert_eq!(v.with_wyz(rhs3), vec4(1_f32, 12_f32, 13_f32, 11_f32)); assert_eq!(v.with_wzx(rhs3), vec4(13_f32, 2_f32, 12_f32, 11_f32)); assert_eq!(v.with_wzy(rhs3), vec4(1_f32, 13_f32, 12_f32, 11_f32)); assert_eq!(v.xx(), vec2(1_f32, 1_f32)); assert_eq!(v.xy(), vec2(1_f32, 2_f32)); assert_eq!(v.xz(), vec2(1_f32, 3_f32)); assert_eq!(v.xw(), vec2(1_f32, 4_f32)); assert_eq!(v.yx(), vec2(2_f32, 1_f32)); assert_eq!(v.yy(), vec2(2_f32, 2_f32)); assert_eq!(v.yz(), vec2(2_f32, 3_f32)); assert_eq!(v.yw(), vec2(2_f32, 4_f32)); assert_eq!(v.zx(), vec2(3_f32, 1_f32)); assert_eq!(v.zy(), vec2(3_f32, 2_f32)); assert_eq!(v.zz(), vec2(3_f32, 3_f32)); assert_eq!(v.zw(), vec2(3_f32, 4_f32)); assert_eq!(v.wx(), vec2(4_f32, 1_f32)); assert_eq!(v.wy(), vec2(4_f32, 2_f32)); assert_eq!(v.wz(), vec2(4_f32, 3_f32)); assert_eq!(v.ww(), vec2(4_f32, 4_f32)); assert_eq!(v.with_xy(rhs2), vec4(11_f32, 12_f32, 3_f32, 4_f32)); assert_eq!(v.with_xz(rhs2), vec4(11_f32, 2_f32, 12_f32, 4_f32)); assert_eq!(v.with_xw(rhs2), vec4(11_f32, 2_f32, 3_f32, 12_f32)); assert_eq!(v.with_yx(rhs2), vec4(12_f32, 11_f32, 3_f32, 4_f32)); assert_eq!(v.with_yz(rhs2), vec4(1_f32, 11_f32, 12_f32, 4_f32)); assert_eq!(v.with_yw(rhs2), vec4(1_f32, 11_f32, 3_f32, 12_f32)); assert_eq!(v.with_zx(rhs2), vec4(12_f32, 2_f32, 11_f32, 4_f32)); assert_eq!(v.with_zy(rhs2), vec4(1_f32, 12_f32, 11_f32, 4_f32)); assert_eq!(v.with_zw(rhs2), vec4(1_f32, 2_f32, 11_f32, 12_f32)); assert_eq!(v.with_wx(rhs2), vec4(12_f32, 2_f32, 3_f32, 11_f32)); assert_eq!(v.with_wy(rhs2), vec4(1_f32, 12_f32, 3_f32, 11_f32)); assert_eq!(v.with_wz(rhs2), vec4(1_f32, 2_f32, 12_f32, 11_f32)); }); glam_test!(test_vec3a_swizzles, { let v = vec3a(1_f32, 2_f32, 3_f32); let rhs2 = vec2(11_f32, 12_f32); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), vec4(1_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.xxxy(), vec4(1_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.xxxz(), vec4(1_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.xxyx(), vec4(1_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.xxyy(), vec4(1_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.xxyz(), vec4(1_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.xxzx(), vec4(1_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.xxzy(), vec4(1_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.xxzz(), vec4(1_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.xyxx(), vec4(1_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.xyxy(), vec4(1_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.xyxz(), vec4(1_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.xyyx(), vec4(1_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.xyyy(), vec4(1_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.xyyz(), vec4(1_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.xyzx(), vec4(1_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.xyzy(), vec4(1_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.xyzz(), vec4(1_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.xzxx(), vec4(1_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.xzxy(), vec4(1_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.xzxz(), vec4(1_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.xzyx(), vec4(1_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.xzyy(), vec4(1_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.xzyz(), vec4(1_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.xzzx(), vec4(1_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.xzzy(), vec4(1_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.xzzz(), vec4(1_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.yxxx(), vec4(2_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.yxxy(), vec4(2_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.yxxz(), vec4(2_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.yxyx(), vec4(2_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.yxyy(), vec4(2_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.yxyz(), vec4(2_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.yxzx(), vec4(2_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.yxzy(), vec4(2_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.yxzz(), vec4(2_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.yyxx(), vec4(2_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.yyxy(), vec4(2_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.yyxz(), vec4(2_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.yyyx(), vec4(2_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.yyyy(), vec4(2_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.yyyz(), vec4(2_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.yyzx(), vec4(2_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.yyzy(), vec4(2_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.yyzz(), vec4(2_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.yzxx(), vec4(2_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.yzxy(), vec4(2_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.yzxz(), vec4(2_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.yzyx(), vec4(2_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.yzyy(), vec4(2_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.yzyz(), vec4(2_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.yzzx(), vec4(2_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.yzzy(), vec4(2_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.yzzz(), vec4(2_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.zxxx(), vec4(3_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.zxxy(), vec4(3_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.zxxz(), vec4(3_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.zxyx(), vec4(3_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.zxyy(), vec4(3_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.zxyz(), vec4(3_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.zxzx(), vec4(3_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.zxzy(), vec4(3_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.zxzz(), vec4(3_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.zyxx(), vec4(3_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.zyxy(), vec4(3_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.zyxz(), vec4(3_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.zyyx(), vec4(3_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.zyyy(), vec4(3_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.zyyz(), vec4(3_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.zyzx(), vec4(3_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.zyzy(), vec4(3_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.zyzz(), vec4(3_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.zzxx(), vec4(3_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.zzxy(), vec4(3_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.zzxz(), vec4(3_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.zzyx(), vec4(3_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.zzyy(), vec4(3_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.zzyz(), vec4(3_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.zzzx(), vec4(3_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.zzzy(), vec4(3_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.zzzz(), vec4(3_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.xxx(), vec3a(1_f32, 1_f32, 1_f32)); assert_eq!(v.xxy(), vec3a(1_f32, 1_f32, 2_f32)); assert_eq!(v.xxz(), vec3a(1_f32, 1_f32, 3_f32)); assert_eq!(v.xyx(), vec3a(1_f32, 2_f32, 1_f32)); assert_eq!(v.xyy(), vec3a(1_f32, 2_f32, 2_f32)); assert_eq!(v.xzx(), vec3a(1_f32, 3_f32, 1_f32)); assert_eq!(v.xzy(), vec3a(1_f32, 3_f32, 2_f32)); assert_eq!(v.xzz(), vec3a(1_f32, 3_f32, 3_f32)); assert_eq!(v.yxx(), vec3a(2_f32, 1_f32, 1_f32)); assert_eq!(v.yxy(), vec3a(2_f32, 1_f32, 2_f32)); assert_eq!(v.yxz(), vec3a(2_f32, 1_f32, 3_f32)); assert_eq!(v.yyx(), vec3a(2_f32, 2_f32, 1_f32)); assert_eq!(v.yyy(), vec3a(2_f32, 2_f32, 2_f32)); assert_eq!(v.yyz(), vec3a(2_f32, 2_f32, 3_f32)); assert_eq!(v.yzx(), vec3a(2_f32, 3_f32, 1_f32)); assert_eq!(v.yzy(), vec3a(2_f32, 3_f32, 2_f32)); assert_eq!(v.yzz(), vec3a(2_f32, 3_f32, 3_f32)); assert_eq!(v.zxx(), vec3a(3_f32, 1_f32, 1_f32)); assert_eq!(v.zxy(), vec3a(3_f32, 1_f32, 2_f32)); assert_eq!(v.zxz(), vec3a(3_f32, 1_f32, 3_f32)); assert_eq!(v.zyx(), vec3a(3_f32, 2_f32, 1_f32)); assert_eq!(v.zyy(), vec3a(3_f32, 2_f32, 2_f32)); assert_eq!(v.zyz(), vec3a(3_f32, 2_f32, 3_f32)); assert_eq!(v.zzx(), vec3a(3_f32, 3_f32, 1_f32)); assert_eq!(v.zzy(), vec3a(3_f32, 3_f32, 2_f32)); assert_eq!(v.zzz(), vec3a(3_f32, 3_f32, 3_f32)); assert_eq!(v.xx(), vec2(1_f32, 1_f32)); assert_eq!(v.xy(), vec2(1_f32, 2_f32)); assert_eq!(v.xz(), vec2(1_f32, 3_f32)); assert_eq!(v.yx(), vec2(2_f32, 1_f32)); assert_eq!(v.yy(), vec2(2_f32, 2_f32)); assert_eq!(v.yz(), vec2(2_f32, 3_f32)); assert_eq!(v.zx(), vec2(3_f32, 1_f32)); assert_eq!(v.zy(), vec2(3_f32, 2_f32)); assert_eq!(v.zz(), vec2(3_f32, 3_f32)); assert_eq!(v.with_xy(rhs2), vec3a(11_f32, 12_f32, 3_f32)); assert_eq!(v.with_xz(rhs2), vec3a(11_f32, 2_f32, 12_f32)); assert_eq!(v.with_yx(rhs2), vec3a(12_f32, 11_f32, 3_f32)); assert_eq!(v.with_yz(rhs2), vec3a(1_f32, 11_f32, 12_f32)); assert_eq!(v.with_zx(rhs2), vec3a(12_f32, 2_f32, 11_f32)); assert_eq!(v.with_zy(rhs2), vec3a(1_f32, 12_f32, 11_f32)); }); glam_test!(test_vec3_swizzles, { let v = vec3(1_f32, 2_f32, 3_f32); let rhs2 = vec2(11_f32, 12_f32); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), vec4(1_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.xxxy(), vec4(1_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.xxxz(), vec4(1_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.xxyx(), vec4(1_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.xxyy(), vec4(1_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.xxyz(), vec4(1_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.xxzx(), vec4(1_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.xxzy(), vec4(1_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.xxzz(), vec4(1_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.xyxx(), vec4(1_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.xyxy(), vec4(1_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.xyxz(), vec4(1_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.xyyx(), vec4(1_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.xyyy(), vec4(1_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.xyyz(), vec4(1_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.xyzx(), vec4(1_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.xyzy(), vec4(1_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.xyzz(), vec4(1_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.xzxx(), vec4(1_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.xzxy(), vec4(1_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.xzxz(), vec4(1_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.xzyx(), vec4(1_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.xzyy(), vec4(1_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.xzyz(), vec4(1_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.xzzx(), vec4(1_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.xzzy(), vec4(1_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.xzzz(), vec4(1_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.yxxx(), vec4(2_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.yxxy(), vec4(2_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.yxxz(), vec4(2_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.yxyx(), vec4(2_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.yxyy(), vec4(2_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.yxyz(), vec4(2_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.yxzx(), vec4(2_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.yxzy(), vec4(2_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.yxzz(), vec4(2_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.yyxx(), vec4(2_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.yyxy(), vec4(2_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.yyxz(), vec4(2_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.yyyx(), vec4(2_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.yyyy(), vec4(2_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.yyyz(), vec4(2_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.yyzx(), vec4(2_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.yyzy(), vec4(2_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.yyzz(), vec4(2_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.yzxx(), vec4(2_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.yzxy(), vec4(2_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.yzxz(), vec4(2_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.yzyx(), vec4(2_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.yzyy(), vec4(2_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.yzyz(), vec4(2_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.yzzx(), vec4(2_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.yzzy(), vec4(2_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.yzzz(), vec4(2_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.zxxx(), vec4(3_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.zxxy(), vec4(3_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.zxxz(), vec4(3_f32, 1_f32, 1_f32, 3_f32)); assert_eq!(v.zxyx(), vec4(3_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.zxyy(), vec4(3_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.zxyz(), vec4(3_f32, 1_f32, 2_f32, 3_f32)); assert_eq!(v.zxzx(), vec4(3_f32, 1_f32, 3_f32, 1_f32)); assert_eq!(v.zxzy(), vec4(3_f32, 1_f32, 3_f32, 2_f32)); assert_eq!(v.zxzz(), vec4(3_f32, 1_f32, 3_f32, 3_f32)); assert_eq!(v.zyxx(), vec4(3_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.zyxy(), vec4(3_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.zyxz(), vec4(3_f32, 2_f32, 1_f32, 3_f32)); assert_eq!(v.zyyx(), vec4(3_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.zyyy(), vec4(3_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.zyyz(), vec4(3_f32, 2_f32, 2_f32, 3_f32)); assert_eq!(v.zyzx(), vec4(3_f32, 2_f32, 3_f32, 1_f32)); assert_eq!(v.zyzy(), vec4(3_f32, 2_f32, 3_f32, 2_f32)); assert_eq!(v.zyzz(), vec4(3_f32, 2_f32, 3_f32, 3_f32)); assert_eq!(v.zzxx(), vec4(3_f32, 3_f32, 1_f32, 1_f32)); assert_eq!(v.zzxy(), vec4(3_f32, 3_f32, 1_f32, 2_f32)); assert_eq!(v.zzxz(), vec4(3_f32, 3_f32, 1_f32, 3_f32)); assert_eq!(v.zzyx(), vec4(3_f32, 3_f32, 2_f32, 1_f32)); assert_eq!(v.zzyy(), vec4(3_f32, 3_f32, 2_f32, 2_f32)); assert_eq!(v.zzyz(), vec4(3_f32, 3_f32, 2_f32, 3_f32)); assert_eq!(v.zzzx(), vec4(3_f32, 3_f32, 3_f32, 1_f32)); assert_eq!(v.zzzy(), vec4(3_f32, 3_f32, 3_f32, 2_f32)); assert_eq!(v.zzzz(), vec4(3_f32, 3_f32, 3_f32, 3_f32)); assert_eq!(v.xxx(), vec3(1_f32, 1_f32, 1_f32)); assert_eq!(v.xxy(), vec3(1_f32, 1_f32, 2_f32)); assert_eq!(v.xxz(), vec3(1_f32, 1_f32, 3_f32)); assert_eq!(v.xyx(), vec3(1_f32, 2_f32, 1_f32)); assert_eq!(v.xyy(), vec3(1_f32, 2_f32, 2_f32)); assert_eq!(v.xzx(), vec3(1_f32, 3_f32, 1_f32)); assert_eq!(v.xzy(), vec3(1_f32, 3_f32, 2_f32)); assert_eq!(v.xzz(), vec3(1_f32, 3_f32, 3_f32)); assert_eq!(v.yxx(), vec3(2_f32, 1_f32, 1_f32)); assert_eq!(v.yxy(), vec3(2_f32, 1_f32, 2_f32)); assert_eq!(v.yxz(), vec3(2_f32, 1_f32, 3_f32)); assert_eq!(v.yyx(), vec3(2_f32, 2_f32, 1_f32)); assert_eq!(v.yyy(), vec3(2_f32, 2_f32, 2_f32)); assert_eq!(v.yyz(), vec3(2_f32, 2_f32, 3_f32)); assert_eq!(v.yzx(), vec3(2_f32, 3_f32, 1_f32)); assert_eq!(v.yzy(), vec3(2_f32, 3_f32, 2_f32)); assert_eq!(v.yzz(), vec3(2_f32, 3_f32, 3_f32)); assert_eq!(v.zxx(), vec3(3_f32, 1_f32, 1_f32)); assert_eq!(v.zxy(), vec3(3_f32, 1_f32, 2_f32)); assert_eq!(v.zxz(), vec3(3_f32, 1_f32, 3_f32)); assert_eq!(v.zyx(), vec3(3_f32, 2_f32, 1_f32)); assert_eq!(v.zyy(), vec3(3_f32, 2_f32, 2_f32)); assert_eq!(v.zyz(), vec3(3_f32, 2_f32, 3_f32)); assert_eq!(v.zzx(), vec3(3_f32, 3_f32, 1_f32)); assert_eq!(v.zzy(), vec3(3_f32, 3_f32, 2_f32)); assert_eq!(v.zzz(), vec3(3_f32, 3_f32, 3_f32)); assert_eq!(v.xx(), vec2(1_f32, 1_f32)); assert_eq!(v.xy(), vec2(1_f32, 2_f32)); assert_eq!(v.xz(), vec2(1_f32, 3_f32)); assert_eq!(v.yx(), vec2(2_f32, 1_f32)); assert_eq!(v.yy(), vec2(2_f32, 2_f32)); assert_eq!(v.yz(), vec2(2_f32, 3_f32)); assert_eq!(v.zx(), vec2(3_f32, 1_f32)); assert_eq!(v.zy(), vec2(3_f32, 2_f32)); assert_eq!(v.zz(), vec2(3_f32, 3_f32)); assert_eq!(v.with_xy(rhs2), vec3(11_f32, 12_f32, 3_f32)); assert_eq!(v.with_xz(rhs2), vec3(11_f32, 2_f32, 12_f32)); assert_eq!(v.with_yx(rhs2), vec3(12_f32, 11_f32, 3_f32)); assert_eq!(v.with_yz(rhs2), vec3(1_f32, 11_f32, 12_f32)); assert_eq!(v.with_zx(rhs2), vec3(12_f32, 2_f32, 11_f32)); assert_eq!(v.with_zy(rhs2), vec3(1_f32, 12_f32, 11_f32)); }); glam_test!(test_vec2_swizzles, { let v = vec2(1_f32, 2_f32); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), vec4(1_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.xxxy(), vec4(1_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.xxyx(), vec4(1_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.xxyy(), vec4(1_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.xyxx(), vec4(1_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.xyxy(), vec4(1_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.xyyx(), vec4(1_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.xyyy(), vec4(1_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.yxxx(), vec4(2_f32, 1_f32, 1_f32, 1_f32)); assert_eq!(v.yxxy(), vec4(2_f32, 1_f32, 1_f32, 2_f32)); assert_eq!(v.yxyx(), vec4(2_f32, 1_f32, 2_f32, 1_f32)); assert_eq!(v.yxyy(), vec4(2_f32, 1_f32, 2_f32, 2_f32)); assert_eq!(v.yyxx(), vec4(2_f32, 2_f32, 1_f32, 1_f32)); assert_eq!(v.yyxy(), vec4(2_f32, 2_f32, 1_f32, 2_f32)); assert_eq!(v.yyyx(), vec4(2_f32, 2_f32, 2_f32, 1_f32)); assert_eq!(v.yyyy(), vec4(2_f32, 2_f32, 2_f32, 2_f32)); assert_eq!(v.xxx(), vec3(1_f32, 1_f32, 1_f32)); assert_eq!(v.xxy(), vec3(1_f32, 1_f32, 2_f32)); assert_eq!(v.xyx(), vec3(1_f32, 2_f32, 1_f32)); assert_eq!(v.xyy(), vec3(1_f32, 2_f32, 2_f32)); assert_eq!(v.yxx(), vec3(2_f32, 1_f32, 1_f32)); assert_eq!(v.yxy(), vec3(2_f32, 1_f32, 2_f32)); assert_eq!(v.yyx(), vec3(2_f32, 2_f32, 1_f32)); assert_eq!(v.yyy(), vec3(2_f32, 2_f32, 2_f32)); assert_eq!(v.xx(), vec2(1_f32, 1_f32)); assert_eq!(v.yx(), vec2(2_f32, 1_f32)); assert_eq!(v.yy(), vec2(2_f32, 2_f32)); }); glam-0.30.1/tests/swizzles_f64.rs000064400000000000000000000752431046102023000147210ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_dvec4_swizzles, { let v = dvec4(1_f64, 2_f64, 3_f64, 4_f64); let rhs3 = dvec3(11_f64, 12_f64, 13_f64); let rhs2 = dvec2(11_f64, 12_f64); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), dvec4(1_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.xxxy(), dvec4(1_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.xxxz(), dvec4(1_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.xxxw(), dvec4(1_f64, 1_f64, 1_f64, 4_f64)); assert_eq!(v.xxyx(), dvec4(1_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.xxyy(), dvec4(1_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.xxyz(), dvec4(1_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.xxyw(), dvec4(1_f64, 1_f64, 2_f64, 4_f64)); assert_eq!(v.xxzx(), dvec4(1_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.xxzy(), dvec4(1_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.xxzz(), dvec4(1_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.xxzw(), dvec4(1_f64, 1_f64, 3_f64, 4_f64)); assert_eq!(v.xxwx(), dvec4(1_f64, 1_f64, 4_f64, 1_f64)); assert_eq!(v.xxwy(), dvec4(1_f64, 1_f64, 4_f64, 2_f64)); assert_eq!(v.xxwz(), dvec4(1_f64, 1_f64, 4_f64, 3_f64)); assert_eq!(v.xxww(), dvec4(1_f64, 1_f64, 4_f64, 4_f64)); assert_eq!(v.xyxx(), dvec4(1_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.xyxy(), dvec4(1_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.xyxz(), dvec4(1_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.xyxw(), dvec4(1_f64, 2_f64, 1_f64, 4_f64)); assert_eq!(v.xyyx(), dvec4(1_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.xyyy(), dvec4(1_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.xyyz(), dvec4(1_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.xyyw(), dvec4(1_f64, 2_f64, 2_f64, 4_f64)); assert_eq!(v.xyzx(), dvec4(1_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.xyzy(), dvec4(1_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.xyzz(), dvec4(1_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.xywx(), dvec4(1_f64, 2_f64, 4_f64, 1_f64)); assert_eq!(v.xywy(), dvec4(1_f64, 2_f64, 4_f64, 2_f64)); assert_eq!(v.xywz(), dvec4(1_f64, 2_f64, 4_f64, 3_f64)); assert_eq!(v.xyww(), dvec4(1_f64, 2_f64, 4_f64, 4_f64)); assert_eq!(v.xzxx(), dvec4(1_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.xzxy(), dvec4(1_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.xzxz(), dvec4(1_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.xzxw(), dvec4(1_f64, 3_f64, 1_f64, 4_f64)); assert_eq!(v.xzyx(), dvec4(1_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.xzyy(), dvec4(1_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.xzyz(), dvec4(1_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.xzyw(), dvec4(1_f64, 3_f64, 2_f64, 4_f64)); assert_eq!(v.xzzx(), dvec4(1_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.xzzy(), dvec4(1_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.xzzz(), dvec4(1_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.xzzw(), dvec4(1_f64, 3_f64, 3_f64, 4_f64)); assert_eq!(v.xzwx(), dvec4(1_f64, 3_f64, 4_f64, 1_f64)); assert_eq!(v.xzwy(), dvec4(1_f64, 3_f64, 4_f64, 2_f64)); assert_eq!(v.xzwz(), dvec4(1_f64, 3_f64, 4_f64, 3_f64)); assert_eq!(v.xzww(), dvec4(1_f64, 3_f64, 4_f64, 4_f64)); assert_eq!(v.xwxx(), dvec4(1_f64, 4_f64, 1_f64, 1_f64)); assert_eq!(v.xwxy(), dvec4(1_f64, 4_f64, 1_f64, 2_f64)); assert_eq!(v.xwxz(), dvec4(1_f64, 4_f64, 1_f64, 3_f64)); assert_eq!(v.xwxw(), dvec4(1_f64, 4_f64, 1_f64, 4_f64)); assert_eq!(v.xwyx(), dvec4(1_f64, 4_f64, 2_f64, 1_f64)); assert_eq!(v.xwyy(), dvec4(1_f64, 4_f64, 2_f64, 2_f64)); assert_eq!(v.xwyz(), dvec4(1_f64, 4_f64, 2_f64, 3_f64)); assert_eq!(v.xwyw(), dvec4(1_f64, 4_f64, 2_f64, 4_f64)); assert_eq!(v.xwzx(), dvec4(1_f64, 4_f64, 3_f64, 1_f64)); assert_eq!(v.xwzy(), dvec4(1_f64, 4_f64, 3_f64, 2_f64)); assert_eq!(v.xwzz(), dvec4(1_f64, 4_f64, 3_f64, 3_f64)); assert_eq!(v.xwzw(), dvec4(1_f64, 4_f64, 3_f64, 4_f64)); assert_eq!(v.xwwx(), dvec4(1_f64, 4_f64, 4_f64, 1_f64)); assert_eq!(v.xwwy(), dvec4(1_f64, 4_f64, 4_f64, 2_f64)); assert_eq!(v.xwwz(), dvec4(1_f64, 4_f64, 4_f64, 3_f64)); assert_eq!(v.xwww(), dvec4(1_f64, 4_f64, 4_f64, 4_f64)); assert_eq!(v.yxxx(), dvec4(2_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.yxxy(), dvec4(2_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.yxxz(), dvec4(2_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.yxxw(), dvec4(2_f64, 1_f64, 1_f64, 4_f64)); assert_eq!(v.yxyx(), dvec4(2_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.yxyy(), dvec4(2_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.yxyz(), dvec4(2_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.yxyw(), dvec4(2_f64, 1_f64, 2_f64, 4_f64)); assert_eq!(v.yxzx(), dvec4(2_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.yxzy(), dvec4(2_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.yxzz(), dvec4(2_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.yxzw(), dvec4(2_f64, 1_f64, 3_f64, 4_f64)); assert_eq!(v.yxwx(), dvec4(2_f64, 1_f64, 4_f64, 1_f64)); assert_eq!(v.yxwy(), dvec4(2_f64, 1_f64, 4_f64, 2_f64)); assert_eq!(v.yxwz(), dvec4(2_f64, 1_f64, 4_f64, 3_f64)); assert_eq!(v.yxww(), dvec4(2_f64, 1_f64, 4_f64, 4_f64)); assert_eq!(v.yyxx(), dvec4(2_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.yyxy(), dvec4(2_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.yyxz(), dvec4(2_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.yyxw(), dvec4(2_f64, 2_f64, 1_f64, 4_f64)); assert_eq!(v.yyyx(), dvec4(2_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.yyyy(), dvec4(2_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.yyyz(), dvec4(2_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.yyyw(), dvec4(2_f64, 2_f64, 2_f64, 4_f64)); assert_eq!(v.yyzx(), dvec4(2_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.yyzy(), dvec4(2_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.yyzz(), dvec4(2_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.yyzw(), dvec4(2_f64, 2_f64, 3_f64, 4_f64)); assert_eq!(v.yywx(), dvec4(2_f64, 2_f64, 4_f64, 1_f64)); assert_eq!(v.yywy(), dvec4(2_f64, 2_f64, 4_f64, 2_f64)); assert_eq!(v.yywz(), dvec4(2_f64, 2_f64, 4_f64, 3_f64)); assert_eq!(v.yyww(), dvec4(2_f64, 2_f64, 4_f64, 4_f64)); assert_eq!(v.yzxx(), dvec4(2_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.yzxy(), dvec4(2_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.yzxz(), dvec4(2_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.yzxw(), dvec4(2_f64, 3_f64, 1_f64, 4_f64)); assert_eq!(v.yzyx(), dvec4(2_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.yzyy(), dvec4(2_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.yzyz(), dvec4(2_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.yzyw(), dvec4(2_f64, 3_f64, 2_f64, 4_f64)); assert_eq!(v.yzzx(), dvec4(2_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.yzzy(), dvec4(2_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.yzzz(), dvec4(2_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.yzzw(), dvec4(2_f64, 3_f64, 3_f64, 4_f64)); assert_eq!(v.yzwx(), dvec4(2_f64, 3_f64, 4_f64, 1_f64)); assert_eq!(v.yzwy(), dvec4(2_f64, 3_f64, 4_f64, 2_f64)); assert_eq!(v.yzwz(), dvec4(2_f64, 3_f64, 4_f64, 3_f64)); assert_eq!(v.yzww(), dvec4(2_f64, 3_f64, 4_f64, 4_f64)); assert_eq!(v.ywxx(), dvec4(2_f64, 4_f64, 1_f64, 1_f64)); assert_eq!(v.ywxy(), dvec4(2_f64, 4_f64, 1_f64, 2_f64)); assert_eq!(v.ywxz(), dvec4(2_f64, 4_f64, 1_f64, 3_f64)); assert_eq!(v.ywxw(), dvec4(2_f64, 4_f64, 1_f64, 4_f64)); assert_eq!(v.ywyx(), dvec4(2_f64, 4_f64, 2_f64, 1_f64)); assert_eq!(v.ywyy(), dvec4(2_f64, 4_f64, 2_f64, 2_f64)); assert_eq!(v.ywyz(), dvec4(2_f64, 4_f64, 2_f64, 3_f64)); assert_eq!(v.ywyw(), dvec4(2_f64, 4_f64, 2_f64, 4_f64)); assert_eq!(v.ywzx(), dvec4(2_f64, 4_f64, 3_f64, 1_f64)); assert_eq!(v.ywzy(), dvec4(2_f64, 4_f64, 3_f64, 2_f64)); assert_eq!(v.ywzz(), dvec4(2_f64, 4_f64, 3_f64, 3_f64)); assert_eq!(v.ywzw(), dvec4(2_f64, 4_f64, 3_f64, 4_f64)); assert_eq!(v.ywwx(), dvec4(2_f64, 4_f64, 4_f64, 1_f64)); assert_eq!(v.ywwy(), dvec4(2_f64, 4_f64, 4_f64, 2_f64)); assert_eq!(v.ywwz(), dvec4(2_f64, 4_f64, 4_f64, 3_f64)); assert_eq!(v.ywww(), dvec4(2_f64, 4_f64, 4_f64, 4_f64)); assert_eq!(v.zxxx(), dvec4(3_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.zxxy(), dvec4(3_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.zxxz(), dvec4(3_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.zxxw(), dvec4(3_f64, 1_f64, 1_f64, 4_f64)); assert_eq!(v.zxyx(), dvec4(3_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.zxyy(), dvec4(3_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.zxyz(), dvec4(3_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.zxyw(), dvec4(3_f64, 1_f64, 2_f64, 4_f64)); assert_eq!(v.zxzx(), dvec4(3_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.zxzy(), dvec4(3_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.zxzz(), dvec4(3_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.zxzw(), dvec4(3_f64, 1_f64, 3_f64, 4_f64)); assert_eq!(v.zxwx(), dvec4(3_f64, 1_f64, 4_f64, 1_f64)); assert_eq!(v.zxwy(), dvec4(3_f64, 1_f64, 4_f64, 2_f64)); assert_eq!(v.zxwz(), dvec4(3_f64, 1_f64, 4_f64, 3_f64)); assert_eq!(v.zxww(), dvec4(3_f64, 1_f64, 4_f64, 4_f64)); assert_eq!(v.zyxx(), dvec4(3_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.zyxy(), dvec4(3_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.zyxz(), dvec4(3_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.zyxw(), dvec4(3_f64, 2_f64, 1_f64, 4_f64)); assert_eq!(v.zyyx(), dvec4(3_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.zyyy(), dvec4(3_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.zyyz(), dvec4(3_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.zyyw(), dvec4(3_f64, 2_f64, 2_f64, 4_f64)); assert_eq!(v.zyzx(), dvec4(3_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.zyzy(), dvec4(3_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.zyzz(), dvec4(3_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.zyzw(), dvec4(3_f64, 2_f64, 3_f64, 4_f64)); assert_eq!(v.zywx(), dvec4(3_f64, 2_f64, 4_f64, 1_f64)); assert_eq!(v.zywy(), dvec4(3_f64, 2_f64, 4_f64, 2_f64)); assert_eq!(v.zywz(), dvec4(3_f64, 2_f64, 4_f64, 3_f64)); assert_eq!(v.zyww(), dvec4(3_f64, 2_f64, 4_f64, 4_f64)); assert_eq!(v.zzxx(), dvec4(3_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.zzxy(), dvec4(3_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.zzxz(), dvec4(3_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.zzxw(), dvec4(3_f64, 3_f64, 1_f64, 4_f64)); assert_eq!(v.zzyx(), dvec4(3_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.zzyy(), dvec4(3_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.zzyz(), dvec4(3_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.zzyw(), dvec4(3_f64, 3_f64, 2_f64, 4_f64)); assert_eq!(v.zzzx(), dvec4(3_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.zzzy(), dvec4(3_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.zzzz(), dvec4(3_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.zzzw(), dvec4(3_f64, 3_f64, 3_f64, 4_f64)); assert_eq!(v.zzwx(), dvec4(3_f64, 3_f64, 4_f64, 1_f64)); assert_eq!(v.zzwy(), dvec4(3_f64, 3_f64, 4_f64, 2_f64)); assert_eq!(v.zzwz(), dvec4(3_f64, 3_f64, 4_f64, 3_f64)); assert_eq!(v.zzww(), dvec4(3_f64, 3_f64, 4_f64, 4_f64)); assert_eq!(v.zwxx(), dvec4(3_f64, 4_f64, 1_f64, 1_f64)); assert_eq!(v.zwxy(), dvec4(3_f64, 4_f64, 1_f64, 2_f64)); assert_eq!(v.zwxz(), dvec4(3_f64, 4_f64, 1_f64, 3_f64)); assert_eq!(v.zwxw(), dvec4(3_f64, 4_f64, 1_f64, 4_f64)); assert_eq!(v.zwyx(), dvec4(3_f64, 4_f64, 2_f64, 1_f64)); assert_eq!(v.zwyy(), dvec4(3_f64, 4_f64, 2_f64, 2_f64)); assert_eq!(v.zwyz(), dvec4(3_f64, 4_f64, 2_f64, 3_f64)); assert_eq!(v.zwyw(), dvec4(3_f64, 4_f64, 2_f64, 4_f64)); assert_eq!(v.zwzx(), dvec4(3_f64, 4_f64, 3_f64, 1_f64)); assert_eq!(v.zwzy(), dvec4(3_f64, 4_f64, 3_f64, 2_f64)); assert_eq!(v.zwzz(), dvec4(3_f64, 4_f64, 3_f64, 3_f64)); assert_eq!(v.zwzw(), dvec4(3_f64, 4_f64, 3_f64, 4_f64)); assert_eq!(v.zwwx(), dvec4(3_f64, 4_f64, 4_f64, 1_f64)); assert_eq!(v.zwwy(), dvec4(3_f64, 4_f64, 4_f64, 2_f64)); assert_eq!(v.zwwz(), dvec4(3_f64, 4_f64, 4_f64, 3_f64)); assert_eq!(v.zwww(), dvec4(3_f64, 4_f64, 4_f64, 4_f64)); assert_eq!(v.wxxx(), dvec4(4_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.wxxy(), dvec4(4_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.wxxz(), dvec4(4_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.wxxw(), dvec4(4_f64, 1_f64, 1_f64, 4_f64)); assert_eq!(v.wxyx(), dvec4(4_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.wxyy(), dvec4(4_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.wxyz(), dvec4(4_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.wxyw(), dvec4(4_f64, 1_f64, 2_f64, 4_f64)); assert_eq!(v.wxzx(), dvec4(4_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.wxzy(), dvec4(4_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.wxzz(), dvec4(4_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.wxzw(), dvec4(4_f64, 1_f64, 3_f64, 4_f64)); assert_eq!(v.wxwx(), dvec4(4_f64, 1_f64, 4_f64, 1_f64)); assert_eq!(v.wxwy(), dvec4(4_f64, 1_f64, 4_f64, 2_f64)); assert_eq!(v.wxwz(), dvec4(4_f64, 1_f64, 4_f64, 3_f64)); assert_eq!(v.wxww(), dvec4(4_f64, 1_f64, 4_f64, 4_f64)); assert_eq!(v.wyxx(), dvec4(4_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.wyxy(), dvec4(4_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.wyxz(), dvec4(4_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.wyxw(), dvec4(4_f64, 2_f64, 1_f64, 4_f64)); assert_eq!(v.wyyx(), dvec4(4_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.wyyy(), dvec4(4_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.wyyz(), dvec4(4_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.wyyw(), dvec4(4_f64, 2_f64, 2_f64, 4_f64)); assert_eq!(v.wyzx(), dvec4(4_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.wyzy(), dvec4(4_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.wyzz(), dvec4(4_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.wyzw(), dvec4(4_f64, 2_f64, 3_f64, 4_f64)); assert_eq!(v.wywx(), dvec4(4_f64, 2_f64, 4_f64, 1_f64)); assert_eq!(v.wywy(), dvec4(4_f64, 2_f64, 4_f64, 2_f64)); assert_eq!(v.wywz(), dvec4(4_f64, 2_f64, 4_f64, 3_f64)); assert_eq!(v.wyww(), dvec4(4_f64, 2_f64, 4_f64, 4_f64)); assert_eq!(v.wzxx(), dvec4(4_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.wzxy(), dvec4(4_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.wzxz(), dvec4(4_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.wzxw(), dvec4(4_f64, 3_f64, 1_f64, 4_f64)); assert_eq!(v.wzyx(), dvec4(4_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.wzyy(), dvec4(4_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.wzyz(), dvec4(4_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.wzyw(), dvec4(4_f64, 3_f64, 2_f64, 4_f64)); assert_eq!(v.wzzx(), dvec4(4_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.wzzy(), dvec4(4_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.wzzz(), dvec4(4_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.wzzw(), dvec4(4_f64, 3_f64, 3_f64, 4_f64)); assert_eq!(v.wzwx(), dvec4(4_f64, 3_f64, 4_f64, 1_f64)); assert_eq!(v.wzwy(), dvec4(4_f64, 3_f64, 4_f64, 2_f64)); assert_eq!(v.wzwz(), dvec4(4_f64, 3_f64, 4_f64, 3_f64)); assert_eq!(v.wzww(), dvec4(4_f64, 3_f64, 4_f64, 4_f64)); assert_eq!(v.wwxx(), dvec4(4_f64, 4_f64, 1_f64, 1_f64)); assert_eq!(v.wwxy(), dvec4(4_f64, 4_f64, 1_f64, 2_f64)); assert_eq!(v.wwxz(), dvec4(4_f64, 4_f64, 1_f64, 3_f64)); assert_eq!(v.wwxw(), dvec4(4_f64, 4_f64, 1_f64, 4_f64)); assert_eq!(v.wwyx(), dvec4(4_f64, 4_f64, 2_f64, 1_f64)); assert_eq!(v.wwyy(), dvec4(4_f64, 4_f64, 2_f64, 2_f64)); assert_eq!(v.wwyz(), dvec4(4_f64, 4_f64, 2_f64, 3_f64)); assert_eq!(v.wwyw(), dvec4(4_f64, 4_f64, 2_f64, 4_f64)); assert_eq!(v.wwzx(), dvec4(4_f64, 4_f64, 3_f64, 1_f64)); assert_eq!(v.wwzy(), dvec4(4_f64, 4_f64, 3_f64, 2_f64)); assert_eq!(v.wwzz(), dvec4(4_f64, 4_f64, 3_f64, 3_f64)); assert_eq!(v.wwzw(), dvec4(4_f64, 4_f64, 3_f64, 4_f64)); assert_eq!(v.wwwx(), dvec4(4_f64, 4_f64, 4_f64, 1_f64)); assert_eq!(v.wwwy(), dvec4(4_f64, 4_f64, 4_f64, 2_f64)); assert_eq!(v.wwwz(), dvec4(4_f64, 4_f64, 4_f64, 3_f64)); assert_eq!(v.wwww(), dvec4(4_f64, 4_f64, 4_f64, 4_f64)); assert_eq!(v.xxx(), dvec3(1_f64, 1_f64, 1_f64)); assert_eq!(v.xxy(), dvec3(1_f64, 1_f64, 2_f64)); assert_eq!(v.xxz(), dvec3(1_f64, 1_f64, 3_f64)); assert_eq!(v.xxw(), dvec3(1_f64, 1_f64, 4_f64)); assert_eq!(v.xyx(), dvec3(1_f64, 2_f64, 1_f64)); assert_eq!(v.xyy(), dvec3(1_f64, 2_f64, 2_f64)); assert_eq!(v.xyz(), dvec3(1_f64, 2_f64, 3_f64)); assert_eq!(v.xyw(), dvec3(1_f64, 2_f64, 4_f64)); assert_eq!(v.xzx(), dvec3(1_f64, 3_f64, 1_f64)); assert_eq!(v.xzy(), dvec3(1_f64, 3_f64, 2_f64)); assert_eq!(v.xzz(), dvec3(1_f64, 3_f64, 3_f64)); assert_eq!(v.xzw(), dvec3(1_f64, 3_f64, 4_f64)); assert_eq!(v.xwx(), dvec3(1_f64, 4_f64, 1_f64)); assert_eq!(v.xwy(), dvec3(1_f64, 4_f64, 2_f64)); assert_eq!(v.xwz(), dvec3(1_f64, 4_f64, 3_f64)); assert_eq!(v.xww(), dvec3(1_f64, 4_f64, 4_f64)); assert_eq!(v.yxx(), dvec3(2_f64, 1_f64, 1_f64)); assert_eq!(v.yxy(), dvec3(2_f64, 1_f64, 2_f64)); assert_eq!(v.yxz(), dvec3(2_f64, 1_f64, 3_f64)); assert_eq!(v.yxw(), dvec3(2_f64, 1_f64, 4_f64)); assert_eq!(v.yyx(), dvec3(2_f64, 2_f64, 1_f64)); assert_eq!(v.yyy(), dvec3(2_f64, 2_f64, 2_f64)); assert_eq!(v.yyz(), dvec3(2_f64, 2_f64, 3_f64)); assert_eq!(v.yyw(), dvec3(2_f64, 2_f64, 4_f64)); assert_eq!(v.yzx(), dvec3(2_f64, 3_f64, 1_f64)); assert_eq!(v.yzy(), dvec3(2_f64, 3_f64, 2_f64)); assert_eq!(v.yzz(), dvec3(2_f64, 3_f64, 3_f64)); assert_eq!(v.yzw(), dvec3(2_f64, 3_f64, 4_f64)); assert_eq!(v.ywx(), dvec3(2_f64, 4_f64, 1_f64)); assert_eq!(v.ywy(), dvec3(2_f64, 4_f64, 2_f64)); assert_eq!(v.ywz(), dvec3(2_f64, 4_f64, 3_f64)); assert_eq!(v.yww(), dvec3(2_f64, 4_f64, 4_f64)); assert_eq!(v.zxx(), dvec3(3_f64, 1_f64, 1_f64)); assert_eq!(v.zxy(), dvec3(3_f64, 1_f64, 2_f64)); assert_eq!(v.zxz(), dvec3(3_f64, 1_f64, 3_f64)); assert_eq!(v.zxw(), dvec3(3_f64, 1_f64, 4_f64)); assert_eq!(v.zyx(), dvec3(3_f64, 2_f64, 1_f64)); assert_eq!(v.zyy(), dvec3(3_f64, 2_f64, 2_f64)); assert_eq!(v.zyz(), dvec3(3_f64, 2_f64, 3_f64)); assert_eq!(v.zyw(), dvec3(3_f64, 2_f64, 4_f64)); assert_eq!(v.zzx(), dvec3(3_f64, 3_f64, 1_f64)); assert_eq!(v.zzy(), dvec3(3_f64, 3_f64, 2_f64)); assert_eq!(v.zzz(), dvec3(3_f64, 3_f64, 3_f64)); assert_eq!(v.zzw(), dvec3(3_f64, 3_f64, 4_f64)); assert_eq!(v.zwx(), dvec3(3_f64, 4_f64, 1_f64)); assert_eq!(v.zwy(), dvec3(3_f64, 4_f64, 2_f64)); assert_eq!(v.zwz(), dvec3(3_f64, 4_f64, 3_f64)); assert_eq!(v.zww(), dvec3(3_f64, 4_f64, 4_f64)); assert_eq!(v.wxx(), dvec3(4_f64, 1_f64, 1_f64)); assert_eq!(v.wxy(), dvec3(4_f64, 1_f64, 2_f64)); assert_eq!(v.wxz(), dvec3(4_f64, 1_f64, 3_f64)); assert_eq!(v.wxw(), dvec3(4_f64, 1_f64, 4_f64)); assert_eq!(v.wyx(), dvec3(4_f64, 2_f64, 1_f64)); assert_eq!(v.wyy(), dvec3(4_f64, 2_f64, 2_f64)); assert_eq!(v.wyz(), dvec3(4_f64, 2_f64, 3_f64)); assert_eq!(v.wyw(), dvec3(4_f64, 2_f64, 4_f64)); assert_eq!(v.wzx(), dvec3(4_f64, 3_f64, 1_f64)); assert_eq!(v.wzy(), dvec3(4_f64, 3_f64, 2_f64)); assert_eq!(v.wzz(), dvec3(4_f64, 3_f64, 3_f64)); assert_eq!(v.wzw(), dvec3(4_f64, 3_f64, 4_f64)); assert_eq!(v.wwx(), dvec3(4_f64, 4_f64, 1_f64)); assert_eq!(v.wwy(), dvec3(4_f64, 4_f64, 2_f64)); assert_eq!(v.wwz(), dvec3(4_f64, 4_f64, 3_f64)); assert_eq!(v.www(), dvec3(4_f64, 4_f64, 4_f64)); assert_eq!(v.with_xyz(rhs3), dvec4(11_f64, 12_f64, 13_f64, 4_f64)); assert_eq!(v.with_xyw(rhs3), dvec4(11_f64, 12_f64, 3_f64, 13_f64)); assert_eq!(v.with_xzy(rhs3), dvec4(11_f64, 13_f64, 12_f64, 4_f64)); assert_eq!(v.with_xzw(rhs3), dvec4(11_f64, 2_f64, 12_f64, 13_f64)); assert_eq!(v.with_xwy(rhs3), dvec4(11_f64, 13_f64, 3_f64, 12_f64)); assert_eq!(v.with_xwz(rhs3), dvec4(11_f64, 2_f64, 13_f64, 12_f64)); assert_eq!(v.with_yxz(rhs3), dvec4(12_f64, 11_f64, 13_f64, 4_f64)); assert_eq!(v.with_yxw(rhs3), dvec4(12_f64, 11_f64, 3_f64, 13_f64)); assert_eq!(v.with_yzx(rhs3), dvec4(13_f64, 11_f64, 12_f64, 4_f64)); assert_eq!(v.with_yzw(rhs3), dvec4(1_f64, 11_f64, 12_f64, 13_f64)); assert_eq!(v.with_ywx(rhs3), dvec4(13_f64, 11_f64, 3_f64, 12_f64)); assert_eq!(v.with_ywz(rhs3), dvec4(1_f64, 11_f64, 13_f64, 12_f64)); assert_eq!(v.with_zxy(rhs3), dvec4(12_f64, 13_f64, 11_f64, 4_f64)); assert_eq!(v.with_zxw(rhs3), dvec4(12_f64, 2_f64, 11_f64, 13_f64)); assert_eq!(v.with_zyx(rhs3), dvec4(13_f64, 12_f64, 11_f64, 4_f64)); assert_eq!(v.with_zyw(rhs3), dvec4(1_f64, 12_f64, 11_f64, 13_f64)); assert_eq!(v.with_zwx(rhs3), dvec4(13_f64, 2_f64, 11_f64, 12_f64)); assert_eq!(v.with_zwy(rhs3), dvec4(1_f64, 13_f64, 11_f64, 12_f64)); assert_eq!(v.with_wxy(rhs3), dvec4(12_f64, 13_f64, 3_f64, 11_f64)); assert_eq!(v.with_wxz(rhs3), dvec4(12_f64, 2_f64, 13_f64, 11_f64)); assert_eq!(v.with_wyx(rhs3), dvec4(13_f64, 12_f64, 3_f64, 11_f64)); assert_eq!(v.with_wyz(rhs3), dvec4(1_f64, 12_f64, 13_f64, 11_f64)); assert_eq!(v.with_wzx(rhs3), dvec4(13_f64, 2_f64, 12_f64, 11_f64)); assert_eq!(v.with_wzy(rhs3), dvec4(1_f64, 13_f64, 12_f64, 11_f64)); assert_eq!(v.xx(), dvec2(1_f64, 1_f64)); assert_eq!(v.xy(), dvec2(1_f64, 2_f64)); assert_eq!(v.xz(), dvec2(1_f64, 3_f64)); assert_eq!(v.xw(), dvec2(1_f64, 4_f64)); assert_eq!(v.yx(), dvec2(2_f64, 1_f64)); assert_eq!(v.yy(), dvec2(2_f64, 2_f64)); assert_eq!(v.yz(), dvec2(2_f64, 3_f64)); assert_eq!(v.yw(), dvec2(2_f64, 4_f64)); assert_eq!(v.zx(), dvec2(3_f64, 1_f64)); assert_eq!(v.zy(), dvec2(3_f64, 2_f64)); assert_eq!(v.zz(), dvec2(3_f64, 3_f64)); assert_eq!(v.zw(), dvec2(3_f64, 4_f64)); assert_eq!(v.wx(), dvec2(4_f64, 1_f64)); assert_eq!(v.wy(), dvec2(4_f64, 2_f64)); assert_eq!(v.wz(), dvec2(4_f64, 3_f64)); assert_eq!(v.ww(), dvec2(4_f64, 4_f64)); assert_eq!(v.with_xy(rhs2), dvec4(11_f64, 12_f64, 3_f64, 4_f64)); assert_eq!(v.with_xz(rhs2), dvec4(11_f64, 2_f64, 12_f64, 4_f64)); assert_eq!(v.with_xw(rhs2), dvec4(11_f64, 2_f64, 3_f64, 12_f64)); assert_eq!(v.with_yx(rhs2), dvec4(12_f64, 11_f64, 3_f64, 4_f64)); assert_eq!(v.with_yz(rhs2), dvec4(1_f64, 11_f64, 12_f64, 4_f64)); assert_eq!(v.with_yw(rhs2), dvec4(1_f64, 11_f64, 3_f64, 12_f64)); assert_eq!(v.with_zx(rhs2), dvec4(12_f64, 2_f64, 11_f64, 4_f64)); assert_eq!(v.with_zy(rhs2), dvec4(1_f64, 12_f64, 11_f64, 4_f64)); assert_eq!(v.with_zw(rhs2), dvec4(1_f64, 2_f64, 11_f64, 12_f64)); assert_eq!(v.with_wx(rhs2), dvec4(12_f64, 2_f64, 3_f64, 11_f64)); assert_eq!(v.with_wy(rhs2), dvec4(1_f64, 12_f64, 3_f64, 11_f64)); assert_eq!(v.with_wz(rhs2), dvec4(1_f64, 2_f64, 12_f64, 11_f64)); }); glam_test!(test_dvec3_swizzles, { let v = dvec3(1_f64, 2_f64, 3_f64); let rhs2 = dvec2(11_f64, 12_f64); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), dvec4(1_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.xxxy(), dvec4(1_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.xxxz(), dvec4(1_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.xxyx(), dvec4(1_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.xxyy(), dvec4(1_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.xxyz(), dvec4(1_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.xxzx(), dvec4(1_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.xxzy(), dvec4(1_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.xxzz(), dvec4(1_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.xyxx(), dvec4(1_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.xyxy(), dvec4(1_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.xyxz(), dvec4(1_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.xyyx(), dvec4(1_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.xyyy(), dvec4(1_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.xyyz(), dvec4(1_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.xyzx(), dvec4(1_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.xyzy(), dvec4(1_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.xyzz(), dvec4(1_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.xzxx(), dvec4(1_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.xzxy(), dvec4(1_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.xzxz(), dvec4(1_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.xzyx(), dvec4(1_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.xzyy(), dvec4(1_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.xzyz(), dvec4(1_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.xzzx(), dvec4(1_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.xzzy(), dvec4(1_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.xzzz(), dvec4(1_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.yxxx(), dvec4(2_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.yxxy(), dvec4(2_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.yxxz(), dvec4(2_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.yxyx(), dvec4(2_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.yxyy(), dvec4(2_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.yxyz(), dvec4(2_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.yxzx(), dvec4(2_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.yxzy(), dvec4(2_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.yxzz(), dvec4(2_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.yyxx(), dvec4(2_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.yyxy(), dvec4(2_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.yyxz(), dvec4(2_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.yyyx(), dvec4(2_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.yyyy(), dvec4(2_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.yyyz(), dvec4(2_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.yyzx(), dvec4(2_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.yyzy(), dvec4(2_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.yyzz(), dvec4(2_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.yzxx(), dvec4(2_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.yzxy(), dvec4(2_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.yzxz(), dvec4(2_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.yzyx(), dvec4(2_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.yzyy(), dvec4(2_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.yzyz(), dvec4(2_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.yzzx(), dvec4(2_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.yzzy(), dvec4(2_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.yzzz(), dvec4(2_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.zxxx(), dvec4(3_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.zxxy(), dvec4(3_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.zxxz(), dvec4(3_f64, 1_f64, 1_f64, 3_f64)); assert_eq!(v.zxyx(), dvec4(3_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.zxyy(), dvec4(3_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.zxyz(), dvec4(3_f64, 1_f64, 2_f64, 3_f64)); assert_eq!(v.zxzx(), dvec4(3_f64, 1_f64, 3_f64, 1_f64)); assert_eq!(v.zxzy(), dvec4(3_f64, 1_f64, 3_f64, 2_f64)); assert_eq!(v.zxzz(), dvec4(3_f64, 1_f64, 3_f64, 3_f64)); assert_eq!(v.zyxx(), dvec4(3_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.zyxy(), dvec4(3_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.zyxz(), dvec4(3_f64, 2_f64, 1_f64, 3_f64)); assert_eq!(v.zyyx(), dvec4(3_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.zyyy(), dvec4(3_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.zyyz(), dvec4(3_f64, 2_f64, 2_f64, 3_f64)); assert_eq!(v.zyzx(), dvec4(3_f64, 2_f64, 3_f64, 1_f64)); assert_eq!(v.zyzy(), dvec4(3_f64, 2_f64, 3_f64, 2_f64)); assert_eq!(v.zyzz(), dvec4(3_f64, 2_f64, 3_f64, 3_f64)); assert_eq!(v.zzxx(), dvec4(3_f64, 3_f64, 1_f64, 1_f64)); assert_eq!(v.zzxy(), dvec4(3_f64, 3_f64, 1_f64, 2_f64)); assert_eq!(v.zzxz(), dvec4(3_f64, 3_f64, 1_f64, 3_f64)); assert_eq!(v.zzyx(), dvec4(3_f64, 3_f64, 2_f64, 1_f64)); assert_eq!(v.zzyy(), dvec4(3_f64, 3_f64, 2_f64, 2_f64)); assert_eq!(v.zzyz(), dvec4(3_f64, 3_f64, 2_f64, 3_f64)); assert_eq!(v.zzzx(), dvec4(3_f64, 3_f64, 3_f64, 1_f64)); assert_eq!(v.zzzy(), dvec4(3_f64, 3_f64, 3_f64, 2_f64)); assert_eq!(v.zzzz(), dvec4(3_f64, 3_f64, 3_f64, 3_f64)); assert_eq!(v.xxx(), dvec3(1_f64, 1_f64, 1_f64)); assert_eq!(v.xxy(), dvec3(1_f64, 1_f64, 2_f64)); assert_eq!(v.xxz(), dvec3(1_f64, 1_f64, 3_f64)); assert_eq!(v.xyx(), dvec3(1_f64, 2_f64, 1_f64)); assert_eq!(v.xyy(), dvec3(1_f64, 2_f64, 2_f64)); assert_eq!(v.xzx(), dvec3(1_f64, 3_f64, 1_f64)); assert_eq!(v.xzy(), dvec3(1_f64, 3_f64, 2_f64)); assert_eq!(v.xzz(), dvec3(1_f64, 3_f64, 3_f64)); assert_eq!(v.yxx(), dvec3(2_f64, 1_f64, 1_f64)); assert_eq!(v.yxy(), dvec3(2_f64, 1_f64, 2_f64)); assert_eq!(v.yxz(), dvec3(2_f64, 1_f64, 3_f64)); assert_eq!(v.yyx(), dvec3(2_f64, 2_f64, 1_f64)); assert_eq!(v.yyy(), dvec3(2_f64, 2_f64, 2_f64)); assert_eq!(v.yyz(), dvec3(2_f64, 2_f64, 3_f64)); assert_eq!(v.yzx(), dvec3(2_f64, 3_f64, 1_f64)); assert_eq!(v.yzy(), dvec3(2_f64, 3_f64, 2_f64)); assert_eq!(v.yzz(), dvec3(2_f64, 3_f64, 3_f64)); assert_eq!(v.zxx(), dvec3(3_f64, 1_f64, 1_f64)); assert_eq!(v.zxy(), dvec3(3_f64, 1_f64, 2_f64)); assert_eq!(v.zxz(), dvec3(3_f64, 1_f64, 3_f64)); assert_eq!(v.zyx(), dvec3(3_f64, 2_f64, 1_f64)); assert_eq!(v.zyy(), dvec3(3_f64, 2_f64, 2_f64)); assert_eq!(v.zyz(), dvec3(3_f64, 2_f64, 3_f64)); assert_eq!(v.zzx(), dvec3(3_f64, 3_f64, 1_f64)); assert_eq!(v.zzy(), dvec3(3_f64, 3_f64, 2_f64)); assert_eq!(v.zzz(), dvec3(3_f64, 3_f64, 3_f64)); assert_eq!(v.xx(), dvec2(1_f64, 1_f64)); assert_eq!(v.xy(), dvec2(1_f64, 2_f64)); assert_eq!(v.xz(), dvec2(1_f64, 3_f64)); assert_eq!(v.yx(), dvec2(2_f64, 1_f64)); assert_eq!(v.yy(), dvec2(2_f64, 2_f64)); assert_eq!(v.yz(), dvec2(2_f64, 3_f64)); assert_eq!(v.zx(), dvec2(3_f64, 1_f64)); assert_eq!(v.zy(), dvec2(3_f64, 2_f64)); assert_eq!(v.zz(), dvec2(3_f64, 3_f64)); assert_eq!(v.with_xy(rhs2), dvec3(11_f64, 12_f64, 3_f64)); assert_eq!(v.with_xz(rhs2), dvec3(11_f64, 2_f64, 12_f64)); assert_eq!(v.with_yx(rhs2), dvec3(12_f64, 11_f64, 3_f64)); assert_eq!(v.with_yz(rhs2), dvec3(1_f64, 11_f64, 12_f64)); assert_eq!(v.with_zx(rhs2), dvec3(12_f64, 2_f64, 11_f64)); assert_eq!(v.with_zy(rhs2), dvec3(1_f64, 12_f64, 11_f64)); }); glam_test!(test_dvec2_swizzles, { let v = dvec2(1_f64, 2_f64); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), dvec4(1_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.xxxy(), dvec4(1_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.xxyx(), dvec4(1_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.xxyy(), dvec4(1_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.xyxx(), dvec4(1_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.xyxy(), dvec4(1_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.xyyx(), dvec4(1_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.xyyy(), dvec4(1_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.yxxx(), dvec4(2_f64, 1_f64, 1_f64, 1_f64)); assert_eq!(v.yxxy(), dvec4(2_f64, 1_f64, 1_f64, 2_f64)); assert_eq!(v.yxyx(), dvec4(2_f64, 1_f64, 2_f64, 1_f64)); assert_eq!(v.yxyy(), dvec4(2_f64, 1_f64, 2_f64, 2_f64)); assert_eq!(v.yyxx(), dvec4(2_f64, 2_f64, 1_f64, 1_f64)); assert_eq!(v.yyxy(), dvec4(2_f64, 2_f64, 1_f64, 2_f64)); assert_eq!(v.yyyx(), dvec4(2_f64, 2_f64, 2_f64, 1_f64)); assert_eq!(v.yyyy(), dvec4(2_f64, 2_f64, 2_f64, 2_f64)); assert_eq!(v.xxx(), dvec3(1_f64, 1_f64, 1_f64)); assert_eq!(v.xxy(), dvec3(1_f64, 1_f64, 2_f64)); assert_eq!(v.xyx(), dvec3(1_f64, 2_f64, 1_f64)); assert_eq!(v.xyy(), dvec3(1_f64, 2_f64, 2_f64)); assert_eq!(v.yxx(), dvec3(2_f64, 1_f64, 1_f64)); assert_eq!(v.yxy(), dvec3(2_f64, 1_f64, 2_f64)); assert_eq!(v.yyx(), dvec3(2_f64, 2_f64, 1_f64)); assert_eq!(v.yyy(), dvec3(2_f64, 2_f64, 2_f64)); assert_eq!(v.xx(), dvec2(1_f64, 1_f64)); assert_eq!(v.yx(), dvec2(2_f64, 1_f64)); assert_eq!(v.yy(), dvec2(2_f64, 2_f64)); }); glam-0.30.1/tests/swizzles_i16.rs000064400000000000000000000773051046102023000147220ustar 00000000000000// 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); let rhs3 = i16vec3(11_i16, 12_i16, 13_i16); let rhs2 = i16vec2(11_i16, 12_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.with_xyz(rhs3), i16vec4(11_i16, 12_i16, 13_i16, 4_i16)); assert_eq!(v.with_xyw(rhs3), i16vec4(11_i16, 12_i16, 3_i16, 13_i16)); assert_eq!(v.with_xzy(rhs3), i16vec4(11_i16, 13_i16, 12_i16, 4_i16)); assert_eq!(v.with_xzw(rhs3), i16vec4(11_i16, 2_i16, 12_i16, 13_i16)); assert_eq!(v.with_xwy(rhs3), i16vec4(11_i16, 13_i16, 3_i16, 12_i16)); assert_eq!(v.with_xwz(rhs3), i16vec4(11_i16, 2_i16, 13_i16, 12_i16)); assert_eq!(v.with_yxz(rhs3), i16vec4(12_i16, 11_i16, 13_i16, 4_i16)); assert_eq!(v.with_yxw(rhs3), i16vec4(12_i16, 11_i16, 3_i16, 13_i16)); assert_eq!(v.with_yzx(rhs3), i16vec4(13_i16, 11_i16, 12_i16, 4_i16)); assert_eq!(v.with_yzw(rhs3), i16vec4(1_i16, 11_i16, 12_i16, 13_i16)); assert_eq!(v.with_ywx(rhs3), i16vec4(13_i16, 11_i16, 3_i16, 12_i16)); assert_eq!(v.with_ywz(rhs3), i16vec4(1_i16, 11_i16, 13_i16, 12_i16)); assert_eq!(v.with_zxy(rhs3), i16vec4(12_i16, 13_i16, 11_i16, 4_i16)); assert_eq!(v.with_zxw(rhs3), i16vec4(12_i16, 2_i16, 11_i16, 13_i16)); assert_eq!(v.with_zyx(rhs3), i16vec4(13_i16, 12_i16, 11_i16, 4_i16)); assert_eq!(v.with_zyw(rhs3), i16vec4(1_i16, 12_i16, 11_i16, 13_i16)); assert_eq!(v.with_zwx(rhs3), i16vec4(13_i16, 2_i16, 11_i16, 12_i16)); assert_eq!(v.with_zwy(rhs3), i16vec4(1_i16, 13_i16, 11_i16, 12_i16)); assert_eq!(v.with_wxy(rhs3), i16vec4(12_i16, 13_i16, 3_i16, 11_i16)); assert_eq!(v.with_wxz(rhs3), i16vec4(12_i16, 2_i16, 13_i16, 11_i16)); assert_eq!(v.with_wyx(rhs3), i16vec4(13_i16, 12_i16, 3_i16, 11_i16)); assert_eq!(v.with_wyz(rhs3), i16vec4(1_i16, 12_i16, 13_i16, 11_i16)); assert_eq!(v.with_wzx(rhs3), i16vec4(13_i16, 2_i16, 12_i16, 11_i16)); assert_eq!(v.with_wzy(rhs3), i16vec4(1_i16, 13_i16, 12_i16, 11_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)); assert_eq!(v.with_xy(rhs2), i16vec4(11_i16, 12_i16, 3_i16, 4_i16)); assert_eq!(v.with_xz(rhs2), i16vec4(11_i16, 2_i16, 12_i16, 4_i16)); assert_eq!(v.with_xw(rhs2), i16vec4(11_i16, 2_i16, 3_i16, 12_i16)); assert_eq!(v.with_yx(rhs2), i16vec4(12_i16, 11_i16, 3_i16, 4_i16)); assert_eq!(v.with_yz(rhs2), i16vec4(1_i16, 11_i16, 12_i16, 4_i16)); assert_eq!(v.with_yw(rhs2), i16vec4(1_i16, 11_i16, 3_i16, 12_i16)); assert_eq!(v.with_zx(rhs2), i16vec4(12_i16, 2_i16, 11_i16, 4_i16)); assert_eq!(v.with_zy(rhs2), i16vec4(1_i16, 12_i16, 11_i16, 4_i16)); assert_eq!(v.with_zw(rhs2), i16vec4(1_i16, 2_i16, 11_i16, 12_i16)); assert_eq!(v.with_wx(rhs2), i16vec4(12_i16, 2_i16, 3_i16, 11_i16)); assert_eq!(v.with_wy(rhs2), i16vec4(1_i16, 12_i16, 3_i16, 11_i16)); assert_eq!(v.with_wz(rhs2), i16vec4(1_i16, 2_i16, 12_i16, 11_i16)); }); glam_test!(test_i16vec3_swizzles, { let v = i16vec3(1_i16, 2_i16, 3_i16); let rhs2 = i16vec2(11_i16, 12_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)); assert_eq!(v.with_xy(rhs2), i16vec3(11_i16, 12_i16, 3_i16)); assert_eq!(v.with_xz(rhs2), i16vec3(11_i16, 2_i16, 12_i16)); assert_eq!(v.with_yx(rhs2), i16vec3(12_i16, 11_i16, 3_i16)); assert_eq!(v.with_yz(rhs2), i16vec3(1_i16, 11_i16, 12_i16)); assert_eq!(v.with_zx(rhs2), i16vec3(12_i16, 2_i16, 11_i16)); assert_eq!(v.with_zy(rhs2), i16vec3(1_i16, 12_i16, 11_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)); }); glam-0.30.1/tests/swizzles_i32.rs000064400000000000000000000752431046102023000147170ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_ivec4_swizzles, { let v = ivec4(1_i32, 2_i32, 3_i32, 4_i32); let rhs3 = ivec3(11_i32, 12_i32, 13_i32); let rhs2 = ivec2(11_i32, 12_i32); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), ivec4(1_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.xxxy(), ivec4(1_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.xxxz(), ivec4(1_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.xxxw(), ivec4(1_i32, 1_i32, 1_i32, 4_i32)); assert_eq!(v.xxyx(), ivec4(1_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.xxyy(), ivec4(1_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.xxyz(), ivec4(1_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.xxyw(), ivec4(1_i32, 1_i32, 2_i32, 4_i32)); assert_eq!(v.xxzx(), ivec4(1_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.xxzy(), ivec4(1_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.xxzz(), ivec4(1_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.xxzw(), ivec4(1_i32, 1_i32, 3_i32, 4_i32)); assert_eq!(v.xxwx(), ivec4(1_i32, 1_i32, 4_i32, 1_i32)); assert_eq!(v.xxwy(), ivec4(1_i32, 1_i32, 4_i32, 2_i32)); assert_eq!(v.xxwz(), ivec4(1_i32, 1_i32, 4_i32, 3_i32)); assert_eq!(v.xxww(), ivec4(1_i32, 1_i32, 4_i32, 4_i32)); assert_eq!(v.xyxx(), ivec4(1_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.xyxy(), ivec4(1_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.xyxz(), ivec4(1_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.xyxw(), ivec4(1_i32, 2_i32, 1_i32, 4_i32)); assert_eq!(v.xyyx(), ivec4(1_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.xyyy(), ivec4(1_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.xyyz(), ivec4(1_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.xyyw(), ivec4(1_i32, 2_i32, 2_i32, 4_i32)); assert_eq!(v.xyzx(), ivec4(1_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.xyzy(), ivec4(1_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.xyzz(), ivec4(1_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.xywx(), ivec4(1_i32, 2_i32, 4_i32, 1_i32)); assert_eq!(v.xywy(), ivec4(1_i32, 2_i32, 4_i32, 2_i32)); assert_eq!(v.xywz(), ivec4(1_i32, 2_i32, 4_i32, 3_i32)); assert_eq!(v.xyww(), ivec4(1_i32, 2_i32, 4_i32, 4_i32)); assert_eq!(v.xzxx(), ivec4(1_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.xzxy(), ivec4(1_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.xzxz(), ivec4(1_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.xzxw(), ivec4(1_i32, 3_i32, 1_i32, 4_i32)); assert_eq!(v.xzyx(), ivec4(1_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.xzyy(), ivec4(1_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.xzyz(), ivec4(1_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.xzyw(), ivec4(1_i32, 3_i32, 2_i32, 4_i32)); assert_eq!(v.xzzx(), ivec4(1_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.xzzy(), ivec4(1_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.xzzz(), ivec4(1_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.xzzw(), ivec4(1_i32, 3_i32, 3_i32, 4_i32)); assert_eq!(v.xzwx(), ivec4(1_i32, 3_i32, 4_i32, 1_i32)); assert_eq!(v.xzwy(), ivec4(1_i32, 3_i32, 4_i32, 2_i32)); assert_eq!(v.xzwz(), ivec4(1_i32, 3_i32, 4_i32, 3_i32)); assert_eq!(v.xzww(), ivec4(1_i32, 3_i32, 4_i32, 4_i32)); assert_eq!(v.xwxx(), ivec4(1_i32, 4_i32, 1_i32, 1_i32)); assert_eq!(v.xwxy(), ivec4(1_i32, 4_i32, 1_i32, 2_i32)); assert_eq!(v.xwxz(), ivec4(1_i32, 4_i32, 1_i32, 3_i32)); assert_eq!(v.xwxw(), ivec4(1_i32, 4_i32, 1_i32, 4_i32)); assert_eq!(v.xwyx(), ivec4(1_i32, 4_i32, 2_i32, 1_i32)); assert_eq!(v.xwyy(), ivec4(1_i32, 4_i32, 2_i32, 2_i32)); assert_eq!(v.xwyz(), ivec4(1_i32, 4_i32, 2_i32, 3_i32)); assert_eq!(v.xwyw(), ivec4(1_i32, 4_i32, 2_i32, 4_i32)); assert_eq!(v.xwzx(), ivec4(1_i32, 4_i32, 3_i32, 1_i32)); assert_eq!(v.xwzy(), ivec4(1_i32, 4_i32, 3_i32, 2_i32)); assert_eq!(v.xwzz(), ivec4(1_i32, 4_i32, 3_i32, 3_i32)); assert_eq!(v.xwzw(), ivec4(1_i32, 4_i32, 3_i32, 4_i32)); assert_eq!(v.xwwx(), ivec4(1_i32, 4_i32, 4_i32, 1_i32)); assert_eq!(v.xwwy(), ivec4(1_i32, 4_i32, 4_i32, 2_i32)); assert_eq!(v.xwwz(), ivec4(1_i32, 4_i32, 4_i32, 3_i32)); assert_eq!(v.xwww(), ivec4(1_i32, 4_i32, 4_i32, 4_i32)); assert_eq!(v.yxxx(), ivec4(2_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.yxxy(), ivec4(2_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.yxxz(), ivec4(2_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.yxxw(), ivec4(2_i32, 1_i32, 1_i32, 4_i32)); assert_eq!(v.yxyx(), ivec4(2_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.yxyy(), ivec4(2_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.yxyz(), ivec4(2_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.yxyw(), ivec4(2_i32, 1_i32, 2_i32, 4_i32)); assert_eq!(v.yxzx(), ivec4(2_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.yxzy(), ivec4(2_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.yxzz(), ivec4(2_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.yxzw(), ivec4(2_i32, 1_i32, 3_i32, 4_i32)); assert_eq!(v.yxwx(), ivec4(2_i32, 1_i32, 4_i32, 1_i32)); assert_eq!(v.yxwy(), ivec4(2_i32, 1_i32, 4_i32, 2_i32)); assert_eq!(v.yxwz(), ivec4(2_i32, 1_i32, 4_i32, 3_i32)); assert_eq!(v.yxww(), ivec4(2_i32, 1_i32, 4_i32, 4_i32)); assert_eq!(v.yyxx(), ivec4(2_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.yyxy(), ivec4(2_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.yyxz(), ivec4(2_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.yyxw(), ivec4(2_i32, 2_i32, 1_i32, 4_i32)); assert_eq!(v.yyyx(), ivec4(2_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.yyyy(), ivec4(2_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.yyyz(), ivec4(2_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.yyyw(), ivec4(2_i32, 2_i32, 2_i32, 4_i32)); assert_eq!(v.yyzx(), ivec4(2_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.yyzy(), ivec4(2_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.yyzz(), ivec4(2_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.yyzw(), ivec4(2_i32, 2_i32, 3_i32, 4_i32)); assert_eq!(v.yywx(), ivec4(2_i32, 2_i32, 4_i32, 1_i32)); assert_eq!(v.yywy(), ivec4(2_i32, 2_i32, 4_i32, 2_i32)); assert_eq!(v.yywz(), ivec4(2_i32, 2_i32, 4_i32, 3_i32)); assert_eq!(v.yyww(), ivec4(2_i32, 2_i32, 4_i32, 4_i32)); assert_eq!(v.yzxx(), ivec4(2_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.yzxy(), ivec4(2_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.yzxz(), ivec4(2_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.yzxw(), ivec4(2_i32, 3_i32, 1_i32, 4_i32)); assert_eq!(v.yzyx(), ivec4(2_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.yzyy(), ivec4(2_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.yzyz(), ivec4(2_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.yzyw(), ivec4(2_i32, 3_i32, 2_i32, 4_i32)); assert_eq!(v.yzzx(), ivec4(2_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.yzzy(), ivec4(2_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.yzzz(), ivec4(2_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.yzzw(), ivec4(2_i32, 3_i32, 3_i32, 4_i32)); assert_eq!(v.yzwx(), ivec4(2_i32, 3_i32, 4_i32, 1_i32)); assert_eq!(v.yzwy(), ivec4(2_i32, 3_i32, 4_i32, 2_i32)); assert_eq!(v.yzwz(), ivec4(2_i32, 3_i32, 4_i32, 3_i32)); assert_eq!(v.yzww(), ivec4(2_i32, 3_i32, 4_i32, 4_i32)); assert_eq!(v.ywxx(), ivec4(2_i32, 4_i32, 1_i32, 1_i32)); assert_eq!(v.ywxy(), ivec4(2_i32, 4_i32, 1_i32, 2_i32)); assert_eq!(v.ywxz(), ivec4(2_i32, 4_i32, 1_i32, 3_i32)); assert_eq!(v.ywxw(), ivec4(2_i32, 4_i32, 1_i32, 4_i32)); assert_eq!(v.ywyx(), ivec4(2_i32, 4_i32, 2_i32, 1_i32)); assert_eq!(v.ywyy(), ivec4(2_i32, 4_i32, 2_i32, 2_i32)); assert_eq!(v.ywyz(), ivec4(2_i32, 4_i32, 2_i32, 3_i32)); assert_eq!(v.ywyw(), ivec4(2_i32, 4_i32, 2_i32, 4_i32)); assert_eq!(v.ywzx(), ivec4(2_i32, 4_i32, 3_i32, 1_i32)); assert_eq!(v.ywzy(), ivec4(2_i32, 4_i32, 3_i32, 2_i32)); assert_eq!(v.ywzz(), ivec4(2_i32, 4_i32, 3_i32, 3_i32)); assert_eq!(v.ywzw(), ivec4(2_i32, 4_i32, 3_i32, 4_i32)); assert_eq!(v.ywwx(), ivec4(2_i32, 4_i32, 4_i32, 1_i32)); assert_eq!(v.ywwy(), ivec4(2_i32, 4_i32, 4_i32, 2_i32)); assert_eq!(v.ywwz(), ivec4(2_i32, 4_i32, 4_i32, 3_i32)); assert_eq!(v.ywww(), ivec4(2_i32, 4_i32, 4_i32, 4_i32)); assert_eq!(v.zxxx(), ivec4(3_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.zxxy(), ivec4(3_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.zxxz(), ivec4(3_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.zxxw(), ivec4(3_i32, 1_i32, 1_i32, 4_i32)); assert_eq!(v.zxyx(), ivec4(3_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.zxyy(), ivec4(3_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.zxyz(), ivec4(3_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.zxyw(), ivec4(3_i32, 1_i32, 2_i32, 4_i32)); assert_eq!(v.zxzx(), ivec4(3_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.zxzy(), ivec4(3_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.zxzz(), ivec4(3_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.zxzw(), ivec4(3_i32, 1_i32, 3_i32, 4_i32)); assert_eq!(v.zxwx(), ivec4(3_i32, 1_i32, 4_i32, 1_i32)); assert_eq!(v.zxwy(), ivec4(3_i32, 1_i32, 4_i32, 2_i32)); assert_eq!(v.zxwz(), ivec4(3_i32, 1_i32, 4_i32, 3_i32)); assert_eq!(v.zxww(), ivec4(3_i32, 1_i32, 4_i32, 4_i32)); assert_eq!(v.zyxx(), ivec4(3_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.zyxy(), ivec4(3_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.zyxz(), ivec4(3_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.zyxw(), ivec4(3_i32, 2_i32, 1_i32, 4_i32)); assert_eq!(v.zyyx(), ivec4(3_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.zyyy(), ivec4(3_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.zyyz(), ivec4(3_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.zyyw(), ivec4(3_i32, 2_i32, 2_i32, 4_i32)); assert_eq!(v.zyzx(), ivec4(3_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.zyzy(), ivec4(3_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.zyzz(), ivec4(3_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.zyzw(), ivec4(3_i32, 2_i32, 3_i32, 4_i32)); assert_eq!(v.zywx(), ivec4(3_i32, 2_i32, 4_i32, 1_i32)); assert_eq!(v.zywy(), ivec4(3_i32, 2_i32, 4_i32, 2_i32)); assert_eq!(v.zywz(), ivec4(3_i32, 2_i32, 4_i32, 3_i32)); assert_eq!(v.zyww(), ivec4(3_i32, 2_i32, 4_i32, 4_i32)); assert_eq!(v.zzxx(), ivec4(3_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.zzxy(), ivec4(3_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.zzxz(), ivec4(3_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.zzxw(), ivec4(3_i32, 3_i32, 1_i32, 4_i32)); assert_eq!(v.zzyx(), ivec4(3_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.zzyy(), ivec4(3_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.zzyz(), ivec4(3_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.zzyw(), ivec4(3_i32, 3_i32, 2_i32, 4_i32)); assert_eq!(v.zzzx(), ivec4(3_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.zzzy(), ivec4(3_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.zzzz(), ivec4(3_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.zzzw(), ivec4(3_i32, 3_i32, 3_i32, 4_i32)); assert_eq!(v.zzwx(), ivec4(3_i32, 3_i32, 4_i32, 1_i32)); assert_eq!(v.zzwy(), ivec4(3_i32, 3_i32, 4_i32, 2_i32)); assert_eq!(v.zzwz(), ivec4(3_i32, 3_i32, 4_i32, 3_i32)); assert_eq!(v.zzww(), ivec4(3_i32, 3_i32, 4_i32, 4_i32)); assert_eq!(v.zwxx(), ivec4(3_i32, 4_i32, 1_i32, 1_i32)); assert_eq!(v.zwxy(), ivec4(3_i32, 4_i32, 1_i32, 2_i32)); assert_eq!(v.zwxz(), ivec4(3_i32, 4_i32, 1_i32, 3_i32)); assert_eq!(v.zwxw(), ivec4(3_i32, 4_i32, 1_i32, 4_i32)); assert_eq!(v.zwyx(), ivec4(3_i32, 4_i32, 2_i32, 1_i32)); assert_eq!(v.zwyy(), ivec4(3_i32, 4_i32, 2_i32, 2_i32)); assert_eq!(v.zwyz(), ivec4(3_i32, 4_i32, 2_i32, 3_i32)); assert_eq!(v.zwyw(), ivec4(3_i32, 4_i32, 2_i32, 4_i32)); assert_eq!(v.zwzx(), ivec4(3_i32, 4_i32, 3_i32, 1_i32)); assert_eq!(v.zwzy(), ivec4(3_i32, 4_i32, 3_i32, 2_i32)); assert_eq!(v.zwzz(), ivec4(3_i32, 4_i32, 3_i32, 3_i32)); assert_eq!(v.zwzw(), ivec4(3_i32, 4_i32, 3_i32, 4_i32)); assert_eq!(v.zwwx(), ivec4(3_i32, 4_i32, 4_i32, 1_i32)); assert_eq!(v.zwwy(), ivec4(3_i32, 4_i32, 4_i32, 2_i32)); assert_eq!(v.zwwz(), ivec4(3_i32, 4_i32, 4_i32, 3_i32)); assert_eq!(v.zwww(), ivec4(3_i32, 4_i32, 4_i32, 4_i32)); assert_eq!(v.wxxx(), ivec4(4_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.wxxy(), ivec4(4_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.wxxz(), ivec4(4_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.wxxw(), ivec4(4_i32, 1_i32, 1_i32, 4_i32)); assert_eq!(v.wxyx(), ivec4(4_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.wxyy(), ivec4(4_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.wxyz(), ivec4(4_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.wxyw(), ivec4(4_i32, 1_i32, 2_i32, 4_i32)); assert_eq!(v.wxzx(), ivec4(4_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.wxzy(), ivec4(4_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.wxzz(), ivec4(4_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.wxzw(), ivec4(4_i32, 1_i32, 3_i32, 4_i32)); assert_eq!(v.wxwx(), ivec4(4_i32, 1_i32, 4_i32, 1_i32)); assert_eq!(v.wxwy(), ivec4(4_i32, 1_i32, 4_i32, 2_i32)); assert_eq!(v.wxwz(), ivec4(4_i32, 1_i32, 4_i32, 3_i32)); assert_eq!(v.wxww(), ivec4(4_i32, 1_i32, 4_i32, 4_i32)); assert_eq!(v.wyxx(), ivec4(4_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.wyxy(), ivec4(4_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.wyxz(), ivec4(4_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.wyxw(), ivec4(4_i32, 2_i32, 1_i32, 4_i32)); assert_eq!(v.wyyx(), ivec4(4_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.wyyy(), ivec4(4_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.wyyz(), ivec4(4_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.wyyw(), ivec4(4_i32, 2_i32, 2_i32, 4_i32)); assert_eq!(v.wyzx(), ivec4(4_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.wyzy(), ivec4(4_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.wyzz(), ivec4(4_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.wyzw(), ivec4(4_i32, 2_i32, 3_i32, 4_i32)); assert_eq!(v.wywx(), ivec4(4_i32, 2_i32, 4_i32, 1_i32)); assert_eq!(v.wywy(), ivec4(4_i32, 2_i32, 4_i32, 2_i32)); assert_eq!(v.wywz(), ivec4(4_i32, 2_i32, 4_i32, 3_i32)); assert_eq!(v.wyww(), ivec4(4_i32, 2_i32, 4_i32, 4_i32)); assert_eq!(v.wzxx(), ivec4(4_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.wzxy(), ivec4(4_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.wzxz(), ivec4(4_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.wzxw(), ivec4(4_i32, 3_i32, 1_i32, 4_i32)); assert_eq!(v.wzyx(), ivec4(4_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.wzyy(), ivec4(4_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.wzyz(), ivec4(4_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.wzyw(), ivec4(4_i32, 3_i32, 2_i32, 4_i32)); assert_eq!(v.wzzx(), ivec4(4_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.wzzy(), ivec4(4_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.wzzz(), ivec4(4_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.wzzw(), ivec4(4_i32, 3_i32, 3_i32, 4_i32)); assert_eq!(v.wzwx(), ivec4(4_i32, 3_i32, 4_i32, 1_i32)); assert_eq!(v.wzwy(), ivec4(4_i32, 3_i32, 4_i32, 2_i32)); assert_eq!(v.wzwz(), ivec4(4_i32, 3_i32, 4_i32, 3_i32)); assert_eq!(v.wzww(), ivec4(4_i32, 3_i32, 4_i32, 4_i32)); assert_eq!(v.wwxx(), ivec4(4_i32, 4_i32, 1_i32, 1_i32)); assert_eq!(v.wwxy(), ivec4(4_i32, 4_i32, 1_i32, 2_i32)); assert_eq!(v.wwxz(), ivec4(4_i32, 4_i32, 1_i32, 3_i32)); assert_eq!(v.wwxw(), ivec4(4_i32, 4_i32, 1_i32, 4_i32)); assert_eq!(v.wwyx(), ivec4(4_i32, 4_i32, 2_i32, 1_i32)); assert_eq!(v.wwyy(), ivec4(4_i32, 4_i32, 2_i32, 2_i32)); assert_eq!(v.wwyz(), ivec4(4_i32, 4_i32, 2_i32, 3_i32)); assert_eq!(v.wwyw(), ivec4(4_i32, 4_i32, 2_i32, 4_i32)); assert_eq!(v.wwzx(), ivec4(4_i32, 4_i32, 3_i32, 1_i32)); assert_eq!(v.wwzy(), ivec4(4_i32, 4_i32, 3_i32, 2_i32)); assert_eq!(v.wwzz(), ivec4(4_i32, 4_i32, 3_i32, 3_i32)); assert_eq!(v.wwzw(), ivec4(4_i32, 4_i32, 3_i32, 4_i32)); assert_eq!(v.wwwx(), ivec4(4_i32, 4_i32, 4_i32, 1_i32)); assert_eq!(v.wwwy(), ivec4(4_i32, 4_i32, 4_i32, 2_i32)); assert_eq!(v.wwwz(), ivec4(4_i32, 4_i32, 4_i32, 3_i32)); assert_eq!(v.wwww(), ivec4(4_i32, 4_i32, 4_i32, 4_i32)); assert_eq!(v.xxx(), ivec3(1_i32, 1_i32, 1_i32)); assert_eq!(v.xxy(), ivec3(1_i32, 1_i32, 2_i32)); assert_eq!(v.xxz(), ivec3(1_i32, 1_i32, 3_i32)); assert_eq!(v.xxw(), ivec3(1_i32, 1_i32, 4_i32)); assert_eq!(v.xyx(), ivec3(1_i32, 2_i32, 1_i32)); assert_eq!(v.xyy(), ivec3(1_i32, 2_i32, 2_i32)); assert_eq!(v.xyz(), ivec3(1_i32, 2_i32, 3_i32)); assert_eq!(v.xyw(), ivec3(1_i32, 2_i32, 4_i32)); assert_eq!(v.xzx(), ivec3(1_i32, 3_i32, 1_i32)); assert_eq!(v.xzy(), ivec3(1_i32, 3_i32, 2_i32)); assert_eq!(v.xzz(), ivec3(1_i32, 3_i32, 3_i32)); assert_eq!(v.xzw(), ivec3(1_i32, 3_i32, 4_i32)); assert_eq!(v.xwx(), ivec3(1_i32, 4_i32, 1_i32)); assert_eq!(v.xwy(), ivec3(1_i32, 4_i32, 2_i32)); assert_eq!(v.xwz(), ivec3(1_i32, 4_i32, 3_i32)); assert_eq!(v.xww(), ivec3(1_i32, 4_i32, 4_i32)); assert_eq!(v.yxx(), ivec3(2_i32, 1_i32, 1_i32)); assert_eq!(v.yxy(), ivec3(2_i32, 1_i32, 2_i32)); assert_eq!(v.yxz(), ivec3(2_i32, 1_i32, 3_i32)); assert_eq!(v.yxw(), ivec3(2_i32, 1_i32, 4_i32)); assert_eq!(v.yyx(), ivec3(2_i32, 2_i32, 1_i32)); assert_eq!(v.yyy(), ivec3(2_i32, 2_i32, 2_i32)); assert_eq!(v.yyz(), ivec3(2_i32, 2_i32, 3_i32)); assert_eq!(v.yyw(), ivec3(2_i32, 2_i32, 4_i32)); assert_eq!(v.yzx(), ivec3(2_i32, 3_i32, 1_i32)); assert_eq!(v.yzy(), ivec3(2_i32, 3_i32, 2_i32)); assert_eq!(v.yzz(), ivec3(2_i32, 3_i32, 3_i32)); assert_eq!(v.yzw(), ivec3(2_i32, 3_i32, 4_i32)); assert_eq!(v.ywx(), ivec3(2_i32, 4_i32, 1_i32)); assert_eq!(v.ywy(), ivec3(2_i32, 4_i32, 2_i32)); assert_eq!(v.ywz(), ivec3(2_i32, 4_i32, 3_i32)); assert_eq!(v.yww(), ivec3(2_i32, 4_i32, 4_i32)); assert_eq!(v.zxx(), ivec3(3_i32, 1_i32, 1_i32)); assert_eq!(v.zxy(), ivec3(3_i32, 1_i32, 2_i32)); assert_eq!(v.zxz(), ivec3(3_i32, 1_i32, 3_i32)); assert_eq!(v.zxw(), ivec3(3_i32, 1_i32, 4_i32)); assert_eq!(v.zyx(), ivec3(3_i32, 2_i32, 1_i32)); assert_eq!(v.zyy(), ivec3(3_i32, 2_i32, 2_i32)); assert_eq!(v.zyz(), ivec3(3_i32, 2_i32, 3_i32)); assert_eq!(v.zyw(), ivec3(3_i32, 2_i32, 4_i32)); assert_eq!(v.zzx(), ivec3(3_i32, 3_i32, 1_i32)); assert_eq!(v.zzy(), ivec3(3_i32, 3_i32, 2_i32)); assert_eq!(v.zzz(), ivec3(3_i32, 3_i32, 3_i32)); assert_eq!(v.zzw(), ivec3(3_i32, 3_i32, 4_i32)); assert_eq!(v.zwx(), ivec3(3_i32, 4_i32, 1_i32)); assert_eq!(v.zwy(), ivec3(3_i32, 4_i32, 2_i32)); assert_eq!(v.zwz(), ivec3(3_i32, 4_i32, 3_i32)); assert_eq!(v.zww(), ivec3(3_i32, 4_i32, 4_i32)); assert_eq!(v.wxx(), ivec3(4_i32, 1_i32, 1_i32)); assert_eq!(v.wxy(), ivec3(4_i32, 1_i32, 2_i32)); assert_eq!(v.wxz(), ivec3(4_i32, 1_i32, 3_i32)); assert_eq!(v.wxw(), ivec3(4_i32, 1_i32, 4_i32)); assert_eq!(v.wyx(), ivec3(4_i32, 2_i32, 1_i32)); assert_eq!(v.wyy(), ivec3(4_i32, 2_i32, 2_i32)); assert_eq!(v.wyz(), ivec3(4_i32, 2_i32, 3_i32)); assert_eq!(v.wyw(), ivec3(4_i32, 2_i32, 4_i32)); assert_eq!(v.wzx(), ivec3(4_i32, 3_i32, 1_i32)); assert_eq!(v.wzy(), ivec3(4_i32, 3_i32, 2_i32)); assert_eq!(v.wzz(), ivec3(4_i32, 3_i32, 3_i32)); assert_eq!(v.wzw(), ivec3(4_i32, 3_i32, 4_i32)); assert_eq!(v.wwx(), ivec3(4_i32, 4_i32, 1_i32)); assert_eq!(v.wwy(), ivec3(4_i32, 4_i32, 2_i32)); assert_eq!(v.wwz(), ivec3(4_i32, 4_i32, 3_i32)); assert_eq!(v.www(), ivec3(4_i32, 4_i32, 4_i32)); assert_eq!(v.with_xyz(rhs3), ivec4(11_i32, 12_i32, 13_i32, 4_i32)); assert_eq!(v.with_xyw(rhs3), ivec4(11_i32, 12_i32, 3_i32, 13_i32)); assert_eq!(v.with_xzy(rhs3), ivec4(11_i32, 13_i32, 12_i32, 4_i32)); assert_eq!(v.with_xzw(rhs3), ivec4(11_i32, 2_i32, 12_i32, 13_i32)); assert_eq!(v.with_xwy(rhs3), ivec4(11_i32, 13_i32, 3_i32, 12_i32)); assert_eq!(v.with_xwz(rhs3), ivec4(11_i32, 2_i32, 13_i32, 12_i32)); assert_eq!(v.with_yxz(rhs3), ivec4(12_i32, 11_i32, 13_i32, 4_i32)); assert_eq!(v.with_yxw(rhs3), ivec4(12_i32, 11_i32, 3_i32, 13_i32)); assert_eq!(v.with_yzx(rhs3), ivec4(13_i32, 11_i32, 12_i32, 4_i32)); assert_eq!(v.with_yzw(rhs3), ivec4(1_i32, 11_i32, 12_i32, 13_i32)); assert_eq!(v.with_ywx(rhs3), ivec4(13_i32, 11_i32, 3_i32, 12_i32)); assert_eq!(v.with_ywz(rhs3), ivec4(1_i32, 11_i32, 13_i32, 12_i32)); assert_eq!(v.with_zxy(rhs3), ivec4(12_i32, 13_i32, 11_i32, 4_i32)); assert_eq!(v.with_zxw(rhs3), ivec4(12_i32, 2_i32, 11_i32, 13_i32)); assert_eq!(v.with_zyx(rhs3), ivec4(13_i32, 12_i32, 11_i32, 4_i32)); assert_eq!(v.with_zyw(rhs3), ivec4(1_i32, 12_i32, 11_i32, 13_i32)); assert_eq!(v.with_zwx(rhs3), ivec4(13_i32, 2_i32, 11_i32, 12_i32)); assert_eq!(v.with_zwy(rhs3), ivec4(1_i32, 13_i32, 11_i32, 12_i32)); assert_eq!(v.with_wxy(rhs3), ivec4(12_i32, 13_i32, 3_i32, 11_i32)); assert_eq!(v.with_wxz(rhs3), ivec4(12_i32, 2_i32, 13_i32, 11_i32)); assert_eq!(v.with_wyx(rhs3), ivec4(13_i32, 12_i32, 3_i32, 11_i32)); assert_eq!(v.with_wyz(rhs3), ivec4(1_i32, 12_i32, 13_i32, 11_i32)); assert_eq!(v.with_wzx(rhs3), ivec4(13_i32, 2_i32, 12_i32, 11_i32)); assert_eq!(v.with_wzy(rhs3), ivec4(1_i32, 13_i32, 12_i32, 11_i32)); assert_eq!(v.xx(), ivec2(1_i32, 1_i32)); assert_eq!(v.xy(), ivec2(1_i32, 2_i32)); assert_eq!(v.xz(), ivec2(1_i32, 3_i32)); assert_eq!(v.xw(), ivec2(1_i32, 4_i32)); assert_eq!(v.yx(), ivec2(2_i32, 1_i32)); assert_eq!(v.yy(), ivec2(2_i32, 2_i32)); assert_eq!(v.yz(), ivec2(2_i32, 3_i32)); assert_eq!(v.yw(), ivec2(2_i32, 4_i32)); assert_eq!(v.zx(), ivec2(3_i32, 1_i32)); assert_eq!(v.zy(), ivec2(3_i32, 2_i32)); assert_eq!(v.zz(), ivec2(3_i32, 3_i32)); assert_eq!(v.zw(), ivec2(3_i32, 4_i32)); assert_eq!(v.wx(), ivec2(4_i32, 1_i32)); assert_eq!(v.wy(), ivec2(4_i32, 2_i32)); assert_eq!(v.wz(), ivec2(4_i32, 3_i32)); assert_eq!(v.ww(), ivec2(4_i32, 4_i32)); assert_eq!(v.with_xy(rhs2), ivec4(11_i32, 12_i32, 3_i32, 4_i32)); assert_eq!(v.with_xz(rhs2), ivec4(11_i32, 2_i32, 12_i32, 4_i32)); assert_eq!(v.with_xw(rhs2), ivec4(11_i32, 2_i32, 3_i32, 12_i32)); assert_eq!(v.with_yx(rhs2), ivec4(12_i32, 11_i32, 3_i32, 4_i32)); assert_eq!(v.with_yz(rhs2), ivec4(1_i32, 11_i32, 12_i32, 4_i32)); assert_eq!(v.with_yw(rhs2), ivec4(1_i32, 11_i32, 3_i32, 12_i32)); assert_eq!(v.with_zx(rhs2), ivec4(12_i32, 2_i32, 11_i32, 4_i32)); assert_eq!(v.with_zy(rhs2), ivec4(1_i32, 12_i32, 11_i32, 4_i32)); assert_eq!(v.with_zw(rhs2), ivec4(1_i32, 2_i32, 11_i32, 12_i32)); assert_eq!(v.with_wx(rhs2), ivec4(12_i32, 2_i32, 3_i32, 11_i32)); assert_eq!(v.with_wy(rhs2), ivec4(1_i32, 12_i32, 3_i32, 11_i32)); assert_eq!(v.with_wz(rhs2), ivec4(1_i32, 2_i32, 12_i32, 11_i32)); }); glam_test!(test_ivec3_swizzles, { let v = ivec3(1_i32, 2_i32, 3_i32); let rhs2 = ivec2(11_i32, 12_i32); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), ivec4(1_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.xxxy(), ivec4(1_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.xxxz(), ivec4(1_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.xxyx(), ivec4(1_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.xxyy(), ivec4(1_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.xxyz(), ivec4(1_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.xxzx(), ivec4(1_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.xxzy(), ivec4(1_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.xxzz(), ivec4(1_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.xyxx(), ivec4(1_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.xyxy(), ivec4(1_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.xyxz(), ivec4(1_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.xyyx(), ivec4(1_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.xyyy(), ivec4(1_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.xyyz(), ivec4(1_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.xyzx(), ivec4(1_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.xyzy(), ivec4(1_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.xyzz(), ivec4(1_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.xzxx(), ivec4(1_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.xzxy(), ivec4(1_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.xzxz(), ivec4(1_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.xzyx(), ivec4(1_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.xzyy(), ivec4(1_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.xzyz(), ivec4(1_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.xzzx(), ivec4(1_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.xzzy(), ivec4(1_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.xzzz(), ivec4(1_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.yxxx(), ivec4(2_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.yxxy(), ivec4(2_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.yxxz(), ivec4(2_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.yxyx(), ivec4(2_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.yxyy(), ivec4(2_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.yxyz(), ivec4(2_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.yxzx(), ivec4(2_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.yxzy(), ivec4(2_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.yxzz(), ivec4(2_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.yyxx(), ivec4(2_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.yyxy(), ivec4(2_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.yyxz(), ivec4(2_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.yyyx(), ivec4(2_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.yyyy(), ivec4(2_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.yyyz(), ivec4(2_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.yyzx(), ivec4(2_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.yyzy(), ivec4(2_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.yyzz(), ivec4(2_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.yzxx(), ivec4(2_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.yzxy(), ivec4(2_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.yzxz(), ivec4(2_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.yzyx(), ivec4(2_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.yzyy(), ivec4(2_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.yzyz(), ivec4(2_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.yzzx(), ivec4(2_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.yzzy(), ivec4(2_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.yzzz(), ivec4(2_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.zxxx(), ivec4(3_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.zxxy(), ivec4(3_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.zxxz(), ivec4(3_i32, 1_i32, 1_i32, 3_i32)); assert_eq!(v.zxyx(), ivec4(3_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.zxyy(), ivec4(3_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.zxyz(), ivec4(3_i32, 1_i32, 2_i32, 3_i32)); assert_eq!(v.zxzx(), ivec4(3_i32, 1_i32, 3_i32, 1_i32)); assert_eq!(v.zxzy(), ivec4(3_i32, 1_i32, 3_i32, 2_i32)); assert_eq!(v.zxzz(), ivec4(3_i32, 1_i32, 3_i32, 3_i32)); assert_eq!(v.zyxx(), ivec4(3_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.zyxy(), ivec4(3_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.zyxz(), ivec4(3_i32, 2_i32, 1_i32, 3_i32)); assert_eq!(v.zyyx(), ivec4(3_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.zyyy(), ivec4(3_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.zyyz(), ivec4(3_i32, 2_i32, 2_i32, 3_i32)); assert_eq!(v.zyzx(), ivec4(3_i32, 2_i32, 3_i32, 1_i32)); assert_eq!(v.zyzy(), ivec4(3_i32, 2_i32, 3_i32, 2_i32)); assert_eq!(v.zyzz(), ivec4(3_i32, 2_i32, 3_i32, 3_i32)); assert_eq!(v.zzxx(), ivec4(3_i32, 3_i32, 1_i32, 1_i32)); assert_eq!(v.zzxy(), ivec4(3_i32, 3_i32, 1_i32, 2_i32)); assert_eq!(v.zzxz(), ivec4(3_i32, 3_i32, 1_i32, 3_i32)); assert_eq!(v.zzyx(), ivec4(3_i32, 3_i32, 2_i32, 1_i32)); assert_eq!(v.zzyy(), ivec4(3_i32, 3_i32, 2_i32, 2_i32)); assert_eq!(v.zzyz(), ivec4(3_i32, 3_i32, 2_i32, 3_i32)); assert_eq!(v.zzzx(), ivec4(3_i32, 3_i32, 3_i32, 1_i32)); assert_eq!(v.zzzy(), ivec4(3_i32, 3_i32, 3_i32, 2_i32)); assert_eq!(v.zzzz(), ivec4(3_i32, 3_i32, 3_i32, 3_i32)); assert_eq!(v.xxx(), ivec3(1_i32, 1_i32, 1_i32)); assert_eq!(v.xxy(), ivec3(1_i32, 1_i32, 2_i32)); assert_eq!(v.xxz(), ivec3(1_i32, 1_i32, 3_i32)); assert_eq!(v.xyx(), ivec3(1_i32, 2_i32, 1_i32)); assert_eq!(v.xyy(), ivec3(1_i32, 2_i32, 2_i32)); assert_eq!(v.xzx(), ivec3(1_i32, 3_i32, 1_i32)); assert_eq!(v.xzy(), ivec3(1_i32, 3_i32, 2_i32)); assert_eq!(v.xzz(), ivec3(1_i32, 3_i32, 3_i32)); assert_eq!(v.yxx(), ivec3(2_i32, 1_i32, 1_i32)); assert_eq!(v.yxy(), ivec3(2_i32, 1_i32, 2_i32)); assert_eq!(v.yxz(), ivec3(2_i32, 1_i32, 3_i32)); assert_eq!(v.yyx(), ivec3(2_i32, 2_i32, 1_i32)); assert_eq!(v.yyy(), ivec3(2_i32, 2_i32, 2_i32)); assert_eq!(v.yyz(), ivec3(2_i32, 2_i32, 3_i32)); assert_eq!(v.yzx(), ivec3(2_i32, 3_i32, 1_i32)); assert_eq!(v.yzy(), ivec3(2_i32, 3_i32, 2_i32)); assert_eq!(v.yzz(), ivec3(2_i32, 3_i32, 3_i32)); assert_eq!(v.zxx(), ivec3(3_i32, 1_i32, 1_i32)); assert_eq!(v.zxy(), ivec3(3_i32, 1_i32, 2_i32)); assert_eq!(v.zxz(), ivec3(3_i32, 1_i32, 3_i32)); assert_eq!(v.zyx(), ivec3(3_i32, 2_i32, 1_i32)); assert_eq!(v.zyy(), ivec3(3_i32, 2_i32, 2_i32)); assert_eq!(v.zyz(), ivec3(3_i32, 2_i32, 3_i32)); assert_eq!(v.zzx(), ivec3(3_i32, 3_i32, 1_i32)); assert_eq!(v.zzy(), ivec3(3_i32, 3_i32, 2_i32)); assert_eq!(v.zzz(), ivec3(3_i32, 3_i32, 3_i32)); assert_eq!(v.xx(), ivec2(1_i32, 1_i32)); assert_eq!(v.xy(), ivec2(1_i32, 2_i32)); assert_eq!(v.xz(), ivec2(1_i32, 3_i32)); assert_eq!(v.yx(), ivec2(2_i32, 1_i32)); assert_eq!(v.yy(), ivec2(2_i32, 2_i32)); assert_eq!(v.yz(), ivec2(2_i32, 3_i32)); assert_eq!(v.zx(), ivec2(3_i32, 1_i32)); assert_eq!(v.zy(), ivec2(3_i32, 2_i32)); assert_eq!(v.zz(), ivec2(3_i32, 3_i32)); assert_eq!(v.with_xy(rhs2), ivec3(11_i32, 12_i32, 3_i32)); assert_eq!(v.with_xz(rhs2), ivec3(11_i32, 2_i32, 12_i32)); assert_eq!(v.with_yx(rhs2), ivec3(12_i32, 11_i32, 3_i32)); assert_eq!(v.with_yz(rhs2), ivec3(1_i32, 11_i32, 12_i32)); assert_eq!(v.with_zx(rhs2), ivec3(12_i32, 2_i32, 11_i32)); assert_eq!(v.with_zy(rhs2), ivec3(1_i32, 12_i32, 11_i32)); }); glam_test!(test_ivec2_swizzles, { let v = ivec2(1_i32, 2_i32); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), ivec4(1_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.xxxy(), ivec4(1_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.xxyx(), ivec4(1_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.xxyy(), ivec4(1_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.xyxx(), ivec4(1_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.xyxy(), ivec4(1_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.xyyx(), ivec4(1_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.xyyy(), ivec4(1_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.yxxx(), ivec4(2_i32, 1_i32, 1_i32, 1_i32)); assert_eq!(v.yxxy(), ivec4(2_i32, 1_i32, 1_i32, 2_i32)); assert_eq!(v.yxyx(), ivec4(2_i32, 1_i32, 2_i32, 1_i32)); assert_eq!(v.yxyy(), ivec4(2_i32, 1_i32, 2_i32, 2_i32)); assert_eq!(v.yyxx(), ivec4(2_i32, 2_i32, 1_i32, 1_i32)); assert_eq!(v.yyxy(), ivec4(2_i32, 2_i32, 1_i32, 2_i32)); assert_eq!(v.yyyx(), ivec4(2_i32, 2_i32, 2_i32, 1_i32)); assert_eq!(v.yyyy(), ivec4(2_i32, 2_i32, 2_i32, 2_i32)); assert_eq!(v.xxx(), ivec3(1_i32, 1_i32, 1_i32)); assert_eq!(v.xxy(), ivec3(1_i32, 1_i32, 2_i32)); assert_eq!(v.xyx(), ivec3(1_i32, 2_i32, 1_i32)); assert_eq!(v.xyy(), ivec3(1_i32, 2_i32, 2_i32)); assert_eq!(v.yxx(), ivec3(2_i32, 1_i32, 1_i32)); assert_eq!(v.yxy(), ivec3(2_i32, 1_i32, 2_i32)); assert_eq!(v.yyx(), ivec3(2_i32, 2_i32, 1_i32)); assert_eq!(v.yyy(), ivec3(2_i32, 2_i32, 2_i32)); assert_eq!(v.xx(), ivec2(1_i32, 1_i32)); assert_eq!(v.yx(), ivec2(2_i32, 1_i32)); assert_eq!(v.yy(), ivec2(2_i32, 2_i32)); }); glam-0.30.1/tests/swizzles_i64.rs000064400000000000000000000773051046102023000147250ustar 00000000000000// 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); let rhs3 = i64vec3(11_i64, 12_i64, 13_i64); let rhs2 = i64vec2(11_i64, 12_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.with_xyz(rhs3), i64vec4(11_i64, 12_i64, 13_i64, 4_i64)); assert_eq!(v.with_xyw(rhs3), i64vec4(11_i64, 12_i64, 3_i64, 13_i64)); assert_eq!(v.with_xzy(rhs3), i64vec4(11_i64, 13_i64, 12_i64, 4_i64)); assert_eq!(v.with_xzw(rhs3), i64vec4(11_i64, 2_i64, 12_i64, 13_i64)); assert_eq!(v.with_xwy(rhs3), i64vec4(11_i64, 13_i64, 3_i64, 12_i64)); assert_eq!(v.with_xwz(rhs3), i64vec4(11_i64, 2_i64, 13_i64, 12_i64)); assert_eq!(v.with_yxz(rhs3), i64vec4(12_i64, 11_i64, 13_i64, 4_i64)); assert_eq!(v.with_yxw(rhs3), i64vec4(12_i64, 11_i64, 3_i64, 13_i64)); assert_eq!(v.with_yzx(rhs3), i64vec4(13_i64, 11_i64, 12_i64, 4_i64)); assert_eq!(v.with_yzw(rhs3), i64vec4(1_i64, 11_i64, 12_i64, 13_i64)); assert_eq!(v.with_ywx(rhs3), i64vec4(13_i64, 11_i64, 3_i64, 12_i64)); assert_eq!(v.with_ywz(rhs3), i64vec4(1_i64, 11_i64, 13_i64, 12_i64)); assert_eq!(v.with_zxy(rhs3), i64vec4(12_i64, 13_i64, 11_i64, 4_i64)); assert_eq!(v.with_zxw(rhs3), i64vec4(12_i64, 2_i64, 11_i64, 13_i64)); assert_eq!(v.with_zyx(rhs3), i64vec4(13_i64, 12_i64, 11_i64, 4_i64)); assert_eq!(v.with_zyw(rhs3), i64vec4(1_i64, 12_i64, 11_i64, 13_i64)); assert_eq!(v.with_zwx(rhs3), i64vec4(13_i64, 2_i64, 11_i64, 12_i64)); assert_eq!(v.with_zwy(rhs3), i64vec4(1_i64, 13_i64, 11_i64, 12_i64)); assert_eq!(v.with_wxy(rhs3), i64vec4(12_i64, 13_i64, 3_i64, 11_i64)); assert_eq!(v.with_wxz(rhs3), i64vec4(12_i64, 2_i64, 13_i64, 11_i64)); assert_eq!(v.with_wyx(rhs3), i64vec4(13_i64, 12_i64, 3_i64, 11_i64)); assert_eq!(v.with_wyz(rhs3), i64vec4(1_i64, 12_i64, 13_i64, 11_i64)); assert_eq!(v.with_wzx(rhs3), i64vec4(13_i64, 2_i64, 12_i64, 11_i64)); assert_eq!(v.with_wzy(rhs3), i64vec4(1_i64, 13_i64, 12_i64, 11_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)); assert_eq!(v.with_xy(rhs2), i64vec4(11_i64, 12_i64, 3_i64, 4_i64)); assert_eq!(v.with_xz(rhs2), i64vec4(11_i64, 2_i64, 12_i64, 4_i64)); assert_eq!(v.with_xw(rhs2), i64vec4(11_i64, 2_i64, 3_i64, 12_i64)); assert_eq!(v.with_yx(rhs2), i64vec4(12_i64, 11_i64, 3_i64, 4_i64)); assert_eq!(v.with_yz(rhs2), i64vec4(1_i64, 11_i64, 12_i64, 4_i64)); assert_eq!(v.with_yw(rhs2), i64vec4(1_i64, 11_i64, 3_i64, 12_i64)); assert_eq!(v.with_zx(rhs2), i64vec4(12_i64, 2_i64, 11_i64, 4_i64)); assert_eq!(v.with_zy(rhs2), i64vec4(1_i64, 12_i64, 11_i64, 4_i64)); assert_eq!(v.with_zw(rhs2), i64vec4(1_i64, 2_i64, 11_i64, 12_i64)); assert_eq!(v.with_wx(rhs2), i64vec4(12_i64, 2_i64, 3_i64, 11_i64)); assert_eq!(v.with_wy(rhs2), i64vec4(1_i64, 12_i64, 3_i64, 11_i64)); assert_eq!(v.with_wz(rhs2), i64vec4(1_i64, 2_i64, 12_i64, 11_i64)); }); glam_test!(test_i64vec3_swizzles, { let v = i64vec3(1_i64, 2_i64, 3_i64); let rhs2 = i64vec2(11_i64, 12_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)); assert_eq!(v.with_xy(rhs2), i64vec3(11_i64, 12_i64, 3_i64)); assert_eq!(v.with_xz(rhs2), i64vec3(11_i64, 2_i64, 12_i64)); assert_eq!(v.with_yx(rhs2), i64vec3(12_i64, 11_i64, 3_i64)); assert_eq!(v.with_yz(rhs2), i64vec3(1_i64, 11_i64, 12_i64)); assert_eq!(v.with_zx(rhs2), i64vec3(12_i64, 2_i64, 11_i64)); assert_eq!(v.with_zy(rhs2), i64vec3(1_i64, 12_i64, 11_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)); }); glam-0.30.1/tests/swizzles_i8.rs000064400000000000000000000724441046102023000146420ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_i8vec4_swizzles, { let v = i8vec4(1_i8, 2_i8, 3_i8, 4_i8); let rhs3 = i8vec3(11_i8, 12_i8, 13_i8); let rhs2 = i8vec2(11_i8, 12_i8); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), i8vec4(1_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.xxxy(), i8vec4(1_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.xxxz(), i8vec4(1_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.xxxw(), i8vec4(1_i8, 1_i8, 1_i8, 4_i8)); assert_eq!(v.xxyx(), i8vec4(1_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.xxyy(), i8vec4(1_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.xxyz(), i8vec4(1_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.xxyw(), i8vec4(1_i8, 1_i8, 2_i8, 4_i8)); assert_eq!(v.xxzx(), i8vec4(1_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.xxzy(), i8vec4(1_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.xxzz(), i8vec4(1_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.xxzw(), i8vec4(1_i8, 1_i8, 3_i8, 4_i8)); assert_eq!(v.xxwx(), i8vec4(1_i8, 1_i8, 4_i8, 1_i8)); assert_eq!(v.xxwy(), i8vec4(1_i8, 1_i8, 4_i8, 2_i8)); assert_eq!(v.xxwz(), i8vec4(1_i8, 1_i8, 4_i8, 3_i8)); assert_eq!(v.xxww(), i8vec4(1_i8, 1_i8, 4_i8, 4_i8)); assert_eq!(v.xyxx(), i8vec4(1_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.xyxy(), i8vec4(1_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.xyxz(), i8vec4(1_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.xyxw(), i8vec4(1_i8, 2_i8, 1_i8, 4_i8)); assert_eq!(v.xyyx(), i8vec4(1_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.xyyy(), i8vec4(1_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.xyyz(), i8vec4(1_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.xyyw(), i8vec4(1_i8, 2_i8, 2_i8, 4_i8)); assert_eq!(v.xyzx(), i8vec4(1_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.xyzy(), i8vec4(1_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.xyzz(), i8vec4(1_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.xywx(), i8vec4(1_i8, 2_i8, 4_i8, 1_i8)); assert_eq!(v.xywy(), i8vec4(1_i8, 2_i8, 4_i8, 2_i8)); assert_eq!(v.xywz(), i8vec4(1_i8, 2_i8, 4_i8, 3_i8)); assert_eq!(v.xyww(), i8vec4(1_i8, 2_i8, 4_i8, 4_i8)); assert_eq!(v.xzxx(), i8vec4(1_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.xzxy(), i8vec4(1_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.xzxz(), i8vec4(1_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.xzxw(), i8vec4(1_i8, 3_i8, 1_i8, 4_i8)); assert_eq!(v.xzyx(), i8vec4(1_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.xzyy(), i8vec4(1_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.xzyz(), i8vec4(1_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.xzyw(), i8vec4(1_i8, 3_i8, 2_i8, 4_i8)); assert_eq!(v.xzzx(), i8vec4(1_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.xzzy(), i8vec4(1_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.xzzz(), i8vec4(1_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.xzzw(), i8vec4(1_i8, 3_i8, 3_i8, 4_i8)); assert_eq!(v.xzwx(), i8vec4(1_i8, 3_i8, 4_i8, 1_i8)); assert_eq!(v.xzwy(), i8vec4(1_i8, 3_i8, 4_i8, 2_i8)); assert_eq!(v.xzwz(), i8vec4(1_i8, 3_i8, 4_i8, 3_i8)); assert_eq!(v.xzww(), i8vec4(1_i8, 3_i8, 4_i8, 4_i8)); assert_eq!(v.xwxx(), i8vec4(1_i8, 4_i8, 1_i8, 1_i8)); assert_eq!(v.xwxy(), i8vec4(1_i8, 4_i8, 1_i8, 2_i8)); assert_eq!(v.xwxz(), i8vec4(1_i8, 4_i8, 1_i8, 3_i8)); assert_eq!(v.xwxw(), i8vec4(1_i8, 4_i8, 1_i8, 4_i8)); assert_eq!(v.xwyx(), i8vec4(1_i8, 4_i8, 2_i8, 1_i8)); assert_eq!(v.xwyy(), i8vec4(1_i8, 4_i8, 2_i8, 2_i8)); assert_eq!(v.xwyz(), i8vec4(1_i8, 4_i8, 2_i8, 3_i8)); assert_eq!(v.xwyw(), i8vec4(1_i8, 4_i8, 2_i8, 4_i8)); assert_eq!(v.xwzx(), i8vec4(1_i8, 4_i8, 3_i8, 1_i8)); assert_eq!(v.xwzy(), i8vec4(1_i8, 4_i8, 3_i8, 2_i8)); assert_eq!(v.xwzz(), i8vec4(1_i8, 4_i8, 3_i8, 3_i8)); assert_eq!(v.xwzw(), i8vec4(1_i8, 4_i8, 3_i8, 4_i8)); assert_eq!(v.xwwx(), i8vec4(1_i8, 4_i8, 4_i8, 1_i8)); assert_eq!(v.xwwy(), i8vec4(1_i8, 4_i8, 4_i8, 2_i8)); assert_eq!(v.xwwz(), i8vec4(1_i8, 4_i8, 4_i8, 3_i8)); assert_eq!(v.xwww(), i8vec4(1_i8, 4_i8, 4_i8, 4_i8)); assert_eq!(v.yxxx(), i8vec4(2_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.yxxy(), i8vec4(2_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.yxxz(), i8vec4(2_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.yxxw(), i8vec4(2_i8, 1_i8, 1_i8, 4_i8)); assert_eq!(v.yxyx(), i8vec4(2_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.yxyy(), i8vec4(2_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.yxyz(), i8vec4(2_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.yxyw(), i8vec4(2_i8, 1_i8, 2_i8, 4_i8)); assert_eq!(v.yxzx(), i8vec4(2_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.yxzy(), i8vec4(2_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.yxzz(), i8vec4(2_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.yxzw(), i8vec4(2_i8, 1_i8, 3_i8, 4_i8)); assert_eq!(v.yxwx(), i8vec4(2_i8, 1_i8, 4_i8, 1_i8)); assert_eq!(v.yxwy(), i8vec4(2_i8, 1_i8, 4_i8, 2_i8)); assert_eq!(v.yxwz(), i8vec4(2_i8, 1_i8, 4_i8, 3_i8)); assert_eq!(v.yxww(), i8vec4(2_i8, 1_i8, 4_i8, 4_i8)); assert_eq!(v.yyxx(), i8vec4(2_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.yyxy(), i8vec4(2_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.yyxz(), i8vec4(2_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.yyxw(), i8vec4(2_i8, 2_i8, 1_i8, 4_i8)); assert_eq!(v.yyyx(), i8vec4(2_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.yyyy(), i8vec4(2_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.yyyz(), i8vec4(2_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.yyyw(), i8vec4(2_i8, 2_i8, 2_i8, 4_i8)); assert_eq!(v.yyzx(), i8vec4(2_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.yyzy(), i8vec4(2_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.yyzz(), i8vec4(2_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.yyzw(), i8vec4(2_i8, 2_i8, 3_i8, 4_i8)); assert_eq!(v.yywx(), i8vec4(2_i8, 2_i8, 4_i8, 1_i8)); assert_eq!(v.yywy(), i8vec4(2_i8, 2_i8, 4_i8, 2_i8)); assert_eq!(v.yywz(), i8vec4(2_i8, 2_i8, 4_i8, 3_i8)); assert_eq!(v.yyww(), i8vec4(2_i8, 2_i8, 4_i8, 4_i8)); assert_eq!(v.yzxx(), i8vec4(2_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.yzxy(), i8vec4(2_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.yzxz(), i8vec4(2_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.yzxw(), i8vec4(2_i8, 3_i8, 1_i8, 4_i8)); assert_eq!(v.yzyx(), i8vec4(2_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.yzyy(), i8vec4(2_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.yzyz(), i8vec4(2_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.yzyw(), i8vec4(2_i8, 3_i8, 2_i8, 4_i8)); assert_eq!(v.yzzx(), i8vec4(2_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.yzzy(), i8vec4(2_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.yzzz(), i8vec4(2_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.yzzw(), i8vec4(2_i8, 3_i8, 3_i8, 4_i8)); assert_eq!(v.yzwx(), i8vec4(2_i8, 3_i8, 4_i8, 1_i8)); assert_eq!(v.yzwy(), i8vec4(2_i8, 3_i8, 4_i8, 2_i8)); assert_eq!(v.yzwz(), i8vec4(2_i8, 3_i8, 4_i8, 3_i8)); assert_eq!(v.yzww(), i8vec4(2_i8, 3_i8, 4_i8, 4_i8)); assert_eq!(v.ywxx(), i8vec4(2_i8, 4_i8, 1_i8, 1_i8)); assert_eq!(v.ywxy(), i8vec4(2_i8, 4_i8, 1_i8, 2_i8)); assert_eq!(v.ywxz(), i8vec4(2_i8, 4_i8, 1_i8, 3_i8)); assert_eq!(v.ywxw(), i8vec4(2_i8, 4_i8, 1_i8, 4_i8)); assert_eq!(v.ywyx(), i8vec4(2_i8, 4_i8, 2_i8, 1_i8)); assert_eq!(v.ywyy(), i8vec4(2_i8, 4_i8, 2_i8, 2_i8)); assert_eq!(v.ywyz(), i8vec4(2_i8, 4_i8, 2_i8, 3_i8)); assert_eq!(v.ywyw(), i8vec4(2_i8, 4_i8, 2_i8, 4_i8)); assert_eq!(v.ywzx(), i8vec4(2_i8, 4_i8, 3_i8, 1_i8)); assert_eq!(v.ywzy(), i8vec4(2_i8, 4_i8, 3_i8, 2_i8)); assert_eq!(v.ywzz(), i8vec4(2_i8, 4_i8, 3_i8, 3_i8)); assert_eq!(v.ywzw(), i8vec4(2_i8, 4_i8, 3_i8, 4_i8)); assert_eq!(v.ywwx(), i8vec4(2_i8, 4_i8, 4_i8, 1_i8)); assert_eq!(v.ywwy(), i8vec4(2_i8, 4_i8, 4_i8, 2_i8)); assert_eq!(v.ywwz(), i8vec4(2_i8, 4_i8, 4_i8, 3_i8)); assert_eq!(v.ywww(), i8vec4(2_i8, 4_i8, 4_i8, 4_i8)); assert_eq!(v.zxxx(), i8vec4(3_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.zxxy(), i8vec4(3_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.zxxz(), i8vec4(3_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.zxxw(), i8vec4(3_i8, 1_i8, 1_i8, 4_i8)); assert_eq!(v.zxyx(), i8vec4(3_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.zxyy(), i8vec4(3_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.zxyz(), i8vec4(3_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.zxyw(), i8vec4(3_i8, 1_i8, 2_i8, 4_i8)); assert_eq!(v.zxzx(), i8vec4(3_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.zxzy(), i8vec4(3_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.zxzz(), i8vec4(3_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.zxzw(), i8vec4(3_i8, 1_i8, 3_i8, 4_i8)); assert_eq!(v.zxwx(), i8vec4(3_i8, 1_i8, 4_i8, 1_i8)); assert_eq!(v.zxwy(), i8vec4(3_i8, 1_i8, 4_i8, 2_i8)); assert_eq!(v.zxwz(), i8vec4(3_i8, 1_i8, 4_i8, 3_i8)); assert_eq!(v.zxww(), i8vec4(3_i8, 1_i8, 4_i8, 4_i8)); assert_eq!(v.zyxx(), i8vec4(3_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.zyxy(), i8vec4(3_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.zyxz(), i8vec4(3_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.zyxw(), i8vec4(3_i8, 2_i8, 1_i8, 4_i8)); assert_eq!(v.zyyx(), i8vec4(3_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.zyyy(), i8vec4(3_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.zyyz(), i8vec4(3_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.zyyw(), i8vec4(3_i8, 2_i8, 2_i8, 4_i8)); assert_eq!(v.zyzx(), i8vec4(3_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.zyzy(), i8vec4(3_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.zyzz(), i8vec4(3_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.zyzw(), i8vec4(3_i8, 2_i8, 3_i8, 4_i8)); assert_eq!(v.zywx(), i8vec4(3_i8, 2_i8, 4_i8, 1_i8)); assert_eq!(v.zywy(), i8vec4(3_i8, 2_i8, 4_i8, 2_i8)); assert_eq!(v.zywz(), i8vec4(3_i8, 2_i8, 4_i8, 3_i8)); assert_eq!(v.zyww(), i8vec4(3_i8, 2_i8, 4_i8, 4_i8)); assert_eq!(v.zzxx(), i8vec4(3_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.zzxy(), i8vec4(3_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.zzxz(), i8vec4(3_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.zzxw(), i8vec4(3_i8, 3_i8, 1_i8, 4_i8)); assert_eq!(v.zzyx(), i8vec4(3_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.zzyy(), i8vec4(3_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.zzyz(), i8vec4(3_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.zzyw(), i8vec4(3_i8, 3_i8, 2_i8, 4_i8)); assert_eq!(v.zzzx(), i8vec4(3_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.zzzy(), i8vec4(3_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.zzzz(), i8vec4(3_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.zzzw(), i8vec4(3_i8, 3_i8, 3_i8, 4_i8)); assert_eq!(v.zzwx(), i8vec4(3_i8, 3_i8, 4_i8, 1_i8)); assert_eq!(v.zzwy(), i8vec4(3_i8, 3_i8, 4_i8, 2_i8)); assert_eq!(v.zzwz(), i8vec4(3_i8, 3_i8, 4_i8, 3_i8)); assert_eq!(v.zzww(), i8vec4(3_i8, 3_i8, 4_i8, 4_i8)); assert_eq!(v.zwxx(), i8vec4(3_i8, 4_i8, 1_i8, 1_i8)); assert_eq!(v.zwxy(), i8vec4(3_i8, 4_i8, 1_i8, 2_i8)); assert_eq!(v.zwxz(), i8vec4(3_i8, 4_i8, 1_i8, 3_i8)); assert_eq!(v.zwxw(), i8vec4(3_i8, 4_i8, 1_i8, 4_i8)); assert_eq!(v.zwyx(), i8vec4(3_i8, 4_i8, 2_i8, 1_i8)); assert_eq!(v.zwyy(), i8vec4(3_i8, 4_i8, 2_i8, 2_i8)); assert_eq!(v.zwyz(), i8vec4(3_i8, 4_i8, 2_i8, 3_i8)); assert_eq!(v.zwyw(), i8vec4(3_i8, 4_i8, 2_i8, 4_i8)); assert_eq!(v.zwzx(), i8vec4(3_i8, 4_i8, 3_i8, 1_i8)); assert_eq!(v.zwzy(), i8vec4(3_i8, 4_i8, 3_i8, 2_i8)); assert_eq!(v.zwzz(), i8vec4(3_i8, 4_i8, 3_i8, 3_i8)); assert_eq!(v.zwzw(), i8vec4(3_i8, 4_i8, 3_i8, 4_i8)); assert_eq!(v.zwwx(), i8vec4(3_i8, 4_i8, 4_i8, 1_i8)); assert_eq!(v.zwwy(), i8vec4(3_i8, 4_i8, 4_i8, 2_i8)); assert_eq!(v.zwwz(), i8vec4(3_i8, 4_i8, 4_i8, 3_i8)); assert_eq!(v.zwww(), i8vec4(3_i8, 4_i8, 4_i8, 4_i8)); assert_eq!(v.wxxx(), i8vec4(4_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.wxxy(), i8vec4(4_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.wxxz(), i8vec4(4_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.wxxw(), i8vec4(4_i8, 1_i8, 1_i8, 4_i8)); assert_eq!(v.wxyx(), i8vec4(4_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.wxyy(), i8vec4(4_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.wxyz(), i8vec4(4_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.wxyw(), i8vec4(4_i8, 1_i8, 2_i8, 4_i8)); assert_eq!(v.wxzx(), i8vec4(4_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.wxzy(), i8vec4(4_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.wxzz(), i8vec4(4_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.wxzw(), i8vec4(4_i8, 1_i8, 3_i8, 4_i8)); assert_eq!(v.wxwx(), i8vec4(4_i8, 1_i8, 4_i8, 1_i8)); assert_eq!(v.wxwy(), i8vec4(4_i8, 1_i8, 4_i8, 2_i8)); assert_eq!(v.wxwz(), i8vec4(4_i8, 1_i8, 4_i8, 3_i8)); assert_eq!(v.wxww(), i8vec4(4_i8, 1_i8, 4_i8, 4_i8)); assert_eq!(v.wyxx(), i8vec4(4_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.wyxy(), i8vec4(4_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.wyxz(), i8vec4(4_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.wyxw(), i8vec4(4_i8, 2_i8, 1_i8, 4_i8)); assert_eq!(v.wyyx(), i8vec4(4_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.wyyy(), i8vec4(4_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.wyyz(), i8vec4(4_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.wyyw(), i8vec4(4_i8, 2_i8, 2_i8, 4_i8)); assert_eq!(v.wyzx(), i8vec4(4_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.wyzy(), i8vec4(4_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.wyzz(), i8vec4(4_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.wyzw(), i8vec4(4_i8, 2_i8, 3_i8, 4_i8)); assert_eq!(v.wywx(), i8vec4(4_i8, 2_i8, 4_i8, 1_i8)); assert_eq!(v.wywy(), i8vec4(4_i8, 2_i8, 4_i8, 2_i8)); assert_eq!(v.wywz(), i8vec4(4_i8, 2_i8, 4_i8, 3_i8)); assert_eq!(v.wyww(), i8vec4(4_i8, 2_i8, 4_i8, 4_i8)); assert_eq!(v.wzxx(), i8vec4(4_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.wzxy(), i8vec4(4_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.wzxz(), i8vec4(4_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.wzxw(), i8vec4(4_i8, 3_i8, 1_i8, 4_i8)); assert_eq!(v.wzyx(), i8vec4(4_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.wzyy(), i8vec4(4_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.wzyz(), i8vec4(4_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.wzyw(), i8vec4(4_i8, 3_i8, 2_i8, 4_i8)); assert_eq!(v.wzzx(), i8vec4(4_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.wzzy(), i8vec4(4_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.wzzz(), i8vec4(4_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.wzzw(), i8vec4(4_i8, 3_i8, 3_i8, 4_i8)); assert_eq!(v.wzwx(), i8vec4(4_i8, 3_i8, 4_i8, 1_i8)); assert_eq!(v.wzwy(), i8vec4(4_i8, 3_i8, 4_i8, 2_i8)); assert_eq!(v.wzwz(), i8vec4(4_i8, 3_i8, 4_i8, 3_i8)); assert_eq!(v.wzww(), i8vec4(4_i8, 3_i8, 4_i8, 4_i8)); assert_eq!(v.wwxx(), i8vec4(4_i8, 4_i8, 1_i8, 1_i8)); assert_eq!(v.wwxy(), i8vec4(4_i8, 4_i8, 1_i8, 2_i8)); assert_eq!(v.wwxz(), i8vec4(4_i8, 4_i8, 1_i8, 3_i8)); assert_eq!(v.wwxw(), i8vec4(4_i8, 4_i8, 1_i8, 4_i8)); assert_eq!(v.wwyx(), i8vec4(4_i8, 4_i8, 2_i8, 1_i8)); assert_eq!(v.wwyy(), i8vec4(4_i8, 4_i8, 2_i8, 2_i8)); assert_eq!(v.wwyz(), i8vec4(4_i8, 4_i8, 2_i8, 3_i8)); assert_eq!(v.wwyw(), i8vec4(4_i8, 4_i8, 2_i8, 4_i8)); assert_eq!(v.wwzx(), i8vec4(4_i8, 4_i8, 3_i8, 1_i8)); assert_eq!(v.wwzy(), i8vec4(4_i8, 4_i8, 3_i8, 2_i8)); assert_eq!(v.wwzz(), i8vec4(4_i8, 4_i8, 3_i8, 3_i8)); assert_eq!(v.wwzw(), i8vec4(4_i8, 4_i8, 3_i8, 4_i8)); assert_eq!(v.wwwx(), i8vec4(4_i8, 4_i8, 4_i8, 1_i8)); assert_eq!(v.wwwy(), i8vec4(4_i8, 4_i8, 4_i8, 2_i8)); assert_eq!(v.wwwz(), i8vec4(4_i8, 4_i8, 4_i8, 3_i8)); assert_eq!(v.wwww(), i8vec4(4_i8, 4_i8, 4_i8, 4_i8)); assert_eq!(v.xxx(), i8vec3(1_i8, 1_i8, 1_i8)); assert_eq!(v.xxy(), i8vec3(1_i8, 1_i8, 2_i8)); assert_eq!(v.xxz(), i8vec3(1_i8, 1_i8, 3_i8)); assert_eq!(v.xxw(), i8vec3(1_i8, 1_i8, 4_i8)); assert_eq!(v.xyx(), i8vec3(1_i8, 2_i8, 1_i8)); assert_eq!(v.xyy(), i8vec3(1_i8, 2_i8, 2_i8)); assert_eq!(v.xyz(), i8vec3(1_i8, 2_i8, 3_i8)); assert_eq!(v.xyw(), i8vec3(1_i8, 2_i8, 4_i8)); assert_eq!(v.xzx(), i8vec3(1_i8, 3_i8, 1_i8)); assert_eq!(v.xzy(), i8vec3(1_i8, 3_i8, 2_i8)); assert_eq!(v.xzz(), i8vec3(1_i8, 3_i8, 3_i8)); assert_eq!(v.xzw(), i8vec3(1_i8, 3_i8, 4_i8)); assert_eq!(v.xwx(), i8vec3(1_i8, 4_i8, 1_i8)); assert_eq!(v.xwy(), i8vec3(1_i8, 4_i8, 2_i8)); assert_eq!(v.xwz(), i8vec3(1_i8, 4_i8, 3_i8)); assert_eq!(v.xww(), i8vec3(1_i8, 4_i8, 4_i8)); assert_eq!(v.yxx(), i8vec3(2_i8, 1_i8, 1_i8)); assert_eq!(v.yxy(), i8vec3(2_i8, 1_i8, 2_i8)); assert_eq!(v.yxz(), i8vec3(2_i8, 1_i8, 3_i8)); assert_eq!(v.yxw(), i8vec3(2_i8, 1_i8, 4_i8)); assert_eq!(v.yyx(), i8vec3(2_i8, 2_i8, 1_i8)); assert_eq!(v.yyy(), i8vec3(2_i8, 2_i8, 2_i8)); assert_eq!(v.yyz(), i8vec3(2_i8, 2_i8, 3_i8)); assert_eq!(v.yyw(), i8vec3(2_i8, 2_i8, 4_i8)); assert_eq!(v.yzx(), i8vec3(2_i8, 3_i8, 1_i8)); assert_eq!(v.yzy(), i8vec3(2_i8, 3_i8, 2_i8)); assert_eq!(v.yzz(), i8vec3(2_i8, 3_i8, 3_i8)); assert_eq!(v.yzw(), i8vec3(2_i8, 3_i8, 4_i8)); assert_eq!(v.ywx(), i8vec3(2_i8, 4_i8, 1_i8)); assert_eq!(v.ywy(), i8vec3(2_i8, 4_i8, 2_i8)); assert_eq!(v.ywz(), i8vec3(2_i8, 4_i8, 3_i8)); assert_eq!(v.yww(), i8vec3(2_i8, 4_i8, 4_i8)); assert_eq!(v.zxx(), i8vec3(3_i8, 1_i8, 1_i8)); assert_eq!(v.zxy(), i8vec3(3_i8, 1_i8, 2_i8)); assert_eq!(v.zxz(), i8vec3(3_i8, 1_i8, 3_i8)); assert_eq!(v.zxw(), i8vec3(3_i8, 1_i8, 4_i8)); assert_eq!(v.zyx(), i8vec3(3_i8, 2_i8, 1_i8)); assert_eq!(v.zyy(), i8vec3(3_i8, 2_i8, 2_i8)); assert_eq!(v.zyz(), i8vec3(3_i8, 2_i8, 3_i8)); assert_eq!(v.zyw(), i8vec3(3_i8, 2_i8, 4_i8)); assert_eq!(v.zzx(), i8vec3(3_i8, 3_i8, 1_i8)); assert_eq!(v.zzy(), i8vec3(3_i8, 3_i8, 2_i8)); assert_eq!(v.zzz(), i8vec3(3_i8, 3_i8, 3_i8)); assert_eq!(v.zzw(), i8vec3(3_i8, 3_i8, 4_i8)); assert_eq!(v.zwx(), i8vec3(3_i8, 4_i8, 1_i8)); assert_eq!(v.zwy(), i8vec3(3_i8, 4_i8, 2_i8)); assert_eq!(v.zwz(), i8vec3(3_i8, 4_i8, 3_i8)); assert_eq!(v.zww(), i8vec3(3_i8, 4_i8, 4_i8)); assert_eq!(v.wxx(), i8vec3(4_i8, 1_i8, 1_i8)); assert_eq!(v.wxy(), i8vec3(4_i8, 1_i8, 2_i8)); assert_eq!(v.wxz(), i8vec3(4_i8, 1_i8, 3_i8)); assert_eq!(v.wxw(), i8vec3(4_i8, 1_i8, 4_i8)); assert_eq!(v.wyx(), i8vec3(4_i8, 2_i8, 1_i8)); assert_eq!(v.wyy(), i8vec3(4_i8, 2_i8, 2_i8)); assert_eq!(v.wyz(), i8vec3(4_i8, 2_i8, 3_i8)); assert_eq!(v.wyw(), i8vec3(4_i8, 2_i8, 4_i8)); assert_eq!(v.wzx(), i8vec3(4_i8, 3_i8, 1_i8)); assert_eq!(v.wzy(), i8vec3(4_i8, 3_i8, 2_i8)); assert_eq!(v.wzz(), i8vec3(4_i8, 3_i8, 3_i8)); assert_eq!(v.wzw(), i8vec3(4_i8, 3_i8, 4_i8)); assert_eq!(v.wwx(), i8vec3(4_i8, 4_i8, 1_i8)); assert_eq!(v.wwy(), i8vec3(4_i8, 4_i8, 2_i8)); assert_eq!(v.wwz(), i8vec3(4_i8, 4_i8, 3_i8)); assert_eq!(v.www(), i8vec3(4_i8, 4_i8, 4_i8)); assert_eq!(v.with_xyz(rhs3), i8vec4(11_i8, 12_i8, 13_i8, 4_i8)); assert_eq!(v.with_xyw(rhs3), i8vec4(11_i8, 12_i8, 3_i8, 13_i8)); assert_eq!(v.with_xzy(rhs3), i8vec4(11_i8, 13_i8, 12_i8, 4_i8)); assert_eq!(v.with_xzw(rhs3), i8vec4(11_i8, 2_i8, 12_i8, 13_i8)); assert_eq!(v.with_xwy(rhs3), i8vec4(11_i8, 13_i8, 3_i8, 12_i8)); assert_eq!(v.with_xwz(rhs3), i8vec4(11_i8, 2_i8, 13_i8, 12_i8)); assert_eq!(v.with_yxz(rhs3), i8vec4(12_i8, 11_i8, 13_i8, 4_i8)); assert_eq!(v.with_yxw(rhs3), i8vec4(12_i8, 11_i8, 3_i8, 13_i8)); assert_eq!(v.with_yzx(rhs3), i8vec4(13_i8, 11_i8, 12_i8, 4_i8)); assert_eq!(v.with_yzw(rhs3), i8vec4(1_i8, 11_i8, 12_i8, 13_i8)); assert_eq!(v.with_ywx(rhs3), i8vec4(13_i8, 11_i8, 3_i8, 12_i8)); assert_eq!(v.with_ywz(rhs3), i8vec4(1_i8, 11_i8, 13_i8, 12_i8)); assert_eq!(v.with_zxy(rhs3), i8vec4(12_i8, 13_i8, 11_i8, 4_i8)); assert_eq!(v.with_zxw(rhs3), i8vec4(12_i8, 2_i8, 11_i8, 13_i8)); assert_eq!(v.with_zyx(rhs3), i8vec4(13_i8, 12_i8, 11_i8, 4_i8)); assert_eq!(v.with_zyw(rhs3), i8vec4(1_i8, 12_i8, 11_i8, 13_i8)); assert_eq!(v.with_zwx(rhs3), i8vec4(13_i8, 2_i8, 11_i8, 12_i8)); assert_eq!(v.with_zwy(rhs3), i8vec4(1_i8, 13_i8, 11_i8, 12_i8)); assert_eq!(v.with_wxy(rhs3), i8vec4(12_i8, 13_i8, 3_i8, 11_i8)); assert_eq!(v.with_wxz(rhs3), i8vec4(12_i8, 2_i8, 13_i8, 11_i8)); assert_eq!(v.with_wyx(rhs3), i8vec4(13_i8, 12_i8, 3_i8, 11_i8)); assert_eq!(v.with_wyz(rhs3), i8vec4(1_i8, 12_i8, 13_i8, 11_i8)); assert_eq!(v.with_wzx(rhs3), i8vec4(13_i8, 2_i8, 12_i8, 11_i8)); assert_eq!(v.with_wzy(rhs3), i8vec4(1_i8, 13_i8, 12_i8, 11_i8)); assert_eq!(v.xx(), i8vec2(1_i8, 1_i8)); assert_eq!(v.xy(), i8vec2(1_i8, 2_i8)); assert_eq!(v.xz(), i8vec2(1_i8, 3_i8)); assert_eq!(v.xw(), i8vec2(1_i8, 4_i8)); assert_eq!(v.yx(), i8vec2(2_i8, 1_i8)); assert_eq!(v.yy(), i8vec2(2_i8, 2_i8)); assert_eq!(v.yz(), i8vec2(2_i8, 3_i8)); assert_eq!(v.yw(), i8vec2(2_i8, 4_i8)); assert_eq!(v.zx(), i8vec2(3_i8, 1_i8)); assert_eq!(v.zy(), i8vec2(3_i8, 2_i8)); assert_eq!(v.zz(), i8vec2(3_i8, 3_i8)); assert_eq!(v.zw(), i8vec2(3_i8, 4_i8)); assert_eq!(v.wx(), i8vec2(4_i8, 1_i8)); assert_eq!(v.wy(), i8vec2(4_i8, 2_i8)); assert_eq!(v.wz(), i8vec2(4_i8, 3_i8)); assert_eq!(v.ww(), i8vec2(4_i8, 4_i8)); assert_eq!(v.with_xy(rhs2), i8vec4(11_i8, 12_i8, 3_i8, 4_i8)); assert_eq!(v.with_xz(rhs2), i8vec4(11_i8, 2_i8, 12_i8, 4_i8)); assert_eq!(v.with_xw(rhs2), i8vec4(11_i8, 2_i8, 3_i8, 12_i8)); assert_eq!(v.with_yx(rhs2), i8vec4(12_i8, 11_i8, 3_i8, 4_i8)); assert_eq!(v.with_yz(rhs2), i8vec4(1_i8, 11_i8, 12_i8, 4_i8)); assert_eq!(v.with_yw(rhs2), i8vec4(1_i8, 11_i8, 3_i8, 12_i8)); assert_eq!(v.with_zx(rhs2), i8vec4(12_i8, 2_i8, 11_i8, 4_i8)); assert_eq!(v.with_zy(rhs2), i8vec4(1_i8, 12_i8, 11_i8, 4_i8)); assert_eq!(v.with_zw(rhs2), i8vec4(1_i8, 2_i8, 11_i8, 12_i8)); assert_eq!(v.with_wx(rhs2), i8vec4(12_i8, 2_i8, 3_i8, 11_i8)); assert_eq!(v.with_wy(rhs2), i8vec4(1_i8, 12_i8, 3_i8, 11_i8)); assert_eq!(v.with_wz(rhs2), i8vec4(1_i8, 2_i8, 12_i8, 11_i8)); }); glam_test!(test_i8vec3_swizzles, { let v = i8vec3(1_i8, 2_i8, 3_i8); let rhs2 = i8vec2(11_i8, 12_i8); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), i8vec4(1_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.xxxy(), i8vec4(1_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.xxxz(), i8vec4(1_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.xxyx(), i8vec4(1_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.xxyy(), i8vec4(1_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.xxyz(), i8vec4(1_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.xxzx(), i8vec4(1_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.xxzy(), i8vec4(1_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.xxzz(), i8vec4(1_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.xyxx(), i8vec4(1_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.xyxy(), i8vec4(1_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.xyxz(), i8vec4(1_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.xyyx(), i8vec4(1_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.xyyy(), i8vec4(1_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.xyyz(), i8vec4(1_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.xyzx(), i8vec4(1_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.xyzy(), i8vec4(1_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.xyzz(), i8vec4(1_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.xzxx(), i8vec4(1_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.xzxy(), i8vec4(1_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.xzxz(), i8vec4(1_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.xzyx(), i8vec4(1_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.xzyy(), i8vec4(1_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.xzyz(), i8vec4(1_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.xzzx(), i8vec4(1_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.xzzy(), i8vec4(1_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.xzzz(), i8vec4(1_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.yxxx(), i8vec4(2_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.yxxy(), i8vec4(2_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.yxxz(), i8vec4(2_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.yxyx(), i8vec4(2_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.yxyy(), i8vec4(2_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.yxyz(), i8vec4(2_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.yxzx(), i8vec4(2_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.yxzy(), i8vec4(2_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.yxzz(), i8vec4(2_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.yyxx(), i8vec4(2_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.yyxy(), i8vec4(2_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.yyxz(), i8vec4(2_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.yyyx(), i8vec4(2_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.yyyy(), i8vec4(2_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.yyyz(), i8vec4(2_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.yyzx(), i8vec4(2_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.yyzy(), i8vec4(2_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.yyzz(), i8vec4(2_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.yzxx(), i8vec4(2_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.yzxy(), i8vec4(2_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.yzxz(), i8vec4(2_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.yzyx(), i8vec4(2_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.yzyy(), i8vec4(2_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.yzyz(), i8vec4(2_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.yzzx(), i8vec4(2_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.yzzy(), i8vec4(2_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.yzzz(), i8vec4(2_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.zxxx(), i8vec4(3_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.zxxy(), i8vec4(3_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.zxxz(), i8vec4(3_i8, 1_i8, 1_i8, 3_i8)); assert_eq!(v.zxyx(), i8vec4(3_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.zxyy(), i8vec4(3_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.zxyz(), i8vec4(3_i8, 1_i8, 2_i8, 3_i8)); assert_eq!(v.zxzx(), i8vec4(3_i8, 1_i8, 3_i8, 1_i8)); assert_eq!(v.zxzy(), i8vec4(3_i8, 1_i8, 3_i8, 2_i8)); assert_eq!(v.zxzz(), i8vec4(3_i8, 1_i8, 3_i8, 3_i8)); assert_eq!(v.zyxx(), i8vec4(3_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.zyxy(), i8vec4(3_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.zyxz(), i8vec4(3_i8, 2_i8, 1_i8, 3_i8)); assert_eq!(v.zyyx(), i8vec4(3_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.zyyy(), i8vec4(3_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.zyyz(), i8vec4(3_i8, 2_i8, 2_i8, 3_i8)); assert_eq!(v.zyzx(), i8vec4(3_i8, 2_i8, 3_i8, 1_i8)); assert_eq!(v.zyzy(), i8vec4(3_i8, 2_i8, 3_i8, 2_i8)); assert_eq!(v.zyzz(), i8vec4(3_i8, 2_i8, 3_i8, 3_i8)); assert_eq!(v.zzxx(), i8vec4(3_i8, 3_i8, 1_i8, 1_i8)); assert_eq!(v.zzxy(), i8vec4(3_i8, 3_i8, 1_i8, 2_i8)); assert_eq!(v.zzxz(), i8vec4(3_i8, 3_i8, 1_i8, 3_i8)); assert_eq!(v.zzyx(), i8vec4(3_i8, 3_i8, 2_i8, 1_i8)); assert_eq!(v.zzyy(), i8vec4(3_i8, 3_i8, 2_i8, 2_i8)); assert_eq!(v.zzyz(), i8vec4(3_i8, 3_i8, 2_i8, 3_i8)); assert_eq!(v.zzzx(), i8vec4(3_i8, 3_i8, 3_i8, 1_i8)); assert_eq!(v.zzzy(), i8vec4(3_i8, 3_i8, 3_i8, 2_i8)); assert_eq!(v.zzzz(), i8vec4(3_i8, 3_i8, 3_i8, 3_i8)); assert_eq!(v.xxx(), i8vec3(1_i8, 1_i8, 1_i8)); assert_eq!(v.xxy(), i8vec3(1_i8, 1_i8, 2_i8)); assert_eq!(v.xxz(), i8vec3(1_i8, 1_i8, 3_i8)); assert_eq!(v.xyx(), i8vec3(1_i8, 2_i8, 1_i8)); assert_eq!(v.xyy(), i8vec3(1_i8, 2_i8, 2_i8)); assert_eq!(v.xzx(), i8vec3(1_i8, 3_i8, 1_i8)); assert_eq!(v.xzy(), i8vec3(1_i8, 3_i8, 2_i8)); assert_eq!(v.xzz(), i8vec3(1_i8, 3_i8, 3_i8)); assert_eq!(v.yxx(), i8vec3(2_i8, 1_i8, 1_i8)); assert_eq!(v.yxy(), i8vec3(2_i8, 1_i8, 2_i8)); assert_eq!(v.yxz(), i8vec3(2_i8, 1_i8, 3_i8)); assert_eq!(v.yyx(), i8vec3(2_i8, 2_i8, 1_i8)); assert_eq!(v.yyy(), i8vec3(2_i8, 2_i8, 2_i8)); assert_eq!(v.yyz(), i8vec3(2_i8, 2_i8, 3_i8)); assert_eq!(v.yzx(), i8vec3(2_i8, 3_i8, 1_i8)); assert_eq!(v.yzy(), i8vec3(2_i8, 3_i8, 2_i8)); assert_eq!(v.yzz(), i8vec3(2_i8, 3_i8, 3_i8)); assert_eq!(v.zxx(), i8vec3(3_i8, 1_i8, 1_i8)); assert_eq!(v.zxy(), i8vec3(3_i8, 1_i8, 2_i8)); assert_eq!(v.zxz(), i8vec3(3_i8, 1_i8, 3_i8)); assert_eq!(v.zyx(), i8vec3(3_i8, 2_i8, 1_i8)); assert_eq!(v.zyy(), i8vec3(3_i8, 2_i8, 2_i8)); assert_eq!(v.zyz(), i8vec3(3_i8, 2_i8, 3_i8)); assert_eq!(v.zzx(), i8vec3(3_i8, 3_i8, 1_i8)); assert_eq!(v.zzy(), i8vec3(3_i8, 3_i8, 2_i8)); assert_eq!(v.zzz(), i8vec3(3_i8, 3_i8, 3_i8)); assert_eq!(v.xx(), i8vec2(1_i8, 1_i8)); assert_eq!(v.xy(), i8vec2(1_i8, 2_i8)); assert_eq!(v.xz(), i8vec2(1_i8, 3_i8)); assert_eq!(v.yx(), i8vec2(2_i8, 1_i8)); assert_eq!(v.yy(), i8vec2(2_i8, 2_i8)); assert_eq!(v.yz(), i8vec2(2_i8, 3_i8)); assert_eq!(v.zx(), i8vec2(3_i8, 1_i8)); assert_eq!(v.zy(), i8vec2(3_i8, 2_i8)); assert_eq!(v.zz(), i8vec2(3_i8, 3_i8)); assert_eq!(v.with_xy(rhs2), i8vec3(11_i8, 12_i8, 3_i8)); assert_eq!(v.with_xz(rhs2), i8vec3(11_i8, 2_i8, 12_i8)); assert_eq!(v.with_yx(rhs2), i8vec3(12_i8, 11_i8, 3_i8)); assert_eq!(v.with_yz(rhs2), i8vec3(1_i8, 11_i8, 12_i8)); assert_eq!(v.with_zx(rhs2), i8vec3(12_i8, 2_i8, 11_i8)); assert_eq!(v.with_zy(rhs2), i8vec3(1_i8, 12_i8, 11_i8)); }); glam_test!(test_i8vec2_swizzles, { let v = i8vec2(1_i8, 2_i8); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), i8vec4(1_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.xxxy(), i8vec4(1_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.xxyx(), i8vec4(1_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.xxyy(), i8vec4(1_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.xyxx(), i8vec4(1_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.xyxy(), i8vec4(1_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.xyyx(), i8vec4(1_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.xyyy(), i8vec4(1_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.yxxx(), i8vec4(2_i8, 1_i8, 1_i8, 1_i8)); assert_eq!(v.yxxy(), i8vec4(2_i8, 1_i8, 1_i8, 2_i8)); assert_eq!(v.yxyx(), i8vec4(2_i8, 1_i8, 2_i8, 1_i8)); assert_eq!(v.yxyy(), i8vec4(2_i8, 1_i8, 2_i8, 2_i8)); assert_eq!(v.yyxx(), i8vec4(2_i8, 2_i8, 1_i8, 1_i8)); assert_eq!(v.yyxy(), i8vec4(2_i8, 2_i8, 1_i8, 2_i8)); assert_eq!(v.yyyx(), i8vec4(2_i8, 2_i8, 2_i8, 1_i8)); assert_eq!(v.yyyy(), i8vec4(2_i8, 2_i8, 2_i8, 2_i8)); assert_eq!(v.xxx(), i8vec3(1_i8, 1_i8, 1_i8)); assert_eq!(v.xxy(), i8vec3(1_i8, 1_i8, 2_i8)); assert_eq!(v.xyx(), i8vec3(1_i8, 2_i8, 1_i8)); assert_eq!(v.xyy(), i8vec3(1_i8, 2_i8, 2_i8)); assert_eq!(v.yxx(), i8vec3(2_i8, 1_i8, 1_i8)); assert_eq!(v.yxy(), i8vec3(2_i8, 1_i8, 2_i8)); assert_eq!(v.yyx(), i8vec3(2_i8, 2_i8, 1_i8)); assert_eq!(v.yyy(), i8vec3(2_i8, 2_i8, 2_i8)); assert_eq!(v.xx(), i8vec2(1_i8, 1_i8)); assert_eq!(v.yx(), i8vec2(2_i8, 1_i8)); assert_eq!(v.yy(), i8vec2(2_i8, 2_i8)); }); glam-0.30.1/tests/swizzles_u16.rs000064400000000000000000000773051046102023000147360ustar 00000000000000// 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); let rhs3 = u16vec3(11_u16, 12_u16, 13_u16); let rhs2 = u16vec2(11_u16, 12_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.with_xyz(rhs3), u16vec4(11_u16, 12_u16, 13_u16, 4_u16)); assert_eq!(v.with_xyw(rhs3), u16vec4(11_u16, 12_u16, 3_u16, 13_u16)); assert_eq!(v.with_xzy(rhs3), u16vec4(11_u16, 13_u16, 12_u16, 4_u16)); assert_eq!(v.with_xzw(rhs3), u16vec4(11_u16, 2_u16, 12_u16, 13_u16)); assert_eq!(v.with_xwy(rhs3), u16vec4(11_u16, 13_u16, 3_u16, 12_u16)); assert_eq!(v.with_xwz(rhs3), u16vec4(11_u16, 2_u16, 13_u16, 12_u16)); assert_eq!(v.with_yxz(rhs3), u16vec4(12_u16, 11_u16, 13_u16, 4_u16)); assert_eq!(v.with_yxw(rhs3), u16vec4(12_u16, 11_u16, 3_u16, 13_u16)); assert_eq!(v.with_yzx(rhs3), u16vec4(13_u16, 11_u16, 12_u16, 4_u16)); assert_eq!(v.with_yzw(rhs3), u16vec4(1_u16, 11_u16, 12_u16, 13_u16)); assert_eq!(v.with_ywx(rhs3), u16vec4(13_u16, 11_u16, 3_u16, 12_u16)); assert_eq!(v.with_ywz(rhs3), u16vec4(1_u16, 11_u16, 13_u16, 12_u16)); assert_eq!(v.with_zxy(rhs3), u16vec4(12_u16, 13_u16, 11_u16, 4_u16)); assert_eq!(v.with_zxw(rhs3), u16vec4(12_u16, 2_u16, 11_u16, 13_u16)); assert_eq!(v.with_zyx(rhs3), u16vec4(13_u16, 12_u16, 11_u16, 4_u16)); assert_eq!(v.with_zyw(rhs3), u16vec4(1_u16, 12_u16, 11_u16, 13_u16)); assert_eq!(v.with_zwx(rhs3), u16vec4(13_u16, 2_u16, 11_u16, 12_u16)); assert_eq!(v.with_zwy(rhs3), u16vec4(1_u16, 13_u16, 11_u16, 12_u16)); assert_eq!(v.with_wxy(rhs3), u16vec4(12_u16, 13_u16, 3_u16, 11_u16)); assert_eq!(v.with_wxz(rhs3), u16vec4(12_u16, 2_u16, 13_u16, 11_u16)); assert_eq!(v.with_wyx(rhs3), u16vec4(13_u16, 12_u16, 3_u16, 11_u16)); assert_eq!(v.with_wyz(rhs3), u16vec4(1_u16, 12_u16, 13_u16, 11_u16)); assert_eq!(v.with_wzx(rhs3), u16vec4(13_u16, 2_u16, 12_u16, 11_u16)); assert_eq!(v.with_wzy(rhs3), u16vec4(1_u16, 13_u16, 12_u16, 11_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)); assert_eq!(v.with_xy(rhs2), u16vec4(11_u16, 12_u16, 3_u16, 4_u16)); assert_eq!(v.with_xz(rhs2), u16vec4(11_u16, 2_u16, 12_u16, 4_u16)); assert_eq!(v.with_xw(rhs2), u16vec4(11_u16, 2_u16, 3_u16, 12_u16)); assert_eq!(v.with_yx(rhs2), u16vec4(12_u16, 11_u16, 3_u16, 4_u16)); assert_eq!(v.with_yz(rhs2), u16vec4(1_u16, 11_u16, 12_u16, 4_u16)); assert_eq!(v.with_yw(rhs2), u16vec4(1_u16, 11_u16, 3_u16, 12_u16)); assert_eq!(v.with_zx(rhs2), u16vec4(12_u16, 2_u16, 11_u16, 4_u16)); assert_eq!(v.with_zy(rhs2), u16vec4(1_u16, 12_u16, 11_u16, 4_u16)); assert_eq!(v.with_zw(rhs2), u16vec4(1_u16, 2_u16, 11_u16, 12_u16)); assert_eq!(v.with_wx(rhs2), u16vec4(12_u16, 2_u16, 3_u16, 11_u16)); assert_eq!(v.with_wy(rhs2), u16vec4(1_u16, 12_u16, 3_u16, 11_u16)); assert_eq!(v.with_wz(rhs2), u16vec4(1_u16, 2_u16, 12_u16, 11_u16)); }); glam_test!(test_u16vec3_swizzles, { let v = u16vec3(1_u16, 2_u16, 3_u16); let rhs2 = u16vec2(11_u16, 12_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)); assert_eq!(v.with_xy(rhs2), u16vec3(11_u16, 12_u16, 3_u16)); assert_eq!(v.with_xz(rhs2), u16vec3(11_u16, 2_u16, 12_u16)); assert_eq!(v.with_yx(rhs2), u16vec3(12_u16, 11_u16, 3_u16)); assert_eq!(v.with_yz(rhs2), u16vec3(1_u16, 11_u16, 12_u16)); assert_eq!(v.with_zx(rhs2), u16vec3(12_u16, 2_u16, 11_u16)); assert_eq!(v.with_zy(rhs2), u16vec3(1_u16, 12_u16, 11_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)); }); glam-0.30.1/tests/swizzles_u32.rs000064400000000000000000000752431046102023000147330ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_uvec4_swizzles, { let v = uvec4(1_u32, 2_u32, 3_u32, 4_u32); let rhs3 = uvec3(11_u32, 12_u32, 13_u32); let rhs2 = uvec2(11_u32, 12_u32); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), uvec4(1_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.xxxy(), uvec4(1_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.xxxz(), uvec4(1_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.xxxw(), uvec4(1_u32, 1_u32, 1_u32, 4_u32)); assert_eq!(v.xxyx(), uvec4(1_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.xxyy(), uvec4(1_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.xxyz(), uvec4(1_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.xxyw(), uvec4(1_u32, 1_u32, 2_u32, 4_u32)); assert_eq!(v.xxzx(), uvec4(1_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.xxzy(), uvec4(1_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.xxzz(), uvec4(1_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.xxzw(), uvec4(1_u32, 1_u32, 3_u32, 4_u32)); assert_eq!(v.xxwx(), uvec4(1_u32, 1_u32, 4_u32, 1_u32)); assert_eq!(v.xxwy(), uvec4(1_u32, 1_u32, 4_u32, 2_u32)); assert_eq!(v.xxwz(), uvec4(1_u32, 1_u32, 4_u32, 3_u32)); assert_eq!(v.xxww(), uvec4(1_u32, 1_u32, 4_u32, 4_u32)); assert_eq!(v.xyxx(), uvec4(1_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.xyxy(), uvec4(1_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.xyxz(), uvec4(1_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.xyxw(), uvec4(1_u32, 2_u32, 1_u32, 4_u32)); assert_eq!(v.xyyx(), uvec4(1_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.xyyy(), uvec4(1_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.xyyz(), uvec4(1_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.xyyw(), uvec4(1_u32, 2_u32, 2_u32, 4_u32)); assert_eq!(v.xyzx(), uvec4(1_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.xyzy(), uvec4(1_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.xyzz(), uvec4(1_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.xywx(), uvec4(1_u32, 2_u32, 4_u32, 1_u32)); assert_eq!(v.xywy(), uvec4(1_u32, 2_u32, 4_u32, 2_u32)); assert_eq!(v.xywz(), uvec4(1_u32, 2_u32, 4_u32, 3_u32)); assert_eq!(v.xyww(), uvec4(1_u32, 2_u32, 4_u32, 4_u32)); assert_eq!(v.xzxx(), uvec4(1_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.xzxy(), uvec4(1_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.xzxz(), uvec4(1_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.xzxw(), uvec4(1_u32, 3_u32, 1_u32, 4_u32)); assert_eq!(v.xzyx(), uvec4(1_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.xzyy(), uvec4(1_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.xzyz(), uvec4(1_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.xzyw(), uvec4(1_u32, 3_u32, 2_u32, 4_u32)); assert_eq!(v.xzzx(), uvec4(1_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.xzzy(), uvec4(1_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.xzzz(), uvec4(1_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.xzzw(), uvec4(1_u32, 3_u32, 3_u32, 4_u32)); assert_eq!(v.xzwx(), uvec4(1_u32, 3_u32, 4_u32, 1_u32)); assert_eq!(v.xzwy(), uvec4(1_u32, 3_u32, 4_u32, 2_u32)); assert_eq!(v.xzwz(), uvec4(1_u32, 3_u32, 4_u32, 3_u32)); assert_eq!(v.xzww(), uvec4(1_u32, 3_u32, 4_u32, 4_u32)); assert_eq!(v.xwxx(), uvec4(1_u32, 4_u32, 1_u32, 1_u32)); assert_eq!(v.xwxy(), uvec4(1_u32, 4_u32, 1_u32, 2_u32)); assert_eq!(v.xwxz(), uvec4(1_u32, 4_u32, 1_u32, 3_u32)); assert_eq!(v.xwxw(), uvec4(1_u32, 4_u32, 1_u32, 4_u32)); assert_eq!(v.xwyx(), uvec4(1_u32, 4_u32, 2_u32, 1_u32)); assert_eq!(v.xwyy(), uvec4(1_u32, 4_u32, 2_u32, 2_u32)); assert_eq!(v.xwyz(), uvec4(1_u32, 4_u32, 2_u32, 3_u32)); assert_eq!(v.xwyw(), uvec4(1_u32, 4_u32, 2_u32, 4_u32)); assert_eq!(v.xwzx(), uvec4(1_u32, 4_u32, 3_u32, 1_u32)); assert_eq!(v.xwzy(), uvec4(1_u32, 4_u32, 3_u32, 2_u32)); assert_eq!(v.xwzz(), uvec4(1_u32, 4_u32, 3_u32, 3_u32)); assert_eq!(v.xwzw(), uvec4(1_u32, 4_u32, 3_u32, 4_u32)); assert_eq!(v.xwwx(), uvec4(1_u32, 4_u32, 4_u32, 1_u32)); assert_eq!(v.xwwy(), uvec4(1_u32, 4_u32, 4_u32, 2_u32)); assert_eq!(v.xwwz(), uvec4(1_u32, 4_u32, 4_u32, 3_u32)); assert_eq!(v.xwww(), uvec4(1_u32, 4_u32, 4_u32, 4_u32)); assert_eq!(v.yxxx(), uvec4(2_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.yxxy(), uvec4(2_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.yxxz(), uvec4(2_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.yxxw(), uvec4(2_u32, 1_u32, 1_u32, 4_u32)); assert_eq!(v.yxyx(), uvec4(2_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.yxyy(), uvec4(2_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.yxyz(), uvec4(2_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.yxyw(), uvec4(2_u32, 1_u32, 2_u32, 4_u32)); assert_eq!(v.yxzx(), uvec4(2_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.yxzy(), uvec4(2_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.yxzz(), uvec4(2_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.yxzw(), uvec4(2_u32, 1_u32, 3_u32, 4_u32)); assert_eq!(v.yxwx(), uvec4(2_u32, 1_u32, 4_u32, 1_u32)); assert_eq!(v.yxwy(), uvec4(2_u32, 1_u32, 4_u32, 2_u32)); assert_eq!(v.yxwz(), uvec4(2_u32, 1_u32, 4_u32, 3_u32)); assert_eq!(v.yxww(), uvec4(2_u32, 1_u32, 4_u32, 4_u32)); assert_eq!(v.yyxx(), uvec4(2_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.yyxy(), uvec4(2_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.yyxz(), uvec4(2_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.yyxw(), uvec4(2_u32, 2_u32, 1_u32, 4_u32)); assert_eq!(v.yyyx(), uvec4(2_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.yyyy(), uvec4(2_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.yyyz(), uvec4(2_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.yyyw(), uvec4(2_u32, 2_u32, 2_u32, 4_u32)); assert_eq!(v.yyzx(), uvec4(2_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.yyzy(), uvec4(2_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.yyzz(), uvec4(2_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.yyzw(), uvec4(2_u32, 2_u32, 3_u32, 4_u32)); assert_eq!(v.yywx(), uvec4(2_u32, 2_u32, 4_u32, 1_u32)); assert_eq!(v.yywy(), uvec4(2_u32, 2_u32, 4_u32, 2_u32)); assert_eq!(v.yywz(), uvec4(2_u32, 2_u32, 4_u32, 3_u32)); assert_eq!(v.yyww(), uvec4(2_u32, 2_u32, 4_u32, 4_u32)); assert_eq!(v.yzxx(), uvec4(2_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.yzxy(), uvec4(2_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.yzxz(), uvec4(2_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.yzxw(), uvec4(2_u32, 3_u32, 1_u32, 4_u32)); assert_eq!(v.yzyx(), uvec4(2_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.yzyy(), uvec4(2_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.yzyz(), uvec4(2_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.yzyw(), uvec4(2_u32, 3_u32, 2_u32, 4_u32)); assert_eq!(v.yzzx(), uvec4(2_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.yzzy(), uvec4(2_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.yzzz(), uvec4(2_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.yzzw(), uvec4(2_u32, 3_u32, 3_u32, 4_u32)); assert_eq!(v.yzwx(), uvec4(2_u32, 3_u32, 4_u32, 1_u32)); assert_eq!(v.yzwy(), uvec4(2_u32, 3_u32, 4_u32, 2_u32)); assert_eq!(v.yzwz(), uvec4(2_u32, 3_u32, 4_u32, 3_u32)); assert_eq!(v.yzww(), uvec4(2_u32, 3_u32, 4_u32, 4_u32)); assert_eq!(v.ywxx(), uvec4(2_u32, 4_u32, 1_u32, 1_u32)); assert_eq!(v.ywxy(), uvec4(2_u32, 4_u32, 1_u32, 2_u32)); assert_eq!(v.ywxz(), uvec4(2_u32, 4_u32, 1_u32, 3_u32)); assert_eq!(v.ywxw(), uvec4(2_u32, 4_u32, 1_u32, 4_u32)); assert_eq!(v.ywyx(), uvec4(2_u32, 4_u32, 2_u32, 1_u32)); assert_eq!(v.ywyy(), uvec4(2_u32, 4_u32, 2_u32, 2_u32)); assert_eq!(v.ywyz(), uvec4(2_u32, 4_u32, 2_u32, 3_u32)); assert_eq!(v.ywyw(), uvec4(2_u32, 4_u32, 2_u32, 4_u32)); assert_eq!(v.ywzx(), uvec4(2_u32, 4_u32, 3_u32, 1_u32)); assert_eq!(v.ywzy(), uvec4(2_u32, 4_u32, 3_u32, 2_u32)); assert_eq!(v.ywzz(), uvec4(2_u32, 4_u32, 3_u32, 3_u32)); assert_eq!(v.ywzw(), uvec4(2_u32, 4_u32, 3_u32, 4_u32)); assert_eq!(v.ywwx(), uvec4(2_u32, 4_u32, 4_u32, 1_u32)); assert_eq!(v.ywwy(), uvec4(2_u32, 4_u32, 4_u32, 2_u32)); assert_eq!(v.ywwz(), uvec4(2_u32, 4_u32, 4_u32, 3_u32)); assert_eq!(v.ywww(), uvec4(2_u32, 4_u32, 4_u32, 4_u32)); assert_eq!(v.zxxx(), uvec4(3_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.zxxy(), uvec4(3_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.zxxz(), uvec4(3_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.zxxw(), uvec4(3_u32, 1_u32, 1_u32, 4_u32)); assert_eq!(v.zxyx(), uvec4(3_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.zxyy(), uvec4(3_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.zxyz(), uvec4(3_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.zxyw(), uvec4(3_u32, 1_u32, 2_u32, 4_u32)); assert_eq!(v.zxzx(), uvec4(3_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.zxzy(), uvec4(3_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.zxzz(), uvec4(3_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.zxzw(), uvec4(3_u32, 1_u32, 3_u32, 4_u32)); assert_eq!(v.zxwx(), uvec4(3_u32, 1_u32, 4_u32, 1_u32)); assert_eq!(v.zxwy(), uvec4(3_u32, 1_u32, 4_u32, 2_u32)); assert_eq!(v.zxwz(), uvec4(3_u32, 1_u32, 4_u32, 3_u32)); assert_eq!(v.zxww(), uvec4(3_u32, 1_u32, 4_u32, 4_u32)); assert_eq!(v.zyxx(), uvec4(3_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.zyxy(), uvec4(3_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.zyxz(), uvec4(3_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.zyxw(), uvec4(3_u32, 2_u32, 1_u32, 4_u32)); assert_eq!(v.zyyx(), uvec4(3_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.zyyy(), uvec4(3_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.zyyz(), uvec4(3_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.zyyw(), uvec4(3_u32, 2_u32, 2_u32, 4_u32)); assert_eq!(v.zyzx(), uvec4(3_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.zyzy(), uvec4(3_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.zyzz(), uvec4(3_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.zyzw(), uvec4(3_u32, 2_u32, 3_u32, 4_u32)); assert_eq!(v.zywx(), uvec4(3_u32, 2_u32, 4_u32, 1_u32)); assert_eq!(v.zywy(), uvec4(3_u32, 2_u32, 4_u32, 2_u32)); assert_eq!(v.zywz(), uvec4(3_u32, 2_u32, 4_u32, 3_u32)); assert_eq!(v.zyww(), uvec4(3_u32, 2_u32, 4_u32, 4_u32)); assert_eq!(v.zzxx(), uvec4(3_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.zzxy(), uvec4(3_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.zzxz(), uvec4(3_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.zzxw(), uvec4(3_u32, 3_u32, 1_u32, 4_u32)); assert_eq!(v.zzyx(), uvec4(3_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.zzyy(), uvec4(3_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.zzyz(), uvec4(3_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.zzyw(), uvec4(3_u32, 3_u32, 2_u32, 4_u32)); assert_eq!(v.zzzx(), uvec4(3_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.zzzy(), uvec4(3_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.zzzz(), uvec4(3_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.zzzw(), uvec4(3_u32, 3_u32, 3_u32, 4_u32)); assert_eq!(v.zzwx(), uvec4(3_u32, 3_u32, 4_u32, 1_u32)); assert_eq!(v.zzwy(), uvec4(3_u32, 3_u32, 4_u32, 2_u32)); assert_eq!(v.zzwz(), uvec4(3_u32, 3_u32, 4_u32, 3_u32)); assert_eq!(v.zzww(), uvec4(3_u32, 3_u32, 4_u32, 4_u32)); assert_eq!(v.zwxx(), uvec4(3_u32, 4_u32, 1_u32, 1_u32)); assert_eq!(v.zwxy(), uvec4(3_u32, 4_u32, 1_u32, 2_u32)); assert_eq!(v.zwxz(), uvec4(3_u32, 4_u32, 1_u32, 3_u32)); assert_eq!(v.zwxw(), uvec4(3_u32, 4_u32, 1_u32, 4_u32)); assert_eq!(v.zwyx(), uvec4(3_u32, 4_u32, 2_u32, 1_u32)); assert_eq!(v.zwyy(), uvec4(3_u32, 4_u32, 2_u32, 2_u32)); assert_eq!(v.zwyz(), uvec4(3_u32, 4_u32, 2_u32, 3_u32)); assert_eq!(v.zwyw(), uvec4(3_u32, 4_u32, 2_u32, 4_u32)); assert_eq!(v.zwzx(), uvec4(3_u32, 4_u32, 3_u32, 1_u32)); assert_eq!(v.zwzy(), uvec4(3_u32, 4_u32, 3_u32, 2_u32)); assert_eq!(v.zwzz(), uvec4(3_u32, 4_u32, 3_u32, 3_u32)); assert_eq!(v.zwzw(), uvec4(3_u32, 4_u32, 3_u32, 4_u32)); assert_eq!(v.zwwx(), uvec4(3_u32, 4_u32, 4_u32, 1_u32)); assert_eq!(v.zwwy(), uvec4(3_u32, 4_u32, 4_u32, 2_u32)); assert_eq!(v.zwwz(), uvec4(3_u32, 4_u32, 4_u32, 3_u32)); assert_eq!(v.zwww(), uvec4(3_u32, 4_u32, 4_u32, 4_u32)); assert_eq!(v.wxxx(), uvec4(4_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.wxxy(), uvec4(4_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.wxxz(), uvec4(4_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.wxxw(), uvec4(4_u32, 1_u32, 1_u32, 4_u32)); assert_eq!(v.wxyx(), uvec4(4_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.wxyy(), uvec4(4_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.wxyz(), uvec4(4_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.wxyw(), uvec4(4_u32, 1_u32, 2_u32, 4_u32)); assert_eq!(v.wxzx(), uvec4(4_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.wxzy(), uvec4(4_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.wxzz(), uvec4(4_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.wxzw(), uvec4(4_u32, 1_u32, 3_u32, 4_u32)); assert_eq!(v.wxwx(), uvec4(4_u32, 1_u32, 4_u32, 1_u32)); assert_eq!(v.wxwy(), uvec4(4_u32, 1_u32, 4_u32, 2_u32)); assert_eq!(v.wxwz(), uvec4(4_u32, 1_u32, 4_u32, 3_u32)); assert_eq!(v.wxww(), uvec4(4_u32, 1_u32, 4_u32, 4_u32)); assert_eq!(v.wyxx(), uvec4(4_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.wyxy(), uvec4(4_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.wyxz(), uvec4(4_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.wyxw(), uvec4(4_u32, 2_u32, 1_u32, 4_u32)); assert_eq!(v.wyyx(), uvec4(4_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.wyyy(), uvec4(4_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.wyyz(), uvec4(4_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.wyyw(), uvec4(4_u32, 2_u32, 2_u32, 4_u32)); assert_eq!(v.wyzx(), uvec4(4_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.wyzy(), uvec4(4_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.wyzz(), uvec4(4_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.wyzw(), uvec4(4_u32, 2_u32, 3_u32, 4_u32)); assert_eq!(v.wywx(), uvec4(4_u32, 2_u32, 4_u32, 1_u32)); assert_eq!(v.wywy(), uvec4(4_u32, 2_u32, 4_u32, 2_u32)); assert_eq!(v.wywz(), uvec4(4_u32, 2_u32, 4_u32, 3_u32)); assert_eq!(v.wyww(), uvec4(4_u32, 2_u32, 4_u32, 4_u32)); assert_eq!(v.wzxx(), uvec4(4_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.wzxy(), uvec4(4_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.wzxz(), uvec4(4_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.wzxw(), uvec4(4_u32, 3_u32, 1_u32, 4_u32)); assert_eq!(v.wzyx(), uvec4(4_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.wzyy(), uvec4(4_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.wzyz(), uvec4(4_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.wzyw(), uvec4(4_u32, 3_u32, 2_u32, 4_u32)); assert_eq!(v.wzzx(), uvec4(4_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.wzzy(), uvec4(4_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.wzzz(), uvec4(4_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.wzzw(), uvec4(4_u32, 3_u32, 3_u32, 4_u32)); assert_eq!(v.wzwx(), uvec4(4_u32, 3_u32, 4_u32, 1_u32)); assert_eq!(v.wzwy(), uvec4(4_u32, 3_u32, 4_u32, 2_u32)); assert_eq!(v.wzwz(), uvec4(4_u32, 3_u32, 4_u32, 3_u32)); assert_eq!(v.wzww(), uvec4(4_u32, 3_u32, 4_u32, 4_u32)); assert_eq!(v.wwxx(), uvec4(4_u32, 4_u32, 1_u32, 1_u32)); assert_eq!(v.wwxy(), uvec4(4_u32, 4_u32, 1_u32, 2_u32)); assert_eq!(v.wwxz(), uvec4(4_u32, 4_u32, 1_u32, 3_u32)); assert_eq!(v.wwxw(), uvec4(4_u32, 4_u32, 1_u32, 4_u32)); assert_eq!(v.wwyx(), uvec4(4_u32, 4_u32, 2_u32, 1_u32)); assert_eq!(v.wwyy(), uvec4(4_u32, 4_u32, 2_u32, 2_u32)); assert_eq!(v.wwyz(), uvec4(4_u32, 4_u32, 2_u32, 3_u32)); assert_eq!(v.wwyw(), uvec4(4_u32, 4_u32, 2_u32, 4_u32)); assert_eq!(v.wwzx(), uvec4(4_u32, 4_u32, 3_u32, 1_u32)); assert_eq!(v.wwzy(), uvec4(4_u32, 4_u32, 3_u32, 2_u32)); assert_eq!(v.wwzz(), uvec4(4_u32, 4_u32, 3_u32, 3_u32)); assert_eq!(v.wwzw(), uvec4(4_u32, 4_u32, 3_u32, 4_u32)); assert_eq!(v.wwwx(), uvec4(4_u32, 4_u32, 4_u32, 1_u32)); assert_eq!(v.wwwy(), uvec4(4_u32, 4_u32, 4_u32, 2_u32)); assert_eq!(v.wwwz(), uvec4(4_u32, 4_u32, 4_u32, 3_u32)); assert_eq!(v.wwww(), uvec4(4_u32, 4_u32, 4_u32, 4_u32)); assert_eq!(v.xxx(), uvec3(1_u32, 1_u32, 1_u32)); assert_eq!(v.xxy(), uvec3(1_u32, 1_u32, 2_u32)); assert_eq!(v.xxz(), uvec3(1_u32, 1_u32, 3_u32)); assert_eq!(v.xxw(), uvec3(1_u32, 1_u32, 4_u32)); assert_eq!(v.xyx(), uvec3(1_u32, 2_u32, 1_u32)); assert_eq!(v.xyy(), uvec3(1_u32, 2_u32, 2_u32)); assert_eq!(v.xyz(), uvec3(1_u32, 2_u32, 3_u32)); assert_eq!(v.xyw(), uvec3(1_u32, 2_u32, 4_u32)); assert_eq!(v.xzx(), uvec3(1_u32, 3_u32, 1_u32)); assert_eq!(v.xzy(), uvec3(1_u32, 3_u32, 2_u32)); assert_eq!(v.xzz(), uvec3(1_u32, 3_u32, 3_u32)); assert_eq!(v.xzw(), uvec3(1_u32, 3_u32, 4_u32)); assert_eq!(v.xwx(), uvec3(1_u32, 4_u32, 1_u32)); assert_eq!(v.xwy(), uvec3(1_u32, 4_u32, 2_u32)); assert_eq!(v.xwz(), uvec3(1_u32, 4_u32, 3_u32)); assert_eq!(v.xww(), uvec3(1_u32, 4_u32, 4_u32)); assert_eq!(v.yxx(), uvec3(2_u32, 1_u32, 1_u32)); assert_eq!(v.yxy(), uvec3(2_u32, 1_u32, 2_u32)); assert_eq!(v.yxz(), uvec3(2_u32, 1_u32, 3_u32)); assert_eq!(v.yxw(), uvec3(2_u32, 1_u32, 4_u32)); assert_eq!(v.yyx(), uvec3(2_u32, 2_u32, 1_u32)); assert_eq!(v.yyy(), uvec3(2_u32, 2_u32, 2_u32)); assert_eq!(v.yyz(), uvec3(2_u32, 2_u32, 3_u32)); assert_eq!(v.yyw(), uvec3(2_u32, 2_u32, 4_u32)); assert_eq!(v.yzx(), uvec3(2_u32, 3_u32, 1_u32)); assert_eq!(v.yzy(), uvec3(2_u32, 3_u32, 2_u32)); assert_eq!(v.yzz(), uvec3(2_u32, 3_u32, 3_u32)); assert_eq!(v.yzw(), uvec3(2_u32, 3_u32, 4_u32)); assert_eq!(v.ywx(), uvec3(2_u32, 4_u32, 1_u32)); assert_eq!(v.ywy(), uvec3(2_u32, 4_u32, 2_u32)); assert_eq!(v.ywz(), uvec3(2_u32, 4_u32, 3_u32)); assert_eq!(v.yww(), uvec3(2_u32, 4_u32, 4_u32)); assert_eq!(v.zxx(), uvec3(3_u32, 1_u32, 1_u32)); assert_eq!(v.zxy(), uvec3(3_u32, 1_u32, 2_u32)); assert_eq!(v.zxz(), uvec3(3_u32, 1_u32, 3_u32)); assert_eq!(v.zxw(), uvec3(3_u32, 1_u32, 4_u32)); assert_eq!(v.zyx(), uvec3(3_u32, 2_u32, 1_u32)); assert_eq!(v.zyy(), uvec3(3_u32, 2_u32, 2_u32)); assert_eq!(v.zyz(), uvec3(3_u32, 2_u32, 3_u32)); assert_eq!(v.zyw(), uvec3(3_u32, 2_u32, 4_u32)); assert_eq!(v.zzx(), uvec3(3_u32, 3_u32, 1_u32)); assert_eq!(v.zzy(), uvec3(3_u32, 3_u32, 2_u32)); assert_eq!(v.zzz(), uvec3(3_u32, 3_u32, 3_u32)); assert_eq!(v.zzw(), uvec3(3_u32, 3_u32, 4_u32)); assert_eq!(v.zwx(), uvec3(3_u32, 4_u32, 1_u32)); assert_eq!(v.zwy(), uvec3(3_u32, 4_u32, 2_u32)); assert_eq!(v.zwz(), uvec3(3_u32, 4_u32, 3_u32)); assert_eq!(v.zww(), uvec3(3_u32, 4_u32, 4_u32)); assert_eq!(v.wxx(), uvec3(4_u32, 1_u32, 1_u32)); assert_eq!(v.wxy(), uvec3(4_u32, 1_u32, 2_u32)); assert_eq!(v.wxz(), uvec3(4_u32, 1_u32, 3_u32)); assert_eq!(v.wxw(), uvec3(4_u32, 1_u32, 4_u32)); assert_eq!(v.wyx(), uvec3(4_u32, 2_u32, 1_u32)); assert_eq!(v.wyy(), uvec3(4_u32, 2_u32, 2_u32)); assert_eq!(v.wyz(), uvec3(4_u32, 2_u32, 3_u32)); assert_eq!(v.wyw(), uvec3(4_u32, 2_u32, 4_u32)); assert_eq!(v.wzx(), uvec3(4_u32, 3_u32, 1_u32)); assert_eq!(v.wzy(), uvec3(4_u32, 3_u32, 2_u32)); assert_eq!(v.wzz(), uvec3(4_u32, 3_u32, 3_u32)); assert_eq!(v.wzw(), uvec3(4_u32, 3_u32, 4_u32)); assert_eq!(v.wwx(), uvec3(4_u32, 4_u32, 1_u32)); assert_eq!(v.wwy(), uvec3(4_u32, 4_u32, 2_u32)); assert_eq!(v.wwz(), uvec3(4_u32, 4_u32, 3_u32)); assert_eq!(v.www(), uvec3(4_u32, 4_u32, 4_u32)); assert_eq!(v.with_xyz(rhs3), uvec4(11_u32, 12_u32, 13_u32, 4_u32)); assert_eq!(v.with_xyw(rhs3), uvec4(11_u32, 12_u32, 3_u32, 13_u32)); assert_eq!(v.with_xzy(rhs3), uvec4(11_u32, 13_u32, 12_u32, 4_u32)); assert_eq!(v.with_xzw(rhs3), uvec4(11_u32, 2_u32, 12_u32, 13_u32)); assert_eq!(v.with_xwy(rhs3), uvec4(11_u32, 13_u32, 3_u32, 12_u32)); assert_eq!(v.with_xwz(rhs3), uvec4(11_u32, 2_u32, 13_u32, 12_u32)); assert_eq!(v.with_yxz(rhs3), uvec4(12_u32, 11_u32, 13_u32, 4_u32)); assert_eq!(v.with_yxw(rhs3), uvec4(12_u32, 11_u32, 3_u32, 13_u32)); assert_eq!(v.with_yzx(rhs3), uvec4(13_u32, 11_u32, 12_u32, 4_u32)); assert_eq!(v.with_yzw(rhs3), uvec4(1_u32, 11_u32, 12_u32, 13_u32)); assert_eq!(v.with_ywx(rhs3), uvec4(13_u32, 11_u32, 3_u32, 12_u32)); assert_eq!(v.with_ywz(rhs3), uvec4(1_u32, 11_u32, 13_u32, 12_u32)); assert_eq!(v.with_zxy(rhs3), uvec4(12_u32, 13_u32, 11_u32, 4_u32)); assert_eq!(v.with_zxw(rhs3), uvec4(12_u32, 2_u32, 11_u32, 13_u32)); assert_eq!(v.with_zyx(rhs3), uvec4(13_u32, 12_u32, 11_u32, 4_u32)); assert_eq!(v.with_zyw(rhs3), uvec4(1_u32, 12_u32, 11_u32, 13_u32)); assert_eq!(v.with_zwx(rhs3), uvec4(13_u32, 2_u32, 11_u32, 12_u32)); assert_eq!(v.with_zwy(rhs3), uvec4(1_u32, 13_u32, 11_u32, 12_u32)); assert_eq!(v.with_wxy(rhs3), uvec4(12_u32, 13_u32, 3_u32, 11_u32)); assert_eq!(v.with_wxz(rhs3), uvec4(12_u32, 2_u32, 13_u32, 11_u32)); assert_eq!(v.with_wyx(rhs3), uvec4(13_u32, 12_u32, 3_u32, 11_u32)); assert_eq!(v.with_wyz(rhs3), uvec4(1_u32, 12_u32, 13_u32, 11_u32)); assert_eq!(v.with_wzx(rhs3), uvec4(13_u32, 2_u32, 12_u32, 11_u32)); assert_eq!(v.with_wzy(rhs3), uvec4(1_u32, 13_u32, 12_u32, 11_u32)); assert_eq!(v.xx(), uvec2(1_u32, 1_u32)); assert_eq!(v.xy(), uvec2(1_u32, 2_u32)); assert_eq!(v.xz(), uvec2(1_u32, 3_u32)); assert_eq!(v.xw(), uvec2(1_u32, 4_u32)); assert_eq!(v.yx(), uvec2(2_u32, 1_u32)); assert_eq!(v.yy(), uvec2(2_u32, 2_u32)); assert_eq!(v.yz(), uvec2(2_u32, 3_u32)); assert_eq!(v.yw(), uvec2(2_u32, 4_u32)); assert_eq!(v.zx(), uvec2(3_u32, 1_u32)); assert_eq!(v.zy(), uvec2(3_u32, 2_u32)); assert_eq!(v.zz(), uvec2(3_u32, 3_u32)); assert_eq!(v.zw(), uvec2(3_u32, 4_u32)); assert_eq!(v.wx(), uvec2(4_u32, 1_u32)); assert_eq!(v.wy(), uvec2(4_u32, 2_u32)); assert_eq!(v.wz(), uvec2(4_u32, 3_u32)); assert_eq!(v.ww(), uvec2(4_u32, 4_u32)); assert_eq!(v.with_xy(rhs2), uvec4(11_u32, 12_u32, 3_u32, 4_u32)); assert_eq!(v.with_xz(rhs2), uvec4(11_u32, 2_u32, 12_u32, 4_u32)); assert_eq!(v.with_xw(rhs2), uvec4(11_u32, 2_u32, 3_u32, 12_u32)); assert_eq!(v.with_yx(rhs2), uvec4(12_u32, 11_u32, 3_u32, 4_u32)); assert_eq!(v.with_yz(rhs2), uvec4(1_u32, 11_u32, 12_u32, 4_u32)); assert_eq!(v.with_yw(rhs2), uvec4(1_u32, 11_u32, 3_u32, 12_u32)); assert_eq!(v.with_zx(rhs2), uvec4(12_u32, 2_u32, 11_u32, 4_u32)); assert_eq!(v.with_zy(rhs2), uvec4(1_u32, 12_u32, 11_u32, 4_u32)); assert_eq!(v.with_zw(rhs2), uvec4(1_u32, 2_u32, 11_u32, 12_u32)); assert_eq!(v.with_wx(rhs2), uvec4(12_u32, 2_u32, 3_u32, 11_u32)); assert_eq!(v.with_wy(rhs2), uvec4(1_u32, 12_u32, 3_u32, 11_u32)); assert_eq!(v.with_wz(rhs2), uvec4(1_u32, 2_u32, 12_u32, 11_u32)); }); glam_test!(test_uvec3_swizzles, { let v = uvec3(1_u32, 2_u32, 3_u32); let rhs2 = uvec2(11_u32, 12_u32); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), uvec4(1_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.xxxy(), uvec4(1_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.xxxz(), uvec4(1_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.xxyx(), uvec4(1_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.xxyy(), uvec4(1_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.xxyz(), uvec4(1_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.xxzx(), uvec4(1_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.xxzy(), uvec4(1_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.xxzz(), uvec4(1_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.xyxx(), uvec4(1_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.xyxy(), uvec4(1_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.xyxz(), uvec4(1_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.xyyx(), uvec4(1_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.xyyy(), uvec4(1_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.xyyz(), uvec4(1_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.xyzx(), uvec4(1_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.xyzy(), uvec4(1_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.xyzz(), uvec4(1_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.xzxx(), uvec4(1_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.xzxy(), uvec4(1_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.xzxz(), uvec4(1_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.xzyx(), uvec4(1_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.xzyy(), uvec4(1_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.xzyz(), uvec4(1_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.xzzx(), uvec4(1_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.xzzy(), uvec4(1_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.xzzz(), uvec4(1_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.yxxx(), uvec4(2_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.yxxy(), uvec4(2_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.yxxz(), uvec4(2_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.yxyx(), uvec4(2_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.yxyy(), uvec4(2_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.yxyz(), uvec4(2_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.yxzx(), uvec4(2_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.yxzy(), uvec4(2_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.yxzz(), uvec4(2_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.yyxx(), uvec4(2_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.yyxy(), uvec4(2_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.yyxz(), uvec4(2_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.yyyx(), uvec4(2_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.yyyy(), uvec4(2_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.yyyz(), uvec4(2_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.yyzx(), uvec4(2_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.yyzy(), uvec4(2_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.yyzz(), uvec4(2_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.yzxx(), uvec4(2_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.yzxy(), uvec4(2_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.yzxz(), uvec4(2_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.yzyx(), uvec4(2_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.yzyy(), uvec4(2_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.yzyz(), uvec4(2_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.yzzx(), uvec4(2_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.yzzy(), uvec4(2_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.yzzz(), uvec4(2_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.zxxx(), uvec4(3_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.zxxy(), uvec4(3_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.zxxz(), uvec4(3_u32, 1_u32, 1_u32, 3_u32)); assert_eq!(v.zxyx(), uvec4(3_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.zxyy(), uvec4(3_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.zxyz(), uvec4(3_u32, 1_u32, 2_u32, 3_u32)); assert_eq!(v.zxzx(), uvec4(3_u32, 1_u32, 3_u32, 1_u32)); assert_eq!(v.zxzy(), uvec4(3_u32, 1_u32, 3_u32, 2_u32)); assert_eq!(v.zxzz(), uvec4(3_u32, 1_u32, 3_u32, 3_u32)); assert_eq!(v.zyxx(), uvec4(3_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.zyxy(), uvec4(3_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.zyxz(), uvec4(3_u32, 2_u32, 1_u32, 3_u32)); assert_eq!(v.zyyx(), uvec4(3_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.zyyy(), uvec4(3_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.zyyz(), uvec4(3_u32, 2_u32, 2_u32, 3_u32)); assert_eq!(v.zyzx(), uvec4(3_u32, 2_u32, 3_u32, 1_u32)); assert_eq!(v.zyzy(), uvec4(3_u32, 2_u32, 3_u32, 2_u32)); assert_eq!(v.zyzz(), uvec4(3_u32, 2_u32, 3_u32, 3_u32)); assert_eq!(v.zzxx(), uvec4(3_u32, 3_u32, 1_u32, 1_u32)); assert_eq!(v.zzxy(), uvec4(3_u32, 3_u32, 1_u32, 2_u32)); assert_eq!(v.zzxz(), uvec4(3_u32, 3_u32, 1_u32, 3_u32)); assert_eq!(v.zzyx(), uvec4(3_u32, 3_u32, 2_u32, 1_u32)); assert_eq!(v.zzyy(), uvec4(3_u32, 3_u32, 2_u32, 2_u32)); assert_eq!(v.zzyz(), uvec4(3_u32, 3_u32, 2_u32, 3_u32)); assert_eq!(v.zzzx(), uvec4(3_u32, 3_u32, 3_u32, 1_u32)); assert_eq!(v.zzzy(), uvec4(3_u32, 3_u32, 3_u32, 2_u32)); assert_eq!(v.zzzz(), uvec4(3_u32, 3_u32, 3_u32, 3_u32)); assert_eq!(v.xxx(), uvec3(1_u32, 1_u32, 1_u32)); assert_eq!(v.xxy(), uvec3(1_u32, 1_u32, 2_u32)); assert_eq!(v.xxz(), uvec3(1_u32, 1_u32, 3_u32)); assert_eq!(v.xyx(), uvec3(1_u32, 2_u32, 1_u32)); assert_eq!(v.xyy(), uvec3(1_u32, 2_u32, 2_u32)); assert_eq!(v.xzx(), uvec3(1_u32, 3_u32, 1_u32)); assert_eq!(v.xzy(), uvec3(1_u32, 3_u32, 2_u32)); assert_eq!(v.xzz(), uvec3(1_u32, 3_u32, 3_u32)); assert_eq!(v.yxx(), uvec3(2_u32, 1_u32, 1_u32)); assert_eq!(v.yxy(), uvec3(2_u32, 1_u32, 2_u32)); assert_eq!(v.yxz(), uvec3(2_u32, 1_u32, 3_u32)); assert_eq!(v.yyx(), uvec3(2_u32, 2_u32, 1_u32)); assert_eq!(v.yyy(), uvec3(2_u32, 2_u32, 2_u32)); assert_eq!(v.yyz(), uvec3(2_u32, 2_u32, 3_u32)); assert_eq!(v.yzx(), uvec3(2_u32, 3_u32, 1_u32)); assert_eq!(v.yzy(), uvec3(2_u32, 3_u32, 2_u32)); assert_eq!(v.yzz(), uvec3(2_u32, 3_u32, 3_u32)); assert_eq!(v.zxx(), uvec3(3_u32, 1_u32, 1_u32)); assert_eq!(v.zxy(), uvec3(3_u32, 1_u32, 2_u32)); assert_eq!(v.zxz(), uvec3(3_u32, 1_u32, 3_u32)); assert_eq!(v.zyx(), uvec3(3_u32, 2_u32, 1_u32)); assert_eq!(v.zyy(), uvec3(3_u32, 2_u32, 2_u32)); assert_eq!(v.zyz(), uvec3(3_u32, 2_u32, 3_u32)); assert_eq!(v.zzx(), uvec3(3_u32, 3_u32, 1_u32)); assert_eq!(v.zzy(), uvec3(3_u32, 3_u32, 2_u32)); assert_eq!(v.zzz(), uvec3(3_u32, 3_u32, 3_u32)); assert_eq!(v.xx(), uvec2(1_u32, 1_u32)); assert_eq!(v.xy(), uvec2(1_u32, 2_u32)); assert_eq!(v.xz(), uvec2(1_u32, 3_u32)); assert_eq!(v.yx(), uvec2(2_u32, 1_u32)); assert_eq!(v.yy(), uvec2(2_u32, 2_u32)); assert_eq!(v.yz(), uvec2(2_u32, 3_u32)); assert_eq!(v.zx(), uvec2(3_u32, 1_u32)); assert_eq!(v.zy(), uvec2(3_u32, 2_u32)); assert_eq!(v.zz(), uvec2(3_u32, 3_u32)); assert_eq!(v.with_xy(rhs2), uvec3(11_u32, 12_u32, 3_u32)); assert_eq!(v.with_xz(rhs2), uvec3(11_u32, 2_u32, 12_u32)); assert_eq!(v.with_yx(rhs2), uvec3(12_u32, 11_u32, 3_u32)); assert_eq!(v.with_yz(rhs2), uvec3(1_u32, 11_u32, 12_u32)); assert_eq!(v.with_zx(rhs2), uvec3(12_u32, 2_u32, 11_u32)); assert_eq!(v.with_zy(rhs2), uvec3(1_u32, 12_u32, 11_u32)); }); glam_test!(test_uvec2_swizzles, { let v = uvec2(1_u32, 2_u32); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), uvec4(1_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.xxxy(), uvec4(1_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.xxyx(), uvec4(1_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.xxyy(), uvec4(1_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.xyxx(), uvec4(1_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.xyxy(), uvec4(1_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.xyyx(), uvec4(1_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.xyyy(), uvec4(1_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.yxxx(), uvec4(2_u32, 1_u32, 1_u32, 1_u32)); assert_eq!(v.yxxy(), uvec4(2_u32, 1_u32, 1_u32, 2_u32)); assert_eq!(v.yxyx(), uvec4(2_u32, 1_u32, 2_u32, 1_u32)); assert_eq!(v.yxyy(), uvec4(2_u32, 1_u32, 2_u32, 2_u32)); assert_eq!(v.yyxx(), uvec4(2_u32, 2_u32, 1_u32, 1_u32)); assert_eq!(v.yyxy(), uvec4(2_u32, 2_u32, 1_u32, 2_u32)); assert_eq!(v.yyyx(), uvec4(2_u32, 2_u32, 2_u32, 1_u32)); assert_eq!(v.yyyy(), uvec4(2_u32, 2_u32, 2_u32, 2_u32)); assert_eq!(v.xxx(), uvec3(1_u32, 1_u32, 1_u32)); assert_eq!(v.xxy(), uvec3(1_u32, 1_u32, 2_u32)); assert_eq!(v.xyx(), uvec3(1_u32, 2_u32, 1_u32)); assert_eq!(v.xyy(), uvec3(1_u32, 2_u32, 2_u32)); assert_eq!(v.yxx(), uvec3(2_u32, 1_u32, 1_u32)); assert_eq!(v.yxy(), uvec3(2_u32, 1_u32, 2_u32)); assert_eq!(v.yyx(), uvec3(2_u32, 2_u32, 1_u32)); assert_eq!(v.yyy(), uvec3(2_u32, 2_u32, 2_u32)); assert_eq!(v.xx(), uvec2(1_u32, 1_u32)); assert_eq!(v.yx(), uvec2(2_u32, 1_u32)); assert_eq!(v.yy(), uvec2(2_u32, 2_u32)); }); glam-0.30.1/tests/swizzles_u64.rs000064400000000000000000000773051046102023000147410ustar 00000000000000// 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); let rhs3 = u64vec3(11_u64, 12_u64, 13_u64); let rhs2 = u64vec2(11_u64, 12_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.with_xyz(rhs3), u64vec4(11_u64, 12_u64, 13_u64, 4_u64)); assert_eq!(v.with_xyw(rhs3), u64vec4(11_u64, 12_u64, 3_u64, 13_u64)); assert_eq!(v.with_xzy(rhs3), u64vec4(11_u64, 13_u64, 12_u64, 4_u64)); assert_eq!(v.with_xzw(rhs3), u64vec4(11_u64, 2_u64, 12_u64, 13_u64)); assert_eq!(v.with_xwy(rhs3), u64vec4(11_u64, 13_u64, 3_u64, 12_u64)); assert_eq!(v.with_xwz(rhs3), u64vec4(11_u64, 2_u64, 13_u64, 12_u64)); assert_eq!(v.with_yxz(rhs3), u64vec4(12_u64, 11_u64, 13_u64, 4_u64)); assert_eq!(v.with_yxw(rhs3), u64vec4(12_u64, 11_u64, 3_u64, 13_u64)); assert_eq!(v.with_yzx(rhs3), u64vec4(13_u64, 11_u64, 12_u64, 4_u64)); assert_eq!(v.with_yzw(rhs3), u64vec4(1_u64, 11_u64, 12_u64, 13_u64)); assert_eq!(v.with_ywx(rhs3), u64vec4(13_u64, 11_u64, 3_u64, 12_u64)); assert_eq!(v.with_ywz(rhs3), u64vec4(1_u64, 11_u64, 13_u64, 12_u64)); assert_eq!(v.with_zxy(rhs3), u64vec4(12_u64, 13_u64, 11_u64, 4_u64)); assert_eq!(v.with_zxw(rhs3), u64vec4(12_u64, 2_u64, 11_u64, 13_u64)); assert_eq!(v.with_zyx(rhs3), u64vec4(13_u64, 12_u64, 11_u64, 4_u64)); assert_eq!(v.with_zyw(rhs3), u64vec4(1_u64, 12_u64, 11_u64, 13_u64)); assert_eq!(v.with_zwx(rhs3), u64vec4(13_u64, 2_u64, 11_u64, 12_u64)); assert_eq!(v.with_zwy(rhs3), u64vec4(1_u64, 13_u64, 11_u64, 12_u64)); assert_eq!(v.with_wxy(rhs3), u64vec4(12_u64, 13_u64, 3_u64, 11_u64)); assert_eq!(v.with_wxz(rhs3), u64vec4(12_u64, 2_u64, 13_u64, 11_u64)); assert_eq!(v.with_wyx(rhs3), u64vec4(13_u64, 12_u64, 3_u64, 11_u64)); assert_eq!(v.with_wyz(rhs3), u64vec4(1_u64, 12_u64, 13_u64, 11_u64)); assert_eq!(v.with_wzx(rhs3), u64vec4(13_u64, 2_u64, 12_u64, 11_u64)); assert_eq!(v.with_wzy(rhs3), u64vec4(1_u64, 13_u64, 12_u64, 11_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)); assert_eq!(v.with_xy(rhs2), u64vec4(11_u64, 12_u64, 3_u64, 4_u64)); assert_eq!(v.with_xz(rhs2), u64vec4(11_u64, 2_u64, 12_u64, 4_u64)); assert_eq!(v.with_xw(rhs2), u64vec4(11_u64, 2_u64, 3_u64, 12_u64)); assert_eq!(v.with_yx(rhs2), u64vec4(12_u64, 11_u64, 3_u64, 4_u64)); assert_eq!(v.with_yz(rhs2), u64vec4(1_u64, 11_u64, 12_u64, 4_u64)); assert_eq!(v.with_yw(rhs2), u64vec4(1_u64, 11_u64, 3_u64, 12_u64)); assert_eq!(v.with_zx(rhs2), u64vec4(12_u64, 2_u64, 11_u64, 4_u64)); assert_eq!(v.with_zy(rhs2), u64vec4(1_u64, 12_u64, 11_u64, 4_u64)); assert_eq!(v.with_zw(rhs2), u64vec4(1_u64, 2_u64, 11_u64, 12_u64)); assert_eq!(v.with_wx(rhs2), u64vec4(12_u64, 2_u64, 3_u64, 11_u64)); assert_eq!(v.with_wy(rhs2), u64vec4(1_u64, 12_u64, 3_u64, 11_u64)); assert_eq!(v.with_wz(rhs2), u64vec4(1_u64, 2_u64, 12_u64, 11_u64)); }); glam_test!(test_u64vec3_swizzles, { let v = u64vec3(1_u64, 2_u64, 3_u64); let rhs2 = u64vec2(11_u64, 12_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)); assert_eq!(v.with_xy(rhs2), u64vec3(11_u64, 12_u64, 3_u64)); assert_eq!(v.with_xz(rhs2), u64vec3(11_u64, 2_u64, 12_u64)); assert_eq!(v.with_yx(rhs2), u64vec3(12_u64, 11_u64, 3_u64)); assert_eq!(v.with_yz(rhs2), u64vec3(1_u64, 11_u64, 12_u64)); assert_eq!(v.with_zx(rhs2), u64vec3(12_u64, 2_u64, 11_u64)); assert_eq!(v.with_zy(rhs2), u64vec3(1_u64, 12_u64, 11_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)); }); glam-0.30.1/tests/swizzles_u8.rs000064400000000000000000000724441046102023000146560ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_u8vec4_swizzles, { let v = u8vec4(1_u8, 2_u8, 3_u8, 4_u8); let rhs3 = u8vec3(11_u8, 12_u8, 13_u8); let rhs2 = u8vec2(11_u8, 12_u8); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), u8vec4(1_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.xxxy(), u8vec4(1_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.xxxz(), u8vec4(1_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.xxxw(), u8vec4(1_u8, 1_u8, 1_u8, 4_u8)); assert_eq!(v.xxyx(), u8vec4(1_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.xxyy(), u8vec4(1_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.xxyz(), u8vec4(1_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.xxyw(), u8vec4(1_u8, 1_u8, 2_u8, 4_u8)); assert_eq!(v.xxzx(), u8vec4(1_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.xxzy(), u8vec4(1_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.xxzz(), u8vec4(1_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.xxzw(), u8vec4(1_u8, 1_u8, 3_u8, 4_u8)); assert_eq!(v.xxwx(), u8vec4(1_u8, 1_u8, 4_u8, 1_u8)); assert_eq!(v.xxwy(), u8vec4(1_u8, 1_u8, 4_u8, 2_u8)); assert_eq!(v.xxwz(), u8vec4(1_u8, 1_u8, 4_u8, 3_u8)); assert_eq!(v.xxww(), u8vec4(1_u8, 1_u8, 4_u8, 4_u8)); assert_eq!(v.xyxx(), u8vec4(1_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.xyxy(), u8vec4(1_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.xyxz(), u8vec4(1_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.xyxw(), u8vec4(1_u8, 2_u8, 1_u8, 4_u8)); assert_eq!(v.xyyx(), u8vec4(1_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.xyyy(), u8vec4(1_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.xyyz(), u8vec4(1_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.xyyw(), u8vec4(1_u8, 2_u8, 2_u8, 4_u8)); assert_eq!(v.xyzx(), u8vec4(1_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.xyzy(), u8vec4(1_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.xyzz(), u8vec4(1_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.xywx(), u8vec4(1_u8, 2_u8, 4_u8, 1_u8)); assert_eq!(v.xywy(), u8vec4(1_u8, 2_u8, 4_u8, 2_u8)); assert_eq!(v.xywz(), u8vec4(1_u8, 2_u8, 4_u8, 3_u8)); assert_eq!(v.xyww(), u8vec4(1_u8, 2_u8, 4_u8, 4_u8)); assert_eq!(v.xzxx(), u8vec4(1_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.xzxy(), u8vec4(1_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.xzxz(), u8vec4(1_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.xzxw(), u8vec4(1_u8, 3_u8, 1_u8, 4_u8)); assert_eq!(v.xzyx(), u8vec4(1_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.xzyy(), u8vec4(1_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.xzyz(), u8vec4(1_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.xzyw(), u8vec4(1_u8, 3_u8, 2_u8, 4_u8)); assert_eq!(v.xzzx(), u8vec4(1_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.xzzy(), u8vec4(1_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.xzzz(), u8vec4(1_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.xzzw(), u8vec4(1_u8, 3_u8, 3_u8, 4_u8)); assert_eq!(v.xzwx(), u8vec4(1_u8, 3_u8, 4_u8, 1_u8)); assert_eq!(v.xzwy(), u8vec4(1_u8, 3_u8, 4_u8, 2_u8)); assert_eq!(v.xzwz(), u8vec4(1_u8, 3_u8, 4_u8, 3_u8)); assert_eq!(v.xzww(), u8vec4(1_u8, 3_u8, 4_u8, 4_u8)); assert_eq!(v.xwxx(), u8vec4(1_u8, 4_u8, 1_u8, 1_u8)); assert_eq!(v.xwxy(), u8vec4(1_u8, 4_u8, 1_u8, 2_u8)); assert_eq!(v.xwxz(), u8vec4(1_u8, 4_u8, 1_u8, 3_u8)); assert_eq!(v.xwxw(), u8vec4(1_u8, 4_u8, 1_u8, 4_u8)); assert_eq!(v.xwyx(), u8vec4(1_u8, 4_u8, 2_u8, 1_u8)); assert_eq!(v.xwyy(), u8vec4(1_u8, 4_u8, 2_u8, 2_u8)); assert_eq!(v.xwyz(), u8vec4(1_u8, 4_u8, 2_u8, 3_u8)); assert_eq!(v.xwyw(), u8vec4(1_u8, 4_u8, 2_u8, 4_u8)); assert_eq!(v.xwzx(), u8vec4(1_u8, 4_u8, 3_u8, 1_u8)); assert_eq!(v.xwzy(), u8vec4(1_u8, 4_u8, 3_u8, 2_u8)); assert_eq!(v.xwzz(), u8vec4(1_u8, 4_u8, 3_u8, 3_u8)); assert_eq!(v.xwzw(), u8vec4(1_u8, 4_u8, 3_u8, 4_u8)); assert_eq!(v.xwwx(), u8vec4(1_u8, 4_u8, 4_u8, 1_u8)); assert_eq!(v.xwwy(), u8vec4(1_u8, 4_u8, 4_u8, 2_u8)); assert_eq!(v.xwwz(), u8vec4(1_u8, 4_u8, 4_u8, 3_u8)); assert_eq!(v.xwww(), u8vec4(1_u8, 4_u8, 4_u8, 4_u8)); assert_eq!(v.yxxx(), u8vec4(2_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.yxxy(), u8vec4(2_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.yxxz(), u8vec4(2_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.yxxw(), u8vec4(2_u8, 1_u8, 1_u8, 4_u8)); assert_eq!(v.yxyx(), u8vec4(2_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.yxyy(), u8vec4(2_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.yxyz(), u8vec4(2_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.yxyw(), u8vec4(2_u8, 1_u8, 2_u8, 4_u8)); assert_eq!(v.yxzx(), u8vec4(2_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.yxzy(), u8vec4(2_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.yxzz(), u8vec4(2_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.yxzw(), u8vec4(2_u8, 1_u8, 3_u8, 4_u8)); assert_eq!(v.yxwx(), u8vec4(2_u8, 1_u8, 4_u8, 1_u8)); assert_eq!(v.yxwy(), u8vec4(2_u8, 1_u8, 4_u8, 2_u8)); assert_eq!(v.yxwz(), u8vec4(2_u8, 1_u8, 4_u8, 3_u8)); assert_eq!(v.yxww(), u8vec4(2_u8, 1_u8, 4_u8, 4_u8)); assert_eq!(v.yyxx(), u8vec4(2_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.yyxy(), u8vec4(2_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.yyxz(), u8vec4(2_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.yyxw(), u8vec4(2_u8, 2_u8, 1_u8, 4_u8)); assert_eq!(v.yyyx(), u8vec4(2_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.yyyy(), u8vec4(2_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.yyyz(), u8vec4(2_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.yyyw(), u8vec4(2_u8, 2_u8, 2_u8, 4_u8)); assert_eq!(v.yyzx(), u8vec4(2_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.yyzy(), u8vec4(2_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.yyzz(), u8vec4(2_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.yyzw(), u8vec4(2_u8, 2_u8, 3_u8, 4_u8)); assert_eq!(v.yywx(), u8vec4(2_u8, 2_u8, 4_u8, 1_u8)); assert_eq!(v.yywy(), u8vec4(2_u8, 2_u8, 4_u8, 2_u8)); assert_eq!(v.yywz(), u8vec4(2_u8, 2_u8, 4_u8, 3_u8)); assert_eq!(v.yyww(), u8vec4(2_u8, 2_u8, 4_u8, 4_u8)); assert_eq!(v.yzxx(), u8vec4(2_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.yzxy(), u8vec4(2_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.yzxz(), u8vec4(2_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.yzxw(), u8vec4(2_u8, 3_u8, 1_u8, 4_u8)); assert_eq!(v.yzyx(), u8vec4(2_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.yzyy(), u8vec4(2_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.yzyz(), u8vec4(2_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.yzyw(), u8vec4(2_u8, 3_u8, 2_u8, 4_u8)); assert_eq!(v.yzzx(), u8vec4(2_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.yzzy(), u8vec4(2_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.yzzz(), u8vec4(2_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.yzzw(), u8vec4(2_u8, 3_u8, 3_u8, 4_u8)); assert_eq!(v.yzwx(), u8vec4(2_u8, 3_u8, 4_u8, 1_u8)); assert_eq!(v.yzwy(), u8vec4(2_u8, 3_u8, 4_u8, 2_u8)); assert_eq!(v.yzwz(), u8vec4(2_u8, 3_u8, 4_u8, 3_u8)); assert_eq!(v.yzww(), u8vec4(2_u8, 3_u8, 4_u8, 4_u8)); assert_eq!(v.ywxx(), u8vec4(2_u8, 4_u8, 1_u8, 1_u8)); assert_eq!(v.ywxy(), u8vec4(2_u8, 4_u8, 1_u8, 2_u8)); assert_eq!(v.ywxz(), u8vec4(2_u8, 4_u8, 1_u8, 3_u8)); assert_eq!(v.ywxw(), u8vec4(2_u8, 4_u8, 1_u8, 4_u8)); assert_eq!(v.ywyx(), u8vec4(2_u8, 4_u8, 2_u8, 1_u8)); assert_eq!(v.ywyy(), u8vec4(2_u8, 4_u8, 2_u8, 2_u8)); assert_eq!(v.ywyz(), u8vec4(2_u8, 4_u8, 2_u8, 3_u8)); assert_eq!(v.ywyw(), u8vec4(2_u8, 4_u8, 2_u8, 4_u8)); assert_eq!(v.ywzx(), u8vec4(2_u8, 4_u8, 3_u8, 1_u8)); assert_eq!(v.ywzy(), u8vec4(2_u8, 4_u8, 3_u8, 2_u8)); assert_eq!(v.ywzz(), u8vec4(2_u8, 4_u8, 3_u8, 3_u8)); assert_eq!(v.ywzw(), u8vec4(2_u8, 4_u8, 3_u8, 4_u8)); assert_eq!(v.ywwx(), u8vec4(2_u8, 4_u8, 4_u8, 1_u8)); assert_eq!(v.ywwy(), u8vec4(2_u8, 4_u8, 4_u8, 2_u8)); assert_eq!(v.ywwz(), u8vec4(2_u8, 4_u8, 4_u8, 3_u8)); assert_eq!(v.ywww(), u8vec4(2_u8, 4_u8, 4_u8, 4_u8)); assert_eq!(v.zxxx(), u8vec4(3_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.zxxy(), u8vec4(3_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.zxxz(), u8vec4(3_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.zxxw(), u8vec4(3_u8, 1_u8, 1_u8, 4_u8)); assert_eq!(v.zxyx(), u8vec4(3_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.zxyy(), u8vec4(3_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.zxyz(), u8vec4(3_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.zxyw(), u8vec4(3_u8, 1_u8, 2_u8, 4_u8)); assert_eq!(v.zxzx(), u8vec4(3_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.zxzy(), u8vec4(3_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.zxzz(), u8vec4(3_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.zxzw(), u8vec4(3_u8, 1_u8, 3_u8, 4_u8)); assert_eq!(v.zxwx(), u8vec4(3_u8, 1_u8, 4_u8, 1_u8)); assert_eq!(v.zxwy(), u8vec4(3_u8, 1_u8, 4_u8, 2_u8)); assert_eq!(v.zxwz(), u8vec4(3_u8, 1_u8, 4_u8, 3_u8)); assert_eq!(v.zxww(), u8vec4(3_u8, 1_u8, 4_u8, 4_u8)); assert_eq!(v.zyxx(), u8vec4(3_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.zyxy(), u8vec4(3_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.zyxz(), u8vec4(3_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.zyxw(), u8vec4(3_u8, 2_u8, 1_u8, 4_u8)); assert_eq!(v.zyyx(), u8vec4(3_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.zyyy(), u8vec4(3_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.zyyz(), u8vec4(3_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.zyyw(), u8vec4(3_u8, 2_u8, 2_u8, 4_u8)); assert_eq!(v.zyzx(), u8vec4(3_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.zyzy(), u8vec4(3_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.zyzz(), u8vec4(3_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.zyzw(), u8vec4(3_u8, 2_u8, 3_u8, 4_u8)); assert_eq!(v.zywx(), u8vec4(3_u8, 2_u8, 4_u8, 1_u8)); assert_eq!(v.zywy(), u8vec4(3_u8, 2_u8, 4_u8, 2_u8)); assert_eq!(v.zywz(), u8vec4(3_u8, 2_u8, 4_u8, 3_u8)); assert_eq!(v.zyww(), u8vec4(3_u8, 2_u8, 4_u8, 4_u8)); assert_eq!(v.zzxx(), u8vec4(3_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.zzxy(), u8vec4(3_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.zzxz(), u8vec4(3_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.zzxw(), u8vec4(3_u8, 3_u8, 1_u8, 4_u8)); assert_eq!(v.zzyx(), u8vec4(3_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.zzyy(), u8vec4(3_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.zzyz(), u8vec4(3_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.zzyw(), u8vec4(3_u8, 3_u8, 2_u8, 4_u8)); assert_eq!(v.zzzx(), u8vec4(3_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.zzzy(), u8vec4(3_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.zzzz(), u8vec4(3_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.zzzw(), u8vec4(3_u8, 3_u8, 3_u8, 4_u8)); assert_eq!(v.zzwx(), u8vec4(3_u8, 3_u8, 4_u8, 1_u8)); assert_eq!(v.zzwy(), u8vec4(3_u8, 3_u8, 4_u8, 2_u8)); assert_eq!(v.zzwz(), u8vec4(3_u8, 3_u8, 4_u8, 3_u8)); assert_eq!(v.zzww(), u8vec4(3_u8, 3_u8, 4_u8, 4_u8)); assert_eq!(v.zwxx(), u8vec4(3_u8, 4_u8, 1_u8, 1_u8)); assert_eq!(v.zwxy(), u8vec4(3_u8, 4_u8, 1_u8, 2_u8)); assert_eq!(v.zwxz(), u8vec4(3_u8, 4_u8, 1_u8, 3_u8)); assert_eq!(v.zwxw(), u8vec4(3_u8, 4_u8, 1_u8, 4_u8)); assert_eq!(v.zwyx(), u8vec4(3_u8, 4_u8, 2_u8, 1_u8)); assert_eq!(v.zwyy(), u8vec4(3_u8, 4_u8, 2_u8, 2_u8)); assert_eq!(v.zwyz(), u8vec4(3_u8, 4_u8, 2_u8, 3_u8)); assert_eq!(v.zwyw(), u8vec4(3_u8, 4_u8, 2_u8, 4_u8)); assert_eq!(v.zwzx(), u8vec4(3_u8, 4_u8, 3_u8, 1_u8)); assert_eq!(v.zwzy(), u8vec4(3_u8, 4_u8, 3_u8, 2_u8)); assert_eq!(v.zwzz(), u8vec4(3_u8, 4_u8, 3_u8, 3_u8)); assert_eq!(v.zwzw(), u8vec4(3_u8, 4_u8, 3_u8, 4_u8)); assert_eq!(v.zwwx(), u8vec4(3_u8, 4_u8, 4_u8, 1_u8)); assert_eq!(v.zwwy(), u8vec4(3_u8, 4_u8, 4_u8, 2_u8)); assert_eq!(v.zwwz(), u8vec4(3_u8, 4_u8, 4_u8, 3_u8)); assert_eq!(v.zwww(), u8vec4(3_u8, 4_u8, 4_u8, 4_u8)); assert_eq!(v.wxxx(), u8vec4(4_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.wxxy(), u8vec4(4_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.wxxz(), u8vec4(4_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.wxxw(), u8vec4(4_u8, 1_u8, 1_u8, 4_u8)); assert_eq!(v.wxyx(), u8vec4(4_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.wxyy(), u8vec4(4_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.wxyz(), u8vec4(4_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.wxyw(), u8vec4(4_u8, 1_u8, 2_u8, 4_u8)); assert_eq!(v.wxzx(), u8vec4(4_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.wxzy(), u8vec4(4_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.wxzz(), u8vec4(4_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.wxzw(), u8vec4(4_u8, 1_u8, 3_u8, 4_u8)); assert_eq!(v.wxwx(), u8vec4(4_u8, 1_u8, 4_u8, 1_u8)); assert_eq!(v.wxwy(), u8vec4(4_u8, 1_u8, 4_u8, 2_u8)); assert_eq!(v.wxwz(), u8vec4(4_u8, 1_u8, 4_u8, 3_u8)); assert_eq!(v.wxww(), u8vec4(4_u8, 1_u8, 4_u8, 4_u8)); assert_eq!(v.wyxx(), u8vec4(4_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.wyxy(), u8vec4(4_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.wyxz(), u8vec4(4_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.wyxw(), u8vec4(4_u8, 2_u8, 1_u8, 4_u8)); assert_eq!(v.wyyx(), u8vec4(4_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.wyyy(), u8vec4(4_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.wyyz(), u8vec4(4_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.wyyw(), u8vec4(4_u8, 2_u8, 2_u8, 4_u8)); assert_eq!(v.wyzx(), u8vec4(4_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.wyzy(), u8vec4(4_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.wyzz(), u8vec4(4_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.wyzw(), u8vec4(4_u8, 2_u8, 3_u8, 4_u8)); assert_eq!(v.wywx(), u8vec4(4_u8, 2_u8, 4_u8, 1_u8)); assert_eq!(v.wywy(), u8vec4(4_u8, 2_u8, 4_u8, 2_u8)); assert_eq!(v.wywz(), u8vec4(4_u8, 2_u8, 4_u8, 3_u8)); assert_eq!(v.wyww(), u8vec4(4_u8, 2_u8, 4_u8, 4_u8)); assert_eq!(v.wzxx(), u8vec4(4_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.wzxy(), u8vec4(4_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.wzxz(), u8vec4(4_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.wzxw(), u8vec4(4_u8, 3_u8, 1_u8, 4_u8)); assert_eq!(v.wzyx(), u8vec4(4_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.wzyy(), u8vec4(4_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.wzyz(), u8vec4(4_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.wzyw(), u8vec4(4_u8, 3_u8, 2_u8, 4_u8)); assert_eq!(v.wzzx(), u8vec4(4_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.wzzy(), u8vec4(4_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.wzzz(), u8vec4(4_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.wzzw(), u8vec4(4_u8, 3_u8, 3_u8, 4_u8)); assert_eq!(v.wzwx(), u8vec4(4_u8, 3_u8, 4_u8, 1_u8)); assert_eq!(v.wzwy(), u8vec4(4_u8, 3_u8, 4_u8, 2_u8)); assert_eq!(v.wzwz(), u8vec4(4_u8, 3_u8, 4_u8, 3_u8)); assert_eq!(v.wzww(), u8vec4(4_u8, 3_u8, 4_u8, 4_u8)); assert_eq!(v.wwxx(), u8vec4(4_u8, 4_u8, 1_u8, 1_u8)); assert_eq!(v.wwxy(), u8vec4(4_u8, 4_u8, 1_u8, 2_u8)); assert_eq!(v.wwxz(), u8vec4(4_u8, 4_u8, 1_u8, 3_u8)); assert_eq!(v.wwxw(), u8vec4(4_u8, 4_u8, 1_u8, 4_u8)); assert_eq!(v.wwyx(), u8vec4(4_u8, 4_u8, 2_u8, 1_u8)); assert_eq!(v.wwyy(), u8vec4(4_u8, 4_u8, 2_u8, 2_u8)); assert_eq!(v.wwyz(), u8vec4(4_u8, 4_u8, 2_u8, 3_u8)); assert_eq!(v.wwyw(), u8vec4(4_u8, 4_u8, 2_u8, 4_u8)); assert_eq!(v.wwzx(), u8vec4(4_u8, 4_u8, 3_u8, 1_u8)); assert_eq!(v.wwzy(), u8vec4(4_u8, 4_u8, 3_u8, 2_u8)); assert_eq!(v.wwzz(), u8vec4(4_u8, 4_u8, 3_u8, 3_u8)); assert_eq!(v.wwzw(), u8vec4(4_u8, 4_u8, 3_u8, 4_u8)); assert_eq!(v.wwwx(), u8vec4(4_u8, 4_u8, 4_u8, 1_u8)); assert_eq!(v.wwwy(), u8vec4(4_u8, 4_u8, 4_u8, 2_u8)); assert_eq!(v.wwwz(), u8vec4(4_u8, 4_u8, 4_u8, 3_u8)); assert_eq!(v.wwww(), u8vec4(4_u8, 4_u8, 4_u8, 4_u8)); assert_eq!(v.xxx(), u8vec3(1_u8, 1_u8, 1_u8)); assert_eq!(v.xxy(), u8vec3(1_u8, 1_u8, 2_u8)); assert_eq!(v.xxz(), u8vec3(1_u8, 1_u8, 3_u8)); assert_eq!(v.xxw(), u8vec3(1_u8, 1_u8, 4_u8)); assert_eq!(v.xyx(), u8vec3(1_u8, 2_u8, 1_u8)); assert_eq!(v.xyy(), u8vec3(1_u8, 2_u8, 2_u8)); assert_eq!(v.xyz(), u8vec3(1_u8, 2_u8, 3_u8)); assert_eq!(v.xyw(), u8vec3(1_u8, 2_u8, 4_u8)); assert_eq!(v.xzx(), u8vec3(1_u8, 3_u8, 1_u8)); assert_eq!(v.xzy(), u8vec3(1_u8, 3_u8, 2_u8)); assert_eq!(v.xzz(), u8vec3(1_u8, 3_u8, 3_u8)); assert_eq!(v.xzw(), u8vec3(1_u8, 3_u8, 4_u8)); assert_eq!(v.xwx(), u8vec3(1_u8, 4_u8, 1_u8)); assert_eq!(v.xwy(), u8vec3(1_u8, 4_u8, 2_u8)); assert_eq!(v.xwz(), u8vec3(1_u8, 4_u8, 3_u8)); assert_eq!(v.xww(), u8vec3(1_u8, 4_u8, 4_u8)); assert_eq!(v.yxx(), u8vec3(2_u8, 1_u8, 1_u8)); assert_eq!(v.yxy(), u8vec3(2_u8, 1_u8, 2_u8)); assert_eq!(v.yxz(), u8vec3(2_u8, 1_u8, 3_u8)); assert_eq!(v.yxw(), u8vec3(2_u8, 1_u8, 4_u8)); assert_eq!(v.yyx(), u8vec3(2_u8, 2_u8, 1_u8)); assert_eq!(v.yyy(), u8vec3(2_u8, 2_u8, 2_u8)); assert_eq!(v.yyz(), u8vec3(2_u8, 2_u8, 3_u8)); assert_eq!(v.yyw(), u8vec3(2_u8, 2_u8, 4_u8)); assert_eq!(v.yzx(), u8vec3(2_u8, 3_u8, 1_u8)); assert_eq!(v.yzy(), u8vec3(2_u8, 3_u8, 2_u8)); assert_eq!(v.yzz(), u8vec3(2_u8, 3_u8, 3_u8)); assert_eq!(v.yzw(), u8vec3(2_u8, 3_u8, 4_u8)); assert_eq!(v.ywx(), u8vec3(2_u8, 4_u8, 1_u8)); assert_eq!(v.ywy(), u8vec3(2_u8, 4_u8, 2_u8)); assert_eq!(v.ywz(), u8vec3(2_u8, 4_u8, 3_u8)); assert_eq!(v.yww(), u8vec3(2_u8, 4_u8, 4_u8)); assert_eq!(v.zxx(), u8vec3(3_u8, 1_u8, 1_u8)); assert_eq!(v.zxy(), u8vec3(3_u8, 1_u8, 2_u8)); assert_eq!(v.zxz(), u8vec3(3_u8, 1_u8, 3_u8)); assert_eq!(v.zxw(), u8vec3(3_u8, 1_u8, 4_u8)); assert_eq!(v.zyx(), u8vec3(3_u8, 2_u8, 1_u8)); assert_eq!(v.zyy(), u8vec3(3_u8, 2_u8, 2_u8)); assert_eq!(v.zyz(), u8vec3(3_u8, 2_u8, 3_u8)); assert_eq!(v.zyw(), u8vec3(3_u8, 2_u8, 4_u8)); assert_eq!(v.zzx(), u8vec3(3_u8, 3_u8, 1_u8)); assert_eq!(v.zzy(), u8vec3(3_u8, 3_u8, 2_u8)); assert_eq!(v.zzz(), u8vec3(3_u8, 3_u8, 3_u8)); assert_eq!(v.zzw(), u8vec3(3_u8, 3_u8, 4_u8)); assert_eq!(v.zwx(), u8vec3(3_u8, 4_u8, 1_u8)); assert_eq!(v.zwy(), u8vec3(3_u8, 4_u8, 2_u8)); assert_eq!(v.zwz(), u8vec3(3_u8, 4_u8, 3_u8)); assert_eq!(v.zww(), u8vec3(3_u8, 4_u8, 4_u8)); assert_eq!(v.wxx(), u8vec3(4_u8, 1_u8, 1_u8)); assert_eq!(v.wxy(), u8vec3(4_u8, 1_u8, 2_u8)); assert_eq!(v.wxz(), u8vec3(4_u8, 1_u8, 3_u8)); assert_eq!(v.wxw(), u8vec3(4_u8, 1_u8, 4_u8)); assert_eq!(v.wyx(), u8vec3(4_u8, 2_u8, 1_u8)); assert_eq!(v.wyy(), u8vec3(4_u8, 2_u8, 2_u8)); assert_eq!(v.wyz(), u8vec3(4_u8, 2_u8, 3_u8)); assert_eq!(v.wyw(), u8vec3(4_u8, 2_u8, 4_u8)); assert_eq!(v.wzx(), u8vec3(4_u8, 3_u8, 1_u8)); assert_eq!(v.wzy(), u8vec3(4_u8, 3_u8, 2_u8)); assert_eq!(v.wzz(), u8vec3(4_u8, 3_u8, 3_u8)); assert_eq!(v.wzw(), u8vec3(4_u8, 3_u8, 4_u8)); assert_eq!(v.wwx(), u8vec3(4_u8, 4_u8, 1_u8)); assert_eq!(v.wwy(), u8vec3(4_u8, 4_u8, 2_u8)); assert_eq!(v.wwz(), u8vec3(4_u8, 4_u8, 3_u8)); assert_eq!(v.www(), u8vec3(4_u8, 4_u8, 4_u8)); assert_eq!(v.with_xyz(rhs3), u8vec4(11_u8, 12_u8, 13_u8, 4_u8)); assert_eq!(v.with_xyw(rhs3), u8vec4(11_u8, 12_u8, 3_u8, 13_u8)); assert_eq!(v.with_xzy(rhs3), u8vec4(11_u8, 13_u8, 12_u8, 4_u8)); assert_eq!(v.with_xzw(rhs3), u8vec4(11_u8, 2_u8, 12_u8, 13_u8)); assert_eq!(v.with_xwy(rhs3), u8vec4(11_u8, 13_u8, 3_u8, 12_u8)); assert_eq!(v.with_xwz(rhs3), u8vec4(11_u8, 2_u8, 13_u8, 12_u8)); assert_eq!(v.with_yxz(rhs3), u8vec4(12_u8, 11_u8, 13_u8, 4_u8)); assert_eq!(v.with_yxw(rhs3), u8vec4(12_u8, 11_u8, 3_u8, 13_u8)); assert_eq!(v.with_yzx(rhs3), u8vec4(13_u8, 11_u8, 12_u8, 4_u8)); assert_eq!(v.with_yzw(rhs3), u8vec4(1_u8, 11_u8, 12_u8, 13_u8)); assert_eq!(v.with_ywx(rhs3), u8vec4(13_u8, 11_u8, 3_u8, 12_u8)); assert_eq!(v.with_ywz(rhs3), u8vec4(1_u8, 11_u8, 13_u8, 12_u8)); assert_eq!(v.with_zxy(rhs3), u8vec4(12_u8, 13_u8, 11_u8, 4_u8)); assert_eq!(v.with_zxw(rhs3), u8vec4(12_u8, 2_u8, 11_u8, 13_u8)); assert_eq!(v.with_zyx(rhs3), u8vec4(13_u8, 12_u8, 11_u8, 4_u8)); assert_eq!(v.with_zyw(rhs3), u8vec4(1_u8, 12_u8, 11_u8, 13_u8)); assert_eq!(v.with_zwx(rhs3), u8vec4(13_u8, 2_u8, 11_u8, 12_u8)); assert_eq!(v.with_zwy(rhs3), u8vec4(1_u8, 13_u8, 11_u8, 12_u8)); assert_eq!(v.with_wxy(rhs3), u8vec4(12_u8, 13_u8, 3_u8, 11_u8)); assert_eq!(v.with_wxz(rhs3), u8vec4(12_u8, 2_u8, 13_u8, 11_u8)); assert_eq!(v.with_wyx(rhs3), u8vec4(13_u8, 12_u8, 3_u8, 11_u8)); assert_eq!(v.with_wyz(rhs3), u8vec4(1_u8, 12_u8, 13_u8, 11_u8)); assert_eq!(v.with_wzx(rhs3), u8vec4(13_u8, 2_u8, 12_u8, 11_u8)); assert_eq!(v.with_wzy(rhs3), u8vec4(1_u8, 13_u8, 12_u8, 11_u8)); assert_eq!(v.xx(), u8vec2(1_u8, 1_u8)); assert_eq!(v.xy(), u8vec2(1_u8, 2_u8)); assert_eq!(v.xz(), u8vec2(1_u8, 3_u8)); assert_eq!(v.xw(), u8vec2(1_u8, 4_u8)); assert_eq!(v.yx(), u8vec2(2_u8, 1_u8)); assert_eq!(v.yy(), u8vec2(2_u8, 2_u8)); assert_eq!(v.yz(), u8vec2(2_u8, 3_u8)); assert_eq!(v.yw(), u8vec2(2_u8, 4_u8)); assert_eq!(v.zx(), u8vec2(3_u8, 1_u8)); assert_eq!(v.zy(), u8vec2(3_u8, 2_u8)); assert_eq!(v.zz(), u8vec2(3_u8, 3_u8)); assert_eq!(v.zw(), u8vec2(3_u8, 4_u8)); assert_eq!(v.wx(), u8vec2(4_u8, 1_u8)); assert_eq!(v.wy(), u8vec2(4_u8, 2_u8)); assert_eq!(v.wz(), u8vec2(4_u8, 3_u8)); assert_eq!(v.ww(), u8vec2(4_u8, 4_u8)); assert_eq!(v.with_xy(rhs2), u8vec4(11_u8, 12_u8, 3_u8, 4_u8)); assert_eq!(v.with_xz(rhs2), u8vec4(11_u8, 2_u8, 12_u8, 4_u8)); assert_eq!(v.with_xw(rhs2), u8vec4(11_u8, 2_u8, 3_u8, 12_u8)); assert_eq!(v.with_yx(rhs2), u8vec4(12_u8, 11_u8, 3_u8, 4_u8)); assert_eq!(v.with_yz(rhs2), u8vec4(1_u8, 11_u8, 12_u8, 4_u8)); assert_eq!(v.with_yw(rhs2), u8vec4(1_u8, 11_u8, 3_u8, 12_u8)); assert_eq!(v.with_zx(rhs2), u8vec4(12_u8, 2_u8, 11_u8, 4_u8)); assert_eq!(v.with_zy(rhs2), u8vec4(1_u8, 12_u8, 11_u8, 4_u8)); assert_eq!(v.with_zw(rhs2), u8vec4(1_u8, 2_u8, 11_u8, 12_u8)); assert_eq!(v.with_wx(rhs2), u8vec4(12_u8, 2_u8, 3_u8, 11_u8)); assert_eq!(v.with_wy(rhs2), u8vec4(1_u8, 12_u8, 3_u8, 11_u8)); assert_eq!(v.with_wz(rhs2), u8vec4(1_u8, 2_u8, 12_u8, 11_u8)); }); glam_test!(test_u8vec3_swizzles, { let v = u8vec3(1_u8, 2_u8, 3_u8); let rhs2 = u8vec2(11_u8, 12_u8); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), u8vec4(1_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.xxxy(), u8vec4(1_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.xxxz(), u8vec4(1_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.xxyx(), u8vec4(1_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.xxyy(), u8vec4(1_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.xxyz(), u8vec4(1_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.xxzx(), u8vec4(1_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.xxzy(), u8vec4(1_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.xxzz(), u8vec4(1_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.xyxx(), u8vec4(1_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.xyxy(), u8vec4(1_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.xyxz(), u8vec4(1_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.xyyx(), u8vec4(1_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.xyyy(), u8vec4(1_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.xyyz(), u8vec4(1_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.xyzx(), u8vec4(1_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.xyzy(), u8vec4(1_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.xyzz(), u8vec4(1_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.xzxx(), u8vec4(1_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.xzxy(), u8vec4(1_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.xzxz(), u8vec4(1_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.xzyx(), u8vec4(1_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.xzyy(), u8vec4(1_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.xzyz(), u8vec4(1_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.xzzx(), u8vec4(1_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.xzzy(), u8vec4(1_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.xzzz(), u8vec4(1_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.yxxx(), u8vec4(2_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.yxxy(), u8vec4(2_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.yxxz(), u8vec4(2_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.yxyx(), u8vec4(2_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.yxyy(), u8vec4(2_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.yxyz(), u8vec4(2_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.yxzx(), u8vec4(2_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.yxzy(), u8vec4(2_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.yxzz(), u8vec4(2_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.yyxx(), u8vec4(2_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.yyxy(), u8vec4(2_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.yyxz(), u8vec4(2_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.yyyx(), u8vec4(2_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.yyyy(), u8vec4(2_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.yyyz(), u8vec4(2_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.yyzx(), u8vec4(2_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.yyzy(), u8vec4(2_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.yyzz(), u8vec4(2_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.yzxx(), u8vec4(2_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.yzxy(), u8vec4(2_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.yzxz(), u8vec4(2_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.yzyx(), u8vec4(2_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.yzyy(), u8vec4(2_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.yzyz(), u8vec4(2_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.yzzx(), u8vec4(2_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.yzzy(), u8vec4(2_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.yzzz(), u8vec4(2_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.zxxx(), u8vec4(3_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.zxxy(), u8vec4(3_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.zxxz(), u8vec4(3_u8, 1_u8, 1_u8, 3_u8)); assert_eq!(v.zxyx(), u8vec4(3_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.zxyy(), u8vec4(3_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.zxyz(), u8vec4(3_u8, 1_u8, 2_u8, 3_u8)); assert_eq!(v.zxzx(), u8vec4(3_u8, 1_u8, 3_u8, 1_u8)); assert_eq!(v.zxzy(), u8vec4(3_u8, 1_u8, 3_u8, 2_u8)); assert_eq!(v.zxzz(), u8vec4(3_u8, 1_u8, 3_u8, 3_u8)); assert_eq!(v.zyxx(), u8vec4(3_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.zyxy(), u8vec4(3_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.zyxz(), u8vec4(3_u8, 2_u8, 1_u8, 3_u8)); assert_eq!(v.zyyx(), u8vec4(3_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.zyyy(), u8vec4(3_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.zyyz(), u8vec4(3_u8, 2_u8, 2_u8, 3_u8)); assert_eq!(v.zyzx(), u8vec4(3_u8, 2_u8, 3_u8, 1_u8)); assert_eq!(v.zyzy(), u8vec4(3_u8, 2_u8, 3_u8, 2_u8)); assert_eq!(v.zyzz(), u8vec4(3_u8, 2_u8, 3_u8, 3_u8)); assert_eq!(v.zzxx(), u8vec4(3_u8, 3_u8, 1_u8, 1_u8)); assert_eq!(v.zzxy(), u8vec4(3_u8, 3_u8, 1_u8, 2_u8)); assert_eq!(v.zzxz(), u8vec4(3_u8, 3_u8, 1_u8, 3_u8)); assert_eq!(v.zzyx(), u8vec4(3_u8, 3_u8, 2_u8, 1_u8)); assert_eq!(v.zzyy(), u8vec4(3_u8, 3_u8, 2_u8, 2_u8)); assert_eq!(v.zzyz(), u8vec4(3_u8, 3_u8, 2_u8, 3_u8)); assert_eq!(v.zzzx(), u8vec4(3_u8, 3_u8, 3_u8, 1_u8)); assert_eq!(v.zzzy(), u8vec4(3_u8, 3_u8, 3_u8, 2_u8)); assert_eq!(v.zzzz(), u8vec4(3_u8, 3_u8, 3_u8, 3_u8)); assert_eq!(v.xxx(), u8vec3(1_u8, 1_u8, 1_u8)); assert_eq!(v.xxy(), u8vec3(1_u8, 1_u8, 2_u8)); assert_eq!(v.xxz(), u8vec3(1_u8, 1_u8, 3_u8)); assert_eq!(v.xyx(), u8vec3(1_u8, 2_u8, 1_u8)); assert_eq!(v.xyy(), u8vec3(1_u8, 2_u8, 2_u8)); assert_eq!(v.xzx(), u8vec3(1_u8, 3_u8, 1_u8)); assert_eq!(v.xzy(), u8vec3(1_u8, 3_u8, 2_u8)); assert_eq!(v.xzz(), u8vec3(1_u8, 3_u8, 3_u8)); assert_eq!(v.yxx(), u8vec3(2_u8, 1_u8, 1_u8)); assert_eq!(v.yxy(), u8vec3(2_u8, 1_u8, 2_u8)); assert_eq!(v.yxz(), u8vec3(2_u8, 1_u8, 3_u8)); assert_eq!(v.yyx(), u8vec3(2_u8, 2_u8, 1_u8)); assert_eq!(v.yyy(), u8vec3(2_u8, 2_u8, 2_u8)); assert_eq!(v.yyz(), u8vec3(2_u8, 2_u8, 3_u8)); assert_eq!(v.yzx(), u8vec3(2_u8, 3_u8, 1_u8)); assert_eq!(v.yzy(), u8vec3(2_u8, 3_u8, 2_u8)); assert_eq!(v.yzz(), u8vec3(2_u8, 3_u8, 3_u8)); assert_eq!(v.zxx(), u8vec3(3_u8, 1_u8, 1_u8)); assert_eq!(v.zxy(), u8vec3(3_u8, 1_u8, 2_u8)); assert_eq!(v.zxz(), u8vec3(3_u8, 1_u8, 3_u8)); assert_eq!(v.zyx(), u8vec3(3_u8, 2_u8, 1_u8)); assert_eq!(v.zyy(), u8vec3(3_u8, 2_u8, 2_u8)); assert_eq!(v.zyz(), u8vec3(3_u8, 2_u8, 3_u8)); assert_eq!(v.zzx(), u8vec3(3_u8, 3_u8, 1_u8)); assert_eq!(v.zzy(), u8vec3(3_u8, 3_u8, 2_u8)); assert_eq!(v.zzz(), u8vec3(3_u8, 3_u8, 3_u8)); assert_eq!(v.xx(), u8vec2(1_u8, 1_u8)); assert_eq!(v.xy(), u8vec2(1_u8, 2_u8)); assert_eq!(v.xz(), u8vec2(1_u8, 3_u8)); assert_eq!(v.yx(), u8vec2(2_u8, 1_u8)); assert_eq!(v.yy(), u8vec2(2_u8, 2_u8)); assert_eq!(v.yz(), u8vec2(2_u8, 3_u8)); assert_eq!(v.zx(), u8vec2(3_u8, 1_u8)); assert_eq!(v.zy(), u8vec2(3_u8, 2_u8)); assert_eq!(v.zz(), u8vec2(3_u8, 3_u8)); assert_eq!(v.with_xy(rhs2), u8vec3(11_u8, 12_u8, 3_u8)); assert_eq!(v.with_xz(rhs2), u8vec3(11_u8, 2_u8, 12_u8)); assert_eq!(v.with_yx(rhs2), u8vec3(12_u8, 11_u8, 3_u8)); assert_eq!(v.with_yz(rhs2), u8vec3(1_u8, 11_u8, 12_u8)); assert_eq!(v.with_zx(rhs2), u8vec3(12_u8, 2_u8, 11_u8)); assert_eq!(v.with_zy(rhs2), u8vec3(1_u8, 12_u8, 11_u8)); }); glam_test!(test_u8vec2_swizzles, { let v = u8vec2(1_u8, 2_u8); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), u8vec4(1_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.xxxy(), u8vec4(1_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.xxyx(), u8vec4(1_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.xxyy(), u8vec4(1_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.xyxx(), u8vec4(1_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.xyxy(), u8vec4(1_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.xyyx(), u8vec4(1_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.xyyy(), u8vec4(1_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.yxxx(), u8vec4(2_u8, 1_u8, 1_u8, 1_u8)); assert_eq!(v.yxxy(), u8vec4(2_u8, 1_u8, 1_u8, 2_u8)); assert_eq!(v.yxyx(), u8vec4(2_u8, 1_u8, 2_u8, 1_u8)); assert_eq!(v.yxyy(), u8vec4(2_u8, 1_u8, 2_u8, 2_u8)); assert_eq!(v.yyxx(), u8vec4(2_u8, 2_u8, 1_u8, 1_u8)); assert_eq!(v.yyxy(), u8vec4(2_u8, 2_u8, 1_u8, 2_u8)); assert_eq!(v.yyyx(), u8vec4(2_u8, 2_u8, 2_u8, 1_u8)); assert_eq!(v.yyyy(), u8vec4(2_u8, 2_u8, 2_u8, 2_u8)); assert_eq!(v.xxx(), u8vec3(1_u8, 1_u8, 1_u8)); assert_eq!(v.xxy(), u8vec3(1_u8, 1_u8, 2_u8)); assert_eq!(v.xyx(), u8vec3(1_u8, 2_u8, 1_u8)); assert_eq!(v.xyy(), u8vec3(1_u8, 2_u8, 2_u8)); assert_eq!(v.yxx(), u8vec3(2_u8, 1_u8, 1_u8)); assert_eq!(v.yxy(), u8vec3(2_u8, 1_u8, 2_u8)); assert_eq!(v.yyx(), u8vec3(2_u8, 2_u8, 1_u8)); assert_eq!(v.yyy(), u8vec3(2_u8, 2_u8, 2_u8)); assert_eq!(v.xx(), u8vec2(1_u8, 1_u8)); assert_eq!(v.yx(), u8vec2(2_u8, 1_u8)); assert_eq!(v.yy(), u8vec2(2_u8, 2_u8)); }); glam-0.30.1/tests/swizzles_usize.rs000064400000000000000000001124371046102023000154560ustar 00000000000000// Generated by swizzlegen. Do not edit. #[macro_use] mod support; use glam::*; glam_test!(test_usizevec4_swizzles, { let v = usizevec4(1_usize, 2_usize, 3_usize, 4_usize); let rhs3 = usizevec3(11_usize, 12_usize, 13_usize); let rhs2 = usizevec2(11_usize, 12_usize); assert_eq!(v, v.xyzw()); assert_eq!(v.xxxx(), usizevec4(1_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.xxxy(), usizevec4(1_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.xxxz(), usizevec4(1_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.xxxw(), usizevec4(1_usize, 1_usize, 1_usize, 4_usize)); assert_eq!(v.xxyx(), usizevec4(1_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.xxyy(), usizevec4(1_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.xxyz(), usizevec4(1_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.xxyw(), usizevec4(1_usize, 1_usize, 2_usize, 4_usize)); assert_eq!(v.xxzx(), usizevec4(1_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.xxzy(), usizevec4(1_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.xxzz(), usizevec4(1_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.xxzw(), usizevec4(1_usize, 1_usize, 3_usize, 4_usize)); assert_eq!(v.xxwx(), usizevec4(1_usize, 1_usize, 4_usize, 1_usize)); assert_eq!(v.xxwy(), usizevec4(1_usize, 1_usize, 4_usize, 2_usize)); assert_eq!(v.xxwz(), usizevec4(1_usize, 1_usize, 4_usize, 3_usize)); assert_eq!(v.xxww(), usizevec4(1_usize, 1_usize, 4_usize, 4_usize)); assert_eq!(v.xyxx(), usizevec4(1_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.xyxy(), usizevec4(1_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.xyxz(), usizevec4(1_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.xyxw(), usizevec4(1_usize, 2_usize, 1_usize, 4_usize)); assert_eq!(v.xyyx(), usizevec4(1_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.xyyy(), usizevec4(1_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.xyyz(), usizevec4(1_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.xyyw(), usizevec4(1_usize, 2_usize, 2_usize, 4_usize)); assert_eq!(v.xyzx(), usizevec4(1_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.xyzy(), usizevec4(1_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.xyzz(), usizevec4(1_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.xywx(), usizevec4(1_usize, 2_usize, 4_usize, 1_usize)); assert_eq!(v.xywy(), usizevec4(1_usize, 2_usize, 4_usize, 2_usize)); assert_eq!(v.xywz(), usizevec4(1_usize, 2_usize, 4_usize, 3_usize)); assert_eq!(v.xyww(), usizevec4(1_usize, 2_usize, 4_usize, 4_usize)); assert_eq!(v.xzxx(), usizevec4(1_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.xzxy(), usizevec4(1_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.xzxz(), usizevec4(1_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.xzxw(), usizevec4(1_usize, 3_usize, 1_usize, 4_usize)); assert_eq!(v.xzyx(), usizevec4(1_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.xzyy(), usizevec4(1_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.xzyz(), usizevec4(1_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.xzyw(), usizevec4(1_usize, 3_usize, 2_usize, 4_usize)); assert_eq!(v.xzzx(), usizevec4(1_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.xzzy(), usizevec4(1_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.xzzz(), usizevec4(1_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.xzzw(), usizevec4(1_usize, 3_usize, 3_usize, 4_usize)); assert_eq!(v.xzwx(), usizevec4(1_usize, 3_usize, 4_usize, 1_usize)); assert_eq!(v.xzwy(), usizevec4(1_usize, 3_usize, 4_usize, 2_usize)); assert_eq!(v.xzwz(), usizevec4(1_usize, 3_usize, 4_usize, 3_usize)); assert_eq!(v.xzww(), usizevec4(1_usize, 3_usize, 4_usize, 4_usize)); assert_eq!(v.xwxx(), usizevec4(1_usize, 4_usize, 1_usize, 1_usize)); assert_eq!(v.xwxy(), usizevec4(1_usize, 4_usize, 1_usize, 2_usize)); assert_eq!(v.xwxz(), usizevec4(1_usize, 4_usize, 1_usize, 3_usize)); assert_eq!(v.xwxw(), usizevec4(1_usize, 4_usize, 1_usize, 4_usize)); assert_eq!(v.xwyx(), usizevec4(1_usize, 4_usize, 2_usize, 1_usize)); assert_eq!(v.xwyy(), usizevec4(1_usize, 4_usize, 2_usize, 2_usize)); assert_eq!(v.xwyz(), usizevec4(1_usize, 4_usize, 2_usize, 3_usize)); assert_eq!(v.xwyw(), usizevec4(1_usize, 4_usize, 2_usize, 4_usize)); assert_eq!(v.xwzx(), usizevec4(1_usize, 4_usize, 3_usize, 1_usize)); assert_eq!(v.xwzy(), usizevec4(1_usize, 4_usize, 3_usize, 2_usize)); assert_eq!(v.xwzz(), usizevec4(1_usize, 4_usize, 3_usize, 3_usize)); assert_eq!(v.xwzw(), usizevec4(1_usize, 4_usize, 3_usize, 4_usize)); assert_eq!(v.xwwx(), usizevec4(1_usize, 4_usize, 4_usize, 1_usize)); assert_eq!(v.xwwy(), usizevec4(1_usize, 4_usize, 4_usize, 2_usize)); assert_eq!(v.xwwz(), usizevec4(1_usize, 4_usize, 4_usize, 3_usize)); assert_eq!(v.xwww(), usizevec4(1_usize, 4_usize, 4_usize, 4_usize)); assert_eq!(v.yxxx(), usizevec4(2_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.yxxy(), usizevec4(2_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.yxxz(), usizevec4(2_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.yxxw(), usizevec4(2_usize, 1_usize, 1_usize, 4_usize)); assert_eq!(v.yxyx(), usizevec4(2_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.yxyy(), usizevec4(2_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.yxyz(), usizevec4(2_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.yxyw(), usizevec4(2_usize, 1_usize, 2_usize, 4_usize)); assert_eq!(v.yxzx(), usizevec4(2_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.yxzy(), usizevec4(2_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.yxzz(), usizevec4(2_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.yxzw(), usizevec4(2_usize, 1_usize, 3_usize, 4_usize)); assert_eq!(v.yxwx(), usizevec4(2_usize, 1_usize, 4_usize, 1_usize)); assert_eq!(v.yxwy(), usizevec4(2_usize, 1_usize, 4_usize, 2_usize)); assert_eq!(v.yxwz(), usizevec4(2_usize, 1_usize, 4_usize, 3_usize)); assert_eq!(v.yxww(), usizevec4(2_usize, 1_usize, 4_usize, 4_usize)); assert_eq!(v.yyxx(), usizevec4(2_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.yyxy(), usizevec4(2_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.yyxz(), usizevec4(2_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.yyxw(), usizevec4(2_usize, 2_usize, 1_usize, 4_usize)); assert_eq!(v.yyyx(), usizevec4(2_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.yyyy(), usizevec4(2_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.yyyz(), usizevec4(2_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.yyyw(), usizevec4(2_usize, 2_usize, 2_usize, 4_usize)); assert_eq!(v.yyzx(), usizevec4(2_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.yyzy(), usizevec4(2_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.yyzz(), usizevec4(2_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.yyzw(), usizevec4(2_usize, 2_usize, 3_usize, 4_usize)); assert_eq!(v.yywx(), usizevec4(2_usize, 2_usize, 4_usize, 1_usize)); assert_eq!(v.yywy(), usizevec4(2_usize, 2_usize, 4_usize, 2_usize)); assert_eq!(v.yywz(), usizevec4(2_usize, 2_usize, 4_usize, 3_usize)); assert_eq!(v.yyww(), usizevec4(2_usize, 2_usize, 4_usize, 4_usize)); assert_eq!(v.yzxx(), usizevec4(2_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.yzxy(), usizevec4(2_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.yzxz(), usizevec4(2_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.yzxw(), usizevec4(2_usize, 3_usize, 1_usize, 4_usize)); assert_eq!(v.yzyx(), usizevec4(2_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.yzyy(), usizevec4(2_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.yzyz(), usizevec4(2_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.yzyw(), usizevec4(2_usize, 3_usize, 2_usize, 4_usize)); assert_eq!(v.yzzx(), usizevec4(2_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.yzzy(), usizevec4(2_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.yzzz(), usizevec4(2_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.yzzw(), usizevec4(2_usize, 3_usize, 3_usize, 4_usize)); assert_eq!(v.yzwx(), usizevec4(2_usize, 3_usize, 4_usize, 1_usize)); assert_eq!(v.yzwy(), usizevec4(2_usize, 3_usize, 4_usize, 2_usize)); assert_eq!(v.yzwz(), usizevec4(2_usize, 3_usize, 4_usize, 3_usize)); assert_eq!(v.yzww(), usizevec4(2_usize, 3_usize, 4_usize, 4_usize)); assert_eq!(v.ywxx(), usizevec4(2_usize, 4_usize, 1_usize, 1_usize)); assert_eq!(v.ywxy(), usizevec4(2_usize, 4_usize, 1_usize, 2_usize)); assert_eq!(v.ywxz(), usizevec4(2_usize, 4_usize, 1_usize, 3_usize)); assert_eq!(v.ywxw(), usizevec4(2_usize, 4_usize, 1_usize, 4_usize)); assert_eq!(v.ywyx(), usizevec4(2_usize, 4_usize, 2_usize, 1_usize)); assert_eq!(v.ywyy(), usizevec4(2_usize, 4_usize, 2_usize, 2_usize)); assert_eq!(v.ywyz(), usizevec4(2_usize, 4_usize, 2_usize, 3_usize)); assert_eq!(v.ywyw(), usizevec4(2_usize, 4_usize, 2_usize, 4_usize)); assert_eq!(v.ywzx(), usizevec4(2_usize, 4_usize, 3_usize, 1_usize)); assert_eq!(v.ywzy(), usizevec4(2_usize, 4_usize, 3_usize, 2_usize)); assert_eq!(v.ywzz(), usizevec4(2_usize, 4_usize, 3_usize, 3_usize)); assert_eq!(v.ywzw(), usizevec4(2_usize, 4_usize, 3_usize, 4_usize)); assert_eq!(v.ywwx(), usizevec4(2_usize, 4_usize, 4_usize, 1_usize)); assert_eq!(v.ywwy(), usizevec4(2_usize, 4_usize, 4_usize, 2_usize)); assert_eq!(v.ywwz(), usizevec4(2_usize, 4_usize, 4_usize, 3_usize)); assert_eq!(v.ywww(), usizevec4(2_usize, 4_usize, 4_usize, 4_usize)); assert_eq!(v.zxxx(), usizevec4(3_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.zxxy(), usizevec4(3_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.zxxz(), usizevec4(3_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.zxxw(), usizevec4(3_usize, 1_usize, 1_usize, 4_usize)); assert_eq!(v.zxyx(), usizevec4(3_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.zxyy(), usizevec4(3_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.zxyz(), usizevec4(3_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.zxyw(), usizevec4(3_usize, 1_usize, 2_usize, 4_usize)); assert_eq!(v.zxzx(), usizevec4(3_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.zxzy(), usizevec4(3_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.zxzz(), usizevec4(3_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.zxzw(), usizevec4(3_usize, 1_usize, 3_usize, 4_usize)); assert_eq!(v.zxwx(), usizevec4(3_usize, 1_usize, 4_usize, 1_usize)); assert_eq!(v.zxwy(), usizevec4(3_usize, 1_usize, 4_usize, 2_usize)); assert_eq!(v.zxwz(), usizevec4(3_usize, 1_usize, 4_usize, 3_usize)); assert_eq!(v.zxww(), usizevec4(3_usize, 1_usize, 4_usize, 4_usize)); assert_eq!(v.zyxx(), usizevec4(3_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.zyxy(), usizevec4(3_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.zyxz(), usizevec4(3_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.zyxw(), usizevec4(3_usize, 2_usize, 1_usize, 4_usize)); assert_eq!(v.zyyx(), usizevec4(3_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.zyyy(), usizevec4(3_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.zyyz(), usizevec4(3_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.zyyw(), usizevec4(3_usize, 2_usize, 2_usize, 4_usize)); assert_eq!(v.zyzx(), usizevec4(3_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.zyzy(), usizevec4(3_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.zyzz(), usizevec4(3_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.zyzw(), usizevec4(3_usize, 2_usize, 3_usize, 4_usize)); assert_eq!(v.zywx(), usizevec4(3_usize, 2_usize, 4_usize, 1_usize)); assert_eq!(v.zywy(), usizevec4(3_usize, 2_usize, 4_usize, 2_usize)); assert_eq!(v.zywz(), usizevec4(3_usize, 2_usize, 4_usize, 3_usize)); assert_eq!(v.zyww(), usizevec4(3_usize, 2_usize, 4_usize, 4_usize)); assert_eq!(v.zzxx(), usizevec4(3_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.zzxy(), usizevec4(3_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.zzxz(), usizevec4(3_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.zzxw(), usizevec4(3_usize, 3_usize, 1_usize, 4_usize)); assert_eq!(v.zzyx(), usizevec4(3_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.zzyy(), usizevec4(3_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.zzyz(), usizevec4(3_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.zzyw(), usizevec4(3_usize, 3_usize, 2_usize, 4_usize)); assert_eq!(v.zzzx(), usizevec4(3_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.zzzy(), usizevec4(3_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.zzzz(), usizevec4(3_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.zzzw(), usizevec4(3_usize, 3_usize, 3_usize, 4_usize)); assert_eq!(v.zzwx(), usizevec4(3_usize, 3_usize, 4_usize, 1_usize)); assert_eq!(v.zzwy(), usizevec4(3_usize, 3_usize, 4_usize, 2_usize)); assert_eq!(v.zzwz(), usizevec4(3_usize, 3_usize, 4_usize, 3_usize)); assert_eq!(v.zzww(), usizevec4(3_usize, 3_usize, 4_usize, 4_usize)); assert_eq!(v.zwxx(), usizevec4(3_usize, 4_usize, 1_usize, 1_usize)); assert_eq!(v.zwxy(), usizevec4(3_usize, 4_usize, 1_usize, 2_usize)); assert_eq!(v.zwxz(), usizevec4(3_usize, 4_usize, 1_usize, 3_usize)); assert_eq!(v.zwxw(), usizevec4(3_usize, 4_usize, 1_usize, 4_usize)); assert_eq!(v.zwyx(), usizevec4(3_usize, 4_usize, 2_usize, 1_usize)); assert_eq!(v.zwyy(), usizevec4(3_usize, 4_usize, 2_usize, 2_usize)); assert_eq!(v.zwyz(), usizevec4(3_usize, 4_usize, 2_usize, 3_usize)); assert_eq!(v.zwyw(), usizevec4(3_usize, 4_usize, 2_usize, 4_usize)); assert_eq!(v.zwzx(), usizevec4(3_usize, 4_usize, 3_usize, 1_usize)); assert_eq!(v.zwzy(), usizevec4(3_usize, 4_usize, 3_usize, 2_usize)); assert_eq!(v.zwzz(), usizevec4(3_usize, 4_usize, 3_usize, 3_usize)); assert_eq!(v.zwzw(), usizevec4(3_usize, 4_usize, 3_usize, 4_usize)); assert_eq!(v.zwwx(), usizevec4(3_usize, 4_usize, 4_usize, 1_usize)); assert_eq!(v.zwwy(), usizevec4(3_usize, 4_usize, 4_usize, 2_usize)); assert_eq!(v.zwwz(), usizevec4(3_usize, 4_usize, 4_usize, 3_usize)); assert_eq!(v.zwww(), usizevec4(3_usize, 4_usize, 4_usize, 4_usize)); assert_eq!(v.wxxx(), usizevec4(4_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.wxxy(), usizevec4(4_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.wxxz(), usizevec4(4_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.wxxw(), usizevec4(4_usize, 1_usize, 1_usize, 4_usize)); assert_eq!(v.wxyx(), usizevec4(4_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.wxyy(), usizevec4(4_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.wxyz(), usizevec4(4_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.wxyw(), usizevec4(4_usize, 1_usize, 2_usize, 4_usize)); assert_eq!(v.wxzx(), usizevec4(4_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.wxzy(), usizevec4(4_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.wxzz(), usizevec4(4_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.wxzw(), usizevec4(4_usize, 1_usize, 3_usize, 4_usize)); assert_eq!(v.wxwx(), usizevec4(4_usize, 1_usize, 4_usize, 1_usize)); assert_eq!(v.wxwy(), usizevec4(4_usize, 1_usize, 4_usize, 2_usize)); assert_eq!(v.wxwz(), usizevec4(4_usize, 1_usize, 4_usize, 3_usize)); assert_eq!(v.wxww(), usizevec4(4_usize, 1_usize, 4_usize, 4_usize)); assert_eq!(v.wyxx(), usizevec4(4_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.wyxy(), usizevec4(4_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.wyxz(), usizevec4(4_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.wyxw(), usizevec4(4_usize, 2_usize, 1_usize, 4_usize)); assert_eq!(v.wyyx(), usizevec4(4_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.wyyy(), usizevec4(4_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.wyyz(), usizevec4(4_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.wyyw(), usizevec4(4_usize, 2_usize, 2_usize, 4_usize)); assert_eq!(v.wyzx(), usizevec4(4_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.wyzy(), usizevec4(4_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.wyzz(), usizevec4(4_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.wyzw(), usizevec4(4_usize, 2_usize, 3_usize, 4_usize)); assert_eq!(v.wywx(), usizevec4(4_usize, 2_usize, 4_usize, 1_usize)); assert_eq!(v.wywy(), usizevec4(4_usize, 2_usize, 4_usize, 2_usize)); assert_eq!(v.wywz(), usizevec4(4_usize, 2_usize, 4_usize, 3_usize)); assert_eq!(v.wyww(), usizevec4(4_usize, 2_usize, 4_usize, 4_usize)); assert_eq!(v.wzxx(), usizevec4(4_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.wzxy(), usizevec4(4_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.wzxz(), usizevec4(4_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.wzxw(), usizevec4(4_usize, 3_usize, 1_usize, 4_usize)); assert_eq!(v.wzyx(), usizevec4(4_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.wzyy(), usizevec4(4_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.wzyz(), usizevec4(4_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.wzyw(), usizevec4(4_usize, 3_usize, 2_usize, 4_usize)); assert_eq!(v.wzzx(), usizevec4(4_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.wzzy(), usizevec4(4_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.wzzz(), usizevec4(4_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.wzzw(), usizevec4(4_usize, 3_usize, 3_usize, 4_usize)); assert_eq!(v.wzwx(), usizevec4(4_usize, 3_usize, 4_usize, 1_usize)); assert_eq!(v.wzwy(), usizevec4(4_usize, 3_usize, 4_usize, 2_usize)); assert_eq!(v.wzwz(), usizevec4(4_usize, 3_usize, 4_usize, 3_usize)); assert_eq!(v.wzww(), usizevec4(4_usize, 3_usize, 4_usize, 4_usize)); assert_eq!(v.wwxx(), usizevec4(4_usize, 4_usize, 1_usize, 1_usize)); assert_eq!(v.wwxy(), usizevec4(4_usize, 4_usize, 1_usize, 2_usize)); assert_eq!(v.wwxz(), usizevec4(4_usize, 4_usize, 1_usize, 3_usize)); assert_eq!(v.wwxw(), usizevec4(4_usize, 4_usize, 1_usize, 4_usize)); assert_eq!(v.wwyx(), usizevec4(4_usize, 4_usize, 2_usize, 1_usize)); assert_eq!(v.wwyy(), usizevec4(4_usize, 4_usize, 2_usize, 2_usize)); assert_eq!(v.wwyz(), usizevec4(4_usize, 4_usize, 2_usize, 3_usize)); assert_eq!(v.wwyw(), usizevec4(4_usize, 4_usize, 2_usize, 4_usize)); assert_eq!(v.wwzx(), usizevec4(4_usize, 4_usize, 3_usize, 1_usize)); assert_eq!(v.wwzy(), usizevec4(4_usize, 4_usize, 3_usize, 2_usize)); assert_eq!(v.wwzz(), usizevec4(4_usize, 4_usize, 3_usize, 3_usize)); assert_eq!(v.wwzw(), usizevec4(4_usize, 4_usize, 3_usize, 4_usize)); assert_eq!(v.wwwx(), usizevec4(4_usize, 4_usize, 4_usize, 1_usize)); assert_eq!(v.wwwy(), usizevec4(4_usize, 4_usize, 4_usize, 2_usize)); assert_eq!(v.wwwz(), usizevec4(4_usize, 4_usize, 4_usize, 3_usize)); assert_eq!(v.wwww(), usizevec4(4_usize, 4_usize, 4_usize, 4_usize)); assert_eq!(v.xxx(), usizevec3(1_usize, 1_usize, 1_usize)); assert_eq!(v.xxy(), usizevec3(1_usize, 1_usize, 2_usize)); assert_eq!(v.xxz(), usizevec3(1_usize, 1_usize, 3_usize)); assert_eq!(v.xxw(), usizevec3(1_usize, 1_usize, 4_usize)); assert_eq!(v.xyx(), usizevec3(1_usize, 2_usize, 1_usize)); assert_eq!(v.xyy(), usizevec3(1_usize, 2_usize, 2_usize)); assert_eq!(v.xyz(), usizevec3(1_usize, 2_usize, 3_usize)); assert_eq!(v.xyw(), usizevec3(1_usize, 2_usize, 4_usize)); assert_eq!(v.xzx(), usizevec3(1_usize, 3_usize, 1_usize)); assert_eq!(v.xzy(), usizevec3(1_usize, 3_usize, 2_usize)); assert_eq!(v.xzz(), usizevec3(1_usize, 3_usize, 3_usize)); assert_eq!(v.xzw(), usizevec3(1_usize, 3_usize, 4_usize)); assert_eq!(v.xwx(), usizevec3(1_usize, 4_usize, 1_usize)); assert_eq!(v.xwy(), usizevec3(1_usize, 4_usize, 2_usize)); assert_eq!(v.xwz(), usizevec3(1_usize, 4_usize, 3_usize)); assert_eq!(v.xww(), usizevec3(1_usize, 4_usize, 4_usize)); assert_eq!(v.yxx(), usizevec3(2_usize, 1_usize, 1_usize)); assert_eq!(v.yxy(), usizevec3(2_usize, 1_usize, 2_usize)); assert_eq!(v.yxz(), usizevec3(2_usize, 1_usize, 3_usize)); assert_eq!(v.yxw(), usizevec3(2_usize, 1_usize, 4_usize)); assert_eq!(v.yyx(), usizevec3(2_usize, 2_usize, 1_usize)); assert_eq!(v.yyy(), usizevec3(2_usize, 2_usize, 2_usize)); assert_eq!(v.yyz(), usizevec3(2_usize, 2_usize, 3_usize)); assert_eq!(v.yyw(), usizevec3(2_usize, 2_usize, 4_usize)); assert_eq!(v.yzx(), usizevec3(2_usize, 3_usize, 1_usize)); assert_eq!(v.yzy(), usizevec3(2_usize, 3_usize, 2_usize)); assert_eq!(v.yzz(), usizevec3(2_usize, 3_usize, 3_usize)); assert_eq!(v.yzw(), usizevec3(2_usize, 3_usize, 4_usize)); assert_eq!(v.ywx(), usizevec3(2_usize, 4_usize, 1_usize)); assert_eq!(v.ywy(), usizevec3(2_usize, 4_usize, 2_usize)); assert_eq!(v.ywz(), usizevec3(2_usize, 4_usize, 3_usize)); assert_eq!(v.yww(), usizevec3(2_usize, 4_usize, 4_usize)); assert_eq!(v.zxx(), usizevec3(3_usize, 1_usize, 1_usize)); assert_eq!(v.zxy(), usizevec3(3_usize, 1_usize, 2_usize)); assert_eq!(v.zxz(), usizevec3(3_usize, 1_usize, 3_usize)); assert_eq!(v.zxw(), usizevec3(3_usize, 1_usize, 4_usize)); assert_eq!(v.zyx(), usizevec3(3_usize, 2_usize, 1_usize)); assert_eq!(v.zyy(), usizevec3(3_usize, 2_usize, 2_usize)); assert_eq!(v.zyz(), usizevec3(3_usize, 2_usize, 3_usize)); assert_eq!(v.zyw(), usizevec3(3_usize, 2_usize, 4_usize)); assert_eq!(v.zzx(), usizevec3(3_usize, 3_usize, 1_usize)); assert_eq!(v.zzy(), usizevec3(3_usize, 3_usize, 2_usize)); assert_eq!(v.zzz(), usizevec3(3_usize, 3_usize, 3_usize)); assert_eq!(v.zzw(), usizevec3(3_usize, 3_usize, 4_usize)); assert_eq!(v.zwx(), usizevec3(3_usize, 4_usize, 1_usize)); assert_eq!(v.zwy(), usizevec3(3_usize, 4_usize, 2_usize)); assert_eq!(v.zwz(), usizevec3(3_usize, 4_usize, 3_usize)); assert_eq!(v.zww(), usizevec3(3_usize, 4_usize, 4_usize)); assert_eq!(v.wxx(), usizevec3(4_usize, 1_usize, 1_usize)); assert_eq!(v.wxy(), usizevec3(4_usize, 1_usize, 2_usize)); assert_eq!(v.wxz(), usizevec3(4_usize, 1_usize, 3_usize)); assert_eq!(v.wxw(), usizevec3(4_usize, 1_usize, 4_usize)); assert_eq!(v.wyx(), usizevec3(4_usize, 2_usize, 1_usize)); assert_eq!(v.wyy(), usizevec3(4_usize, 2_usize, 2_usize)); assert_eq!(v.wyz(), usizevec3(4_usize, 2_usize, 3_usize)); assert_eq!(v.wyw(), usizevec3(4_usize, 2_usize, 4_usize)); assert_eq!(v.wzx(), usizevec3(4_usize, 3_usize, 1_usize)); assert_eq!(v.wzy(), usizevec3(4_usize, 3_usize, 2_usize)); assert_eq!(v.wzz(), usizevec3(4_usize, 3_usize, 3_usize)); assert_eq!(v.wzw(), usizevec3(4_usize, 3_usize, 4_usize)); assert_eq!(v.wwx(), usizevec3(4_usize, 4_usize, 1_usize)); assert_eq!(v.wwy(), usizevec3(4_usize, 4_usize, 2_usize)); assert_eq!(v.wwz(), usizevec3(4_usize, 4_usize, 3_usize)); assert_eq!(v.www(), usizevec3(4_usize, 4_usize, 4_usize)); assert_eq!( v.with_xyz(rhs3), usizevec4(11_usize, 12_usize, 13_usize, 4_usize) ); assert_eq!( v.with_xyw(rhs3), usizevec4(11_usize, 12_usize, 3_usize, 13_usize) ); assert_eq!( v.with_xzy(rhs3), usizevec4(11_usize, 13_usize, 12_usize, 4_usize) ); assert_eq!( v.with_xzw(rhs3), usizevec4(11_usize, 2_usize, 12_usize, 13_usize) ); assert_eq!( v.with_xwy(rhs3), usizevec4(11_usize, 13_usize, 3_usize, 12_usize) ); assert_eq!( v.with_xwz(rhs3), usizevec4(11_usize, 2_usize, 13_usize, 12_usize) ); assert_eq!( v.with_yxz(rhs3), usizevec4(12_usize, 11_usize, 13_usize, 4_usize) ); assert_eq!( v.with_yxw(rhs3), usizevec4(12_usize, 11_usize, 3_usize, 13_usize) ); assert_eq!( v.with_yzx(rhs3), usizevec4(13_usize, 11_usize, 12_usize, 4_usize) ); assert_eq!( v.with_yzw(rhs3), usizevec4(1_usize, 11_usize, 12_usize, 13_usize) ); assert_eq!( v.with_ywx(rhs3), usizevec4(13_usize, 11_usize, 3_usize, 12_usize) ); assert_eq!( v.with_ywz(rhs3), usizevec4(1_usize, 11_usize, 13_usize, 12_usize) ); assert_eq!( v.with_zxy(rhs3), usizevec4(12_usize, 13_usize, 11_usize, 4_usize) ); assert_eq!( v.with_zxw(rhs3), usizevec4(12_usize, 2_usize, 11_usize, 13_usize) ); assert_eq!( v.with_zyx(rhs3), usizevec4(13_usize, 12_usize, 11_usize, 4_usize) ); assert_eq!( v.with_zyw(rhs3), usizevec4(1_usize, 12_usize, 11_usize, 13_usize) ); assert_eq!( v.with_zwx(rhs3), usizevec4(13_usize, 2_usize, 11_usize, 12_usize) ); assert_eq!( v.with_zwy(rhs3), usizevec4(1_usize, 13_usize, 11_usize, 12_usize) ); assert_eq!( v.with_wxy(rhs3), usizevec4(12_usize, 13_usize, 3_usize, 11_usize) ); assert_eq!( v.with_wxz(rhs3), usizevec4(12_usize, 2_usize, 13_usize, 11_usize) ); assert_eq!( v.with_wyx(rhs3), usizevec4(13_usize, 12_usize, 3_usize, 11_usize) ); assert_eq!( v.with_wyz(rhs3), usizevec4(1_usize, 12_usize, 13_usize, 11_usize) ); assert_eq!( v.with_wzx(rhs3), usizevec4(13_usize, 2_usize, 12_usize, 11_usize) ); assert_eq!( v.with_wzy(rhs3), usizevec4(1_usize, 13_usize, 12_usize, 11_usize) ); assert_eq!(v.xx(), usizevec2(1_usize, 1_usize)); assert_eq!(v.xy(), usizevec2(1_usize, 2_usize)); assert_eq!(v.xz(), usizevec2(1_usize, 3_usize)); assert_eq!(v.xw(), usizevec2(1_usize, 4_usize)); assert_eq!(v.yx(), usizevec2(2_usize, 1_usize)); assert_eq!(v.yy(), usizevec2(2_usize, 2_usize)); assert_eq!(v.yz(), usizevec2(2_usize, 3_usize)); assert_eq!(v.yw(), usizevec2(2_usize, 4_usize)); assert_eq!(v.zx(), usizevec2(3_usize, 1_usize)); assert_eq!(v.zy(), usizevec2(3_usize, 2_usize)); assert_eq!(v.zz(), usizevec2(3_usize, 3_usize)); assert_eq!(v.zw(), usizevec2(3_usize, 4_usize)); assert_eq!(v.wx(), usizevec2(4_usize, 1_usize)); assert_eq!(v.wy(), usizevec2(4_usize, 2_usize)); assert_eq!(v.wz(), usizevec2(4_usize, 3_usize)); assert_eq!(v.ww(), usizevec2(4_usize, 4_usize)); assert_eq!( v.with_xy(rhs2), usizevec4(11_usize, 12_usize, 3_usize, 4_usize) ); assert_eq!( v.with_xz(rhs2), usizevec4(11_usize, 2_usize, 12_usize, 4_usize) ); assert_eq!( v.with_xw(rhs2), usizevec4(11_usize, 2_usize, 3_usize, 12_usize) ); assert_eq!( v.with_yx(rhs2), usizevec4(12_usize, 11_usize, 3_usize, 4_usize) ); assert_eq!( v.with_yz(rhs2), usizevec4(1_usize, 11_usize, 12_usize, 4_usize) ); assert_eq!( v.with_yw(rhs2), usizevec4(1_usize, 11_usize, 3_usize, 12_usize) ); assert_eq!( v.with_zx(rhs2), usizevec4(12_usize, 2_usize, 11_usize, 4_usize) ); assert_eq!( v.with_zy(rhs2), usizevec4(1_usize, 12_usize, 11_usize, 4_usize) ); assert_eq!( v.with_zw(rhs2), usizevec4(1_usize, 2_usize, 11_usize, 12_usize) ); assert_eq!( v.with_wx(rhs2), usizevec4(12_usize, 2_usize, 3_usize, 11_usize) ); assert_eq!( v.with_wy(rhs2), usizevec4(1_usize, 12_usize, 3_usize, 11_usize) ); assert_eq!( v.with_wz(rhs2), usizevec4(1_usize, 2_usize, 12_usize, 11_usize) ); }); glam_test!(test_usizevec3_swizzles, { let v = usizevec3(1_usize, 2_usize, 3_usize); let rhs2 = usizevec2(11_usize, 12_usize); assert_eq!(v, v.xyz()); assert_eq!(v.xxxx(), usizevec4(1_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.xxxy(), usizevec4(1_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.xxxz(), usizevec4(1_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.xxyx(), usizevec4(1_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.xxyy(), usizevec4(1_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.xxyz(), usizevec4(1_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.xxzx(), usizevec4(1_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.xxzy(), usizevec4(1_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.xxzz(), usizevec4(1_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.xyxx(), usizevec4(1_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.xyxy(), usizevec4(1_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.xyxz(), usizevec4(1_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.xyyx(), usizevec4(1_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.xyyy(), usizevec4(1_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.xyyz(), usizevec4(1_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.xyzx(), usizevec4(1_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.xyzy(), usizevec4(1_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.xyzz(), usizevec4(1_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.xzxx(), usizevec4(1_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.xzxy(), usizevec4(1_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.xzxz(), usizevec4(1_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.xzyx(), usizevec4(1_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.xzyy(), usizevec4(1_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.xzyz(), usizevec4(1_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.xzzx(), usizevec4(1_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.xzzy(), usizevec4(1_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.xzzz(), usizevec4(1_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.yxxx(), usizevec4(2_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.yxxy(), usizevec4(2_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.yxxz(), usizevec4(2_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.yxyx(), usizevec4(2_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.yxyy(), usizevec4(2_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.yxyz(), usizevec4(2_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.yxzx(), usizevec4(2_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.yxzy(), usizevec4(2_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.yxzz(), usizevec4(2_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.yyxx(), usizevec4(2_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.yyxy(), usizevec4(2_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.yyxz(), usizevec4(2_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.yyyx(), usizevec4(2_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.yyyy(), usizevec4(2_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.yyyz(), usizevec4(2_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.yyzx(), usizevec4(2_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.yyzy(), usizevec4(2_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.yyzz(), usizevec4(2_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.yzxx(), usizevec4(2_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.yzxy(), usizevec4(2_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.yzxz(), usizevec4(2_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.yzyx(), usizevec4(2_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.yzyy(), usizevec4(2_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.yzyz(), usizevec4(2_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.yzzx(), usizevec4(2_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.yzzy(), usizevec4(2_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.yzzz(), usizevec4(2_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.zxxx(), usizevec4(3_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.zxxy(), usizevec4(3_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.zxxz(), usizevec4(3_usize, 1_usize, 1_usize, 3_usize)); assert_eq!(v.zxyx(), usizevec4(3_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.zxyy(), usizevec4(3_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.zxyz(), usizevec4(3_usize, 1_usize, 2_usize, 3_usize)); assert_eq!(v.zxzx(), usizevec4(3_usize, 1_usize, 3_usize, 1_usize)); assert_eq!(v.zxzy(), usizevec4(3_usize, 1_usize, 3_usize, 2_usize)); assert_eq!(v.zxzz(), usizevec4(3_usize, 1_usize, 3_usize, 3_usize)); assert_eq!(v.zyxx(), usizevec4(3_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.zyxy(), usizevec4(3_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.zyxz(), usizevec4(3_usize, 2_usize, 1_usize, 3_usize)); assert_eq!(v.zyyx(), usizevec4(3_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.zyyy(), usizevec4(3_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.zyyz(), usizevec4(3_usize, 2_usize, 2_usize, 3_usize)); assert_eq!(v.zyzx(), usizevec4(3_usize, 2_usize, 3_usize, 1_usize)); assert_eq!(v.zyzy(), usizevec4(3_usize, 2_usize, 3_usize, 2_usize)); assert_eq!(v.zyzz(), usizevec4(3_usize, 2_usize, 3_usize, 3_usize)); assert_eq!(v.zzxx(), usizevec4(3_usize, 3_usize, 1_usize, 1_usize)); assert_eq!(v.zzxy(), usizevec4(3_usize, 3_usize, 1_usize, 2_usize)); assert_eq!(v.zzxz(), usizevec4(3_usize, 3_usize, 1_usize, 3_usize)); assert_eq!(v.zzyx(), usizevec4(3_usize, 3_usize, 2_usize, 1_usize)); assert_eq!(v.zzyy(), usizevec4(3_usize, 3_usize, 2_usize, 2_usize)); assert_eq!(v.zzyz(), usizevec4(3_usize, 3_usize, 2_usize, 3_usize)); assert_eq!(v.zzzx(), usizevec4(3_usize, 3_usize, 3_usize, 1_usize)); assert_eq!(v.zzzy(), usizevec4(3_usize, 3_usize, 3_usize, 2_usize)); assert_eq!(v.zzzz(), usizevec4(3_usize, 3_usize, 3_usize, 3_usize)); assert_eq!(v.xxx(), usizevec3(1_usize, 1_usize, 1_usize)); assert_eq!(v.xxy(), usizevec3(1_usize, 1_usize, 2_usize)); assert_eq!(v.xxz(), usizevec3(1_usize, 1_usize, 3_usize)); assert_eq!(v.xyx(), usizevec3(1_usize, 2_usize, 1_usize)); assert_eq!(v.xyy(), usizevec3(1_usize, 2_usize, 2_usize)); assert_eq!(v.xzx(), usizevec3(1_usize, 3_usize, 1_usize)); assert_eq!(v.xzy(), usizevec3(1_usize, 3_usize, 2_usize)); assert_eq!(v.xzz(), usizevec3(1_usize, 3_usize, 3_usize)); assert_eq!(v.yxx(), usizevec3(2_usize, 1_usize, 1_usize)); assert_eq!(v.yxy(), usizevec3(2_usize, 1_usize, 2_usize)); assert_eq!(v.yxz(), usizevec3(2_usize, 1_usize, 3_usize)); assert_eq!(v.yyx(), usizevec3(2_usize, 2_usize, 1_usize)); assert_eq!(v.yyy(), usizevec3(2_usize, 2_usize, 2_usize)); assert_eq!(v.yyz(), usizevec3(2_usize, 2_usize, 3_usize)); assert_eq!(v.yzx(), usizevec3(2_usize, 3_usize, 1_usize)); assert_eq!(v.yzy(), usizevec3(2_usize, 3_usize, 2_usize)); assert_eq!(v.yzz(), usizevec3(2_usize, 3_usize, 3_usize)); assert_eq!(v.zxx(), usizevec3(3_usize, 1_usize, 1_usize)); assert_eq!(v.zxy(), usizevec3(3_usize, 1_usize, 2_usize)); assert_eq!(v.zxz(), usizevec3(3_usize, 1_usize, 3_usize)); assert_eq!(v.zyx(), usizevec3(3_usize, 2_usize, 1_usize)); assert_eq!(v.zyy(), usizevec3(3_usize, 2_usize, 2_usize)); assert_eq!(v.zyz(), usizevec3(3_usize, 2_usize, 3_usize)); assert_eq!(v.zzx(), usizevec3(3_usize, 3_usize, 1_usize)); assert_eq!(v.zzy(), usizevec3(3_usize, 3_usize, 2_usize)); assert_eq!(v.zzz(), usizevec3(3_usize, 3_usize, 3_usize)); assert_eq!(v.xx(), usizevec2(1_usize, 1_usize)); assert_eq!(v.xy(), usizevec2(1_usize, 2_usize)); assert_eq!(v.xz(), usizevec2(1_usize, 3_usize)); assert_eq!(v.yx(), usizevec2(2_usize, 1_usize)); assert_eq!(v.yy(), usizevec2(2_usize, 2_usize)); assert_eq!(v.yz(), usizevec2(2_usize, 3_usize)); assert_eq!(v.zx(), usizevec2(3_usize, 1_usize)); assert_eq!(v.zy(), usizevec2(3_usize, 2_usize)); assert_eq!(v.zz(), usizevec2(3_usize, 3_usize)); assert_eq!(v.with_xy(rhs2), usizevec3(11_usize, 12_usize, 3_usize)); assert_eq!(v.with_xz(rhs2), usizevec3(11_usize, 2_usize, 12_usize)); assert_eq!(v.with_yx(rhs2), usizevec3(12_usize, 11_usize, 3_usize)); assert_eq!(v.with_yz(rhs2), usizevec3(1_usize, 11_usize, 12_usize)); assert_eq!(v.with_zx(rhs2), usizevec3(12_usize, 2_usize, 11_usize)); assert_eq!(v.with_zy(rhs2), usizevec3(1_usize, 12_usize, 11_usize)); }); glam_test!(test_usizevec2_swizzles, { let v = usizevec2(1_usize, 2_usize); assert_eq!(v, v.xy()); assert_eq!(v.xxxx(), usizevec4(1_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.xxxy(), usizevec4(1_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.xxyx(), usizevec4(1_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.xxyy(), usizevec4(1_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.xyxx(), usizevec4(1_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.xyxy(), usizevec4(1_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.xyyx(), usizevec4(1_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.xyyy(), usizevec4(1_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.yxxx(), usizevec4(2_usize, 1_usize, 1_usize, 1_usize)); assert_eq!(v.yxxy(), usizevec4(2_usize, 1_usize, 1_usize, 2_usize)); assert_eq!(v.yxyx(), usizevec4(2_usize, 1_usize, 2_usize, 1_usize)); assert_eq!(v.yxyy(), usizevec4(2_usize, 1_usize, 2_usize, 2_usize)); assert_eq!(v.yyxx(), usizevec4(2_usize, 2_usize, 1_usize, 1_usize)); assert_eq!(v.yyxy(), usizevec4(2_usize, 2_usize, 1_usize, 2_usize)); assert_eq!(v.yyyx(), usizevec4(2_usize, 2_usize, 2_usize, 1_usize)); assert_eq!(v.yyyy(), usizevec4(2_usize, 2_usize, 2_usize, 2_usize)); assert_eq!(v.xxx(), usizevec3(1_usize, 1_usize, 1_usize)); assert_eq!(v.xxy(), usizevec3(1_usize, 1_usize, 2_usize)); assert_eq!(v.xyx(), usizevec3(1_usize, 2_usize, 1_usize)); assert_eq!(v.xyy(), usizevec3(1_usize, 2_usize, 2_usize)); assert_eq!(v.yxx(), usizevec3(2_usize, 1_usize, 1_usize)); assert_eq!(v.yxy(), usizevec3(2_usize, 1_usize, 2_usize)); assert_eq!(v.yyx(), usizevec3(2_usize, 2_usize, 1_usize)); assert_eq!(v.yyy(), usizevec3(2_usize, 2_usize, 2_usize)); assert_eq!(v.xx(), usizevec2(1_usize, 1_usize)); assert_eq!(v.yx(), usizevec2(2_usize, 1_usize)); assert_eq!(v.yy(), usizevec2(2_usize, 2_usize)); }); glam-0.30.1/tests/vec2.rs000064400000000000000000003172151046102023000132050ustar 00000000000000#![allow(clippy::excessive_precision)] #[macro_use] mod support; macro_rules! impl_bvec2_tests { ($mask:ident, $masknew:ident) => { glam_test!(test_mask_new, { assert_eq!($mask::new(false, false), $masknew(false, false)); assert_eq!($mask::new(true, false), $masknew(true, false)); assert_eq!($mask::new(false, true), $masknew(false, true)); assert_eq!($mask::new(true, true), $masknew(true, true)); }); glam_test!(test_mask_from_array_bool, { assert_eq!($mask::new(false, false), $mask::from([false, false])); assert_eq!($mask::new(true, false), $mask::from([true, false])); assert_eq!($mask::new(false, true), $mask::from([false, true])); assert_eq!($mask::new(true, true), $mask::from([true, true])); }); glam_test!(test_mask_into_array_u32, { assert_eq!(Into::<[u32; 2]>::into($mask::new(false, false)), [0, 0]); assert_eq!(Into::<[u32; 2]>::into($mask::new(true, false)), [!0, 0]); assert_eq!(Into::<[u32; 2]>::into($mask::new(false, true)), [0, !0]); assert_eq!(Into::<[u32; 2]>::into($mask::new(true, true)), [!0, !0]); }); glam_test!(test_mask_into_array_bool, { assert_eq!( Into::<[bool; 2]>::into($mask::new(false, false)), [false, false] ); assert_eq!( Into::<[bool; 2]>::into($mask::new(true, false)), [true, false] ); assert_eq!( Into::<[bool; 2]>::into($mask::new(false, true)), [false, true] ); assert_eq!( Into::<[bool; 2]>::into($mask::new(true, true)), [true, true] ); }); glam_test!(test_mask_splat, { assert_eq!($mask::splat(false), $mask::new(false, false)); assert_eq!($mask::splat(true), $mask::new(true, true)); }); glam_test!(test_mask_bitmask, { assert_eq!($mask::new(false, false).bitmask(), 0b00); assert_eq!($mask::new(true, false).bitmask(), 0b01); assert_eq!($mask::new(false, true).bitmask(), 0b10); assert_eq!($mask::new(true, true).bitmask(), 0b11); }); glam_test!(test_mask_any, { assert_eq!($mask::new(false, false).any(), false); assert_eq!($mask::new(true, false).any(), true); assert_eq!($mask::new(false, true).any(), true); assert_eq!($mask::new(true, true).any(), true); }); glam_test!(test_mask_all, { assert_eq!($mask::new(false, false).all(), false); assert_eq!($mask::new(true, false).all(), false); assert_eq!($mask::new(false, true).all(), false); assert_eq!($mask::new(true, true).all(), true); }); glam_test!(test_mask_and, { assert_eq!( ($mask::new(false, false) & $mask::new(false, false)).bitmask(), 0b00, ); assert_eq!( ($mask::new(true, true) & $mask::new(true, false)).bitmask(), 0b01, ); assert_eq!( ($mask::new(true, false) & $mask::new(false, true)).bitmask(), 0b00, ); assert_eq!( ($mask::new(true, true) & $mask::new(true, true)).bitmask(), 0b11, ); let mut mask = $mask::new(true, true); mask &= $mask::new(true, false); assert_eq!(mask.bitmask(), 0b01); }); glam_test!(test_mask_or, { assert_eq!( ($mask::new(false, false) | $mask::new(false, false)).bitmask(), 0b00, ); assert_eq!( ($mask::new(false, false) | $mask::new(false, true)).bitmask(), 0b10, ); assert_eq!( ($mask::new(true, false) | $mask::new(false, true)).bitmask(), 0b11, ); assert_eq!( ($mask::new(true, true) | $mask::new(true, true)).bitmask(), 0b11, ); let mut mask = $mask::new(true, true); mask |= $mask::new(true, false); assert_eq!(mask.bitmask(), 0b11); }); glam_test!(test_mask_xor, { assert_eq!( ($mask::new(false, false) ^ $mask::new(false, false)).bitmask(), 0b00, ); assert_eq!( ($mask::new(false, false) ^ $mask::new(false, true)).bitmask(), 0b10, ); assert_eq!( ($mask::new(true, false) ^ $mask::new(false, true)).bitmask(), 0b11, ); assert_eq!( ($mask::new(true, true) ^ $mask::new(true, true)).bitmask(), 0b00, ); let mut mask = $mask::new(false, true); mask ^= $mask::new(true, false); assert_eq!(mask.bitmask(), 0b11); }); glam_test!(test_mask_not, { assert_eq!((!$mask::new(false, false)).bitmask(), 0b11); assert_eq!((!$mask::new(true, false)).bitmask(), 0b10); assert_eq!((!$mask::new(false, true)).bitmask(), 0b01); assert_eq!((!$mask::new(true, true)).bitmask(), 0b00); }); glam_test!(test_mask_fmt, { let a = $mask::new(true, false); assert_eq!( format!("{:?}", a), format!("{}(0xffffffff, 0x0)", stringify!($mask)) ); assert_eq!(format!("{}", a), "[true, false]"); }); glam_test!(test_mask_eq, { let a = $mask::new(true, false); let b = $mask::new(true, false); let c = $mask::new(false, true); assert_eq!(a, b); assert_eq!(b, a); assert_ne!(a, c); 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; use std::hash::Hasher; let a = $mask::new(true, false); let b = $mask::new(true, false); let c = $mask::new(false, true); let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); let a_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); b.hash(&mut hasher); let b_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); c.hash(&mut hasher); let c_hashed = hasher.finish(); assert_eq!(a, b); assert_eq!(a_hashed, b_hashed); assert_ne!(a, c); assert_ne!(a_hashed, c_hashed); }); }; } macro_rules! impl_vec2_tests { ($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); const V2: $vec2 = $vec2::from_array([1 as $t, 2 as $t]); assert_eq!([1 as $t, 1 as $t], *V0.as_ref()); assert_eq!([1 as $t, 2 as $t], *V1.as_ref()); assert_eq!([1 as $t, 2 as $t], *V2.as_ref()); }); glam_test!(test_vec2_consts, { assert_eq!($vec2::ZERO, $new(0 as $t, 0 as $t)); 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, { let v = $new(1 as $t, 2 as $t); assert_eq!(v.x, 1 as $t); assert_eq!(v.y, 2 as $t); let t = (1 as $t, 2 as $t); let v = $vec2::from(t); assert_eq!(t, v.into()); let a = [1 as $t, 2 as $t]; let v = $vec2::from(a); let a1: [$t; 2] = v.into(); assert_eq!(a, a1); assert_eq!(a, v.to_array()); assert_eq!(a, *v.as_ref()); let mut v2 = $vec2::default(); *v2.as_mut() = a; assert_eq!(a, v2.to_array()); let v = $vec2::new(t.0, t.1); assert_eq!(t, v.into()); assert_eq!($vec2::new(1 as $t, 0 as $t), BVec2::new(true, false).into()); assert_eq!($vec2::new(0 as $t, 1 as $t), BVec2::new(false, true).into()); assert_eq!($vec2::new(1 as $t, 0 as $t), $vec2::X); assert_eq!($vec2::new(0 as $t, 1 as $t), $vec2::Y); }); glam_test!(test_fmt, { let a = $vec2::new(1 as $t, 2 as $t); assert_eq!( format!("{:?}", a), format!("{}({:?}, {:?})", stringify!($vec2), a.x, a.y) ); assert_eq!( format!("{:#?}", a), format!( "{}(\n {:#?},\n {:#?},\n)", stringify!($vec2), a.x, a.y ) ); assert_eq!(format!("{}", a), "[1, 2]"); }); glam_test!(test_zero, { let v = $vec2::ZERO; assert_eq!($new(0 as $t, 0 as $t), v); assert_eq!(v, $vec2::default()); }); glam_test!(test_splat, { let v = $vec2::splat(1 as $t); assert_eq!($vec2::ONE, v); }); glam_test!(test_map, { let v = $vec2::new(1 as $t, 2 as $t); assert_eq!(v.map(|n| n + 3 as $t), v + $vec2::splat(3 as $t)); assert_eq!(v.map(|_| 0 as $t), $vec2::ZERO); }); glam_test!(test_with, { assert_eq!($vec2::X, $vec2::ZERO.with_x(1 as $t)); assert_eq!($vec2::Y, $vec2::ZERO.with_y(1 as $t)); }); glam_test!(test_accessors, { let mut a = $vec2::ZERO; a.x = 1 as $t; a.y = 2 as $t; assert_eq!(1 as $t, a.x); assert_eq!(2 as $t, a.y); assert_eq!($vec2::new(1 as $t, 2 as $t), a); let mut a = $vec2::ZERO; a[0] = 1 as $t; a[1] = 2 as $t; assert_eq!(1 as $t, a[0]); assert_eq!(2 as $t, a[1]); assert_eq!($vec2::new(1 as $t, 2 as $t), a); }); glam_test!(test_dot_unsigned, { let x = $new(1 as $t, 0 as $t); 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, { let a = $new(2 as $t, 4 as $t); assert_eq!($new(4 as $t, 8 as $t), (a + a)); assert_eq!($new(2 as $t, 4 as $t), 0 as $t + a); assert_eq!($new(0 as $t, 0 as $t), (a - a)); assert_eq!($new(14 as $t, 12 as $t), 16 as $t - a); assert_eq!($new(4 as $t, 16 as $t), (a * a)); assert_eq!($new(4 as $t, 8 as $t), (a * 2 as $t)); assert_eq!($new(4 as $t, 8 as $t), (2 as $t * a)); assert_eq!($new(1 as $t, 1 as $t), (a / a)); assert_eq!($new(1 as $t, 2 as $t), (a / 2 as $t)); assert_eq!($new(2 as $t, 1 as $t), (4 as $t / a)); assert_eq!($new(0 as $t, 0 as $t), a % a); assert_eq!($new(0 as $t, 1 as $t), a % (a - 1 as $t)); assert_eq!($new(0 as $t, 0 as $t), a % 1 as $t); assert_eq!($new(2 as $t, 1 as $t), a % 3 as $t); assert_eq!($new(1 as $t, 1 as $t), 17 as $t % a); assert_eq!($new(2 as $t, 4 as $t), a % 8 as $t); }); glam_test!(test_ops_propagated, { let vec = $new(2 as $t, 4 as $t); let scalar = 2 as $t; let g_scalar = 16 as $t; assert_eq!((vec + vec), (vec + &vec)); assert_eq!((vec + vec), (&vec + vec)); assert_eq!((vec + vec), (&vec + &vec)); assert_eq!((vec + scalar), (vec + &scalar)); assert_eq!((vec + scalar), (&vec + &scalar)); assert_eq!((vec + scalar), (&vec + scalar)); assert_eq!((scalar + vec), (&scalar + vec)); assert_eq!((scalar + vec), (&scalar + &vec)); assert_eq!((scalar + vec), (scalar + &vec)); assert_eq!((vec - vec), (vec - &vec)); assert_eq!((vec - vec), (&vec - vec)); assert_eq!((vec - vec), (&vec - &vec)); assert_eq!((vec - scalar), (vec - &scalar)); assert_eq!((vec - scalar), (&vec - &scalar)); assert_eq!((vec - scalar), (&vec - scalar)); assert_eq!((g_scalar - vec), (&g_scalar - vec)); assert_eq!((g_scalar - vec), (&g_scalar - &vec)); assert_eq!((g_scalar - vec), (g_scalar - &vec)); assert_eq!((vec * vec), (vec * &vec)); assert_eq!((vec * vec), (&vec * vec)); assert_eq!((vec * vec), (&vec * &vec)); assert_eq!((vec * scalar), (vec * &scalar)); assert_eq!((vec * scalar), (&vec * &scalar)); assert_eq!((vec * scalar), (&vec * scalar)); assert_eq!((scalar * vec), (&scalar * vec)); assert_eq!((scalar * vec), (&scalar * &vec)); assert_eq!((scalar * vec), (scalar * &vec)); assert_eq!((vec / vec), (vec / &vec)); assert_eq!((vec / vec), (&vec / vec)); assert_eq!((vec / vec), (&vec / &vec)); assert_eq!((vec / scalar), (vec / &scalar)); assert_eq!((vec / scalar), (&vec / &scalar)); assert_eq!((vec / scalar), (&vec / scalar)); assert_eq!((scalar / vec), (&scalar / vec)); assert_eq!((scalar / vec), (&scalar / &vec)); assert_eq!((scalar / vec), (scalar / &vec)); assert_eq!((vec % vec), (vec % &vec)); assert_eq!((vec % vec), (&vec % vec)); assert_eq!((vec % vec), (&vec % &vec)); assert_eq!((vec % scalar), (vec % &scalar)); assert_eq!((vec % scalar), (&vec % &scalar)); assert_eq!((vec % scalar), (&vec % scalar)); assert_eq!((scalar % vec), (&scalar % vec)); assert_eq!((scalar % vec), (&scalar % &vec)); assert_eq!((scalar % vec), (scalar % &vec)); }); glam_test!(test_assign_ops, { let a = $new(1 as $t, 2 as $t); let mut b = a; b += 2 as $t; assert_eq!($new(3 as $t, 4 as $t), b); b -= 2 as $t; assert_eq!($new(1 as $t, 2 as $t), b); b *= 2 as $t; assert_eq!($new(2 as $t, 4 as $t), b); b /= 2 as $t; assert_eq!($new(1 as $t, 2 as $t), b); b %= 2 as $t; assert_eq!($new(1 as $t, 0 as $t), b); b = a; b += a; assert_eq!($new(2 as $t, 4 as $t), b); b -= a; assert_eq!($new(1 as $t, 2 as $t), b); b *= a; assert_eq!($new(1 as $t, 4 as $t), b); b /= a; assert_eq!($new(1 as $t, 2 as $t), b); b *= 2 as $t; assert_eq!($new(2 as $t, 4 as $t), b); b /= 2 as $t; assert_eq!($new(1 as $t, 2 as $t), b); b %= (b + 1 as $t); assert_eq!($new(1 as $t, 2 as $t), b); b %= b; assert_eq!($new(0 as $t, 0 as $t), b); }); glam_test!(test_assign_ops_propagation, { let vec = $new(1 as $t, 2 as $t); let mut a = vec; let mut b = vec; let scalar = 2 as $t; a += &scalar; b += scalar; assert_eq!(b, a, "AddAssign"); a -= &scalar; b -= scalar; assert_eq!(b, a, "SubAssign"); a *= &scalar; b *= scalar; assert_eq!(b, a, "MulAssign"); a /= &scalar; b /= scalar; assert_eq!(b, a, "DivAssign"); a %= &scalar; b %= scalar; assert_eq!(b, a, "MulAssign"); a = vec; b = vec; a += &vec; b += vec; assert_eq!(b, a, "AddAssign"); a -= &vec; b -= vec; assert_eq!(b, a, "SubAssign"); a *= &vec; b *= vec; assert_eq!(b, a, "MulAssign"); a /= &vec; b /= vec; assert_eq!(b, a, "DivAssign"); a %= &vec; b %= vec; assert_eq!(b, a, "RemAssign"); }); glam_test!(test_min_max, { let a = $new(0 as $t, 2 as $t); let b = $new(1 as $t, 1 as $t); assert_eq!($new(0 as $t, 1 as $t), a.min(b)); assert_eq!($new(0 as $t, 1 as $t), b.min(a)); assert_eq!($new(1 as $t, 2 as $t), a.max(b)); assert_eq!($new(1 as $t, 2 as $t), b.max(a)); }); glam_test!(test_min_position_max_position, { let a = $new(0 as $t, 2 as $t); let b = $new(1 as $t, 1 as $t); let c = $new(2 as $t, 1 as $t); assert_eq!(0, a.min_position()); assert_eq!(0, b.min_position()); assert_eq!(1, c.min_position()); assert_eq!(1, a.max_position()); assert_eq!(0, b.max_position()); assert_eq!(0, c.max_position()); }); glam_test!(test_sum_product, { let a = $new(2 as $t, 3 as $t); assert_eq!(a.element_sum(), 5 as $t); assert_eq!(a.element_product(), 6 as $t); }); glam_test!(test_clamp, { fn vec(x: i32, y: i32) -> $vec2 { $vec2::new(x as $t, y as $t) } let min = vec(1, 3); let max = vec(6, 8); assert_eq!(vec(0, 0).clamp(min, max), vec(1, 3)); assert_eq!(vec(2, 2).clamp(min, max), vec(2, 3)); assert_eq!(vec(4, 5).clamp(min, max), vec(4, 5)); assert_eq!(vec(6, 6).clamp(min, max), vec(6, 6)); assert_eq!(vec(7, 7).clamp(min, max), vec(6, 7)); assert_eq!(vec(9, 9).clamp(min, max), vec(6, 8)); should_glam_assert!({ $vec2::clamp($vec2::ZERO, $vec2::ONE, $vec2::ZERO) }); }); glam_test!(test_hmin_hmax, { assert_eq!(1 as $t, $new(1 as $t, 2 as $t).min_element()); assert_eq!(1 as $t, $new(2 as $t, 1 as $t).min_element()); assert_eq!(2 as $t, $new(1 as $t, 2 as $t).max_element()); assert_eq!(2 as $t, $new(2 as $t, 1 as $t).max_element()); }); glam_test!(test_eq, { let a = $new(1 as $t, 1 as $t); let b = $new(1 as $t, 2 as $t); assert!(a.cmpeq(a).all()); assert!(b.cmpeq(b).all()); assert!(a.cmpne(b).any()); assert!(b.cmpne(a).any()); assert!(b.cmpeq(a).any()); }); glam_test!(test_cmp, { assert!(!$mask::default().any()); assert!(!$mask::default().all()); assert_eq!($mask::default().bitmask(), 0x0); let a = $new(1 as $t, 1 as $t); let b = $new(2 as $t, 2 as $t); let c = $new(1 as $t, 1 as $t); let d = $new(2 as $t, 1 as $t); assert_eq!(a.cmplt(a).bitmask(), 0x0); assert_eq!(a.cmplt(b).bitmask(), 0x3); assert_eq!(a.cmplt(d).bitmask(), 0x1); assert_eq!(c.cmple(a).bitmask(), 0x3); assert!(a.cmplt(b).all()); assert!(a.cmplt(d).any()); assert!(a.cmple(b).all()); assert!(a.cmple(a).all()); assert!(b.cmpgt(a).all()); assert!(b.cmpge(a).all()); assert!(b.cmpge(b).all()); assert!(!(a.cmpge(d).all())); assert!(c.cmple(c).all()); assert!(c.cmpge(c).all()); assert!(a == a); }); glam_test!(test_select, { let a = $vec2::new(1 as $t, 2 as $t); let b = $vec2::new(3 as $t, 4 as $t); assert_eq!( $vec2::select($mask::new(true, true), a, b), $vec2::new(1 as $t, 2 as $t), ); assert_eq!( $vec2::select($mask::new(true, false), a, b), $vec2::new(1 as $t, 4 as $t), ); assert_eq!( $vec2::select($mask::new(false, true), a, b), $vec2::new(3 as $t, 2 as $t), ); assert_eq!( $vec2::select($mask::new(false, false), a, b), $vec2::new(3 as $t, 4 as $t), ); }); glam_test!(test_extend_truncate, { let a = $new(1 as $t, 2 as $t); let b = a.extend(3 as $t); assert_eq!($vec3::new(1 as $t, 2 as $t, 3 as $t), b); }); glam_test!(test_to_from_slice, { let v = $vec2::new(1 as $t, 2 as $t); let mut a = [0 as $t, 0 as $t]; v.write_to_slice(&mut a); assert_eq!(v, $vec2::from_slice(&a)); let mut a = [0 as $t; 17]; v.write_to_slice(&mut a); assert_eq!(v, $vec2::from_slice(&a[..2])); assert_eq!([0 as $t; 15], a[2..]); should_panic!({ $vec2::ONE.write_to_slice(&mut [0 as $t]) }); should_panic!({ $vec2::from_slice(&[0 as $t]) }); }); glam_test!(test_sum, { let one = $vec2::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!([two, two].iter().product::<$vec2>(), two * two); assert_eq!([two, two].into_iter().product::<$vec2>(), two * two); }); }; } macro_rules! impl_vec2_signed_tests { ($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); assert_eq!(1 as $t, x.dot(x)); assert_eq!(0 as $t, x.dot(y)); 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)); assert_eq!($new(-0.0 as $t, -0.0 as $t), -$new(0.0 as $t, 0.0 as $t)); assert_eq!($new(0.0 as $t, -0.0 as $t), -$new(-0.0 as $t, 0.0 as $t)); }); glam_test!(test_neg_propagation, { let a = $new(1 as $t, 2 as $t); assert_eq!(-a, -(&a)); }); glam_test!(test_perp, { let v1 = $vec2::new(1 as $t, 2 as $t); let v2 = $vec2::new(1 as $t, 1 as $t); let v1_perp = $vec2::new(-2 as $t, 1 as $t); assert_eq!(v1_perp, v1.perp()); assert_eq!(v1.perp().dot(v1), 0 as $t); assert_eq!(v2.perp().dot(v2), 0 as $t); assert_eq!(v1.perp().dot(v2), v1.perp_dot(v2)); }); glam_test!(test_rotate, { assert_eq!( $vec2::new(0 as $t, 1 as $t).rotate($vec2::new(1 as $t, 1 as $t)), $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!($vec2::ZERO.signum(), $vec2::ZERO); assert_eq!($vec2::ONE.signum(), $vec2::ONE); assert_eq!((-$vec2::ONE).signum(), -$vec2::ONE); }); glam_test!(test_checked_add, { assert_eq!($vec2::MAX.checked_add($vec2::ONE), None); assert_eq!($vec2::MAX.checked_add($vec2::X), None); assert_eq!($vec2::MAX.checked_add($vec2::Y), None); assert_eq!($vec2::MAX.checked_add($vec2::ZERO), Some($vec2::MAX)); }); glam_test!(test_checked_sub, { assert_eq!($vec2::MIN.checked_sub($vec2::ONE), None); assert_eq!($vec2::MIN.checked_sub($vec2::X), None); assert_eq!($vec2::MIN.checked_sub($vec2::Y), None); assert_eq!($vec2::MIN.checked_sub($vec2::ZERO), Some($vec2::MIN)); }); glam_test!(test_checked_mul, { assert_eq!($vec2::MIN.checked_mul($vec2::MIN), None); assert_eq!($vec2::MAX.checked_mul($vec2::MIN), None); assert_eq!($vec2::MIN.checked_mul($vec2::MAX), None); assert_eq!($vec2::MAX.checked_mul($vec2::MAX), None); assert_eq!($vec2::ZERO.checked_mul($vec2::MIN), Some($vec2::ZERO)); assert_eq!($vec2::MAX.checked_mul($vec2::ZERO), Some($vec2::ZERO)); assert_eq!($vec2::MIN.checked_mul($vec2::ONE), Some($vec2::MIN)); assert_eq!($vec2::MAX.checked_mul($vec2::ONE), Some($vec2::MAX)); assert_eq!($vec2::ZERO.checked_mul($vec2::ZERO), Some($vec2::ZERO)); assert_eq!($vec2::ONE.checked_mul($vec2::ONE), Some($vec2::ONE)); }); glam_test!(test_checked_div, { assert_eq!($vec2::MIN.checked_div($vec2::ZERO), None); assert_eq!($vec2::MAX.checked_div($vec2::ZERO), None); assert_eq!($vec2::MAX.checked_div($vec2::X), None); assert_eq!($vec2::MAX.checked_div($vec2::Y), None); assert_eq!($vec2::ZERO.checked_div($vec2::ONE), Some($vec2::ZERO)); assert_eq!($vec2::MIN.checked_div($vec2::ONE), Some($vec2::MIN)); assert_eq!($vec2::MAX.checked_div($vec2::ONE), Some($vec2::MAX)); }); glam_test!(test_manhattan_distance, { assert_eq!($vec2::new(5, 2).manhattan_distance($vec2::new(23, 16)), 32); assert_eq!($vec2::new(30, 11).manhattan_distance($vec2::new(30, 11)), 0); assert_eq!( $vec2::new(-8, -23).manhattan_distance($vec2::new(12, 7)), 50 ); assert_eq!( $vec2::new(5, 2).checked_manhattan_distance($vec2::new(23, 16)), Some(32) ); assert_eq!( $vec2::new(30, 11).checked_manhattan_distance($vec2::new(30, 11)), Some(0) ); assert_eq!( $vec2::new(-8, -23).checked_manhattan_distance($vec2::new(12, 7)), Some(50) ); assert_eq!( $vec2::new($t::MIN, $t::MIN) .checked_manhattan_distance($vec2::new($t::MAX, $t::MAX)), None ); }); glam_test!(test_chebyshev_distance, { assert_eq!($vec2::new(5, 2).chebyshev_distance($vec2::new(23, 16)), 18); assert_eq!($vec2::new(30, 11).chebyshev_distance($vec2::new(30, 11)), 0); assert_eq!( $vec2::new(-8, -23).chebyshev_distance($vec2::new(12, 7)), 30 ); }); }; } macro_rules! impl_vec2_unsigned_integer_tests { ($t:ident, $new:ident, $vec2:ident, $vec3:ident, $mask:ident) => { impl_vec2_tests!($t, $new, $vec2, $vec3, $mask); glam_test!(test_checked_add, { assert_eq!($vec2::MAX.checked_add($vec2::ONE), None); assert_eq!($vec2::MAX.checked_add($vec2::X), None); assert_eq!($vec2::MAX.checked_add($vec2::Y), None); assert_eq!($vec2::MAX.checked_add($vec2::ZERO), Some($vec2::MAX)); }); glam_test!(test_checked_sub, { assert_eq!($vec2::ZERO.checked_sub($vec2::ONE), None); assert_eq!($vec2::ZERO.checked_sub($vec2::X), None); assert_eq!($vec2::ZERO.checked_sub($vec2::Y), None); assert_eq!($vec2::ZERO.checked_sub($vec2::ZERO), Some($vec2::MIN)); }); glam_test!(test_checked_mul, { assert_eq!($vec2::MAX.checked_mul($vec2::MAX), None); assert_eq!($vec2::MAX.checked_mul($vec2::ZERO), Some($vec2::ZERO)); assert_eq!($vec2::MAX.checked_mul($vec2::ONE), Some($vec2::MAX)); assert_eq!($vec2::ZERO.checked_mul($vec2::ZERO), Some($vec2::ZERO)); assert_eq!($vec2::ONE.checked_mul($vec2::ONE), Some($vec2::ONE)); }); glam_test!(test_checked_div, { assert_eq!($vec2::MAX.checked_div($vec2::ZERO), None); assert_eq!($vec2::MAX.checked_div($vec2::X), None); assert_eq!($vec2::MAX.checked_div($vec2::Y), None); assert_eq!($vec2::ZERO.checked_div($vec2::ONE), Some($vec2::ZERO)); assert_eq!($vec2::MAX.checked_div($vec2::ONE), Some($vec2::MAX)); }); glam_test!(test_manhattan_distance, { assert_eq!($vec2::new(5, 2).manhattan_distance($vec2::new(23, 16)), 32); assert_eq!($vec2::new(30, 11).manhattan_distance($vec2::new(30, 11)), 0); assert_eq!( $vec2::new(5, 2).checked_manhattan_distance($vec2::new(23, 16)), Some(32) ); assert_eq!( $vec2::new(30, 11).checked_manhattan_distance($vec2::new(30, 11)), Some(0) ); assert_eq!( $vec2::new($t::MIN, $t::MIN) .checked_manhattan_distance($vec2::new($t::MAX, $t::MAX)), None ); }); glam_test!(test_chebyshev_distance, { assert_eq!($vec2::new(5, 2).chebyshev_distance($vec2::new(23, 16)), 18); assert_eq!($vec2::new(30, 11).chebyshev_distance($vec2::new(30, 11)), 0); }); }; } macro_rules! impl_vec2_eq_hash_tests { ($t:ident, $new:ident) => { glam_test!(test_ve2_hash, { use std::collections::hash_map::DefaultHasher; use std::hash::Hash; use std::hash::Hasher; let a = $new(1 as $t, 2 as $t); let b = $new(1 as $t, 2 as $t); let c = $new(3 as $t, 2 as $t); let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); let a_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); b.hash(&mut hasher); let b_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); c.hash(&mut hasher); let c_hashed = hasher.finish(); assert_eq!(a, b); assert_eq!(a_hashed, b_hashed); assert_ne!(a, c); assert_ne!(a_hashed, c_hashed); }); }; } macro_rules! impl_vec2_float_tests { ($t:ident, $new:ident, $vec2:ident, $vec3:ident, $mask:ident) => { impl_vec2_signed_tests!($t, $new, $vec2, $vec3, $mask); impl_vec_float_normalize_tests!($t, $vec2); glam_test!(test_vec2_nan, { assert!($vec2::NAN.is_nan()); assert!(!$vec2::NAN.is_finite()); }); glam_test!(test_length, { let x = $new(1.0, 0.0); let y = $new(0.0, 1.0); assert_eq!(2.0, (-2.0 * x).length()); assert_eq!(3.0, (3.0 * y).length()); 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!( (2.0 as $t * 2.0 + 3.0 * 3.0).sqrt(), $new(2.0, 3.0).length() ); assert_eq!( 1.0 / (2.0 as $t * 2.0 + 3.0 * 3.0).sqrt(), $new(2.0, 3.0).length_recip() ); assert!($new(2.0, 3.0).normalize().is_normalized()); assert_eq!( $new(2.0, 3.0) / (2.0 as $t * 2.0 + 3.0 * 3.0).sqrt(), $new(2.0, 3.0).normalize() ); assert_eq!($new(0.5, 0.25), $new(2.0, 4.0).recip()); }); glam_test!(test_project_reject, { assert_eq!($new(0.0, 1.0), $new(1.0, 1.0).project_onto($new(0.0, 2.0))); assert_eq!($new(1.0, 0.0), $new(1.0, 1.0).reject_from($new(0.0, 2.0))); assert_eq!( $new(0.0, 1.0), $new(1.0, 1.0).project_onto_normalized($new(0.0, 1.0)) ); assert_eq!( $new(1.0, 0.0), $new(1.0, 1.0).reject_from_normalized($new(0.0, 1.0)) ); should_glam_assert!({ $vec2::ONE.project_onto($vec2::ZERO) }); should_glam_assert!({ $vec2::ONE.reject_from($vec2::ZERO) }); should_glam_assert!({ $vec2::ONE.project_onto_normalized($vec2::ONE) }); should_glam_assert!({ $vec2::ONE.reject_from_normalized($vec2::ONE) }); }); glam_test!(test_signum, { assert_eq!($vec2::ZERO.signum(), $vec2::ONE); assert_eq!((-$vec2::ZERO).signum(), -$vec2::ONE); assert_eq!($vec2::ONE.signum(), $vec2::ONE); assert_eq!((-$vec2::ONE).signum(), -$vec2::ONE); 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, { assert_eq!($vec2::ZERO.copysign(-$vec2::ZERO), -$vec2::ZERO); assert_eq!((-$vec2::ZERO).copysign(-$vec2::ZERO), -$vec2::ZERO); assert_eq!($vec2::ZERO.copysign($vec2::ZERO), $vec2::ZERO); assert_eq!((-$vec2::ZERO).copysign($vec2::ZERO), $vec2::ZERO); assert_eq!($vec2::ONE.copysign(-$vec2::ZERO), -$vec2::ONE); assert_eq!((-$vec2::ONE).copysign(-$vec2::ZERO), -$vec2::ONE); assert_eq!($vec2::ONE.copysign($vec2::ZERO), $vec2::ONE); assert_eq!((-$vec2::ONE).copysign($vec2::ZERO), $vec2::ONE); assert_eq!($vec2::ZERO.copysign(-$vec2::ONE), -$vec2::ZERO); assert_eq!((-$vec2::ZERO).copysign(-$vec2::ONE), -$vec2::ZERO); assert_eq!($vec2::ZERO.copysign($vec2::ONE), $vec2::ZERO); assert_eq!((-$vec2::ZERO).copysign($vec2::ONE), $vec2::ZERO); 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::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::NEG_INFINITY.copysign(-$vec2::ONE), $vec2::NEG_INFINITY ); assert!($vec2::NAN.copysign($vec2::ONE).is_nan_mask().all()); assert!($vec2::NAN.copysign(-$vec2::ONE).is_nan_mask().all()); }); 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(-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, { assert_eq!($vec2::new(1.35, 0.0).round().x, 1.0); assert_eq!($vec2::new(0.0, 1.5).round().y, 2.0); assert_eq!($vec2::new(0.0, -15.5).round().y, -16.0); assert_eq!($vec2::new(0.0, 0.0).round().y, 0.0); assert_eq!($vec2::new(0.0, 21.1).round().y, 21.0); assert_eq!($vec2::new(0.0, 11.123).round().y, 11.0); assert_eq!($vec2::new(0.0, 11.499).round().y, 11.0); assert_eq!( $vec2::new($t::NEG_INFINITY, $t::INFINITY).round(), $vec2::new($t::NEG_INFINITY, $t::INFINITY) ); assert!($vec2::new($t::NAN, 0.0).round().x.is_nan()); }); glam_test!(test_floor, { assert_eq!($vec2::new(1.35, -1.5).floor(), $vec2::new(1.0, -2.0)); assert_eq!( $vec2::new($t::INFINITY, $t::NEG_INFINITY).floor(), $vec2::new($t::INFINITY, $t::NEG_INFINITY) ); assert!($vec2::new($t::NAN, 0.0).floor().x.is_nan()); assert_eq!( $vec2::new(-2000000.123, 10000000.123).floor(), $vec2::new(-2000001.0, 10000000.0) ); }); glam_test!(test_fract_gl, { assert_approx_eq!($vec2::new(1.35, -1.5).fract_gl(), $vec2::new(0.35, 0.5)); assert_approx_eq!( $vec2::new(-2000000.123, 1000000.123).fract_gl(), $vec2::new(0.877, 0.123), 0.002 ); }); glam_test!(test_fract, { assert_approx_eq!($vec2::new(1.35, -1.5).fract(), $vec2::new(0.35, -0.5)); assert_approx_eq!( $vec2::new(-2000000.123, 1000000.123).fract(), $vec2::new(-0.123, 0.123), 0.002 ); }); glam_test!(test_ceil, { assert_eq!($vec2::new(1.35, -1.5).ceil(), $vec2::new(2.0, -1.0)); assert_eq!( $vec2::new($t::INFINITY, $t::NEG_INFINITY).ceil(), $vec2::new($t::INFINITY, $t::NEG_INFINITY) ); assert!($vec2::new($t::NAN, 0.0).ceil().x.is_nan()); assert_eq!( $vec2::new(-2000000.123, 1000000.123).ceil(), $vec2::new(-2000000.0, 1000001.0) ); }); glam_test!(test_trunc, { assert_eq!($vec2::new(1.35, -1.5).trunc(), $vec2::new(1.0, -1.0)); assert_eq!( $vec2::new($t::INFINITY, $t::NEG_INFINITY).trunc(), $vec2::new($t::INFINITY, $t::NEG_INFINITY) ); assert!($vec2::new(0.0, $t::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); assert_approx_eq!(v0, v0.lerp(v1, 0.0)); assert_approx_eq!(v1, v0.lerp(v1, 1.0)); assert_approx_eq!($vec2::ZERO, v0.lerp(v1, 0.5)); }); glam_test!(test_lerp_big_difference, { let v0 = $vec2::new(-1e30, -1e30); let v1 = $vec2::new(16.0, 16.0); assert_approx_eq!(v0, v0.lerp(v1, 0.0)); assert_approx_eq!(v1, v0.lerp(v1, 1.0)); }); glam_test!(test_move_towards, { let v0 = $vec2::new(-1.0, -1.0); let v1 = $vec2::new(1.0, 1.0); assert_approx_eq!(v0, v0.move_towards(v1, 0.0)); assert_approx_eq!(v1, v0.move_towards(v1, v0.distance(v1))); assert_approx_eq!(v1, v0.move_towards(v1, v0.distance(v1) + 1.0)); }); glam_test!(test_rotate_towards, { use core::$t::consts::{FRAC_PI_2, FRAC_PI_4}; let eps = 10.0 * $t::EPSILON as f32; // Self assert_approx_eq!($vec2::X, $vec2::X.rotate_towards($vec2::X, FRAC_PI_2), eps); assert_approx_eq!( $vec2::Y * 2.0, ($vec2::Y * 2.0).rotate_towards($vec2::Y, FRAC_PI_2) ); assert_approx_eq!( $vec2::NEG_X, $vec2::NEG_X.rotate_towards($vec2::NEG_X, FRAC_PI_2) ); // Positive delta assert_approx_eq!($vec2::X, $vec2::X.rotate_towards($vec2::NEG_Y, 0.0), eps); assert_approx_eq!( $vec2::new($t::sqrt(2.0) / 2.0, -$t::sqrt(2.0) / 2.0), $vec2::X.rotate_towards($vec2::NEG_Y, FRAC_PI_4), eps ); assert_approx_eq!( $vec2::NEG_Y, $vec2::X.rotate_towards($vec2::NEG_Y, FRAC_PI_2), eps ); assert_approx_eq!( $vec2::NEG_Y, $vec2::X.rotate_towards($vec2::NEG_Y, FRAC_PI_2 * 1.5), eps ); // Negative delta assert_approx_eq!( $vec2::new($t::sqrt(2.0) / 2.0, $t::sqrt(2.0) / 2.0), $vec2::X.rotate_towards($vec2::NEG_Y, -FRAC_PI_4), eps ); assert_approx_eq!( $vec2::Y, $vec2::X.rotate_towards($vec2::NEG_Y, -FRAC_PI_2), eps ); assert_approx_eq!( $vec2::Y, $vec2::X.rotate_towards($vec2::NEG_Y, -FRAC_PI_2 * 1.5), eps ); // Not normalized assert_approx_eq!( $vec2::NEG_Y * 2., ($vec2::X * 2.).rotate_towards($vec2::NEG_Y, FRAC_PI_2), eps ); assert_approx_eq!( $vec2::NEG_Y, $vec2::X.rotate_towards($vec2::NEG_Y * 2., FRAC_PI_2), eps ); // Parallel assert_approx_eq!($vec2::Y, $vec2::X.rotate_towards(-$vec2::X, FRAC_PI_2), eps); }); glam_test!(test_midpoint, { let v0 = $vec2::new(-1.0, -1.0); let v1 = $vec2::new(1.0, 1.0); let v2 = $vec2::new(-1.5, 0.0); assert_approx_eq!($vec2::ZERO, v0.midpoint(v1)); assert_approx_eq!($vec2::new(-0.25, 0.5), v1.midpoint(v2)); }); glam_test!(test_is_finite, { assert!($vec2::new(0.0, 0.0).is_finite()); assert!($vec2::new(-1e-10, 1e10).is_finite()); assert!(!$vec2::new($t::INFINITY, 0.0).is_finite()); assert!(!$vec2::new(0.0, $t::NAN).is_finite()); assert!(!$vec2::new(0.0, $t::NEG_INFINITY).is_finite()); assert!(!$vec2::new($t::INFINITY, $t::NEG_INFINITY).is_finite()); assert!(!$vec2::INFINITY.is_finite()); assert!(!$vec2::NEG_INFINITY.is_finite()); }); glam_test!(test_powf, { assert_eq!($vec2::new(2.0, 4.0).powf(2.0), $vec2::new(4.0, 16.0)); }); glam_test!(test_exp, { assert_approx_eq!( $vec2::new(1.0, 2.0).exp(), $vec2::new((1.0 as $t).exp(), (2.0 as $t).exp()) ); }); glam_test!(test_angle_to, { let angle = $vec2::new(1.0, 0.0).angle_to($vec2::new(0.0, 1.0)); assert_approx_eq!(core::$t::consts::FRAC_PI_2, angle, 1e-6); let angle = $vec2::new(10.0, 0.0).angle_to($vec2::new(0.0, 5.0)); assert_approx_eq!(core::$t::consts::FRAC_PI_2, angle, 1e-6); let angle = $vec2::new(-1.0, 0.0).angle_to($vec2::new(0.0, 1.0)); assert_approx_eq!(-core::$t::consts::FRAC_PI_2, angle, 1e-6); // the angle returned by angle_to should rotate the input vector to the // destination vector assert_approx_eq!( $vec2::from_angle($vec2::X.angle_to($vec2::Y)).rotate($vec2::X), $vec2::Y ); }); glam_test!(test_clamp_length, { // Too long gets shortened assert_eq!( $vec2::new(12.0, 16.0).clamp_length(7.0, 10.0), $vec2::new(6.0, 8.0) // shortened to length 10.0 ); // In the middle is unchanged assert_eq!( $vec2::new(2.0, 1.0).clamp_length(0.5, 5.0), $vec2::new(2.0, 1.0) // unchanged ); // Too short gets lengthened assert_eq!( $vec2::new(0.6, 0.8).clamp_length(10.0, 20.0), $vec2::new(6.0, 8.0) // lengthened to length 10.0 ); should_glam_assert!({ $vec2::ONE.clamp_length(1.0, 0.0) }); }); glam_test!(test_clamp_length_max, { // Too long gets shortened assert_eq!( $vec2::new(12.0, 16.0).clamp_length_max(10.0), $vec2::new(6.0, 8.0) // shortened to length 10.0 ); // Not too long is unchanged assert_eq!( $vec2::new(2.0, 1.0).clamp_length_max(5.0), $vec2::new(2.0, 1.0) // unchanged ); }); glam_test!(test_clamp_length_min, { // Not too short is unchanged assert_eq!( $vec2::new(2.0, 1.0).clamp_length_min(0.5), $vec2::new(2.0, 1.0) // unchanged ); // Too short gets lengthened assert_eq!( $vec2::new(0.6, 0.8).clamp_length_min(10.0), $vec2::new(6.0, 8.0) // lengthened to length 10.0 ); }); #[cfg(any(feature = "glam-assert", feature = "debug-glam-assert"))] glam_test!(test_float_glam_assert, { use std::panic::catch_unwind; assert!(catch_unwind(|| $vec2::ZERO.normalize()).is_err()); }); glam_test!(test_mul_add, { assert_eq!( $vec2::new(1.0, 1.0).mul_add($vec2::new(0.5, 2.0), $vec2::new(-1.0, -1.0)), $vec2::new(-0.5, 1.0) ); }); glam_test!(test_fmt_float, { let a = $vec2::new(1.0, 2.0); assert_eq!(format!("{:.2}", a), "[1.00, 2.00]"); }); 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); }); glam_test!(test_reflect, { let incident = $vec2::new(1.0, -1.0); let normal = $vec2::Y; assert_approx_eq!(incident.reflect(normal), $vec2::ONE); }); glam_test!(test_refract, { let incident = $vec2::NEG_ONE.normalize(); let normal = $vec2::ONE.normalize(); assert_approx_eq!(incident.refract(normal, 0.5), incident); let incident = $vec2::new(1.0, -1.0).normalize(); let normal = $vec2::Y; assert_approx_eq!(incident.refract(normal, 1.5), $vec2::ZERO); }); }; } macro_rules! impl_vec2_scalar_shift_op_test { ($vec2:ident, $t_min:literal, $t_max:literal, $rhs_min:literal, $rhs_max:literal) => { glam_test!(test_vec2_scalar_shift_ops, { for x in $t_min..$t_max { for y in $t_min..$t_max { for rhs in $rhs_min..$rhs_max { assert_eq!($vec2::new(x, y) << rhs, $vec2::new(x << rhs, y << rhs)); assert_eq!($vec2::new(x, y) >> rhs, $vec2::new(x >> rhs, y >> rhs)); } } } }); }; } macro_rules! impl_vec2_scalar_shift_op_tests { ($vec2:ident, $t_min:literal, $t_max:literal) => { mod shift_by_i8 { use glam::$vec2; impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0i8, 2); } mod shift_by_i16 { use glam::$vec2; impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0i16, 2); } mod shift_by_i32 { 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); } mod shift_by_u16 { use glam::$vec2; impl_vec2_scalar_shift_op_test!($vec2, $t_min, $t_max, 0u16, 2); } mod shift_by_u32 { 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); } }; } macro_rules! impl_vec2_shift_op_test { ($vec2:ident, $rhs:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec2_shift_ops, { for x1 in $t_min..$t_max { for y1 in $t_min..$t_max { for x2 in $t_min..$t_max { for y2 in $t_min..$t_max { assert_eq!( $vec2::new(x1, y1) << $rhs::new(x2, y2), $vec2::new(x1 << x2, y1 << y2) ); assert_eq!( $vec2::new(x1, y1) >> $rhs::new(x2, y2), $vec2::new(x1 >> x2, y1 >> y2) ); } } } } }); }; } macro_rules! impl_vec2_shift_op_tests { ($vec2:ident) => { mod shift_ivec2_by_ivec2 { use super::*; impl_vec2_shift_op_test!($vec2, IVec2, 0, 2); } mod shift_ivec2_by_uvec2 { use super::*; impl_vec2_shift_op_test!($vec2, UVec2, 0, 2); } }; } macro_rules! impl_vec2_scalar_bit_op_tests { ($vec2:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec2_scalar_bit_ops, { for x in $t_min..$t_max { for y in $t_min..$t_max { for rhs in $t_min..$t_max { assert_eq!($vec2::new(x, y) & rhs, $vec2::new(x & rhs, y & rhs)); assert_eq!($vec2::new(x, y) | rhs, $vec2::new(x | rhs, y | rhs)); assert_eq!($vec2::new(x, y) ^ rhs, $vec2::new(x ^ rhs, y ^ rhs)); } } } }); }; } macro_rules! impl_vec2_bit_op_tests { ($vec2:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec2_bit_ops, { for x1 in $t_min..$t_max { for y1 in $t_min..$t_max { assert_eq!(!$vec2::new(x1, y1), $vec2::new(!x1, !y1)); for x2 in $t_min..$t_max { for y2 in $t_min..$t_max { assert_eq!( $vec2::new(x1, y1) & $vec2::new(x2, y2), $vec2::new(x1 & x2, y1 & y2) ); assert_eq!( $vec2::new(x1, y1) | $vec2::new(x2, y2), $vec2::new(x1 | x2, y1 | y2) ); assert_eq!( $vec2::new(x1, y1) ^ $vec2::new(x2, y2), $vec2::new(x1 ^ x2, y1 ^ y2) ); } } } } }); }; } mod bvec2 { use glam::{bvec2, BVec2}; glam_test!(test_mask_align, { use core::mem; assert_eq!(2, mem::size_of::()); assert_eq!(1, mem::align_of::()); }); impl_bvec2_tests!(BVec2, bvec2); } mod vec2 { use glam::{vec2, BVec2, Vec2, Vec3}; glam_test!(test_align, { use core::mem; assert_eq!(8, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(4, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(8, mem::align_of::()); }); glam_test!(test_as, { use glam::{ DVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2, }; assert_eq!(DVec2::new(-1.0, -2.0), Vec2::new(-1.0, -2.0).as_dvec2()); assert_eq!(I8Vec2::new(-1, -2), Vec2::new(-1.0, -2.0).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), Vec2::new(1.0, 2.0).as_u8vec2()); 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!(USizeVec2::new(1, 2), Vec2::new(1.0, 2.0).as_usizevec2()); assert_eq!(Vec2::new(-1.0, -2.0), DVec2::new(-1.0, -2.0).as_vec2()); assert_eq!(I8Vec2::new(-1, -2), DVec2::new(-1.0, -2.0).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), DVec2::new(1.0, 2.0).as_u8vec2()); 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!(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!(USizeVec2::new(1, 2), DVec2::new(1.0, 2.0).as_usizevec2()); assert_eq!(Vec2::new(-1.0, -2.0), I8Vec2::new(-1, -2).as_vec2()); assert_eq!(DVec2::new(-1.0, -2.0), I8Vec2::new(-1, -2).as_dvec2()); assert_eq!(U8Vec2::new(1, 2), I8Vec2::new(1, 2).as_u8vec2()); assert_eq!(I16Vec2::new(-1, -2), I8Vec2::new(-1, -2).as_i16vec2()); assert_eq!(U16Vec2::new(1, 2), I8Vec2::new(1, 2).as_u16vec2()); assert_eq!(IVec2::new(-1, -2), I8Vec2::new(-1, -2).as_ivec2()); assert_eq!(UVec2::new(1, 2), I8Vec2::new(1, 2).as_uvec2()); assert_eq!(I64Vec2::new(-1, -2), I8Vec2::new(-1, -2).as_i64vec2()); assert_eq!(U64Vec2::new(1, 2), I8Vec2::new(1, 2).as_u64vec2()); assert_eq!(USizeVec2::new(1, 2), I8Vec2::new(1, 2).as_usizevec2()); assert_eq!(Vec2::new(1.0, 2.0), U8Vec2::new(1, 2).as_vec2()); assert_eq!(DVec2::new(1.0, 2.0), U8Vec2::new(1, 2).as_dvec2()); assert_eq!(I8Vec2::new(1, 2), U8Vec2::new(1, 2).as_i8vec2()); assert_eq!(I16Vec2::new(1, 2), U8Vec2::new(1, 2).as_i16vec2()); assert_eq!(U16Vec2::new(1, 2), U8Vec2::new(1, 2).as_u16vec2()); assert_eq!(IVec2::new(1, 2), U8Vec2::new(1, 2).as_ivec2()); assert_eq!(UVec2::new(1, 2), U8Vec2::new(1, 2).as_uvec2()); assert_eq!(I64Vec2::new(1, 2), U8Vec2::new(1, 2).as_i64vec2()); assert_eq!(U64Vec2::new(1, 2), U8Vec2::new(1, 2).as_u64vec2()); assert_eq!(USizeVec2::new(1, 2), U8Vec2::new(1, 2).as_usizevec2()); 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!(I8Vec2::new(-1, -2), I16Vec2::new(-1, -2).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), I16Vec2::new(1, 2).as_u8vec2()); 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!(USizeVec2::new(1, 2), I16Vec2::new(1, 2).as_usizevec2()); 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!(I8Vec2::new(1, 2), U16Vec2::new(1, 2).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), U16Vec2::new(1, 2).as_u8vec2()); 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!(USizeVec2::new(1, 2), U16Vec2::new(1, 2).as_usizevec2()); 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!(I8Vec2::new(-1, -2), IVec2::new(-1, -2).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), IVec2::new(1, 2).as_u8vec2()); 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!(USizeVec2::new(1, 2), IVec2::new(1, 2).as_usizevec2()); 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!(I8Vec2::new(1, 2), UVec2::new(1, 2).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), UVec2::new(1, 2).as_u8vec2()); 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!(USizeVec2::new(1, 2), UVec2::new(1, 2).as_usizevec2()); 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!(U8Vec2::new(1, 2), I64Vec2::new(1, 2).as_u8vec2()); assert_eq!(I8Vec2::new(-1, -2), I64Vec2::new(-1, -2).as_i8vec2()); 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!(USizeVec2::new(1, 2), I64Vec2::new(1, 2).as_usizevec2()); 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!(I8Vec2::new(1, 2), U64Vec2::new(1, 2).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), U64Vec2::new(1, 2).as_u8vec2()); 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()); assert_eq!(USizeVec2::new(1, 2), U64Vec2::new(1, 2).as_usizevec2()); assert_eq!(Vec2::new(1.0, 2.0), USizeVec2::new(1, 2).as_vec2()); assert_eq!(DVec2::new(1.0, 2.0), USizeVec2::new(1, 2).as_dvec2()); assert_eq!(I8Vec2::new(1, 2), USizeVec2::new(1, 2).as_i8vec2()); assert_eq!(U8Vec2::new(1, 2), USizeVec2::new(1, 2).as_u8vec2()); assert_eq!(I16Vec2::new(1, 2), USizeVec2::new(1, 2).as_i16vec2()); assert_eq!(U16Vec2::new(1, 2), USizeVec2::new(1, 2).as_u16vec2()); assert_eq!(IVec2::new(1, 2), USizeVec2::new(1, 2).as_ivec2()); assert_eq!(UVec2::new(1, 2), USizeVec2::new(1, 2).as_uvec2()); assert_eq!(I64Vec2::new(1, 2), USizeVec2::new(1, 2).as_i64vec2()); assert_eq!(U64Vec2::new(1, 2), USizeVec2::new(1, 2).as_u64vec2()); }); impl_vec2_float_tests!(f32, vec2, Vec2, Vec3, BVec2); } mod dvec2 { use glam::{dvec2, BVec2, DVec2, DVec3, IVec2, UVec2, Vec2}; glam_test!(test_align, { use core::mem; assert_eq!(16, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(mem::align_of::(), mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); 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 i8vec2 { use glam::{ i8vec2, BVec2, I16Vec2, I64Vec2, I8Vec2, I8Vec3, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(2, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(1, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(2, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(U8Vec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(U8Vec2::new(u8::MAX, 2)).is_err()); assert!(I8Vec2::try_from(U8Vec2::new(1, u8::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(I16Vec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(I16Vec2::new(i16::MAX, 2)).is_err()); assert!(I8Vec2::try_from(I16Vec2::new(1, i16::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(U16Vec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(U16Vec2::new(u16::MAX, 2)).is_err()); assert!(I8Vec2::try_from(U16Vec2::new(1, u16::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(IVec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(IVec2::new(i32::MAX, 2)).is_err()); assert!(I8Vec2::try_from(IVec2::new(1, i32::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(UVec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(UVec2::new(u32::MAX, 2)).is_err()); assert!(I8Vec2::try_from(UVec2::new(1, u32::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(I64Vec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(I64Vec2::new(i64::MAX, 2)).is_err()); assert!(I8Vec2::try_from(I64Vec2::new(1, i64::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(U64Vec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err()); assert!(I8Vec2::try_from(U64Vec2::new(1, u64::MAX)).is_err()); assert_eq!( I8Vec2::new(1, 2), I8Vec2::try_from(USizeVec2::new(1, 2)).unwrap() ); assert!(I8Vec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(I8Vec2::try_from(USizeVec2::new(1, usize::MAX)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( I8Vec2::new(i8::MAX, 5).wrapping_add(I8Vec2::new(1, 3)), I8Vec2::new(i8::MIN, 8), ); }); glam_test!(test_wrapping_sub, { assert_eq!( I8Vec2::new(i8::MAX, 5).wrapping_sub(I8Vec2::new(1, 3)), I8Vec2::new(126, 2) ); }); glam_test!(test_wrapping_mul, { assert_eq!( I8Vec2::new(i8::MAX, 5).wrapping_mul(I8Vec2::new(3, 3)), I8Vec2::new(125, 15) ); }); glam_test!(test_wrapping_div, { assert_eq!( I8Vec2::new(i8::MAX, 5).wrapping_div(I8Vec2::new(3, 3)), I8Vec2::new(42, 1) ); }); glam_test!(test_saturating_add, { assert_eq!( I8Vec2::new(i8::MAX, i8::MIN,).saturating_add(I8Vec2::new(1, -1)), I8Vec2::new(i8::MAX, i8::MIN) ); }); glam_test!(test_saturating_sub, { assert_eq!( I8Vec2::new(i8::MIN, i8::MAX).saturating_sub(I8Vec2::new(1, -1)), I8Vec2::new(i8::MIN, i8::MAX) ); }); glam_test!(test_saturating_mul, { assert_eq!( I8Vec2::new(i8::MAX, i8::MIN).saturating_mul(I8Vec2::new(2, 2)), I8Vec2::new(i8::MAX, i8::MIN) ); }); glam_test!(test_saturating_div, { assert_eq!( I8Vec2::new(i8::MAX, i8::MIN).saturating_div(I8Vec2::new(2, 2)), I8Vec2::new(63, -64) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(I8Vec2::MAX.checked_add_unsigned(U8Vec2::ONE), None); assert_eq!( I8Vec2::NEG_ONE.checked_add_unsigned(U8Vec2::ONE), Some(I8Vec2::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I8Vec2::MIN.checked_sub_unsigned(U8Vec2::ONE), None); assert_eq!( I8Vec2::ZERO.checked_sub_unsigned(U8Vec2::ONE), Some(I8Vec2::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I8Vec2::new(i8::MAX, i8::MAX).wrapping_add_unsigned(U8Vec2::new(1, 1)), I8Vec2::new(i8::MIN, i8::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I8Vec2::new(i8::MIN, i8::MIN).wrapping_sub_unsigned(U8Vec2::new(1, 1)), I8Vec2::new(i8::MAX, i8::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I8Vec2::new(i8::MAX, i8::MAX).saturating_add_unsigned(U8Vec2::new(1, 1)), I8Vec2::new(i8::MAX, i8::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I8Vec2::new(i8::MIN, i8::MIN).saturating_sub_unsigned(U8Vec2::new(1, 1)), I8Vec2::new(i8::MIN, i8::MIN) ); }); impl_vec2_signed_integer_tests!(i8, i8vec2, I8Vec2, I8Vec3, BVec2); impl_vec2_eq_hash_tests!(i8, i8vec2); impl_vec2_scalar_shift_op_tests!(I8Vec2, -2, 2); impl_vec2_shift_op_tests!(I8Vec2); impl_vec2_scalar_bit_op_tests!(I8Vec2, -2, 2); impl_vec2_bit_op_tests!(I8Vec2, -2, 2); } mod u8vec2 { use glam::{ u8vec2, BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, U8Vec3, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(2, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(1, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(2, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(I8Vec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(I8Vec2::new(-1, 2)).is_err()); assert!(U8Vec2::try_from(I8Vec2::new(1, -2)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(I16Vec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(I16Vec2::new(-1, 2)).is_err()); assert!(U8Vec2::try_from(I16Vec2::new(1, -2)).is_err()); assert!(U8Vec2::try_from(I16Vec2::new(i16::MAX, 2)).is_err()); assert!(U8Vec2::try_from(I16Vec2::new(1, i16::MAX)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(U16Vec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(U16Vec2::new(u16::MAX, 2)).is_err()); assert!(U8Vec2::try_from(U16Vec2::new(1, u16::MAX)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(IVec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(IVec2::new(-1, 2)).is_err()); assert!(U8Vec2::try_from(IVec2::new(1, -2)).is_err()); assert!(U8Vec2::try_from(IVec2::new(i32::MAX, 2)).is_err()); assert!(U8Vec2::try_from(IVec2::new(1, i32::MAX)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(UVec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(UVec2::new(u32::MAX, 2)).is_err()); assert!(U8Vec2::try_from(UVec2::new(1, u32::MAX)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(I64Vec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(I64Vec2::new(-1, 2)).is_err()); assert!(U8Vec2::try_from(I64Vec2::new(1, -2)).is_err()); assert!(U8Vec2::try_from(I64Vec2::new(i64::MAX, 2)).is_err()); assert!(U8Vec2::try_from(I64Vec2::new(1, i64::MAX)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(U64Vec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(U64Vec2::new(u64::MAX, 2)).is_err()); assert!(U8Vec2::try_from(U64Vec2::new(1, u64::MAX)).is_err()); assert_eq!( U8Vec2::new(1, 2), U8Vec2::try_from(USizeVec2::new(1, 2)).unwrap() ); assert!(U8Vec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(U8Vec2::try_from(USizeVec2::new(1, usize::MAX)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( U8Vec2::new(u8::MAX, 5).wrapping_add(U8Vec2::new(1, 3)), U8Vec2::new(0, 8), ); }); glam_test!(test_wrapping_sub, { assert_eq!( U8Vec2::new(u8::MAX, 5).wrapping_sub(U8Vec2::new(1, 3)), U8Vec2::new(254, 2) ); }); glam_test!(test_wrapping_mul, { assert_eq!( U8Vec2::new(u8::MAX, 5).wrapping_mul(U8Vec2::new(3, 3)), U8Vec2::new(253, 15) ); }); glam_test!(test_wrapping_div, { assert_eq!( U8Vec2::new(u8::MAX, 5).wrapping_div(U8Vec2::new(3, 3)), U8Vec2::new(85, 1) ); }); glam_test!(test_saturating_add, { assert_eq!( U8Vec2::new(u8::MAX, u8::MAX).saturating_add(U8Vec2::new(1, u8::MAX)), U8Vec2::new(u8::MAX, u8::MAX) ); }); glam_test!(test_saturating_sub, { assert_eq!( U8Vec2::new(0, u8::MAX).saturating_sub(U8Vec2::new(1, 1)), U8Vec2::new(0, 254) ); }); glam_test!(test_saturating_mul, { assert_eq!( U8Vec2::new(u8::MAX, u8::MAX).saturating_mul(U8Vec2::new(2, u8::MAX)), U8Vec2::new(u8::MAX, u8::MAX) ); }); glam_test!(test_saturating_div, { assert_eq!( U8Vec2::new(u8::MAX, u8::MAX).saturating_div(U8Vec2::new(2, u8::MAX)), U8Vec2::new(127, 1) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U8Vec2::new(u8::MAX, u8::MAX).wrapping_add_signed(I8Vec2::new(1, 1)), U8Vec2::new(u8::MIN, u8::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U8Vec2::new(u8::MAX, u8::MAX).saturating_add_signed(I8Vec2::new(1, 1)), U8Vec2::new(u8::MAX, u8::MAX) ); }); impl_vec2_unsigned_integer_tests!(u8, u8vec2, U8Vec2, U8Vec3, BVec2); impl_vec2_eq_hash_tests!(u8, u8vec2); impl_vec2_scalar_shift_op_tests!(U8Vec2, 0, 2); impl_vec2_shift_op_tests!(U8Vec2); impl_vec2_scalar_bit_op_tests!(U8Vec2, 0, 2); impl_vec2_bit_op_tests!(U8Vec2, 0, 2); } mod i16vec2 { use glam::{ i16vec2, BVec2, I16Vec2, I16Vec3, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(4, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(2, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(4, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(I16Vec2::new(1, 2), I16Vec2::from(U8Vec2::new(1, 2))); assert_eq!(I16Vec2::new(1, 2), I16Vec2::from(I8Vec2::new(1, 2))); 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()); assert_eq!( I16Vec2::new(1, 2), I16Vec2::try_from(USizeVec2::new(1, 2)).unwrap() ); assert!(I16Vec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(I16Vec2::try_from(USizeVec2::new(1, usize::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) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(I16Vec2::MAX.checked_add_unsigned(U16Vec2::ONE), None); assert_eq!( I16Vec2::NEG_ONE.checked_add_unsigned(U16Vec2::ONE), Some(I16Vec2::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I16Vec2::MIN.checked_sub_unsigned(U16Vec2::ONE), None); assert_eq!( I16Vec2::ZERO.checked_sub_unsigned(U16Vec2::ONE), Some(I16Vec2::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I16Vec2::new(i16::MAX, i16::MAX).wrapping_add_unsigned(U16Vec2::new(1, 1)), I16Vec2::new(i16::MIN, i16::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I16Vec2::new(i16::MIN, i16::MIN).wrapping_sub_unsigned(U16Vec2::new(1, 1)), I16Vec2::new(i16::MAX, i16::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I16Vec2::new(i16::MAX, i16::MAX).saturating_add_unsigned(U16Vec2::new(1, 1)), I16Vec2::new(i16::MAX, i16::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I16Vec2::new(i16::MIN, i16::MIN).saturating_sub_unsigned(U16Vec2::new(1, 1)), I16Vec2::new(i16::MIN, i16::MIN) ); }); 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, I8Vec2, IVec2, U16Vec2, U16Vec3, U64Vec2, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(4, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(2, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(4, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U16Vec2::new(1, 2), U16Vec2::try_from(I8Vec2::new(1, 2)).unwrap() ); assert!(U16Vec2::try_from(I8Vec2::new(-1, 2)).is_err()); assert!(U16Vec2::try_from(I8Vec2::new(1, -2)).is_err()); 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()); assert_eq!( U16Vec2::new(1, 2), U16Vec2::try_from(USizeVec2::new(1, 2)).unwrap() ); assert!(U16Vec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(U16Vec2::try_from(USizeVec2::new(1, usize::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) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U16Vec2::new(u16::MAX, u16::MAX).wrapping_add_signed(I16Vec2::new(1, 1)), U16Vec2::new(u16::MIN, u16::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U16Vec2::new(u16::MAX, u16::MAX).saturating_add_signed(I16Vec2::new(1, 1)), U16Vec2::new(u16::MAX, u16::MAX) ); }); impl_vec2_unsigned_integer_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, I16Vec2, I64Vec2, I8Vec2, IVec2, IVec3, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(8, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(4, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(8, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(IVec2::new(1, 2), IVec2::from(U8Vec2::new(1, 2))); assert_eq!(IVec2::new(1, 2), IVec2::from(I8Vec2::new(1, 2))); 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()); assert_eq!( IVec2::new(1, 2), IVec2::try_from(USizeVec2::new(1, 2)).unwrap() ); assert!(IVec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(IVec2::try_from(USizeVec2::new(1, usize::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) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(IVec2::MAX.checked_add_unsigned(UVec2::ONE), None); assert_eq!( IVec2::NEG_ONE.checked_add_unsigned(UVec2::ONE), Some(IVec2::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(IVec2::MIN.checked_sub_unsigned(UVec2::ONE), None); assert_eq!( IVec2::ZERO.checked_sub_unsigned(UVec2::ONE), Some(IVec2::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( IVec2::new(i32::MAX, i32::MAX).wrapping_add_unsigned(UVec2::new(1, 1)), IVec2::new(i32::MIN, i32::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( IVec2::new(i32::MIN, i32::MIN).wrapping_sub_unsigned(UVec2::new(1, 1)), IVec2::new(i32::MAX, i32::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( IVec2::new(i32::MAX, i32::MAX).saturating_add_unsigned(UVec2::new(1, 1)), IVec2::new(i32::MAX, i32::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( IVec2::new(i32::MIN, i32::MIN).saturating_sub_unsigned(UVec2::new(1, 1)), IVec2::new(i32::MIN, i32::MIN) ); }); 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); impl_vec2_shift_op_tests!(IVec2); impl_vec2_scalar_bit_op_tests!(IVec2, -2, 2); impl_vec2_bit_op_tests!(IVec2, -2, 2); } mod uvec2 { use glam::{ uvec2, BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2, UVec3, }; glam_test!(test_align, { use core::mem; assert_eq!(8, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(4, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(8, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( UVec2::new(1, 2), UVec2::try_from(I8Vec2::new(1, 2)).unwrap() ); assert!(UVec2::try_from(I8Vec2::new(-1, 2)).is_err()); assert!(UVec2::try_from(I8Vec2::new(1, -2)).is_err()); assert_eq!(UVec2::new(1, 2), UVec2::from(U8Vec2::new(1, 2))); 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()); assert_eq!( UVec2::new(1, 2), UVec2::try_from(USizeVec2::new(1, 2)).unwrap() ); if core::mem::size_of::() > 4 { assert!(UVec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(UVec2::try_from(USizeVec2::new(1, usize::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) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( UVec2::new(u32::MAX, u32::MAX).wrapping_add_signed(IVec2::new(1, 1)), UVec2::new(u32::MIN, u32::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( UVec2::new(u32::MAX, u32::MAX).saturating_add_signed(IVec2::new(1, 1)), UVec2::new(u32::MAX, u32::MAX) ); }); impl_vec2_unsigned_integer_tests!(u32, uvec2, UVec2, UVec3, BVec2); impl_vec2_eq_hash_tests!(u32, uvec2); impl_vec2_scalar_shift_op_tests!(UVec2, 0, 2); impl_vec2_shift_op_tests!(UVec2); 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, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(16, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(8, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(I64Vec2::new(1, 2), I64Vec2::from(I8Vec2::new(1, 2))); assert_eq!(I64Vec2::new(1, 2), I64Vec2::from(U8Vec2::new(1, 2))); 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()); assert_eq!( I64Vec2::new(1, 2), I64Vec2::try_from(USizeVec2::new(1, 2)).unwrap() ); if core::mem::size_of::() > 4 { assert!(I64Vec2::try_from(USizeVec2::new(usize::MAX, 2)).is_err()); assert!(I64Vec2::try_from(USizeVec2::new(1, usize::MAX)).is_err()); } }); glam_test!(test_checked_add_unsigned, { assert_eq!(I64Vec2::MAX.checked_add_unsigned(U64Vec2::ONE), None); assert_eq!( I64Vec2::NEG_ONE.checked_add_unsigned(U64Vec2::ONE), Some(I64Vec2::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I64Vec2::MIN.checked_sub_unsigned(U64Vec2::ONE), None); assert_eq!( I64Vec2::ZERO.checked_sub_unsigned(U64Vec2::ONE), Some(I64Vec2::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I64Vec2::new(i64::MAX, i64::MAX).wrapping_add_unsigned(U64Vec2::new(1, 1)), I64Vec2::new(i64::MIN, i64::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I64Vec2::new(i64::MIN, i64::MIN).wrapping_sub_unsigned(U64Vec2::new(1, 1)), I64Vec2::new(i64::MAX, i64::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I64Vec2::new(i64::MAX, i64::MAX).saturating_add_unsigned(U64Vec2::new(1, 1)), I64Vec2::new(i64::MAX, i64::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I64Vec2::new(i64::MIN, i64::MIN).saturating_sub_unsigned(U64Vec2::new(1, 1)), I64Vec2::new(i64::MIN, i64::MIN) ); }); 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, I8Vec2, IVec2, U16Vec2, U64Vec2, U64Vec3, U8Vec2, USizeVec2, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(16, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(8, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U64Vec2::new(1, 2), U64Vec2::try_from(I8Vec2::new(1, 2)).unwrap() ); assert!(U64Vec2::try_from(I8Vec2::new(-1, 2)).is_err()); assert!(U64Vec2::try_from(I8Vec2::new(1, -2)).is_err()); assert_eq!(U64Vec2::new(1, 2), U64Vec2::from(U8Vec2::new(1, 2))); 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()); assert_eq!( U64Vec2::new(1, 2), U64Vec2::try_from(USizeVec2::new(1, 2)).unwrap() ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U64Vec2::new(u64::MAX, u64::MAX).wrapping_add_signed(I64Vec2::new(1, 1)), U64Vec2::new(u64::MIN, u64::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U64Vec2::new(u64::MAX, u64::MAX).saturating_add_signed(I64Vec2::new(1, 1)), U64Vec2::new(u64::MAX, u64::MAX) ); }); impl_vec2_unsigned_integer_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); } mod usizevec2 { use glam::{ usizevec2, BVec2, I16Vec2, I64Vec2, I8Vec2, IVec2, U16Vec2, U64Vec2, U8Vec2, USizeVec2, USizeVec3, UVec2, }; glam_test!(test_align, { use core::mem; assert_eq!(mem::size_of::() * 2, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(mem::align_of::(), mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( USizeVec2::new(1, 2), USizeVec2::try_from(I8Vec2::new(1, 2)).unwrap() ); assert!(USizeVec2::try_from(I8Vec2::new(-1, 2)).is_err()); assert!(USizeVec2::try_from(I8Vec2::new(1, -2)).is_err()); assert_eq!(USizeVec2::new(1, 2), USizeVec2::from(U8Vec2::new(1, 2))); assert_eq!( USizeVec2::new(1, 2), USizeVec2::try_from(I16Vec2::new(1, 2)).unwrap() ); assert!(USizeVec2::try_from(I16Vec2::new(-1, 2)).is_err()); assert!(USizeVec2::try_from(I16Vec2::new(1, -2)).is_err()); assert_eq!(USizeVec2::new(1, 2), USizeVec2::from(U16Vec2::new(1, 2))); assert_eq!( USizeVec2::new(1, 2), USizeVec2::try_from(IVec2::new(1, 2)).unwrap() ); assert!(USizeVec2::try_from(IVec2::new(-1, 2)).is_err()); assert!(USizeVec2::try_from(IVec2::new(1, -2)).is_err()); assert_eq!( USizeVec2::new(1, 2), USizeVec2::try_from(UVec2::new(1, 2)).unwrap() ); assert_eq!( USizeVec2::new(1, 2), USizeVec2::try_from(U64Vec2::new(1, 2)).unwrap() ); assert_eq!( USizeVec2::new(1, 2), USizeVec2::try_from(I64Vec2::new(1, 2)).unwrap() ); assert!(USizeVec2::try_from(I64Vec2::new(-1, 2)).is_err()); assert!(USizeVec2::try_from(I64Vec2::new(1, -2)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( USizeVec2::new(usize::MAX, 5).wrapping_add(USizeVec2::new(1, 3)), USizeVec2::new(usize::MAX.wrapping_add(1), 8), ); }); glam_test!(test_wrapping_sub, { assert_eq!( USizeVec2::new(usize::MAX, 5).wrapping_sub(USizeVec2::new(1, 3)), USizeVec2::new(usize::MAX.wrapping_sub(1), 2) ); }); glam_test!(test_wrapping_mul, { assert_eq!( USizeVec2::new(usize::MAX, 5).wrapping_mul(USizeVec2::new(3, 3)), USizeVec2::new(usize::MAX.wrapping_mul(3), 15) ); }); glam_test!(test_wrapping_div, { assert_eq!( USizeVec2::new(usize::MAX, 5).wrapping_div(USizeVec2::new(3, 3)), USizeVec2::new(usize::MAX.wrapping_div(3), 1) ); }); glam_test!(test_saturating_add, { assert_eq!( USizeVec2::new(usize::MAX, usize::MAX).saturating_add(USizeVec2::new(1, usize::MAX)), USizeVec2::new(usize::MAX, usize::MAX) ); }); glam_test!(test_saturating_sub, { assert_eq!( USizeVec2::new(0, usize::MAX).saturating_sub(USizeVec2::new(1, 1)), USizeVec2::new(0, usize::MAX.saturating_sub(1)) ); }); glam_test!(test_saturating_mul, { assert_eq!( USizeVec2::new(usize::MAX, usize::MAX).saturating_mul(USizeVec2::new(2, usize::MAX)), USizeVec2::new(usize::MAX, usize::MAX) ); }); glam_test!(test_saturating_div, { assert_eq!( USizeVec2::new(usize::MAX, usize::MAX).saturating_div(USizeVec2::new(2, usize::MAX)), USizeVec2::new(usize::MAX.saturating_div(2), 1) ); }); impl_vec2_unsigned_integer_tests!(usize, usizevec2, USizeVec2, USizeVec3, BVec2); impl_vec2_eq_hash_tests!(usize, usizevec2); impl_vec2_scalar_shift_op_tests!(USizeVec2, 0, 2); impl_vec2_shift_op_tests!(USizeVec2); impl_vec2_scalar_bit_op_tests!(USizeVec2, 0, 2); impl_vec2_bit_op_tests!(USizeVec2, 0, 2); } glam-0.30.1/tests/vec3.rs000064400000000000000000003723141046102023000132070ustar 00000000000000#![allow(clippy::excessive_precision)] #[macro_use] mod support; macro_rules! impl_bvec3_tests { ($mask:ident, $masknew:ident) => { glam_test!(test_mask_new, { assert_eq!( $mask::new(false, false, false), $masknew(false, false, false) ); assert_eq!($mask::new(true, false, false), $masknew(true, false, false)); assert_eq!($mask::new(false, true, true), $masknew(false, true, true)); assert_eq!($mask::new(false, true, false), $masknew(false, true, false)); assert_eq!($mask::new(true, false, true), $masknew(true, false, true)); assert_eq!($mask::new(true, true, true), $masknew(true, true, true)); }); glam_test!(test_mask_from_array_bool, { assert_eq!( $mask::new(false, false, false), $mask::from([false, false, false]) ); assert_eq!( $mask::new(true, false, false), $mask::from([true, false, false]) ); assert_eq!( $mask::new(false, true, true), $mask::from([false, true, true]) ); assert_eq!( $mask::new(false, true, false), $mask::from([false, true, false]) ); assert_eq!( $mask::new(true, false, true), $mask::from([true, false, true]) ); assert_eq!( $mask::new(true, true, true), $mask::from([true, true, true]) ); }); glam_test!(test_mask_into_array_u32, { assert_eq!( Into::<[u32; 3]>::into($mask::new(false, false, false)), [0, 0, 0] ); assert_eq!( Into::<[u32; 3]>::into($mask::new(true, false, false)), [!0, 0, 0] ); assert_eq!( Into::<[u32; 3]>::into($mask::new(false, true, true)), [0, !0, !0] ); assert_eq!( Into::<[u32; 3]>::into($mask::new(false, true, false)), [0, !0, 0] ); assert_eq!( Into::<[u32; 3]>::into($mask::new(true, false, true)), [!0, 0, !0] ); assert_eq!( Into::<[u32; 3]>::into($mask::new(true, true, true)), [!0, !0, !0] ); }); glam_test!(test_mask_into_array_bool, { assert_eq!( Into::<[bool; 3]>::into($mask::new(false, false, false)), [false, false, false] ); assert_eq!( Into::<[bool; 3]>::into($mask::new(true, false, false)), [true, false, false] ); assert_eq!( Into::<[bool; 3]>::into($mask::new(false, true, true)), [false, true, true] ); assert_eq!( Into::<[bool; 3]>::into($mask::new(false, true, false)), [false, true, false] ); assert_eq!( Into::<[bool; 3]>::into($mask::new(true, false, true)), [true, false, true] ); assert_eq!( Into::<[bool; 3]>::into($mask::new(true, true, true)), [true, true, true] ); }); glam_test!(test_mask_splat, { assert_eq!($mask::splat(false), $mask::new(false, false, false)); assert_eq!($mask::splat(true), $mask::new(true, true, true)); }); glam_test!(test_mask_bitmask, { assert_eq!($mask::new(false, false, false).bitmask(), 0b000); assert_eq!($mask::new(true, false, false).bitmask(), 0b001); assert_eq!($mask::new(false, true, true).bitmask(), 0b110); assert_eq!($mask::new(false, true, false).bitmask(), 0b010); assert_eq!($mask::new(true, false, true).bitmask(), 0b101); assert_eq!($mask::new(true, true, true).bitmask(), 0b111); }); glam_test!(test_mask_any, { assert_eq!($mask::new(false, false, false).any(), false); assert_eq!($mask::new(true, false, false).any(), true); assert_eq!($mask::new(false, true, false).any(), true); assert_eq!($mask::new(false, false, true).any(), true); }); glam_test!(test_mask_all, { assert_eq!($mask::new(true, true, true).all(), true); assert_eq!($mask::new(false, true, true).all(), false); assert_eq!($mask::new(true, false, true).all(), false); assert_eq!($mask::new(true, true, false).all(), false); }); glam_test!(test_mask_and, { assert_eq!( ($mask::new(false, false, false) & $mask::new(false, false, false)).bitmask(), 0b000, ); assert_eq!( ($mask::new(true, true, true) & $mask::new(true, true, true)).bitmask(), 0b111, ); assert_eq!( ($mask::new(true, false, true) & $mask::new(false, true, false)).bitmask(), 0b000, ); assert_eq!( ($mask::new(true, false, true) & $mask::new(true, true, true)).bitmask(), 0b101, ); let mut mask = $mask::new(true, true, false); mask &= $mask::new(true, false, false); assert_eq!(mask.bitmask(), 0b001); }); glam_test!(test_mask_or, { assert_eq!( ($mask::new(false, false, false) | $mask::new(false, false, false)).bitmask(), 0b000, ); assert_eq!( ($mask::new(true, true, true) | $mask::new(true, true, true)).bitmask(), 0b111, ); assert_eq!( ($mask::new(true, false, true) | $mask::new(false, true, false)).bitmask(), 0b111, ); assert_eq!( ($mask::new(true, false, true) | $mask::new(true, false, true)).bitmask(), 0b101, ); let mut mask = $mask::new(true, true, false); mask |= $mask::new(true, false, false); assert_eq!(mask.bitmask(), 0b011); }); glam_test!(test_mask_xor, { assert_eq!( ($mask::new(false, false, false) ^ $mask::new(false, false, false)).bitmask(), 0b000, ); assert_eq!( ($mask::new(true, true, true) ^ $mask::new(true, true, true)).bitmask(), 0b000, ); assert_eq!( ($mask::new(true, false, true) ^ $mask::new(false, true, false)).bitmask(), 0b111, ); assert_eq!( ($mask::new(true, false, true) ^ $mask::new(true, false, true)).bitmask(), 0b000, ); let mut mask = $mask::new(true, true, false); mask ^= $mask::new(true, false, false); assert_eq!(mask.bitmask(), 0b010); }); glam_test!(test_mask_not, { assert_eq!((!$mask::new(false, false, false)).bitmask(), 0b111); assert_eq!((!$mask::new(true, true, true)).bitmask(), 0b000); assert_eq!((!$mask::new(true, false, true)).bitmask(), 0b010); assert_eq!((!$mask::new(false, true, false)).bitmask(), 0b101); }); glam_test!(test_mask_fmt, { let a = $mask::new(true, false, false); // debug fmt assert_eq!( format!("{:?}", a), format!("{}(0xffffffff, 0x0, 0x0)", stringify!($mask)) ); // display fmt assert_eq!(format!("{}", a), "[true, false, false]"); }); glam_test!(test_mask_eq, { let a = $mask::new(true, false, true); let b = $mask::new(true, false, true); let c = $mask::new(false, true, true); assert_eq!(a, b); assert_eq!(b, a); assert_ne!(a, c); 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; use std::hash::Hasher; let a = $mask::new(true, false, true); let b = $mask::new(true, false, true); let c = $mask::new(false, true, true); let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); let a_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); b.hash(&mut hasher); let b_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); c.hash(&mut hasher); let c_hashed = hasher.finish(); assert_eq!(a, b); assert_eq!(a_hashed, b_hashed); assert_ne!(a, c); assert_ne!(a_hashed, c_hashed); }); }; } macro_rules! impl_vec3_tests { ($t:ident, $new:ident, $vec3:ident, $mask:ident) => { glam_test!(test_const, { const V0: $vec3 = $vec3::splat(1 as $t); const V1: $vec3 = $vec3::new(1 as $t, 2 as $t, 3 as $t); const V2: $vec3 = $vec3::from_array([1 as $t, 2 as $t, 3 as $t]); assert_eq!([1 as $t, 1 as $t, 1 as $t], *V0.as_ref()); assert_eq!([1 as $t, 2 as $t, 3 as $t], *V1.as_ref()); assert_eq!([1 as $t, 2 as $t, 3 as $t], *V2.as_ref()); }); glam_test!(test_vec3_consts, { assert_eq!($vec3::ZERO, $new(0 as $t, 0 as $t, 0 as $t)); assert_eq!($vec3::ONE, $new(1 as $t, 1 as $t, 1 as $t)); 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, { let v = $new(1 as $t, 2 as $t, 3 as $t); assert_eq!(v.x, 1 as $t); assert_eq!(v.y, 2 as $t); assert_eq!(v.z, 3 as $t); let t = (1 as $t, 2 as $t, 3 as $t); let v = $vec3::from(t); assert_eq!(t, v.into()); let a = [1 as $t, 2 as $t, 3 as $t]; let v = $vec3::from(a); let a1: [$t; 3] = v.into(); assert_eq!(a, a1); assert_eq!(a, v.to_array()); assert_eq!(a, *v.as_ref()); let mut v2 = $vec3::default(); *v2.as_mut() = a; assert_eq!(a, v2.to_array()); let v = $vec3::new(t.0, t.1, t.2); assert_eq!(t, v.into()); assert_eq!( $vec3::new(1 as $t, 0 as $t, 0 as $t), glam::BVec3::new(true, false, false).into() ); assert_eq!( $vec3::new(0 as $t, 1 as $t, 0 as $t), glam::BVec3::new(false, true, false).into() ); assert_eq!( $vec3::new(0 as $t, 0 as $t, 1 as $t), glam::BVec3::new(false, false, true).into() ); assert_eq!( $vec3::new(1 as $t, 0 as $t, 0 as $t), glam::BVec3A::new(true, false, false).into() ); assert_eq!( $vec3::new(0 as $t, 1 as $t, 0 as $t), glam::BVec3A::new(false, true, false).into() ); assert_eq!( $vec3::new(0 as $t, 0 as $t, 1 as $t), glam::BVec3A::new(false, false, true).into() ); assert_eq!($vec3::new(1 as $t, 0 as $t, 0 as $t), $vec3::X); assert_eq!($vec3::new(0 as $t, 1 as $t, 0 as $t), $vec3::Y); assert_eq!($vec3::new(0 as $t, 0 as $t, 1 as $t), $vec3::Z); }); glam_test!(test_fmt, { let a = $vec3::new(1 as $t, 2 as $t, 3 as $t); assert_eq!( format!("{:?}", a), format!("{}({:?}, {:?}, {:?})", stringify!($vec3), a.x, a.y, a.z) ); assert_eq!( format!("{:#?}", a), format!( "{}(\n {:#?},\n {:#?},\n {:#?},\n)", stringify!($vec3), a.x, a.y, a.z ) ); assert_eq!(format!("{}", a), "[1, 2, 3]"); }); glam_test!(test_zero, { let v = $vec3::ZERO; assert_eq!((0 as $t, 0 as $t, 0 as $t), v.into()); assert_eq!(v, $vec3::default()); }); glam_test!(test_splat, { let v = $vec3::splat(1 as $t); assert_eq!($vec3::ONE, v); }); glam_test!(test_map, { let v = $vec3::new(1 as $t, 2 as $t, 3 as $t); assert_eq!(v.map(|n| n + 3 as $t), v + $vec3::splat(3 as $t)); assert_eq!(v.map(|_| 0 as $t), $vec3::ZERO); }); glam_test!(test_with, { assert_eq!($vec3::X, $vec3::ZERO.with_x(1 as $t)); assert_eq!($vec3::Y, $vec3::ZERO.with_y(1 as $t)); assert_eq!($vec3::Z, $vec3::ZERO.with_z(1 as $t)); }); glam_test!(test_accessors, { let mut a = $vec3::ZERO; a.x = 1 as $t; a.y = 2 as $t; a.z = 3 as $t; assert_eq!(1 as $t, a.x); assert_eq!(2 as $t, a.y); assert_eq!(3 as $t, a.z); assert_eq!((1 as $t, 2 as $t, 3 as $t), a.into()); let mut a = $vec3::ZERO; a[0] = 1 as $t; a[1] = 2 as $t; a[2] = 3 as $t; assert_eq!(1 as $t, a[0]); assert_eq!(2 as $t, a[1]); assert_eq!(3 as $t, a[2]); assert_eq!((1 as $t, 2 as $t, 3 as $t), a.into()); }); glam_test!(test_dot_unsigned, { let x = $new(1 as $t, 0 as $t, 0 as $t); 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, { 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!(y, z.cross(x)); assert_eq!(z, x.cross(y)); }); glam_test!(test_ops, { let a = $new(2 as $t, 4 as $t, 8 as $t); assert_eq!($new(4 as $t, 8 as $t, 16 as $t), a + a); assert_eq!($new(2 as $t, 4 as $t, 8 as $t), 0 as $t + a); assert_eq!($new(0 as $t, 0 as $t, 0 as $t), a - a); assert_eq!($new(14 as $t, 12 as $t, 8 as $t), 16 as $t - a); assert_eq!($new(4 as $t, 16 as $t, 64 as $t), a * a); assert_eq!($new(4 as $t, 8 as $t, 16 as $t), a * 2 as $t); assert_eq!($new(4 as $t, 8 as $t, 16 as $t), 2 as $t * a); assert_eq!($new(1 as $t, 1 as $t, 1 as $t), a / a); assert_eq!($new(1 as $t, 2 as $t, 4 as $t), a / 2 as $t); assert_eq!($new(4 as $t, 2 as $t, 1 as $t), 8 as $t / a); assert_eq!($new(0 as $t, 0 as $t, 0 as $t), a % a); assert_eq!($new(0 as $t, 1 as $t, 1 as $t), a % (a - 1 as $t)); assert_eq!($new(0 as $t, 0 as $t, 0 as $t), a % 1 as $t); assert_eq!($new(2 as $t, 1 as $t, 2 as $t), a % 3 as $t); assert_eq!($new(1 as $t, 1 as $t, 1 as $t), 17 as $t % a); assert_eq!($new(2 as $t, 4 as $t, 0 as $t), a % 8 as $t); }); glam_test!(test_ops_propagated, { let vec = $new(2 as $t, 4 as $t, 8 as $t); let scalar = 2 as $t; let g_scalar = 16 as $t; assert_eq!((vec + vec), (vec + &vec)); assert_eq!((vec + vec), (&vec + vec)); assert_eq!((vec + vec), (&vec + &vec)); assert_eq!((vec + scalar), (vec + &scalar)); assert_eq!((vec + scalar), (&vec + &scalar)); assert_eq!((vec + scalar), (&vec + scalar)); assert_eq!((scalar + vec), (&scalar + vec)); assert_eq!((scalar + vec), (&scalar + &vec)); assert_eq!((scalar + vec), (scalar + &vec)); assert_eq!((vec - vec), (vec - &vec)); assert_eq!((vec - vec), (&vec - vec)); assert_eq!((vec - vec), (&vec - &vec)); assert_eq!((vec - scalar), (vec - &scalar)); assert_eq!((vec - scalar), (&vec - &scalar)); assert_eq!((vec - scalar), (&vec - scalar)); assert_eq!((g_scalar - vec), (&g_scalar - vec)); assert_eq!((g_scalar - vec), (&g_scalar - &vec)); assert_eq!((g_scalar - vec), (g_scalar - &vec)); assert_eq!((vec * vec), (vec * &vec)); assert_eq!((vec * vec), (&vec * vec)); assert_eq!((vec * vec), (&vec * &vec)); assert_eq!((vec * scalar), (vec * &scalar)); assert_eq!((vec * scalar), (&vec * &scalar)); assert_eq!((vec * scalar), (&vec * scalar)); assert_eq!((scalar * vec), (&scalar * vec)); assert_eq!((scalar * vec), (&scalar * &vec)); assert_eq!((scalar * vec), (scalar * &vec)); assert_eq!((vec / vec), (vec / &vec)); assert_eq!((vec / vec), (&vec / vec)); assert_eq!((vec / vec), (&vec / &vec)); assert_eq!((vec / scalar), (vec / &scalar)); assert_eq!((vec / scalar), (&vec / &scalar)); assert_eq!((vec / scalar), (&vec / scalar)); assert_eq!((scalar / vec), (&scalar / vec)); assert_eq!((scalar / vec), (&scalar / &vec)); assert_eq!((scalar / vec), (scalar / &vec)); assert_eq!((vec % vec), (vec % &vec)); assert_eq!((vec % vec), (&vec % vec)); assert_eq!((vec % vec), (&vec % &vec)); assert_eq!((vec % scalar), (vec % &scalar)); assert_eq!((vec % scalar), (&vec % &scalar)); assert_eq!((vec % scalar), (&vec % scalar)); assert_eq!((scalar % vec), (&scalar % vec)); assert_eq!((scalar % vec), (&scalar % &vec)); assert_eq!((scalar % vec), (scalar % &vec)); }); glam_test!(test_assign_ops, { let a = $new(1 as $t, 2 as $t, 3 as $t); let mut b = a; b += 2 as $t; assert_eq!($new(3 as $t, 4 as $t, 5 as $t), b); b -= 2 as $t; assert_eq!($new(1 as $t, 2 as $t, 3 as $t), b); b *= 2 as $t; assert_eq!($new(2 as $t, 4 as $t, 6 as $t), b); b /= 2 as $t; assert_eq!($new(1 as $t, 2 as $t, 3 as $t), b); b %= 2 as $t; assert_eq!($new(1 as $t, 0 as $t, 1 as $t), b); b = a; b += a; assert_eq!($new(2 as $t, 4 as $t, 6 as $t), b); b -= a; assert_eq!($new(1 as $t, 2 as $t, 3 as $t), b); b *= a; assert_eq!($new(1 as $t, 4 as $t, 9 as $t), b); b /= a; assert_eq!($new(1 as $t, 2 as $t, 3 as $t), b); b *= 2 as $t; assert_eq!($new(2 as $t, 4 as $t, 6 as $t), b); b /= 2 as $t; assert_eq!($new(1 as $t, 2 as $t, 3 as $t), b); b %= (b + 1 as $t); assert_eq!($new(1 as $t, 2 as $t, 3 as $t), b); b %= b; assert_eq!($new(0 as $t, 0 as $t, 0 as $t), b); }); glam_test!(test_assign_ops_propagation, { let vec = $new(1 as $t, 2 as $t, 3 as $t); let mut a = vec; let mut b = vec; let scalar = 2 as $t; a += &scalar; b += scalar; assert_eq!(b, a, "AddAssign"); a -= &scalar; b -= scalar; assert_eq!(b, a, "SubAssign"); a *= &scalar; b *= scalar; assert_eq!(b, a, "MulAssign"); a /= &scalar; b /= scalar; assert_eq!(b, a, "DivAssign"); a %= &scalar; b %= scalar; assert_eq!(b, a, "MulAssign"); a = vec; b = vec; a += &vec; b += vec; assert_eq!(b, a, "AddAssign"); a -= &vec; b -= vec; assert_eq!(b, a, "SubAssign"); a *= &vec; b *= vec; assert_eq!(b, a, "MulAssign"); a /= &vec; b /= vec; assert_eq!(b, a, "DivAssign"); a %= &vec; b %= vec; assert_eq!(b, a, "RemAssign"); }); glam_test!(test_min_max, { let a = $new(3 as $t, 5 as $t, 1 as $t); let b = $new(4 as $t, 2 as $t, 6 as $t); assert_eq!((3 as $t, 2 as $t, 1 as $t), a.min(b).into()); assert_eq!((3 as $t, 2 as $t, 1 as $t), b.min(a).into()); assert_eq!((4 as $t, 5 as $t, 6 as $t), a.max(b).into()); assert_eq!((4 as $t, 5 as $t, 6 as $t), b.max(a).into()); }); glam_test!(test_min_position_max_position, { let a = $new(1 as $t, 2 as $t, 3 as $t); let b = $new(1 as $t, 1 as $t, 1 as $t); let c = $new(3 as $t, 2 as $t, 1 as $t); let d = $new(1 as $t, 2 as $t, 1 as $t); let e = $new(1 as $t, 0 as $t, 1 as $t); assert_eq!(0, a.min_position()); assert_eq!(0, b.min_position()); assert_eq!(2, c.min_position()); assert_eq!(0, d.min_position()); assert_eq!(1, e.min_position()); assert_eq!(2, a.max_position()); assert_eq!(0, b.max_position()); assert_eq!(0, c.max_position()); assert_eq!(1, d.max_position()); assert_eq!(0, e.max_position()); }); glam_test!(test_clamp, { fn vec(x: i32, y: i32, z: i32) -> $vec3 { $vec3::new(x as $t, y as $t, z as $t) } let min = vec(1, 3, 3); let max = vec(6, 8, 8); assert_eq!(vec(0, 0, 0).clamp(min, max), vec(1, 3, 3)); assert_eq!(vec(2, 2, 2).clamp(min, max), vec(2, 3, 3)); assert_eq!(vec(4, 5, 5).clamp(min, max), vec(4, 5, 5)); assert_eq!(vec(6, 6, 6).clamp(min, max), vec(6, 6, 6)); assert_eq!(vec(7, 7, 7).clamp(min, max), vec(6, 7, 7)); assert_eq!(vec(9, 9, 9).clamp(min, max), vec(6, 8, 8)); should_glam_assert!({ $vec3::clamp($vec3::ZERO, $vec3::ONE, $vec3::ZERO) }); }); glam_test!(test_hmin_hmax, { assert_eq!(1 as $t, $new(1 as $t, 2 as $t, 3 as $t).min_element()); assert_eq!(1 as $t, $new(3 as $t, 1 as $t, 2 as $t).min_element()); assert_eq!(1 as $t, $new(2 as $t, 3 as $t, 1 as $t).min_element()); assert_eq!(3 as $t, $new(1 as $t, 2 as $t, 3 as $t).max_element()); assert_eq!(3 as $t, $new(3 as $t, 1 as $t, 2 as $t).max_element()); assert_eq!(3 as $t, $new(2 as $t, 3 as $t, 1 as $t).max_element()); }); glam_test!(test_sum_product, { let a = $new(2 as $t, 3 as $t, 5 as $t); assert_eq!(a.element_sum(), 10 as $t); assert_eq!(a.element_product(), 30 as $t); }); glam_test!(test_eq, { let a = $new(1 as $t, 1 as $t, 1 as $t); let b = $new(1 as $t, 2 as $t, 3 as $t); assert!(a.cmpeq(a).all()); assert!(b.cmpeq(b).all()); assert!(a.cmpne(b).any()); assert!(b.cmpne(a).any()); assert!(b.cmpeq(a).any()); }); glam_test!(test_cmp, { assert!(!$mask::default().any()); assert!(!$mask::default().all()); assert_eq!($mask::default().bitmask(), 0x0); let a = $new(1 as $t, 1 as $t, 1 as $t); let b = $new(2 as $t, 2 as $t, 2 as $t); let c = $new(1 as $t, 1 as $t, 2 as $t); let d = $new(2 as $t, 1 as $t, 1 as $t); assert_eq!(a.cmplt(a).bitmask(), 0x0); assert_eq!(a.cmplt(b).bitmask(), 0x7); assert_eq!(a.cmplt(c).bitmask(), 0x4); assert_eq!(c.cmple(a).bitmask(), 0x3); assert_eq!(a.cmplt(d).bitmask(), 0x1); assert!(a.cmplt(b).all()); assert!(a.cmplt(c).any()); assert!(a.cmple(b).all()); assert!(a.cmple(a).all()); assert!(b.cmpgt(a).all()); assert!(b.cmpge(a).all()); assert!(b.cmpge(b).all()); assert!(!(a.cmpge(c).all())); assert!(c.cmple(c).all()); assert!(c.cmpge(c).all()); assert!(a == a); }); glam_test!(test_extend_truncate, { let a = $new(1 as $t, 2 as $t, 3 as $t); let b = a.extend(4 as $t); assert_eq!((1 as $t, 2 as $t, 3 as $t, 4 as $t), b.into()); let c = $vec3::from(b.truncate()); assert_eq!(a, c); }); glam_test!(test_select, { let a = $vec3::new(1 as $t, 2 as $t, 3 as $t); let b = $vec3::new(4 as $t, 5 as $t, 6 as $t); assert_eq!( $vec3::select($mask::new(true, true, true), a, b), $vec3::new(1 as $t, 2 as $t, 3 as $t), ); assert_eq!( $vec3::select($mask::new(true, false, true), a, b), $vec3::new(1 as $t, 5 as $t, 3 as $t), ); assert_eq!( $vec3::select($mask::new(false, true, false), a, b), $vec3::new(4 as $t, 2 as $t, 6 as $t), ); assert_eq!( $vec3::select($mask::new(false, false, false), a, b), $vec3::new(4 as $t, 5 as $t, 6 as $t), ); }); glam_test!(test_to_from_slice, { let v = $vec3::new(1 as $t, 2 as $t, 3 as $t); let mut a = [0 as $t, 0 as $t, 0 as $t]; v.write_to_slice(&mut a); assert_eq!(v, $vec3::from_slice(&a)); let mut a = [0 as $t; 17]; v.write_to_slice(&mut a); assert_eq!(v, $vec3::from_slice(&a[..3])); assert_eq!([0 as $t; 14], a[3..]); should_panic!({ $vec3::ONE.write_to_slice(&mut [0 as $t; 2]) }); should_panic!({ $vec3::from_slice(&[0 as $t; 2]) }); }); glam_test!(test_sum, { let one = $vec3::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!([two, two].iter().product::<$vec3>(), two * two); assert_eq!([two, two].into_iter().product::<$vec3>(), two * two); }); }; } macro_rules! impl_vec3_signed_tests { ($t:ident, $new:ident, $vec3:ident, $mask:ident) => { impl_vec3_tests!($t, $new, $vec3, $mask); glam_test!(test_neg, { let a = $new(1 as $t, 2 as $t, 3 as $t); assert_eq!((-1 as $t, -2 as $t, -3 as $t), (-a).into()); assert_eq!( $new(-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) ); assert_eq!( $new(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) ); }); glam_test!(test_neg_propagation, { let a = $new(1 as $t, 2 as $t, 3 as $t); assert_eq!(-a, -(&a)); }); 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); let z = $new(0 as $t, 0 as $t, 1 as $t); assert_eq!(1 as $t, x.dot(x)); 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); }); glam_test!(test_checked_add, { assert_eq!($vec3::MAX.checked_add($vec3::ONE), None); assert_eq!($vec3::MAX.checked_add($vec3::X), None); assert_eq!($vec3::MAX.checked_add($vec3::Y), None); assert_eq!($vec3::MAX.checked_add($vec3::Z), None); assert_eq!($vec3::MAX.checked_add($vec3::ZERO), Some($vec3::MAX)); }); glam_test!(test_checked_sub, { assert_eq!($vec3::MIN.checked_sub($vec3::ONE), None); assert_eq!($vec3::MIN.checked_sub($vec3::X), None); assert_eq!($vec3::MIN.checked_sub($vec3::Y), None); assert_eq!($vec3::MIN.checked_sub($vec3::Z), None); assert_eq!($vec3::MIN.checked_sub($vec3::ZERO), Some($vec3::MIN)); }); glam_test!(test_checked_mul, { assert_eq!($vec3::MIN.checked_mul($vec3::MIN), None); assert_eq!($vec3::MAX.checked_mul($vec3::MIN), None); assert_eq!($vec3::MIN.checked_mul($vec3::MAX), None); assert_eq!($vec3::MAX.checked_mul($vec3::MAX), None); assert_eq!($vec3::ZERO.checked_mul($vec3::MIN), Some($vec3::ZERO)); assert_eq!($vec3::MAX.checked_mul($vec3::ZERO), Some($vec3::ZERO)); assert_eq!($vec3::MIN.checked_mul($vec3::ONE), Some($vec3::MIN)); assert_eq!($vec3::MAX.checked_mul($vec3::ONE), Some($vec3::MAX)); assert_eq!($vec3::ZERO.checked_mul($vec3::ZERO), Some($vec3::ZERO)); assert_eq!($vec3::ONE.checked_mul($vec3::ONE), Some($vec3::ONE)); }); glam_test!(test_checked_div, { assert_eq!($vec3::MIN.checked_div($vec3::ZERO), None); assert_eq!($vec3::MAX.checked_div($vec3::ZERO), None); assert_eq!($vec3::MAX.checked_div($vec3::X), None); assert_eq!($vec3::MAX.checked_div($vec3::Y), None); assert_eq!($vec3::MAX.checked_div($vec3::Z), None); assert_eq!($vec3::ZERO.checked_div($vec3::ONE), Some($vec3::ZERO)); assert_eq!($vec3::MIN.checked_div($vec3::ONE), Some($vec3::MIN)); assert_eq!($vec3::MAX.checked_div($vec3::ONE), Some($vec3::MAX)); }); glam_test!(test_manhattan_distance, { assert_eq!( $vec3::new(3, 27, 98).manhattan_distance($vec3::new(20, 65, 97)), 56 ); assert_eq!( $vec3::new(8, 12, 12).manhattan_distance($vec3::new(24, 56, 2)), 70 ); assert_eq!( $vec3::new(-23, 2, -99).manhattan_distance($vec3::new(22, -12, 24)), 182 ); assert_eq!( $vec3::new(3, 27, 98).checked_manhattan_distance($vec3::new(20, 65, 97)), Some(56) ); assert_eq!( $vec3::new(8, 12, 12).checked_manhattan_distance($vec3::new(24, 56, 2)), Some(70) ); assert_eq!( $vec3::new(-23, 2, -99).checked_manhattan_distance($vec3::new(22, -12, 24)), Some(182) ); assert_eq!( $vec3::new($t::MIN, $t::MIN, $t::MIN).checked_manhattan_distance($vec3::new( $t::MAX, $t::MAX, $t::MAX )), None ); }); glam_test!(test_chebyshev_distance, { assert_eq!( $vec3::new(3, 27, 98).chebyshev_distance($vec3::new(20, 65, 97)), 38 ); assert_eq!( $vec3::new(8, 12, 12).chebyshev_distance($vec3::new(24, 56, 2)), 44 ); assert_eq!( $vec3::new(-23, 2, -99).chebyshev_distance($vec3::new(22, -12, 24)), 123 ); }); }; } macro_rules! impl_vec3_unsigned_integer_tests { ($t:ident, $new:ident, $vec3:ident, $mask:ident) => { impl_vec3_tests!($t, $new, $vec3, $mask); glam_test!(test_checked_add, { assert_eq!($vec3::MAX.checked_add($vec3::ONE), None); assert_eq!($vec3::MAX.checked_add($vec3::X), None); assert_eq!($vec3::MAX.checked_add($vec3::Y), None); assert_eq!($vec3::MAX.checked_add($vec3::Z), None); assert_eq!($vec3::MAX.checked_add($vec3::ZERO), Some($vec3::MAX)); }); glam_test!(test_checked_sub, { assert_eq!($vec3::ZERO.checked_sub($vec3::ONE), None); assert_eq!($vec3::ZERO.checked_sub($vec3::X), None); assert_eq!($vec3::ZERO.checked_sub($vec3::Y), None); assert_eq!($vec3::ZERO.checked_sub($vec3::Z), None); assert_eq!($vec3::ZERO.checked_sub($vec3::ZERO), Some($vec3::MIN)); }); glam_test!(test_checked_mul, { assert_eq!($vec3::MAX.checked_mul($vec3::MAX), None); assert_eq!($vec3::MAX.checked_mul($vec3::ZERO), Some($vec3::ZERO)); assert_eq!($vec3::MAX.checked_mul($vec3::ONE), Some($vec3::MAX)); assert_eq!($vec3::ZERO.checked_mul($vec3::ZERO), Some($vec3::ZERO)); assert_eq!($vec3::ONE.checked_mul($vec3::ONE), Some($vec3::ONE)); }); glam_test!(test_checked_div, { assert_eq!($vec3::MAX.checked_div($vec3::ZERO), None); assert_eq!($vec3::MAX.checked_div($vec3::X), None); assert_eq!($vec3::MAX.checked_div($vec3::Y), None); assert_eq!($vec3::MAX.checked_div($vec3::Z), None); assert_eq!($vec3::ZERO.checked_div($vec3::ONE), Some($vec3::ZERO)); assert_eq!($vec3::MAX.checked_div($vec3::ONE), Some($vec3::MAX)); }); glam_test!(test_manhattan_distance, { assert_eq!( $vec3::new(3, 27, 98).manhattan_distance($vec3::new(20, 65, 97)), 56 ); assert_eq!( $vec3::new(8, 12, 12).manhattan_distance($vec3::new(24, 56, 2)), 70 ); assert_eq!( $vec3::new(3, 27, 98).checked_manhattan_distance($vec3::new(20, 65, 97)), Some(56) ); assert_eq!( $vec3::new(8, 12, 12).checked_manhattan_distance($vec3::new(24, 56, 2)), Some(70) ); assert_eq!( $vec3::new($t::MIN, $t::MIN, $t::MIN).checked_manhattan_distance($vec3::new( $t::MAX, $t::MAX, $t::MAX )), None ); }); glam_test!(test_chebyshev_distance, { assert_eq!( $vec3::new(3, 27, 98).chebyshev_distance($vec3::new(20, 65, 97)), 38 ); assert_eq!( $vec3::new(8, 12, 12).chebyshev_distance($vec3::new(24, 56, 2)), 44 ); }); }; } macro_rules! impl_vec3_eq_hash_tests { ($t:ident, $new:ident) => { glam_test!(test_vec3_hash, { use std::collections::hash_map::DefaultHasher; use std::hash::Hash; use std::hash::Hasher; let a = $new(1 as $t, 2 as $t, 3 as $t); let b = $new(1 as $t, 2 as $t, 3 as $t); let c = $new(3 as $t, 2 as $t, 1 as $t); let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); let a_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); b.hash(&mut hasher); let b_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); c.hash(&mut hasher); let c_hashed = hasher.finish(); assert_eq!(a, b); assert_eq!(a_hashed, b_hashed); assert_ne!(a, c); assert_ne!(a_hashed, c_hashed); }); }; } macro_rules! impl_vec3_float_tests { ($t:ident, $new:ident, $vec3:ident, $mask:ident) => { impl_vec3_signed_tests!($t, $new, $vec3, $mask); impl_vec_float_normalize_tests!($t, $vec3); glam_test!(test_nan, { assert!($vec3::NAN.is_nan()); assert!(!$vec3::NAN.is_finite()); }); glam_test!(test_funcs, { let x = $new(1.0, 0.0, 0.0); let y = $new(0.0, 1.0, 0.0); let z = $new(0.0, 0.0, 1.0); assert_eq!(y, z.cross(x)); assert_eq!(z, x.cross(y)); 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 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)); assert_eq!(x, (2.0 * x).normalize()); assert_eq!( 1.0 * 4.0 + 2.0 * 5.0 + 3.0 * 6.0, $new(1.0, 2.0, 3.0).dot($new(4.0, 5.0, 6.0)) ); 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() ); assert_eq!( 1.0 / (2.0 as $t * 2.0 + 3.0 * 3.0 + 4.0 * 4.0).sqrt(), $new(2.0, 3.0, 4.0).length_recip() ); assert!($new(2.0, 3.0, 4.0).normalize().is_normalized()); assert_approx_eq!( $new(2.0, 3.0, 4.0) / (2.0 as $t * 2.0 + 3.0 * 3.0 + 4.0 * 4.0).sqrt(), $new(2.0, 3.0, 4.0).normalize() ); assert_eq!($new(0.5, 0.25, 0.125), $new(2.0, 4.0, 8.0).recip()); }); glam_test!(test_project_reject, { assert_eq!( $new(0.0, 0.0, 1.0), $new(1.0, 0.0, 1.0).project_onto($new(0.0, 0.0, 2.0)) ); assert_eq!( $new(1.0, 0.0, 0.0), $new(1.0, 0.0, 1.0).reject_from($new(0.0, 0.0, 2.0)) ); assert_eq!( $new(0.0, 0.0, 1.0), $new(1.0, 0.0, 1.0).project_onto_normalized($new(0.0, 0.0, 1.0)) ); assert_eq!( $new(1.0, 0.0, 0.0), $new(1.0, 0.0, 1.0).reject_from_normalized($new(0.0, 0.0, 1.0)) ); should_glam_assert!({ $vec3::ONE.project_onto($vec3::ZERO) }); should_glam_assert!({ $vec3::ONE.reject_from($vec3::ZERO) }); should_glam_assert!({ $vec3::ONE.project_onto_normalized($vec3::ONE) }); should_glam_assert!({ $vec3::ONE.reject_from_normalized($vec3::ONE) }); }); glam_test!(test_signum, { assert_eq!($vec3::ZERO.signum(), $vec3::ONE); assert_eq!((-$vec3::ZERO).signum(), -$vec3::ONE); assert_eq!($vec3::ONE.signum(), $vec3::ONE); assert_eq!((-$vec3::ONE).signum(), -$vec3::ONE); 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, { assert_eq!($vec3::ZERO.copysign(-$vec3::ZERO), -$vec3::ZERO); assert_eq!((-$vec3::ZERO).copysign(-$vec3::ZERO), -$vec3::ZERO); assert_eq!($vec3::ZERO.copysign($vec3::ZERO), $vec3::ZERO); assert_eq!((-$vec3::ZERO).copysign($vec3::ZERO), $vec3::ZERO); assert_eq!($vec3::ONE.copysign(-$vec3::ZERO), -$vec3::ONE); assert_eq!((-$vec3::ONE).copysign(-$vec3::ZERO), -$vec3::ONE); assert_eq!($vec3::ONE.copysign($vec3::ZERO), $vec3::ONE); assert_eq!((-$vec3::ONE).copysign($vec3::ZERO), $vec3::ONE); assert_eq!($vec3::ZERO.copysign(-$vec3::ONE), -$vec3::ZERO); assert_eq!((-$vec3::ZERO).copysign(-$vec3::ONE), -$vec3::ZERO); assert_eq!($vec3::ZERO.copysign($vec3::ONE), $vec3::ZERO); assert_eq!((-$vec3::ZERO).copysign($vec3::ONE), $vec3::ZERO); 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::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::NEG_INFINITY.copysign(-$vec3::ONE), $vec3::NEG_INFINITY ); assert!($vec3::NAN.copysign($vec3::ONE).is_nan_mask().all()); assert!($vec3::NAN.copysign(-$vec3::ONE).is_nan_mask().all()); }); 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(-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, { assert_eq!($vec3::new(1.35, 0.0, 0.0).round().x, 1.0); assert_eq!($vec3::new(0.0, 1.5, 0.0).round().y, 2.0); assert_eq!($vec3::new(0.0, 0.0, -15.5).round().z, -16.0); assert_eq!($vec3::new(0.0, 0.0, 0.0).round().z, 0.0); assert_eq!($vec3::new(0.0, 21.1, 0.0).round().y, 21.0); assert_eq!($vec3::new(0.0, 11.123, 0.0).round().y, 11.0); assert_eq!($vec3::new(0.0, 11.499, 0.0).round().y, 11.0); assert_eq!( $vec3::new($t::NEG_INFINITY, $t::INFINITY, 0.0).round(), $vec3::new($t::NEG_INFINITY, $t::INFINITY, 0.0) ); assert!($vec3::new($t::NAN, 0.0, 0.0).round().x.is_nan()); }); glam_test!(test_floor, { assert_eq!( $vec3::new(1.35, 1.5, -1.5).floor(), $vec3::new(1.0, 1.0, -2.0) ); assert_eq!( $vec3::new($t::INFINITY, $t::NEG_INFINITY, 0.0).floor(), $vec3::new($t::INFINITY, $t::NEG_INFINITY, 0.0) ); assert!($vec3::new($t::NAN, 0.0, 0.0).floor().x.is_nan()); assert_eq!( $vec3::new(-2000000.123, 10000000.123, 1000.9).floor(), $vec3::new(-2000001.0, 10000000.0, 1000.0) ); }); glam_test!(test_fract_gl, { assert_approx_eq!( $vec3::new(1.35, 1.5, -1.5).fract_gl(), $vec3::new(0.35, 0.5, 0.5) ); assert_approx_eq!( $vec3::new(-200000.123, 1000000.123, 1000.9).fract_gl(), $vec3::new(0.877, 0.123, 0.9), 0.002 ); }); glam_test!(test_fract, { assert_approx_eq!( $vec3::new(1.35, 1.5, -1.5).fract(), $vec3::new(0.35, 0.5, -0.5) ); assert_approx_eq!( $vec3::new(-200000.123, 1000000.123, 1000.9).fract(), $vec3::new(-0.123, 0.123, 0.9), 0.002 ); }); glam_test!(test_ceil, { assert_eq!( $vec3::new(1.35, 1.5, -1.5).ceil(), $vec3::new(2.0, 2.0, -1.0) ); assert_eq!( $vec3::new($t::INFINITY, $t::NEG_INFINITY, 0.0).ceil(), $vec3::new($t::INFINITY, $t::NEG_INFINITY, 0.0) ); assert!($vec3::new($t::NAN, 0.0, 0.0).ceil().x.is_nan()); assert_eq!( $vec3::new(-2000000.123, 1000000.123, 1000.9).ceil(), $vec3::new(-2000000.0, 1000001.0, 1001.0) ); }); 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($t::INFINITY, $t::NEG_INFINITY, 0.0).trunc(), $vec3::new($t::INFINITY, $t::NEG_INFINITY, 0.0) ); assert!($vec3::new(0.0, $t::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); assert_approx_eq!(v0, v0.lerp(v1, 0.0)); assert_approx_eq!(v1, v0.lerp(v1, 1.0)); assert_approx_eq!($vec3::ZERO, v0.lerp(v1, 0.5)); }); glam_test!(test_lerp_big_difference, { let v0 = $vec3::new(-1e30, -1e30, -1e30); let v1 = $vec3::new(16.0, 16.0, 16.0); assert_approx_eq!(v0, v0.lerp(v1, 0.0)); assert_approx_eq!(v1, v0.lerp(v1, 1.0)); }); glam_test!(test_slerp, { let v0 = $vec3::new(1.0, 2.0, 3.0); let v1 = $vec3::new(4.0, 5.0, 6.0); assert_approx_eq!(v0.slerp(v1, 0.0), v0); assert_approx_eq!(v0.slerp(v1, 1.0), v1); assert_approx_eq!( v0.slerp(v1, 0.5).length(), (v0.length() + v1.length()) / 2., 5e-7 ); assert_approx_eq!( v0.angle_between(v0.slerp(v1, 0.5)) * 2.0, v0.angle_between(v1) ); assert_approx_eq!( $vec3::new(5.0, 0.0, 0.0).slerp($vec3::new(0.0, 5.0, 0.0), 0.5), $vec3::new(5.0, 5.0, 0.0) * std::$t::consts::FRAC_1_SQRT_2 ); }); glam_test!(test_slerp_extrapolate, { let v0 = $vec3::Y; let v1 = $vec3::X; // Normalized assert_approx_eq!(v0.slerp(v1, -1.0), $vec3::NEG_X, 2e-7); assert_approx_eq!(v0.slerp(v1, 2.0), $vec3::NEG_Y, 2e-7); // Scaled assert_approx_eq!(v0.slerp(v1 * 1.5, -1.0), $vec3::NEG_X * 0.5); assert_approx_eq!(v0.slerp(v1 * 1.5, 2.0), $vec3::NEG_Y * 2.0, 4e-7); }); glam_test!(test_slerp_parallel, { // Same direction assert_approx_eq!($vec3::ONE.slerp($vec3::splat(2.), 0.5), $vec3::splat(1.5)); assert_approx_eq!($vec3::splat(2.).slerp($vec3::ONE, 0.5), $vec3::splat(1.5)); // Opposite direction assert_approx_eq!($vec3::Y.slerp($vec3::NEG_Y, 0.5), $vec3::X); assert_approx_eq!(($vec3::Y * 1.5).slerp($vec3::NEG_Y * 0.5, 0.5), $vec3::X); assert_approx_eq!(($vec3::Y * 0.5).slerp($vec3::NEG_Y * 1.5, 0.5), $vec3::X); }); glam_test!(test_slerp_zero_length, { assert_approx_eq!($vec3::ZERO.slerp($vec3::ZERO, 0.5), $vec3::ZERO); assert_approx_eq!($vec3::ZERO.slerp($vec3::ONE, 0.5), $vec3::splat(0.5)); assert_approx_eq!($vec3::ONE.slerp($vec3::ZERO, 0.5), $vec3::splat(0.5)); }); glam_test!(test_move_towards, { let v0 = $vec3::new(-1.0, -1.0, -1.0); let v1 = $vec3::new(1.0, 1.0, 1.0); assert_approx_eq!(v0, v0.move_towards(v1, 0.0)); assert_approx_eq!(v1, v0.move_towards(v1, v0.distance(v1))); assert_approx_eq!(v1, v0.move_towards(v1, v0.distance(v1) + 1.0)); }); glam_test!(test_rotate_towards, { use core::$t::consts::PI; // Self assert_approx_eq!($vec3::X, $vec3::X.rotate_towards($vec3::X, PI / 2.)); assert_approx_eq!( $vec3::Y * 2.0, ($vec3::Y * 2.0).rotate_towards($vec3::Y, PI / 2.) ); assert_approx_eq!($vec3::Z, $vec3::Z.rotate_towards($vec3::Z, PI / 2.)); // Positive angle assert_approx_eq!($vec3::X, $vec3::X.rotate_towards($vec3::NEG_Y, 0.0)); assert_approx_eq!( $vec3::new($t::sqrt(2.0) / 2.0, -$t::sqrt(2.0) / 2.0, 0.0), $vec3::X.rotate_towards($vec3::NEG_Y, PI / 4.) ); assert_approx_eq!( $vec3::new($t::sqrt(2.0) / 2.0, 0.0, $t::sqrt(2.0) / 2.0), $vec3::X.rotate_towards($vec3::Z, PI / 4.) ); assert_approx_eq!($vec3::NEG_Y, $vec3::X.rotate_towards($vec3::NEG_Y, PI / 2.)); assert_approx_eq!($vec3::NEG_Y, $vec3::X.rotate_towards($vec3::NEG_Y, PI)); // Negative angle assert_approx_eq!( $vec3::new($t::sqrt(2.0) / 2.0, $t::sqrt(2.0) / 2.0, 0.0), $vec3::X.rotate_towards($vec3::NEG_Y, -PI / 4.) ); assert_approx_eq!($vec3::Y, $vec3::X.rotate_towards($vec3::NEG_Y, -PI / 2.)); assert_approx_eq!($vec3::Y, $vec3::X.rotate_towards($vec3::NEG_Y, -PI), 2e-7); // Not normalized assert_approx_eq!( $vec3::NEG_Y * 2., ($vec3::X * 2.).rotate_towards($vec3::NEG_Y, PI / 2.), 2e-7 ); assert_approx_eq!( $vec3::NEG_Y, $vec3::X.rotate_towards($vec3::NEG_Y * 2., PI / 2.) ); // Parallel assert_approx_eq!($vec3::Y, $vec3::X.rotate_towards($vec3::NEG_X, PI / 2.)); }); glam_test!(test_midpoint, { let v0 = $vec3::new(-1.0, -1.0, -1.0); let v1 = $vec3::new(1.0, 1.0, 1.0); let v2 = $vec3::new(-1.5, 0.0, 1.0); assert_approx_eq!($vec3::ZERO, v0.midpoint(v1)); assert_approx_eq!($vec3::new(-0.25, 0.5, 1.0), v1.midpoint(v2)); }); glam_test!(test_is_finite, { assert!($vec3::new(0.0, 0.0, 0.0).is_finite()); assert!($vec3::new(-1e-10, 1.0, 1e10).is_finite()); assert!(!$vec3::new($t::INFINITY, 0.0, 0.0).is_finite()); assert!(!$vec3::new(0.0, $t::NAN, 0.0).is_finite()); assert!(!$vec3::new(0.0, 0.0, $t::NEG_INFINITY).is_finite()); assert!(!$vec3::NAN.is_finite()); assert!(!$vec3::INFINITY.is_finite()); assert!(!$vec3::NEG_INFINITY.is_finite()); }); glam_test!(test_powf, { assert_eq!( $vec3::new(2.0, 4.0, 8.0).powf(2.0), $vec3::new(4.0, 16.0, 64.0) ); }); glam_test!(test_exp, { assert_approx_eq!( $vec3::new(1.0, 2.0, 3.0).exp(), $vec3::new((1.0 as $t).exp(), (2.0 as $t).exp(), (3.0 as $t).exp()) ); }); glam_test!(test_angle_between, { let angle = $vec3::new(1.0, 0.0, 1.0).angle_between($vec3::new(1.0, 1.0, 0.0)); assert_approx_eq!(core::$t::consts::FRAC_PI_3, angle, 1e-6); let angle = $vec3::new(10.0, 0.0, 10.0).angle_between($vec3::new(5.0, 5.0, 0.0)); assert_approx_eq!(core::$t::consts::FRAC_PI_3, angle, 1e-6); let angle = $vec3::new(-1.0, 0.0, -1.0).angle_between($vec3::new(1.0, -1.0, 0.0)); assert_approx_eq!(2.0 * core::$t::consts::FRAC_PI_3, angle, 1e-6); }); glam_test!(test_clamp_length, { // Too long gets shortened assert_eq!( $vec3::new(12.0, 16.0, 0.0).clamp_length(7.0, 10.0), $vec3::new(6.0, 8.0, 0.0) // shortened to length 10.0 ); // In the middle is unchanged assert_eq!( $vec3::new(2.0, 1.0, 0.0).clamp_length(0.5, 5.0), $vec3::new(2.0, 1.0, 0.0) // unchanged ); // Too short gets lengthened assert_eq!( $vec3::new(0.6, 0.8, 0.0).clamp_length(10.0, 20.0), $vec3::new(6.0, 8.0, 0.0) // lengthened to length 10.0 ); should_glam_assert!({ $vec3::ONE.clamp_length(1.0, 0.0) }); }); glam_test!(test_clamp_length_max, { // Too long gets shortened assert_eq!( $vec3::new(12.0, 16.0, 0.0).clamp_length_max(10.0), $vec3::new(6.0, 8.0, 0.0) // shortened to length 10.0 ); // Not too long is unchanged assert_eq!( $vec3::new(2.0, 1.0, 0.0).clamp_length_max(5.0), $vec3::new(2.0, 1.0, 0.0) // unchanged ); }); glam_test!(test_clamp_length_min, { // Not too short is unchanged assert_eq!( $vec3::new(2.0, 1.0, 0.0).clamp_length_min(0.5), $vec3::new(2.0, 1.0, 0.0) // unchanged ); // Too short gets lengthened assert_eq!( $vec3::new(0.6, 0.8, 0.0).clamp_length_min(10.0), $vec3::new(6.0, 8.0, 0.0) // lengthened to length 10.0 ); }); glam_test!(test_any_ortho, { let eps = 2.0 * $t::EPSILON; for &v in &vec3_float_test_vectors!($vec3) { let orthogonal = v.any_orthogonal_vector(); assert!(orthogonal != $vec3::ZERO && orthogonal.is_finite()); assert!(v.dot(orthogonal).abs() < eps); let n = v.normalize(); let orthonormal = n.any_orthonormal_vector(); assert!(orthonormal.is_normalized()); assert!(n.dot(orthonormal).abs() < eps); let (a, b) = n.any_orthonormal_pair(); assert!(a.is_normalized() && n.dot(a).abs() < eps); assert!(b.is_normalized() && n.dot(b).abs() < eps); } }); glam_test!(test_mul_add, { assert_eq!( $vec3::new(1.0, 1.0, 1.0) .mul_add($vec3::new(0.5, 2.0, -4.0), $vec3::new(-1.0, -1.0, -1.0)), $vec3::new(-0.5, 1.0, -5.0) ); }); glam_test!(test_fmt_float, { let a = $vec3::new(1.0, 2.0, 3.0); assert_eq!(format!("{:.2}", a), "[1.00, 2.00, 3.00]"); }); glam_test!(test_reflect, { let incident = $vec3::new(1.0, -1.0, 1.0); let normal = $vec3::Y; assert_approx_eq!(incident.reflect(normal), $vec3::ONE); }); glam_test!(test_refract, { let incident = $vec3::NEG_ONE.normalize(); let normal = $vec3::ONE.normalize(); assert_approx_eq!(incident.refract(normal, 0.5), incident); let incident = $vec3::new(1.0, -1.0, 0.0).normalize(); let normal = $vec3::Y; assert_approx_eq!(incident.refract(normal, 1.5), $vec3::ZERO); }); }; } macro_rules! impl_vec3_scalar_shift_op_test { ($vec3:ident, $t_min:literal, $t_max:literal, $rhs_min:literal, $rhs_max:literal) => { glam_test!(test_vec3_scalar_shift_ops, { for x in $t_min..$t_max { for y in $t_min..$t_max { for z in $t_min..$t_max { for rhs in $rhs_min..$rhs_max { assert_eq!( $vec3::new(x, y, z) << rhs, $vec3::new(x << rhs, y << rhs, z << rhs) ); assert_eq!( $vec3::new(x, y, z) >> rhs, $vec3::new(x >> rhs, y >> rhs, z >> rhs) ); } } } } }); }; } macro_rules! impl_vec3_scalar_shift_op_tests { ($vec3:ident, $t_min:literal, $t_max:literal) => { mod shift_by_i8 { use glam::$vec3; impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0i8, 2); } mod shift_by_i16 { use glam::$vec3; impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0i16, 2); } mod shift_by_i32 { 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); } mod shift_by_u16 { use glam::$vec3; impl_vec3_scalar_shift_op_test!($vec3, $t_min, $t_max, 0u16, 2); } mod shift_by_u32 { 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); } }; } macro_rules! impl_vec3_shift_op_test { ($vec3:ident, $rhs:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec3_shift_ops, { for x1 in $t_min..$t_max { for y1 in $t_min..$t_max { for z1 in $t_min..$t_max { for x2 in $t_min..$t_max { for y2 in $t_min..$t_max { for z2 in $t_min..$t_max { assert_eq!( $vec3::new(x1, y1, z1) << $rhs::new(x2, y2, z2), $vec3::new(x1 << x2, y1 << y2, z1 << z2) ); assert_eq!( $vec3::new(x1, y1, z1) >> $rhs::new(x2, y2, z2), $vec3::new(x1 >> x2, y1 >> y2, z1 >> z2) ); } } } } } } }); }; } macro_rules! impl_vec3_shift_op_tests { ($vec3:ident) => { mod shift_ivec3_by_ivec3 { use super::*; impl_vec3_shift_op_test!($vec3, IVec3, 0, 2); } mod shift_ivec3_by_uvec3 { use super::*; impl_vec3_shift_op_test!($vec3, UVec3, 0, 2); } }; } macro_rules! impl_vec3_scalar_bit_op_tests { ($vec3:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec3_scalar_bit_ops, { for x in $t_min..$t_max { for y in $t_min..$t_max { for z in $t_min..$t_max { for rhs in $t_min..$t_max { assert_eq!( $vec3::new(x, y, z) & rhs, $vec3::new(x & rhs, y & rhs, z & rhs) ); assert_eq!( $vec3::new(x, y, z) | rhs, $vec3::new(x | rhs, y | rhs, z | rhs) ); assert_eq!( $vec3::new(x, y, z) ^ rhs, $vec3::new(x ^ rhs, y ^ rhs, z ^ rhs) ); } } } } }); }; } macro_rules! impl_vec3_bit_op_tests { ($vec3:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec3_bit_ops, { for x1 in $t_min..$t_max { for y1 in $t_min..$t_max { for z1 in $t_min..$t_max { assert_eq!(!$vec3::new(x1, y1, z1), $vec3::new(!x1, !y1, !z1)); for x2 in $t_min..$t_max { for y2 in $t_min..$t_max { for z2 in $t_min..$t_max { assert_eq!( $vec3::new(x1, y1, z1) & $vec3::new(x2, y2, z2), $vec3::new(x1 & x2, y1 & y2, z1 & z2) ); assert_eq!( $vec3::new(x1, y1, z1) | $vec3::new(x2, y2, z2), $vec3::new(x1 | x2, y1 | y2, z1 | z2) ); assert_eq!( $vec3::new(x1, y1, z1) ^ $vec3::new(x2, y2, z2), $vec3::new(x1 ^ x2, y1 ^ y2, z1 ^ z2) ); } } } } } } }); }; } mod bvec3 { use glam::{bvec3, BVec3}; glam_test!(test_mask_align, { use std::mem; assert_eq!(3, mem::size_of::()); assert_eq!(1, mem::align_of::()); }); impl_bvec3_tests!(BVec3, bvec3); } mod bvec3a { use glam::{bvec3a, BVec3A}; glam_test!(test_mask_align, { use std::mem; assert_eq!(16, mem::size_of::()); assert_eq!(16, mem::align_of::()); }); impl_bvec3_tests!(BVec3A, bvec3a); } mod vec3 { use glam::{vec3, BVec3, Vec3}; glam_test!(test_align, { use std::mem; assert_eq!(12, mem::size_of::()); assert_eq!(4, mem::align_of::()); }); glam_test!(test_as, { use glam::{ DVec3, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, Vec3A, }; assert_eq!( DVec3::new(-1.0, -2.0, -3.0), Vec3::new(-1.0, -2.0, -3.0).as_dvec3() ); assert_eq!( I8Vec3::new(-1, -2, -3), Vec3::new(-1.0, -2.0, -3.0).as_i8vec3() ); assert_eq!(U8Vec3::new(1, 2, 3), Vec3::new(1.0, 2.0, 3.0).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), Vec3::new(1.0, 2.0, 3.0).as_usizevec3() ); assert_eq!( DVec3::new(-1.0, -2.0, -3.0), Vec3A::new(-1.0, -2.0, -3.0).as_dvec3() ); assert_eq!( I8Vec3::new(-1, -2, -3), Vec3A::new(-1.0, -2.0, -3.0).as_i8vec3() ); assert_eq!(U8Vec3::new(1, 2, 3), Vec3A::new(1.0, 2.0, 3.0).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), Vec3A::new(1.0, 2.0, 3.0).as_usizevec3() ); assert_eq!( I8Vec3::new(-1, -2, -3), DVec3::new(-1.0, -2.0, -3.0).as_i8vec3() ); assert_eq!(U8Vec3::new(1, 2, 3), DVec3::new(1.0, 2.0, 3.0).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), DVec3::new(1.0, 2.0, 3.0).as_usizevec3() ); assert_eq!( Vec3::new(-1.0, -2.0, -3.0), DVec3::new(-1.0, -2.0, -3.0).as_vec3() ); assert_eq!( Vec3A::new(-1.0, -2.0, -3.0), DVec3::new(-1.0, -2.0, -3.0).as_vec3a() ); assert_eq!( DVec3::new(-1.0, -2.0, -3.0), I8Vec3::new(-1, -2, -3).as_dvec3() ); assert_eq!(U8Vec3::new(1, 2, 3), I8Vec3::new(1, 2, 3).as_u8vec3()); assert_eq!( I16Vec3::new(-1, -2, -3), I8Vec3::new(-1, -2, -3).as_i16vec3() ); assert_eq!(U16Vec3::new(1, 2, 3), I8Vec3::new(1, 2, 3).as_u16vec3()); assert_eq!(IVec3::new(-1, -2, -3), I8Vec3::new(-1, -2, -3).as_ivec3()); assert_eq!(UVec3::new(1, 2, 3), I8Vec3::new(1, 2, 3).as_uvec3()); assert_eq!( I64Vec3::new(-1, -2, -3), I8Vec3::new(-1, -2, -3).as_i64vec3() ); assert_eq!(U64Vec3::new(1, 2, 3), I8Vec3::new(1, 2, 3).as_u64vec3()); assert_eq!(USizeVec3::new(1, 2, 3), I8Vec3::new(1, 2, 3).as_usizevec3()); assert_eq!( Vec3::new(-1.0, -2.0, -3.0), I8Vec3::new(-1, -2, -3).as_vec3() ); assert_eq!( Vec3A::new(-1.0, -2.0, -3.0), I8Vec3::new(-1, -2, -3).as_vec3a() ); assert_eq!(DVec3::new(1.0, 2.0, 3.0), U8Vec3::new(1, 2, 3).as_dvec3()); assert_eq!(I8Vec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_i8vec3()); assert_eq!(I16Vec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_i16vec3()); assert_eq!(U16Vec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_u16vec3()); assert_eq!(IVec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_ivec3()); assert_eq!(UVec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_uvec3()); assert_eq!(I64Vec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_i64vec3()); assert_eq!(U64Vec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_u64vec3()); assert_eq!(USizeVec3::new(1, 2, 3), U8Vec3::new(1, 2, 3).as_usizevec3()); assert_eq!(Vec3::new(1.0, 2.0, 3.0), U8Vec3::new(1, 2, 3).as_vec3()); assert_eq!(Vec3A::new(1.0, 2.0, 3.0), U8Vec3::new(1, 2, 3).as_vec3a()); assert_eq!( DVec3::new(-1.0, -2.0, -3.0), I16Vec3::new(-1, -2, -3).as_dvec3() ); assert_eq!( I8Vec3::new(-1, -2, -3), I16Vec3::new(-1, -2, -3).as_i8vec3() ); assert_eq!(U8Vec3::new(1, 2, 3), I16Vec3::new(1, 2, 3).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), I16Vec3::new(1, 2, 3).as_usizevec3() ); 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!(I8Vec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_i8vec3()); assert_eq!(U8Vec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), U16Vec3::new(1, 2, 3).as_usizevec3() ); 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!(I8Vec3::new(-1, -2, -3), IVec3::new(-1, -2, -3).as_i8vec3()); assert_eq!(U8Vec3::new(1, 2, 3), IVec3::new(1, 2, 3).as_u8vec3()); 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!(USizeVec3::new(1, 2, 3), IVec3::new(1, 2, 3).as_usizevec3()); assert_eq!( Vec3::new(-1.0, -2.0, -3.0), IVec3::new(-1, -2, -3).as_vec3() ); assert_eq!( Vec3A::new(-1.0, -2.0, -3.0), IVec3::new(-1, -2, -3).as_vec3a() ); assert_eq!(DVec3::new(1.0, 2.0, 3.0), UVec3::new(1, 2, 3).as_dvec3()); assert_eq!(I8Vec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_i8vec3()); assert_eq!(U8Vec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_u8vec3()); 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!(USizeVec3::new(1, 2, 3), UVec3::new(1, 2, 3).as_usizevec3()); 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!( I8Vec3::new(-1, -2, -3), I64Vec3::new(-1, -2, -3).as_i8vec3() ); assert_eq!(U8Vec3::new(1, 2, 3), I64Vec3::new(1, 2, 3).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), I64Vec3::new(1, 2, 3).as_usizevec3() ); 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!(I8Vec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_i8vec3()); assert_eq!(U8Vec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_u8vec3()); 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!( USizeVec3::new(1, 2, 3), U64Vec3::new(1, 2, 3).as_usizevec3() ); 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()); assert_eq!( DVec3::new(1.0, 2.0, 3.0), USizeVec3::new(1, 2, 3).as_dvec3() ); assert_eq!(I8Vec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_i8vec3()); assert_eq!(U8Vec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_u8vec3()); assert_eq!(I16Vec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_i16vec3()); assert_eq!(U16Vec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_u16vec3()); assert_eq!(IVec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_ivec3()); assert_eq!(UVec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_uvec3()); assert_eq!(I64Vec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_i64vec3()); assert_eq!(U64Vec3::new(1, 2, 3), USizeVec3::new(1, 2, 3).as_u64vec3()); assert_eq!(Vec3::new(1.0, 2.0, 3.0), USizeVec3::new(1, 2, 3).as_vec3()); assert_eq!( Vec3A::new(1.0, 2.0, 3.0), USizeVec3::new(1, 2, 3).as_vec3a() ); }); impl_vec3_float_tests!(f32, vec3, Vec3, BVec3); } mod vec3a { use glam::{vec3a, BVec3A, Vec3A, Vec4}; glam_test!(test_align, { use std::mem; assert_eq!(16, mem::size_of::()); assert_eq!(16, mem::align_of::()); }); glam_test!(test_mask_align16, { // make sure the unused 'w' value doesn't break Vec3Ab behaviour let a = Vec4::ZERO; let mut b = Vec3A::from_vec4(a); b.x = 1.0; b.y = 1.0; b.z = 1.0; assert!(!b.cmpeq(Vec3A::ZERO).any()); assert!(b.cmpeq(Vec3A::splat(1.0)).all()); }); #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] #[test] fn test_m128() { #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C, align(16))] struct F32x3_A16([f32; 3]); let v0 = Vec3A::new(1.0, 2.0, 3.0); let m0: __m128 = v0.into(); let mut a0 = F32x3_A16([0.0, 0.0, 0.0]); unsafe { _mm_store_ps(a0.0.as_mut_ptr(), m0); } assert_eq!([1.0, 2.0, 3.0], a0.0); let v1 = Vec3A::from(m0); assert_eq!(v0, v1); #[repr(C, align(16))] struct U32x3_A16([u32; 3]); let v0 = BVec3A::new(true, false, true); let m0: __m128 = v0.into(); let mut a0 = U32x3_A16([1, 2, 3]); unsafe { _mm_store_ps(a0.0.as_mut_ptr() as *mut f32, m0); } assert_eq!([0xffffffff, 0, 0xffffffff], a0.0); } glam_test!(test_min_max_from_vec4, { // checks that the 4th element is unused. let v1 = Vec3A::from_vec4(Vec4::new(1.0, 2.0, 3.0, 4.0)); assert_eq!(v1.max_element(), 3.0); let v2 = Vec3A::from_vec4(Vec4::new(4.0, 3.0, 2.0, 1.0)); assert_eq!(v2.min_element(), 2.0); }); impl_vec3_float_tests!(f32, vec3a, Vec3A, BVec3A); } mod dvec3 { use glam::{dvec3, BVec3, DVec3, IVec3, UVec3, Vec3}; glam_test!(test_align, { use std::mem; assert_eq!(24, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); 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 i8vec3 { use glam::{ i8vec3, BVec3, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(3, mem::size_of::()); assert_eq!(1, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(U8Vec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(U8Vec3::new(u8::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(U8Vec3::new(1, u8::MAX, 3)).is_err()); assert!(I8Vec3::try_from(U8Vec3::new(1, 2, u8::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(I16Vec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(I16Vec3::new(i16::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(I16Vec3::new(1, i16::MAX, 3)).is_err()); assert!(I8Vec3::try_from(I16Vec3::new(1, 2, i16::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(U16Vec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(U16Vec3::new(u16::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(U16Vec3::new(1, u16::MAX, 3)).is_err()); assert!(I8Vec3::try_from(U16Vec3::new(1, 2, u16::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(IVec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(IVec3::new(i32::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(IVec3::new(1, i32::MAX, 3)).is_err()); assert!(I8Vec3::try_from(IVec3::new(1, 2, i32::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(UVec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(UVec3::new(u32::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(UVec3::new(1, u32::MAX, 3)).is_err()); assert!(I8Vec3::try_from(UVec3::new(1, 2, u32::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(I64Vec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(I64Vec3::new(i64::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(I64Vec3::new(1, i64::MAX, 3)).is_err()); assert!(I8Vec3::try_from(I64Vec3::new(1, 2, i64::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(U64Vec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err()); assert!(I8Vec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err()); assert_eq!( I8Vec3::new(1, 2, 3), I8Vec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); assert!(I8Vec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(I8Vec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(I8Vec3::try_from(USizeVec3::new(1, 2, usize::MAX)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( I8Vec3::new(i8::MAX, 5, i8::MIN).wrapping_add(I8Vec3::new(1, 3, i8::MAX)), I8Vec3::new(i8::MIN, 8, -1), ); }); glam_test!(test_wrapping_sub, { assert_eq!( I8Vec3::new(i8::MAX, 5, i8::MIN).wrapping_sub(I8Vec3::new(1, 3, i8::MAX)), I8Vec3::new(126, 2, 1), ); }); glam_test!(test_wrapping_mul, { assert_eq!( I8Vec3::new(i8::MAX, 5, i8::MIN).wrapping_mul(I8Vec3::new(3, 3, 5)), I8Vec3::new(125, 15, -128) ); }); glam_test!(test_wrapping_div, { assert_eq!( I8Vec3::new(i8::MAX, 5, i8::MIN).wrapping_div(I8Vec3::new(3, 3, 5)), I8Vec3::new(42, 1, -25) ); }); glam_test!(test_saturating_add, { assert_eq!( I8Vec3::new(i8::MAX, i8::MIN, 0).saturating_add(I8Vec3::new(1, -1, 2)), I8Vec3::new(i8::MAX, i8::MIN, 2) ); }); glam_test!(test_saturating_sub, { assert_eq!( I8Vec3::new(i8::MIN, i8::MAX, 0).saturating_sub(I8Vec3::new(1, -1, 2)), I8Vec3::new(i8::MIN, i8::MAX, -2) ); }); glam_test!(test_saturating_mul, { assert_eq!( I8Vec3::new(i8::MAX, i8::MIN, 0).saturating_mul(I8Vec3::new(2, 2, 0)), I8Vec3::new(i8::MAX, i8::MIN, 0) ); }); glam_test!(test_saturating_div, { assert_eq!( I8Vec3::new(i8::MAX, i8::MIN, 0).saturating_div(I8Vec3::new(2, 2, 3)), I8Vec3::new(63, -64, 0) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(I8Vec3::MAX.checked_add_unsigned(U8Vec3::ONE), None); assert_eq!( I8Vec3::NEG_ONE.checked_add_unsigned(U8Vec3::ONE), Some(I8Vec3::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I8Vec3::MIN.checked_sub_unsigned(U8Vec3::ONE), None); assert_eq!( I8Vec3::ZERO.checked_sub_unsigned(U8Vec3::ONE), Some(I8Vec3::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I8Vec3::new(i8::MAX, i8::MAX, i8::MAX).wrapping_add_unsigned(U8Vec3::new(1, 1, 1)), I8Vec3::new(i8::MIN, i8::MIN, i8::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I8Vec3::new(i8::MIN, i8::MIN, i8::MIN).wrapping_sub_unsigned(U8Vec3::new(1, 1, 1)), I8Vec3::new(i8::MAX, i8::MAX, i8::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I8Vec3::new(i8::MAX, i8::MAX, i8::MAX).saturating_add_unsigned(U8Vec3::new(1, 1, 1)), I8Vec3::new(i8::MAX, i8::MAX, i8::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I8Vec3::new(i8::MIN, i8::MIN, i8::MIN).saturating_sub_unsigned(U8Vec3::new(1, 1, 1)), I8Vec3::new(i8::MIN, i8::MIN, i8::MIN) ); }); impl_vec3_signed_integer_tests!(i8, i8vec3, I8Vec3, BVec3); impl_vec3_eq_hash_tests!(i8, i8vec3); impl_vec3_scalar_shift_op_tests!(I8Vec3, -2, 2); impl_vec3_shift_op_tests!(I8Vec3); impl_vec3_scalar_bit_op_tests!(I8Vec3, -2, 2); impl_vec3_bit_op_tests!(I8Vec3, -2, 2); } mod u8vec3 { use glam::{ u8vec3, BVec3, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(3, mem::size_of::()); assert_eq!(1, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(I8Vec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(I8Vec3::new(-1, 2, 3)).is_err()); assert!(U8Vec3::try_from(I8Vec3::new(1, -2, 3)).is_err()); assert!(U8Vec3::try_from(I8Vec3::new(1, 2, -3)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(I16Vec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(I16Vec3::new(-1, 2, 3)).is_err()); assert!(U8Vec3::try_from(I16Vec3::new(1, -2, 3)).is_err()); assert!(U8Vec3::try_from(I16Vec3::new(1, 2, -3)).is_err()); assert!(U8Vec3::try_from(I16Vec3::new(i16::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(I16Vec3::new(1, i16::MAX, 3)).is_err()); assert!(U8Vec3::try_from(I16Vec3::new(1, 2, i16::MAX)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(U16Vec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(U16Vec3::new(u16::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(U16Vec3::new(1, u16::MAX, 3)).is_err()); assert!(U8Vec3::try_from(U16Vec3::new(1, 2, u16::MAX)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(IVec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(IVec3::new(-1, 2, 3)).is_err()); assert!(U8Vec3::try_from(IVec3::new(1, -2, 3)).is_err()); assert!(U8Vec3::try_from(IVec3::new(1, 2, -3)).is_err()); assert!(U8Vec3::try_from(IVec3::new(i32::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(IVec3::new(1, i32::MAX, 3)).is_err()); assert!(U8Vec3::try_from(IVec3::new(1, 2, i32::MAX)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(UVec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(UVec3::new(u32::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(UVec3::new(1, u32::MAX, 3)).is_err()); assert!(U8Vec3::try_from(UVec3::new(1, 2, u32::MAX)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(I64Vec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(I64Vec3::new(-1, 2, 3)).is_err()); assert!(U8Vec3::try_from(I64Vec3::new(1, -2, 3)).is_err()); assert!(U8Vec3::try_from(I64Vec3::new(1, 2, -3)).is_err()); assert!(U8Vec3::try_from(I64Vec3::new(i64::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(I64Vec3::new(1, i64::MAX, 3)).is_err()); assert!(U8Vec3::try_from(I64Vec3::new(1, 2, i64::MAX)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(U64Vec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(U64Vec3::new(u64::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(U64Vec3::new(1, u64::MAX, 3)).is_err()); assert!(U8Vec3::try_from(U64Vec3::new(1, 2, u64::MAX)).is_err()); assert_eq!( U8Vec3::new(1, 2, 3), U8Vec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); assert!(U8Vec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(U8Vec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(U8Vec3::try_from(USizeVec3::new(1, 2, usize::MAX)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( U8Vec3::new(u8::MAX, 5, u8::MAX).wrapping_add(U8Vec3::new(1, 3, u8::MAX)), U8Vec3::new(0, 8, 254), ); }); glam_test!(test_wrapping_sub, { assert_eq!( U8Vec3::new(u8::MAX, 5, u8::MAX - 1).wrapping_sub(U8Vec3::new(1, 3, u8::MAX)), U8Vec3::new(254, 2, 255) ); }); glam_test!(test_wrapping_mul, { assert_eq!( U8Vec3::new(u8::MAX, 5, u8::MAX).wrapping_mul(U8Vec3::new(3, 3, 5)), U8Vec3::new(253, 15, 251) ); }); glam_test!(test_wrapping_div, { assert_eq!( U8Vec3::new(u8::MAX, 5, u8::MAX).wrapping_div(U8Vec3::new(3, 3, 5)), U8Vec3::new(85, 1, 51) ); }); glam_test!(test_saturating_add, { assert_eq!( U8Vec3::new(u8::MAX, u8::MAX, 0).saturating_add(U8Vec3::new(1, u8::MAX, 2)), U8Vec3::new(u8::MAX, u8::MAX, 2) ); }); glam_test!(test_saturating_sub, { assert_eq!( U8Vec3::new(0, u8::MAX, 0).saturating_sub(U8Vec3::new(1, 1, 2)), U8Vec3::new(0, 254, 0) ); }); glam_test!(test_saturating_mul, { assert_eq!( U8Vec3::new(u8::MAX, u8::MAX, 0).saturating_mul(U8Vec3::new(2, u8::MAX, 0)), U8Vec3::new(u8::MAX, u8::MAX, 0) ); }); glam_test!(test_saturating_div, { assert_eq!( U8Vec3::new(u8::MAX, u8::MAX, 0).saturating_div(U8Vec3::new(2, u8::MAX, 3)), U8Vec3::new(127, 1, 0) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U8Vec3::new(u8::MAX, u8::MAX, u8::MAX).wrapping_add_signed(I8Vec3::new(1, 1, 1)), U8Vec3::new(u8::MIN, u8::MIN, u8::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U8Vec3::new(u8::MAX, u8::MAX, u8::MAX).saturating_add_signed(I8Vec3::new(1, 1, 1)), U8Vec3::new(u8::MAX, u8::MAX, u8::MAX) ); }); impl_vec3_unsigned_integer_tests!(u8, u8vec3, U8Vec3, BVec3); impl_vec3_eq_hash_tests!(u8, u8vec3); impl_vec3_scalar_shift_op_tests!(U8Vec3, 0, 2); impl_vec3_shift_op_tests!(U8Vec3); impl_vec3_scalar_bit_op_tests!(U8Vec3, 0, 2); impl_vec3_bit_op_tests!(U8Vec3, 0, 2); } mod i16vec3 { use glam::{ i16vec3, BVec3, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(6, mem::size_of::()); assert_eq!(2, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(I16Vec3::new(1, 2, 3), I16Vec3::from(U8Vec3::new(1, 2, 3))); assert_eq!(I16Vec3::new(1, 2, 3), I16Vec3::from(I8Vec3::new(1, 2, 3))); 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()); assert_eq!( I16Vec3::new(1, 2, 3), I16Vec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); assert!(I16Vec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(I16Vec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(I16Vec3::try_from(USizeVec3::new(1, 2, usize::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) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(I16Vec3::MAX.checked_add_unsigned(U16Vec3::ONE), None); assert_eq!( I16Vec3::NEG_ONE.checked_add_unsigned(U16Vec3::ONE), Some(I16Vec3::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I16Vec3::MIN.checked_sub_unsigned(U16Vec3::ONE), None); assert_eq!( I16Vec3::ZERO.checked_sub_unsigned(U16Vec3::ONE), Some(I16Vec3::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I16Vec3::new(i16::MAX, i16::MAX, i16::MAX).wrapping_add_unsigned(U16Vec3::new(1, 1, 1)), I16Vec3::new(i16::MIN, i16::MIN, i16::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I16Vec3::new(i16::MIN, i16::MIN, i16::MIN).wrapping_sub_unsigned(U16Vec3::new(1, 1, 1)), I16Vec3::new(i16::MAX, i16::MAX, i16::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I16Vec3::new(i16::MAX, i16::MAX, i16::MAX) .saturating_add_unsigned(U16Vec3::new(1, 1, 1)), I16Vec3::new(i16::MAX, i16::MAX, i16::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I16Vec3::new(i16::MIN, i16::MIN, i16::MIN) .saturating_sub_unsigned(U16Vec3::new(1, 1, 1)), I16Vec3::new(i16::MIN, i16::MIN, i16::MIN) ); }); 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, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(6, mem::size_of::()); assert_eq!(2, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U16Vec3::new(1, 2, 3), U16Vec3::try_from(I8Vec3::new(1, 2, 3)).unwrap() ); assert!(U16Vec3::try_from(I8Vec3::new(-1, 2, 3)).is_err()); assert!(U16Vec3::try_from(I8Vec3::new(1, -2, 3)).is_err()); assert!(U16Vec3::try_from(I8Vec3::new(1, 2, -3)).is_err()); assert_eq!(U16Vec3::new(1, 2, 3), U16Vec3::from(U8Vec3::new(1, 2, 3))); 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()); assert_eq!( U16Vec3::new(1, 2, 3), U16Vec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); assert!(U16Vec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(U16Vec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(U16Vec3::try_from(USizeVec3::new(1, 2, usize::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) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U16Vec3::new(u16::MAX, u16::MAX, u16::MAX).wrapping_add_signed(I16Vec3::new(1, 1, 1)), U16Vec3::new(u16::MIN, u16::MIN, u16::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U16Vec3::new(u16::MAX, u16::MAX, u16::MAX).saturating_add_signed(I16Vec3::new(1, 1, 1)), U16Vec3::new(u16::MAX, u16::MAX, u16::MAX) ); }); impl_vec3_unsigned_integer_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, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(12, mem::size_of::()); assert_eq!(4, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(IVec3::new(1, 2, 3), IVec3::from(U8Vec3::new(1, 2, 3))); assert_eq!(IVec3::new(1, 2, 3), IVec3::from(I8Vec3::new(1, 2, 3))); 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()); assert_eq!( IVec3::new(1, 2, 3), IVec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); assert!(IVec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(IVec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(IVec3::try_from(USizeVec3::new(1, 2, usize::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) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(IVec3::MAX.checked_add_unsigned(UVec3::ONE), None); assert_eq!( IVec3::NEG_ONE.checked_add_unsigned(UVec3::ONE), Some(IVec3::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(IVec3::MIN.checked_sub_unsigned(UVec3::ONE), None); assert_eq!( IVec3::ZERO.checked_sub_unsigned(UVec3::ONE), Some(IVec3::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( IVec3::new(i32::MAX, i32::MAX, i32::MAX).wrapping_add_unsigned(UVec3::new(1, 1, 1)), IVec3::new(i32::MIN, i32::MIN, i32::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( IVec3::new(i32::MIN, i32::MIN, i32::MIN).wrapping_sub_unsigned(UVec3::new(1, 1, 1)), IVec3::new(i32::MAX, i32::MAX, i32::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( IVec3::new(i32::MAX, i32::MAX, i32::MAX).saturating_add_unsigned(UVec3::new(1, 1, 1)), IVec3::new(i32::MAX, i32::MAX, i32::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( IVec3::new(i32::MIN, i32::MIN, i32::MIN).saturating_sub_unsigned(UVec3::new(1, 1, 1)), IVec3::new(i32::MIN, i32::MIN, i32::MIN) ); }); 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); impl_vec3_shift_op_tests!(IVec3); impl_vec3_scalar_bit_op_tests!(IVec3, -2, 2); impl_vec3_bit_op_tests!(IVec3, -2, 2); } mod uvec3 { use glam::{ uvec3, BVec3, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(12, mem::size_of::()); assert_eq!(4, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( UVec3::new(1, 2, 3), UVec3::try_from(I8Vec3::new(1, 2, 3)).unwrap() ); assert!(UVec3::try_from(I8Vec3::new(-1, 2, 3)).is_err()); assert!(UVec3::try_from(I8Vec3::new(1, -2, 3)).is_err()); assert!(UVec3::try_from(I8Vec3::new(1, 2, -3)).is_err()); assert_eq!(UVec3::new(1, 2, 3), UVec3::from(U8Vec3::new(1, 2, 3))); 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()); assert_eq!( UVec3::new(1, 2, 3), UVec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); if core::mem::size_of::() > 4 { assert!(UVec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(UVec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(UVec3::try_from(USizeVec3::new(1, 2, usize::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) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( UVec3::new(u32::MAX, u32::MAX, u32::MAX).wrapping_add_signed(IVec3::new(1, 1, 1)), UVec3::new(u32::MIN, u32::MIN, u32::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( UVec3::new(u32::MAX, u32::MAX, u32::MAX).saturating_add_signed(IVec3::new(1, 1, 1)), UVec3::new(u32::MAX, u32::MAX, u32::MAX) ); }); impl_vec3_unsigned_integer_tests!(u32, uvec3, UVec3, BVec3); impl_vec3_eq_hash_tests!(u32, uvec3); impl_vec3_scalar_shift_op_tests!(UVec3, 0, 2); impl_vec3_shift_op_tests!(UVec3); 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, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(24, mem::size_of::()); assert_eq!(8, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(I64Vec3::new(1, 2, 3), I64Vec3::from(I8Vec3::new(1, 2, 3))); assert_eq!(I64Vec3::new(1, 2, 3), I64Vec3::from(U8Vec3::new(1, 2, 3))); 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()); assert_eq!( I64Vec3::new(1, 2, 3), I64Vec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); if core::mem::size_of::() > 4 { assert!(I64Vec3::try_from(USizeVec3::new(usize::MAX, 2, 3)).is_err()); assert!(I64Vec3::try_from(USizeVec3::new(1, usize::MAX, 3)).is_err()); assert!(I64Vec3::try_from(USizeVec3::new(1, 2, usize::MAX)).is_err()); } }); glam_test!(test_checked_add_unsigned, { assert_eq!(I64Vec3::MAX.checked_add_unsigned(U64Vec3::ONE), None); assert_eq!( I64Vec3::NEG_ONE.checked_add_unsigned(U64Vec3::ONE), Some(I64Vec3::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I64Vec3::MIN.checked_sub_unsigned(U64Vec3::ONE), None); assert_eq!( I64Vec3::ZERO.checked_sub_unsigned(U64Vec3::ONE), Some(I64Vec3::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I64Vec3::new(i64::MAX, i64::MAX, i64::MAX).wrapping_add_unsigned(U64Vec3::new(1, 1, 1)), I64Vec3::new(i64::MIN, i64::MIN, i64::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I64Vec3::new(i64::MIN, i64::MIN, i64::MIN).wrapping_sub_unsigned(U64Vec3::new(1, 1, 1)), I64Vec3::new(i64::MAX, i64::MAX, i64::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I64Vec3::new(i64::MAX, i64::MAX, i64::MAX) .saturating_add_unsigned(U64Vec3::new(1, 1, 1)), I64Vec3::new(i64::MAX, i64::MAX, i64::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I64Vec3::new(i64::MIN, i64::MIN, i64::MIN) .saturating_sub_unsigned(U64Vec3::new(1, 1, 1)), I64Vec3::new(i64::MIN, i64::MIN, i64::MIN) ); }); 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, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(24, mem::size_of::()); assert_eq!(8, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U64Vec3::new(1, 2, 3), U64Vec3::try_from(I8Vec3::new(1, 2, 3)).unwrap() ); assert!(U64Vec3::try_from(I8Vec3::new(-1, 2, 3)).is_err()); assert!(U64Vec3::try_from(I8Vec3::new(1, -2, 3)).is_err()); assert!(U64Vec3::try_from(I8Vec3::new(1, 2, -3)).is_err()); assert_eq!(U64Vec3::new(1, 2, 3), U64Vec3::from(U8Vec3::new(1, 2, 3))); 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()); assert_eq!( U64Vec3::new(1, 2, 3), U64Vec3::try_from(USizeVec3::new(1, 2, 3)).unwrap() ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U64Vec3::new(u64::MAX, u64::MAX, u64::MAX).wrapping_add_signed(I64Vec3::new(1, 1, 1)), U64Vec3::new(u64::MIN, u64::MIN, u64::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U64Vec3::new(u64::MAX, u64::MAX, u64::MAX).saturating_add_signed(I64Vec3::new(1, 1, 1)), U64Vec3::new(u64::MAX, u64::MAX, u64::MAX) ); }); impl_vec3_unsigned_integer_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); } mod usizevec3 { use glam::{ usizevec3, BVec3, I16Vec3, I64Vec3, I8Vec3, IVec3, U16Vec3, U64Vec3, U8Vec3, USizeVec3, UVec3, }; glam_test!(test_align, { use std::mem; assert_eq!(mem::size_of::() * 3, mem::size_of::()); assert_eq!(mem::align_of::(), mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::try_from(I8Vec3::new(1, 2, 3)).unwrap() ); assert!(USizeVec3::try_from(I8Vec3::new(-1, 2, 3)).is_err()); assert!(USizeVec3::try_from(I8Vec3::new(1, -2, 3)).is_err()); assert!(USizeVec3::try_from(I8Vec3::new(1, 2, -3)).is_err()); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::from(U8Vec3::new(1, 2, 3)) ); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::try_from(I16Vec3::new(1, 2, 3)).unwrap() ); assert!(USizeVec3::try_from(I16Vec3::new(-1, 2, 3)).is_err()); assert!(USizeVec3::try_from(I16Vec3::new(1, -2, 3)).is_err()); assert!(USizeVec3::try_from(I16Vec3::new(1, 2, -3)).is_err()); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::from(U16Vec3::new(1, 2, 3)) ); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::try_from(IVec3::new(1, 2, 3)).unwrap() ); assert!(USizeVec3::try_from(IVec3::new(-1, 2, 3)).is_err()); assert!(USizeVec3::try_from(IVec3::new(1, -2, 3)).is_err()); assert!(USizeVec3::try_from(IVec3::new(1, 2, -3)).is_err()); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::try_from(UVec3::new(1, 2, 3)).unwrap() ); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::try_from(U64Vec3::new(1, 2, 3)).unwrap() ); assert_eq!( USizeVec3::new(1, 2, 3), USizeVec3::try_from(I64Vec3::new(1, 2, 3)).unwrap() ); assert!(USizeVec3::try_from(I64Vec3::new(-1, 2, 3)).is_err()); assert!(USizeVec3::try_from(I64Vec3::new(1, -2, 3)).is_err()); assert!(USizeVec3::try_from(I64Vec3::new(1, 2, -3)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( USizeVec3::new(usize::MAX, 5, usize::MAX).wrapping_add(USizeVec3::new( 1, 3, usize::MAX )), USizeVec3::new(0, 8, usize::MAX.wrapping_add(usize::MAX)), ); }); glam_test!(test_wrapping_sub, { assert_eq!( USizeVec3::new(usize::MAX, 5, usize::MAX - 1).wrapping_sub(USizeVec3::new( 1, 3, usize::MAX )), USizeVec3::new( usize::MAX.wrapping_sub(1), 2, (usize::MAX - 1).wrapping_sub(usize::MAX) ) ); }); glam_test!(test_wrapping_mul, { assert_eq!( USizeVec3::new(usize::MAX, 5, usize::MAX).wrapping_mul(USizeVec3::new(3, 3, 5)), USizeVec3::new(usize::MAX.wrapping_mul(3), 15, usize::MAX.wrapping_mul(5)) ); }); glam_test!(test_wrapping_div, { assert_eq!( USizeVec3::new(usize::MAX, 5, usize::MAX).wrapping_div(USizeVec3::new(3, 3, 5)), USizeVec3::new(usize::MAX.wrapping_div(3), 1, usize::MAX.wrapping_div(5)) ); }); glam_test!(test_saturating_add, { assert_eq!( USizeVec3::new(usize::MAX, usize::MAX, 0).saturating_add(USizeVec3::new( 1, usize::MAX, 2 )), USizeVec3::new(usize::MAX, usize::MAX, 2) ); }); glam_test!(test_saturating_sub, { assert_eq!( USizeVec3::new(0, usize::MAX, 0).saturating_sub(USizeVec3::new(1, 1, 2)), USizeVec3::new(0, usize::MAX.saturating_sub(1), 0) ); }); glam_test!(test_saturating_mul, { assert_eq!( USizeVec3::new(usize::MAX, usize::MAX, 0).saturating_mul(USizeVec3::new( 2, usize::MAX, 0 )), USizeVec3::new(usize::MAX, usize::MAX, 0) ); }); glam_test!(test_saturating_div, { assert_eq!( USizeVec3::new(usize::MAX, usize::MAX, 0).saturating_div(USizeVec3::new( 2, usize::MAX, 3 )), USizeVec3::new(usize::MAX.saturating_div(2), 1, 0) ); }); impl_vec3_unsigned_integer_tests!(usize, usizevec3, USizeVec3, BVec3); impl_vec3_eq_hash_tests!(usize, usizevec3); impl_vec3_scalar_shift_op_tests!(USizeVec3, 0, 2); impl_vec3_shift_op_tests!(USizeVec3); impl_vec3_scalar_bit_op_tests!(USizeVec3, 0, 2); impl_vec3_bit_op_tests!(USizeVec3, 0, 2); } glam-0.30.1/tests/vec4.rs000064400000000000000000004242041046102023000132040ustar 00000000000000#![allow(clippy::excessive_precision)] #[macro_use] mod support; macro_rules! impl_bvec4_tests { ($mask:ident, $masknew:ident) => { glam_test!(test_mask_new, { assert_eq!( $mask::new(false, false, false, false), $masknew(false, false, false, false) ); assert_eq!( $mask::new(false, false, true, true), $masknew(false, false, true, true) ); assert_eq!( $mask::new(true, true, false, false), $masknew(true, true, false, false) ); assert_eq!( $mask::new(false, true, false, true), $masknew(false, true, false, true) ); assert_eq!( $mask::new(true, false, true, false), $masknew(true, false, true, false) ); assert_eq!( $mask::new(true, true, true, true), $masknew(true, true, true, true) ); }); glam_test!(test_mask_from_array_bool, { assert_eq!( $mask::new(false, false, false, false), $mask::from([false, false, false, false]) ); assert_eq!( $mask::new(false, false, true, true), $mask::from([false, false, true, true]) ); assert_eq!( $mask::new(true, true, false, false), $mask::from([true, true, false, false]) ); assert_eq!( $mask::new(false, true, false, true), $mask::from([false, true, false, true]) ); assert_eq!( $mask::new(true, false, true, false), $mask::from([true, false, true, false]) ); assert_eq!( $mask::new(true, true, true, true), $mask::from([true, true, true, true]) ); }); glam_test!(test_mask_into_array_u32, { assert_eq!( Into::<[u32; 4]>::into($mask::new(false, false, false, false)), [0, 0, 0, 0] ); assert_eq!( Into::<[u32; 4]>::into($mask::new(false, false, true, true)), [0, 0, !0, !0] ); assert_eq!( Into::<[u32; 4]>::into($mask::new(true, true, false, false)), [!0, !0, 0, 0] ); assert_eq!( Into::<[u32; 4]>::into($mask::new(false, true, false, true)), [0, !0, 0, !0] ); assert_eq!( Into::<[u32; 4]>::into($mask::new(true, false, true, false)), [!0, 0, !0, 0] ); assert_eq!( Into::<[u32; 4]>::into($mask::new(true, true, true, true)), [!0, !0, !0, !0] ); }); glam_test!(test_mask_into_array_bool, { assert_eq!( Into::<[bool; 4]>::into($mask::new(false, false, false, false)), [false, false, false, false] ); assert_eq!( Into::<[bool; 4]>::into($mask::new(false, false, true, true)), [false, false, true, true] ); assert_eq!( Into::<[bool; 4]>::into($mask::new(true, true, false, false)), [true, true, false, false] ); assert_eq!( Into::<[bool; 4]>::into($mask::new(false, true, false, true)), [false, true, false, true] ); assert_eq!( Into::<[bool; 4]>::into($mask::new(true, false, true, false)), [true, false, true, false] ); assert_eq!( Into::<[bool; 4]>::into($mask::new(true, true, true, true)), [true, true, true, true] ); }); glam_test!(test_mask_splat, { assert_eq!($mask::splat(false), $mask::new(false, false, false, false)); assert_eq!($mask::splat(true), $mask::new(true, true, true, true)); }); glam_test!(test_mask_bitmask, { assert_eq!($mask::new(false, false, false, false).bitmask(), 0b0000); assert_eq!($mask::new(false, false, true, true).bitmask(), 0b1100); assert_eq!($mask::new(true, true, false, false).bitmask(), 0b0011); assert_eq!($mask::new(false, true, false, true).bitmask(), 0b1010); assert_eq!($mask::new(true, false, true, false).bitmask(), 0b0101); assert_eq!($mask::new(true, true, true, true).bitmask(), 0b1111); }); glam_test!(test_mask_any, { assert_eq!($mask::new(false, false, false, false).any(), false); assert_eq!($mask::new(true, false, false, false).any(), true); assert_eq!($mask::new(false, true, false, false).any(), true); assert_eq!($mask::new(false, false, true, false).any(), true); assert_eq!($mask::new(false, false, false, true).any(), true); }); glam_test!(test_mask_all, { assert_eq!($mask::new(true, true, true, true).all(), true); assert_eq!($mask::new(false, true, true, true).all(), false); assert_eq!($mask::new(true, false, true, true).all(), false); assert_eq!($mask::new(true, true, false, true).all(), false); assert_eq!($mask::new(true, true, true, false).all(), false); }); glam_test!(test_mask_and, { assert_eq!( ($mask::new(false, false, false, false) & $mask::new(false, false, false, false)) .bitmask(), 0b0000, ); assert_eq!( ($mask::new(true, true, true, true) & $mask::new(true, true, true, true)).bitmask(), 0b1111, ); assert_eq!( ($mask::new(true, false, true, false) & $mask::new(false, true, false, true)) .bitmask(), 0b0000, ); assert_eq!( ($mask::new(true, false, true, true) & $mask::new(true, true, true, false)) .bitmask(), 0b0101, ); let mut mask = $mask::new(true, true, false, false); mask &= $mask::new(true, false, true, false); assert_eq!(mask.bitmask(), 0b0001); }); glam_test!(test_mask_or, { assert_eq!( ($mask::new(false, false, false, false) | $mask::new(false, false, false, false)) .bitmask(), 0b0000, ); assert_eq!( ($mask::new(true, true, true, true) | $mask::new(true, true, true, true)).bitmask(), 0b1111, ); assert_eq!( ($mask::new(true, false, true, false) | $mask::new(false, true, false, true)) .bitmask(), 0b1111, ); assert_eq!( ($mask::new(true, false, true, false) | $mask::new(true, false, true, false)) .bitmask(), 0b0101, ); let mut mask = $mask::new(true, true, false, false); mask |= $mask::new(true, false, true, false); assert_eq!(mask.bitmask(), 0b0111); }); glam_test!(test_mask_xor, { assert_eq!( ($mask::new(false, false, false, false) ^ $mask::new(false, false, false, false)) .bitmask(), 0b0000, ); assert_eq!( ($mask::new(true, true, true, true) ^ $mask::new(true, true, true, true)).bitmask(), 0b0000, ); assert_eq!( ($mask::new(true, false, true, false) ^ $mask::new(false, true, false, true)) .bitmask(), 0b1111, ); assert_eq!( ($mask::new(true, false, true, false) ^ $mask::new(true, false, true, false)) .bitmask(), 0b0000, ); let mut mask = $mask::new(true, true, false, false); mask ^= $mask::new(true, false, true, false); assert_eq!(mask.bitmask(), 0b0110); }); glam_test!(test_mask_not, { assert_eq!((!$mask::new(false, false, false, false)).bitmask(), 0b1111); assert_eq!((!$mask::new(true, true, true, true)).bitmask(), 0b0000); assert_eq!((!$mask::new(true, false, true, false)).bitmask(), 0b1010); assert_eq!((!$mask::new(false, true, false, true)).bitmask(), 0b0101); }); glam_test!(test_mask_fmt, { let a = $mask::new(true, false, true, false); assert_eq!(format!("{}", a), "[true, false, true, false]"); assert_eq!( format!("{:?}", a), format!("{}(0xffffffff, 0x0, 0xffffffff, 0x0)", stringify!($mask)) ); }); glam_test!(test_mask_eq, { let a = $mask::new(true, false, true, false); let b = $mask::new(true, false, true, false); let c = $mask::new(false, true, true, false); assert_eq!(a, b); assert_eq!(b, a); assert_ne!(a, c); 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; use std::hash::Hasher; let a = $mask::new(true, false, true, false); let b = $mask::new(true, false, true, false); let c = $mask::new(false, true, true, false); let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); let a_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); b.hash(&mut hasher); let b_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); c.hash(&mut hasher); let c_hashed = hasher.finish(); assert_eq!(a, b); assert_eq!(a_hashed, b_hashed); assert_ne!(a, c); assert_ne!(a_hashed, c_hashed); }); }; } macro_rules! impl_vec4_tests { ($t:ident, $new:ident, $vec4:ident, $vec3:ident, $vec2:ident, $mask:ident) => { glam_test!(test_const, { const V0: $vec4 = $vec4::splat(1 as $t); const V1: $vec4 = $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t); const V2: $vec4 = $vec4::from_array([1 as $t, 2 as $t, 3 as $t, 4 as $t]); assert_eq!([1 as $t, 1 as $t, 1 as $t, 1 as $t], *V0.as_ref()); assert_eq!([1 as $t, 2 as $t, 3 as $t, 4 as $t], *V1.as_ref()); assert_eq!([1 as $t, 2 as $t, 3 as $t, 4 as $t], *V2.as_ref()); }); glam_test!(test_vec4_consts, { assert_eq!($vec4::ZERO, $new(0 as $t, 0 as $t, 0 as $t, 0 as $t)); assert_eq!($vec4::ONE, $new(1 as $t, 1 as $t, 1 as $t, 1 as $t)); assert_eq!($vec4::X, $new(1 as $t, 0 as $t, 0 as $t, 0 as $t)); 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, { let v = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); assert_eq!(v.x, 1 as $t); assert_eq!(v.y, 2 as $t); assert_eq!(v.z, 3 as $t); assert_eq!(v.w, 4 as $t); let t = (1 as $t, 2 as $t, 3 as $t, 4 as $t); let v = $vec4::from(t); assert_eq!(t, v.into()); let a = [1 as $t, 2 as $t, 3 as $t, 4 as $t]; let v = $vec4::from(a); let a1: [$t; 4] = v.into(); assert_eq!(a, a1); assert_eq!(a, v.to_array()); assert_eq!(a, *v.as_ref()); let mut v2 = $vec4::default(); *v2.as_mut() = a; assert_eq!(a, v2.to_array()); let v = $vec4::new(t.0, t.1, t.2, t.3); assert_eq!(t, v.into()); assert_eq!( $vec4::new(1 as $t, 0 as $t, 0 as $t, 0 as $t), glam::BVec4::new(true, false, false, false).into() ); assert_eq!( $vec4::new(0 as $t, 1 as $t, 0 as $t, 0 as $t), glam::BVec4::new(false, true, false, false).into() ); assert_eq!( $vec4::new(0 as $t, 0 as $t, 1 as $t, 0 as $t), glam::BVec4::new(false, false, true, false).into() ); #[cfg(not(feature = "scalar-math"))] { assert_eq!( $vec4::new(0 as $t, 0 as $t, 0 as $t, 1 as $t), glam::BVec4::new(false, false, false, true).into() ); assert_eq!( $vec4::new(1 as $t, 0 as $t, 0 as $t, 0 as $t), glam::BVec4A::new(true, false, false, false).into() ); assert_eq!( $vec4::new(0 as $t, 1 as $t, 0 as $t, 0 as $t), glam::BVec4A::new(false, true, false, false).into() ); assert_eq!( $vec4::new(0 as $t, 0 as $t, 1 as $t, 0 as $t), glam::BVec4A::new(false, false, true, false).into() ); assert_eq!( $vec4::new(0 as $t, 0 as $t, 0 as $t, 1 as $t), glam::BVec4A::new(false, false, false, true).into() ); } assert_eq!($vec4::new(1 as $t, 0 as $t, 0 as $t, 0 as $t), $vec4::X); assert_eq!($vec4::new(0 as $t, 1 as $t, 0 as $t, 0 as $t), $vec4::Y); assert_eq!($vec4::new(0 as $t, 0 as $t, 1 as $t, 0 as $t), $vec4::Z); assert_eq!($vec4::new(0 as $t, 0 as $t, 0 as $t, 1 as $t), $vec4::W); assert_eq!( v, $vec4::from(($vec3::new(1 as $t, 2 as $t, 3 as $t), 4 as $t)) ); assert_eq!( v, $vec4::from((1 as $t, $vec3::new(2 as $t, 3 as $t, 4 as $t))) ); assert_eq!( v, $vec4::from(($vec2::new(1 as $t, 2 as $t), 3 as $t, 4 as $t)) ); assert_eq!( v, $vec4::from(($vec2::new(1 as $t, 2 as $t), $vec2::new(3 as $t, 4 as $t))) ); }); glam_test!(test_fmt, { let a = $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t); assert_eq!( format!("{:?}", a), format!( "{}({:?}, {:?}, {:?}, {:?})", stringify!($vec4), a.x, a.y, a.z, a.w ) ); assert_eq!( format!("{:#?}", a), format!( "{}(\n {:#?},\n {:#?},\n {:#?},\n {:#?},\n)", stringify!($vec4), a.x, a.y, a.z, a.w ) ); assert_eq!(format!("{}", a), "[1, 2, 3, 4]"); }); glam_test!(test_zero, { let v = $vec4::ZERO; assert_eq!((0 as $t, 0 as $t, 0 as $t, 0 as $t), v.into()); assert_eq!(v, $vec4::default()); }); glam_test!(test_splat, { let v = $vec4::splat(1 as $t); assert_eq!($vec4::ONE, v); }); glam_test!(test_map, { let v = $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t); assert_eq!(v.map(|n| n + 3 as $t), v + $vec4::splat(3 as $t)); assert_eq!(v.map(|_| 0 as $t), $vec4::ZERO); }); glam_test!(test_with, { assert_eq!($vec4::X, $vec4::ZERO.with_x(1 as $t)); assert_eq!($vec4::Y, $vec4::ZERO.with_y(1 as $t)); assert_eq!($vec4::Z, $vec4::ZERO.with_z(1 as $t)); assert_eq!($vec4::W, $vec4::ZERO.with_w(1 as $t)); }); glam_test!(test_accessors, { let mut a = $vec4::ZERO; a.x = 1 as $t; a.y = 2 as $t; a.z = 3 as $t; a.w = 4 as $t; assert_eq!(1 as $t, a.x); assert_eq!(2 as $t, a.y); assert_eq!(3 as $t, a.z); assert_eq!(4 as $t, a.w); assert_eq!((1 as $t, 2 as $t, 3 as $t, 4 as $t), a.into()); let mut a = $vec4::ZERO; a[0] = 1 as $t; a[1] = 2 as $t; a[2] = 3 as $t; a[3] = 4 as $t; assert_eq!(1 as $t, a[0]); assert_eq!(2 as $t, a[1]); assert_eq!(3 as $t, a[2]); assert_eq!(4 as $t, a[3]); assert_eq!((1 as $t, 2 as $t, 3 as $t, 4 as $t), a.into()); }); glam_test!(test_dot_unsigned, { 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!(1 as $t, x.dot(x)); 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, { let a = $new(2 as $t, 4 as $t, 8 as $t, 10 as $t); assert_eq!($new(4 as $t, 8 as $t, 16 as $t, 20 as $t), a + a); assert_eq!($new(2 as $t, 4 as $t, 8 as $t, 10 as $t), 0 as $t + a); assert_eq!($new(0 as $t, 0 as $t, 0 as $t, 0 as $t), a - a); assert_eq!($new(8 as $t, 6 as $t, 2 as $t, 0 as $t), 10 as $t - a); assert_eq!($new(4 as $t, 16 as $t, 64 as $t, 100 as $t), a * a); assert_eq!($new(4 as $t, 8 as $t, 16 as $t, 20 as $t), a * 2 as $t); assert_eq!($new(4 as $t, 8 as $t, 16 as $t, 20 as $t), 2 as $t * a); assert_eq!($new(1 as $t, 1 as $t, 1 as $t, 1 as $t), a / a); assert_eq!($new(1 as $t, 2 as $t, 4 as $t, 5 as $t), a / 2 as $t); assert_eq!($new(8 as $t, 4 as $t, 2 as $t, 1.6 as $t), 16 as $t / a); assert_eq!($new(0 as $t, 0 as $t, 0 as $t, 0 as $t), a % a); assert_eq!($new(0 as $t, 1 as $t, 1 as $t, 1 as $t), a % (a - 1 as $t)); assert_eq!($new(0 as $t, 0 as $t, 0 as $t, 0 as $t), a % 1 as $t); assert_eq!($new(2 as $t, 1 as $t, 2 as $t, 1 as $t), a % 3 as $t); assert_eq!($new(1 as $t, 1 as $t, 1 as $t, 7 as $t), 17 as $t % a); assert_eq!($new(2 as $t, 4 as $t, 0 as $t, 2 as $t), a % 8 as $t); }); glam_test!(test_ops_propagated, { let vec = $new(2 as $t, 4 as $t, 8 as $t, 10 as $t); let scalar = 2 as $t; let g_scalar = 10 as $t; assert_eq!((vec + vec), (vec + &vec)); assert_eq!((vec + vec), (&vec + vec)); assert_eq!((vec + vec), (&vec + &vec)); assert_eq!((vec + scalar), (vec + &scalar)); assert_eq!((vec + scalar), (&vec + &scalar)); assert_eq!((vec + scalar), (&vec + scalar)); assert_eq!((scalar + vec), (&scalar + vec)); assert_eq!((scalar + vec), (&scalar + &vec)); assert_eq!((scalar + vec), (scalar + &vec)); assert_eq!((vec - vec), (vec - &vec)); assert_eq!((vec - vec), (&vec - vec)); assert_eq!((vec - vec), (&vec - &vec)); assert_eq!((vec - scalar), (vec - &scalar)); assert_eq!((vec - scalar), (&vec - &scalar)); assert_eq!((vec - scalar), (&vec - scalar)); assert_eq!((g_scalar - vec), (&g_scalar - vec)); assert_eq!((g_scalar - vec), (&g_scalar - &vec)); assert_eq!((g_scalar - vec), (g_scalar - &vec)); assert_eq!((vec * vec), (vec * &vec)); assert_eq!((vec * vec), (&vec * vec)); assert_eq!((vec * vec), (&vec * &vec)); assert_eq!((vec * scalar), (vec * &scalar)); assert_eq!((vec * scalar), (&vec * &scalar)); assert_eq!((vec * scalar), (&vec * scalar)); assert_eq!((scalar * vec), (&scalar * vec)); assert_eq!((scalar * vec), (&scalar * &vec)); assert_eq!((scalar * vec), (scalar * &vec)); assert_eq!((vec / vec), (vec / &vec)); assert_eq!((vec / vec), (&vec / vec)); assert_eq!((vec / vec), (&vec / &vec)); assert_eq!((vec / scalar), (vec / &scalar)); assert_eq!((vec / scalar), (&vec / &scalar)); assert_eq!((vec / scalar), (&vec / scalar)); assert_eq!((scalar / vec), (&scalar / vec)); assert_eq!((scalar / vec), (&scalar / &vec)); assert_eq!((scalar / vec), (scalar / &vec)); assert_eq!((vec % vec), (vec % &vec)); assert_eq!((vec % vec), (&vec % vec)); assert_eq!((vec % vec), (&vec % &vec)); assert_eq!((vec % scalar), (vec % &scalar)); assert_eq!((vec % scalar), (&vec % &scalar)); assert_eq!((vec % scalar), (&vec % scalar)); assert_eq!((scalar % vec), (&scalar % vec)); assert_eq!((scalar % vec), (&scalar % &vec)); assert_eq!((scalar % vec), (scalar % &vec)); }); glam_test!(test_assign_ops, { let a = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let mut b = a; b += 2 as $t; assert_eq!($new(3 as $t, 4 as $t, 5 as $t, 6 as $t), b); b -= 2 as $t; assert_eq!($new(1 as $t, 2 as $t, 3 as $t, 4 as $t), b); b *= 2 as $t; assert_eq!($new(2 as $t, 4 as $t, 6 as $t, 8 as $t), b); b /= 2 as $t; assert_eq!($new(1 as $t, 2 as $t, 3 as $t, 4 as $t), b); b %= 2 as $t; assert_eq!($new(1 as $t, 0 as $t, 1 as $t, 0 as $t), b); b = a; b += a; assert_eq!($new(2 as $t, 4 as $t, 6 as $t, 8 as $t), b); b -= a; assert_eq!($new(1 as $t, 2 as $t, 3 as $t, 4 as $t), b); b *= a; assert_eq!($new(1 as $t, 4 as $t, 9 as $t, 16 as $t), b); b /= a; assert_eq!($new(1 as $t, 2 as $t, 3 as $t, 4 as $t), b); b *= 2 as $t; assert_eq!($new(2 as $t, 4 as $t, 6 as $t, 8 as $t), b); b /= 2 as $t; assert_eq!($new(1 as $t, 2 as $t, 3 as $t, 4 as $t), b); b %= (b + 1 as $t); assert_eq!($new(1 as $t, 2 as $t, 3 as $t, 4 as $t), b); b %= b; assert_eq!($new(0 as $t, 0 as $t, 0 as $t, 0 as $t), b); }); glam_test!(test_assign_ops_propagation, { let vec = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let mut a = vec; let mut b = vec; let scalar = 2 as $t; a += &scalar; b += scalar; assert_eq!(b, a, "AddAssign"); a -= &scalar; b -= scalar; assert_eq!(b, a, "SubAssign"); a *= &scalar; b *= scalar; assert_eq!(b, a, "MulAssign"); a /= &scalar; b /= scalar; assert_eq!(b, a, "DivAssign"); a %= &scalar; b %= scalar; assert_eq!(b, a, "MulAssign"); a = vec; b = vec; a += &vec; b += vec; assert_eq!(b, a, "AddAssign"); a -= &vec; b -= vec; assert_eq!(b, a, "SubAssign"); a *= &vec; b *= vec; assert_eq!(b, a, "MulAssign"); a /= &vec; b /= vec; assert_eq!(b, a, "DivAssign"); a %= &vec; b %= vec; assert_eq!(b, a, "RemAssign"); }); glam_test!(test_min_max, { let a = $new(4 as $t, 6 as $t, 2 as $t, 8 as $t); let b = $new(5 as $t, 3 as $t, 7 as $t, 1 as $t); assert_eq!((4 as $t, 3 as $t, 2 as $t, 1 as $t), a.min(b).into()); assert_eq!((4 as $t, 3 as $t, 2 as $t, 1 as $t), b.min(a).into()); assert_eq!((5 as $t, 6 as $t, 7 as $t, 8 as $t), a.max(b).into()); assert_eq!((5 as $t, 6 as $t, 7 as $t, 8 as $t), b.max(a).into()); }); glam_test!(test_min_position_max_position, { let a = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let b = $new(1 as $t, 1 as $t, 1 as $t, 1 as $t); let c = $new(4 as $t, 3 as $t, 2 as $t, 1 as $t); let d = $new(1 as $t, 2 as $t, 0 as $t, 1 as $t); let e = $new(1 as $t, 0 as $t, 2 as $t, 1 as $t); assert_eq!(0, a.min_position()); assert_eq!(0, b.min_position()); assert_eq!(3, c.min_position()); assert_eq!(2, d.min_position()); assert_eq!(1, e.min_position()); assert_eq!(3, a.max_position()); assert_eq!(0, b.max_position()); assert_eq!(0, c.max_position()); assert_eq!(1, d.max_position()); assert_eq!(2, e.max_position()); }); glam_test!(test_clamp, { fn vec(x: i32, y: i32, z: i32, w: i32) -> $vec4 { $vec4::new(x as $t, y as $t, z as $t, w as $t) } let min = vec(1, 1, 3, 3); let max = vec(6, 6, 8, 8); assert_eq!(vec(0, 0, 0, 0).clamp(min, max), vec(1, 1, 3, 3)); assert_eq!(vec(2, 2, 2, 2).clamp(min, max), vec(2, 2, 3, 3)); assert_eq!(vec(4, 4, 5, 5).clamp(min, max), vec(4, 4, 5, 5)); assert_eq!(vec(6, 6, 6, 6).clamp(min, max), vec(6, 6, 6, 6)); assert_eq!(vec(7, 7, 7, 7).clamp(min, max), vec(6, 6, 7, 7)); assert_eq!(vec(9, 9, 9, 9).clamp(min, max), vec(6, 6, 8, 8)); should_glam_assert!({ $vec4::clamp($vec4::ZERO, $vec4::ONE, $vec4::ZERO) }); }); glam_test!(test_hmin_hmax, { assert_eq!( 1 as $t, $new(1 as $t, 2 as $t, 3 as $t, 4 as $t).min_element() ); assert_eq!( 1 as $t, $new(4 as $t, 1 as $t, 2 as $t, 3 as $t).min_element() ); assert_eq!( 1 as $t, $new(3 as $t, 4 as $t, 1 as $t, 2 as $t).min_element() ); assert_eq!( 1 as $t, $new(2 as $t, 3 as $t, 4 as $t, 1 as $t).min_element() ); assert_eq!( 4 as $t, $new(1 as $t, 2 as $t, 3 as $t, 4 as $t).max_element() ); assert_eq!( 4 as $t, $new(4 as $t, 1 as $t, 2 as $t, 3 as $t).max_element() ); assert_eq!( 4 as $t, $new(3 as $t, 4 as $t, 1 as $t, 2 as $t).max_element() ); assert_eq!( 4 as $t, $new(2 as $t, 3 as $t, 4 as $t, 1 as $t).max_element() ); assert_eq!( 3 as $t, $new(1 as $t, 2 as $t, 3 as $t, 4 as $t) .truncate() .max_element() ); assert_eq!( 2 as $t, $new(4 as $t, 3 as $t, 2 as $t, 1 as $t) .truncate() .min_element() ); }); glam_test!(test_sum_product, { let a = $new(2 as $t, 3 as $t, 4 as $t, 5 as $t); assert_eq!(a.element_sum(), 14 as $t); assert_eq!(a.element_product(), 120 as $t); }); glam_test!(test_eq, { let a = $new(1 as $t, 1 as $t, 1 as $t, 1 as $t); let b = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); assert!(a.cmpeq(a).all()); assert!(b.cmpeq(b).all()); assert!(a.cmpne(b).any()); assert!(b.cmpne(a).any()); assert!(b.cmpeq(a).any()); }); glam_test!(test_cmp, { assert!(!$mask::default().any()); assert!(!$mask::default().all()); assert_eq!($mask::default().bitmask(), 0x0); let a = $new(1 as $t, 1 as $t, 1 as $t, 1 as $t); let b = $new(2 as $t, 2 as $t, 2 as $t, 2 as $t); let c = $new(1 as $t, 1 as $t, 2 as $t, 2 as $t); let d = $new(2 as $t, 1 as $t, 1 as $t, 2 as $t); assert_eq!(a.cmplt(a).bitmask(), 0x0); assert_eq!(a.cmplt(b).bitmask(), 0xf); assert_eq!(a.cmplt(c).bitmask(), 0xc); assert_eq!(c.cmple(a).bitmask(), 0x3); assert_eq!(a.cmplt(d).bitmask(), 0x9); assert!(a.cmplt(b).all()); assert!(a.cmplt(c).any()); assert!(a.cmple(b).all()); assert!(a.cmple(a).all()); assert!(b.cmpgt(a).all()); assert!(b.cmpge(a).all()); assert!(b.cmpge(b).all()); assert!(!(a.cmpge(c).all())); assert!(c.cmple(c).all()); assert!(c.cmpge(c).all()); assert!(a.cmpeq(a).all()); assert!(!a.cmpeq(b).all()); assert!(a.cmpeq(c).any()); assert!(!a.cmpne(a).all()); assert!(a.cmpne(b).all()); assert!(a.cmpne(c).any()); assert!(a == a); }); glam_test!(test_select, { let a = $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let b = $vec4::new(5 as $t, 6 as $t, 7 as $t, 8 as $t); assert_eq!( $vec4::select($mask::new(true, true, true, true), a, b), $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t), ); assert_eq!( $vec4::select($mask::new(true, false, true, false), a, b), $vec4::new(1 as $t, 6 as $t, 3 as $t, 8 as $t), ); assert_eq!( $vec4::select($mask::new(false, true, false, true), a, b), $vec4::new(5 as $t, 2 as $t, 7 as $t, 4 as $t), ); assert_eq!( $vec4::select($mask::new(false, false, false, false), a, b), $vec4::new(5 as $t, 6 as $t, 7 as $t, 8 as $t), ); }); glam_test!(test_slice, { let a = [1 as $t, 2 as $t, 3 as $t, 4 as $t]; let b = $vec4::from_slice(&a); let c: [$t; 4] = b.into(); assert_eq!(a, c); let mut d = [0 as $t, 0 as $t, 0 as $t, 0 as $t]; b.write_to_slice(&mut d[..]); assert_eq!(a, d); should_panic!({ $vec4::ONE.write_to_slice(&mut [0 as $t; 3]) }); should_panic!({ $vec4::from_slice(&[0 as $t; 3]) }); }); glam_test!(test_to_from_slice, { let v = $vec4::new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let mut a = [0 as $t, 0 as $t, 0 as $t, 0 as $t]; v.write_to_slice(&mut a); assert_eq!(v, $vec4::from_slice(&a)); let mut a = [0 as $t; 17]; v.write_to_slice(&mut a); assert_eq!(v, $vec4::from_slice(&a[..4])); assert_eq!([0 as $t; 13], a[4..]); }); glam_test!(test_sum, { let one = $vec4::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!([two, two].iter().product::<$vec4>(), two * two); assert_eq!([two, two].into_iter().product::<$vec4>(), two * two); }); }; } macro_rules! impl_vec4_signed_tests { ($t:ident, $new:ident, $vec4:ident, $vec3:ident, $vec2:ident, $mask:ident) => { impl_vec4_tests!($t, $new, $vec4, $vec3, $vec2, $mask); glam_test!(test_neg, { 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 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 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_neg_propagation, { let a = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); assert_eq!(-a, -(&a)); }); 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); 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!(1 as $t, x.dot(x)); assert_eq!(0 as $t, x.dot(y)); 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); }); glam_test!(test_checked_add, { assert_eq!($vec4::MAX.checked_add($vec4::ONE), None); assert_eq!($vec4::MAX.checked_add($vec4::X), None); assert_eq!($vec4::MAX.checked_add($vec4::Y), None); assert_eq!($vec4::MAX.checked_add($vec4::Z), None); assert_eq!($vec4::MAX.checked_add($vec4::W), None); assert_eq!($vec4::MAX.checked_add($vec4::ZERO), Some($vec4::MAX)); }); glam_test!(test_checked_sub, { assert_eq!($vec4::MIN.checked_sub($vec4::ONE), None); assert_eq!($vec4::MIN.checked_sub($vec4::X), None); assert_eq!($vec4::MIN.checked_sub($vec4::Y), None); assert_eq!($vec4::MIN.checked_sub($vec4::Z), None); assert_eq!($vec4::MIN.checked_sub($vec4::W), None); assert_eq!($vec4::MIN.checked_sub($vec4::ZERO), Some($vec4::MIN)); }); glam_test!(test_checked_mul, { assert_eq!($vec4::MIN.checked_mul($vec4::MIN), None); assert_eq!($vec4::MAX.checked_mul($vec4::MIN), None); assert_eq!($vec4::MIN.checked_mul($vec4::MAX), None); assert_eq!($vec4::MAX.checked_mul($vec4::MAX), None); assert_eq!($vec4::ZERO.checked_mul($vec4::MIN), Some($vec4::ZERO)); assert_eq!($vec4::MAX.checked_mul($vec4::ZERO), Some($vec4::ZERO)); assert_eq!($vec4::MIN.checked_mul($vec4::ONE), Some($vec4::MIN)); assert_eq!($vec4::MAX.checked_mul($vec4::ONE), Some($vec4::MAX)); assert_eq!($vec4::ZERO.checked_mul($vec4::ZERO), Some($vec4::ZERO)); assert_eq!($vec4::ONE.checked_mul($vec4::ONE), Some($vec4::ONE)); }); glam_test!(test_checked_div, { assert_eq!($vec4::MIN.checked_div($vec4::ZERO), None); assert_eq!($vec4::MAX.checked_div($vec4::ZERO), None); assert_eq!($vec4::MAX.checked_div($vec4::X), None); assert_eq!($vec4::MAX.checked_div($vec4::Y), None); assert_eq!($vec4::MAX.checked_div($vec4::Z), None); assert_eq!($vec4::MAX.checked_div($vec4::W), None); assert_eq!($vec4::ZERO.checked_div($vec4::ONE), Some($vec4::ZERO)); assert_eq!($vec4::MIN.checked_div($vec4::ONE), Some($vec4::MIN)); assert_eq!($vec4::MAX.checked_div($vec4::ONE), Some($vec4::MAX)); }); glam_test!(test_manhattan_distance, { assert_eq!( $vec4::new(41, 8, 21, 87).manhattan_distance($vec4::new(49, 48, 28, 40)), 102 ); assert_eq!( $vec4::new(19, 16, 100, 74).manhattan_distance($vec4::new(14, 55, 115, 48)), 85 ); assert_eq!( $vec4::new(26, 2, 24, -22).manhattan_distance($vec4::new(26, 23, 6, 23)), 84 ); assert_eq!( $vec4::new(41, 8, 21, 87).checked_manhattan_distance($vec4::new(49, 48, 28, 40)), Some(102) ); assert_eq!( $vec4::new(19, 16, 100, 74).checked_manhattan_distance($vec4::new(14, 55, 115, 48)), Some(85) ); assert_eq!( $vec4::new(26, 2, 24, -22).checked_manhattan_distance($vec4::new(26, 23, 6, 23)), Some(84) ); assert_eq!( $vec4::new($t::MIN, $t::MIN, $t::MIN, $t::MIN) .checked_manhattan_distance($vec4::new($t::MAX, $t::MAX, $t::MAX, $t::MAX)), None ); }); glam_test!(test_chebyshev_distance, { assert_eq!( $vec4::new(41, 8, 21, 87).chebyshev_distance($vec4::new(49, 48, 28, 40)), 47 ); assert_eq!( $vec4::new(119, 16, 100, 74).chebyshev_distance($vec4::new(14, 55, 115, 48)), 105 ); assert_eq!( $vec4::new(26, 2, 24, -22).chebyshev_distance($vec4::new(26, 23, 6, 23)), 45 ); }); }; } macro_rules! impl_vec4_unsigned_integer_tests { ($t:ident, $new:ident, $vec4:ident, $vec3:ident, $vec2:ident, $mask:ident) => { impl_vec4_tests!($t, $new, $vec4, $vec3, $vec2, $mask); glam_test!(test_checked_add, { assert_eq!($vec4::MAX.checked_add($vec4::ONE), None); assert_eq!($vec4::MAX.checked_add($vec4::X), None); assert_eq!($vec4::MAX.checked_add($vec4::Y), None); assert_eq!($vec4::MAX.checked_add($vec4::Z), None); assert_eq!($vec4::MAX.checked_add($vec4::W), None); assert_eq!($vec4::MAX.checked_add($vec4::ZERO), Some($vec4::MAX)); }); glam_test!(test_checked_sub, { assert_eq!($vec4::ZERO.checked_sub($vec4::ONE), None); assert_eq!($vec4::ZERO.checked_sub($vec4::X), None); assert_eq!($vec4::ZERO.checked_sub($vec4::Y), None); assert_eq!($vec4::ZERO.checked_sub($vec4::Z), None); assert_eq!($vec4::ZERO.checked_sub($vec4::W), None); assert_eq!($vec4::ZERO.checked_sub($vec4::ZERO), Some($vec4::MIN)); }); glam_test!(test_checked_mul, { assert_eq!($vec4::MAX.checked_mul($vec4::MAX), None); assert_eq!($vec4::MAX.checked_mul($vec4::ZERO), Some($vec4::ZERO)); assert_eq!($vec4::MAX.checked_mul($vec4::ONE), Some($vec4::MAX)); assert_eq!($vec4::ZERO.checked_mul($vec4::ZERO), Some($vec4::ZERO)); assert_eq!($vec4::ONE.checked_mul($vec4::ONE), Some($vec4::ONE)); }); glam_test!(test_checked_div, { assert_eq!($vec4::MAX.checked_div($vec4::ZERO), None); assert_eq!($vec4::MAX.checked_div($vec4::X), None); assert_eq!($vec4::MAX.checked_div($vec4::Y), None); assert_eq!($vec4::MAX.checked_div($vec4::Z), None); assert_eq!($vec4::MAX.checked_div($vec4::W), None); assert_eq!($vec4::ZERO.checked_div($vec4::ONE), Some($vec4::ZERO)); assert_eq!($vec4::MAX.checked_div($vec4::ONE), Some($vec4::MAX)); }); glam_test!(test_manhattan_distance, { assert_eq!( $vec4::new(41, 8, 21, 87).manhattan_distance($vec4::new(49, 48, 128, 40)), 202 ); assert_eq!( $vec4::new(19, 16, 179, 174).manhattan_distance($vec4::new(14, 55, 115, 148)), 134 ); assert_eq!( $vec4::new(41, 8, 21, 87).checked_manhattan_distance($vec4::new(49, 48, 128, 40)), Some(202) ); assert_eq!( $vec4::new(19, 16, 179, 174) .checked_manhattan_distance($vec4::new(14, 55, 115, 148)), Some(134) ); assert_eq!( $vec4::new($t::MIN, $t::MIN, $t::MIN, $t::MIN) .checked_manhattan_distance($vec4::new($t::MAX, $t::MAX, $t::MAX, $t::MAX)), None ); }); glam_test!(test_chebyshev_distance, { assert_eq!( $vec4::new(41, 8, 21, 87).chebyshev_distance($vec4::new(49, 48, 128, 40)), 107 ); assert_eq!( $vec4::new(119, 16, 179, 174).chebyshev_distance($vec4::new(14, 55, 115, 148)), 105 ); }); }; } macro_rules! impl_vec4_eq_hash_tests { ($t:ident, $new:ident) => { glam_test!(test_ve2_hash, { use std::collections::hash_map::DefaultHasher; use std::hash::Hash; use std::hash::Hasher; let a = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let b = $new(1 as $t, 2 as $t, 3 as $t, 4 as $t); let c = $new(3 as $t, 2 as $t, 1 as $t, 4 as $t); let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); let a_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); b.hash(&mut hasher); let b_hashed = hasher.finish(); let mut hasher = DefaultHasher::new(); c.hash(&mut hasher); let c_hashed = hasher.finish(); assert_eq!(a, b); assert_eq!(a_hashed, b_hashed); assert_ne!(a, c); assert_ne!(a_hashed, c_hashed); }); }; } macro_rules! impl_vec4_float_tests { ($t:ident, $new:ident, $vec4:ident, $vec3:ident, $vec2:ident, $mask:ident) => { impl_vec4_signed_tests!($t, $new, $vec4, $vec3, $vec2, $mask); impl_vec_float_normalize_tests!($t, $vec4); glam_test!(test_vec4_nan, { assert!($vec4::NAN.is_nan()); assert!(!$vec4::NAN.is_finite()); }); glam_test!(test_funcs, { let x = $new(1.0, 0.0, 0.0, 0.0); 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!(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 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)); assert_eq!(x, (2.0 * x).normalize()); assert_eq!( 1.0 * 5.0 + 2.0 * 6.0 + 3.0 * 7.0 + 4.0 * 8.0, $new(1.0, 2.0, 3.0, 4.0).dot($new(5.0, 6.0, 7.0, 8.0)) ); 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() ); assert_eq!( 1.0 / (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_recip() ); assert!($new(2.0, 3.0, 4.0, 5.0).normalize().is_normalized()); assert_approx_eq!( $new(2.0, 3.0, 4.0, 5.0) / (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).normalize() ); assert_eq!( $new(0.5, 0.25, 0.125, 0.0625), $new(2.0, 4.0, 8.0, 16.0).recip() ); }); glam_test!(test_project_reject, { assert_eq!( $new(0.0, 0.0, 0.0, 1.0), $new(0.0, 1.0, 0.0, 1.0).project_onto($new(0.0, 0.0, 0.0, 2.0)) ); assert_eq!( $new(0.0, 1.0, 0.0, 0.0), $new(0.0, 1.0, 0.0, 1.0).reject_from($new(0.0, 0.0, 0.0, 2.0)) ); assert_eq!( $new(0.0, 0.0, 0.0, 1.0), $new(0.0, 1.0, 0.0, 1.0).project_onto_normalized($new(0.0, 0.0, 0.0, 1.0)) ); assert_eq!( $new(0.0, 1.0, 0.0, 0.0), $new(0.0, 1.0, 0.0, 1.0).reject_from_normalized($new(0.0, 0.0, 0.0, 1.0)) ); should_glam_assert!({ $vec4::ONE.project_onto($vec4::ZERO) }); should_glam_assert!({ $vec4::ONE.reject_from($vec4::ZERO) }); should_glam_assert!({ $vec4::ONE.project_onto_normalized($vec4::ONE) }); should_glam_assert!({ $vec4::ONE.reject_from_normalized($vec4::ONE) }); }); glam_test!(test_signum, { assert_eq!($vec4::ZERO.signum(), $vec4::ONE); assert_eq!((-$vec4::ZERO).signum(), -$vec4::ONE); assert_eq!($vec4::ONE.signum(), $vec4::ONE); assert_eq!((-$vec4::ONE).signum(), -$vec4::ONE); 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, { assert_eq!($vec4::ZERO.copysign(-$vec4::ZERO), -$vec4::ZERO); assert_eq!((-$vec4::ZERO).copysign(-$vec4::ZERO), -$vec4::ZERO); assert_eq!($vec4::ZERO.copysign($vec4::ZERO), $vec4::ZERO); assert_eq!((-$vec4::ZERO).copysign($vec4::ZERO), $vec4::ZERO); assert_eq!($vec4::ONE.copysign(-$vec4::ZERO), -$vec4::ONE); assert_eq!((-$vec4::ONE).copysign(-$vec4::ZERO), -$vec4::ONE); assert_eq!($vec4::ONE.copysign($vec4::ZERO), $vec4::ONE); assert_eq!((-$vec4::ONE).copysign($vec4::ZERO), $vec4::ONE); assert_eq!($vec4::ZERO.copysign(-$vec4::ONE), -$vec4::ZERO); assert_eq!((-$vec4::ZERO).copysign(-$vec4::ONE), -$vec4::ZERO); assert_eq!($vec4::ZERO.copysign($vec4::ONE), $vec4::ZERO); assert_eq!((-$vec4::ZERO).copysign($vec4::ONE), $vec4::ZERO); 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::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::NEG_INFINITY.copysign(-$vec4::ONE), $vec4::NEG_INFINITY ); assert!($vec4::NAN.copysign($vec4::ONE).is_nan_mask().all()); assert!($vec4::NAN.copysign(-$vec4::ONE).is_nan_mask().all()); }); 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(-1.0, 2.0, 3.0, -4.0).is_negative_bitmask(), 0b1001 ); assert_eq!( $vec4::new(8.0, 3.0, 1.0, -0.0).is_negative_bitmask(), 0b1000 ); assert_eq!( $vec4::new(1.0, 5.0, -3.0, 7.0).is_negative_bitmask(), 0b0100 ); assert_eq!( $vec4::new(3.0, -4.0, 1.0, 6.0).is_negative_bitmask(), 0b0010 ); assert_eq!( $vec4::new(2.0, -6.0, 5.0, -3.0).is_negative_bitmask(), 0b1010 ); }); 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); assert_eq!($vec4::new(0.0, 0.0, -15.5, 0.0).round().z, -16.0); assert_eq!($vec4::new(0.0, 0.0, 0.0, 0.0).round().z, 0.0); assert_eq!($vec4::new(0.0, 21.1, 0.0, 0.0).round().y, 21.0); assert_eq!($vec4::new(0.0, 0.0, 0.0, 11.123).round().w, 11.0); assert_eq!($vec4::new(0.0, 0.0, 11.501, 0.0).round().z, 12.0); assert_eq!( $vec4::new($t::NEG_INFINITY, $t::INFINITY, 1.0, -1.0).round(), $vec4::new($t::NEG_INFINITY, $t::INFINITY, 1.0, -1.0) ); assert!($vec4::new($t::NAN, 0.0, 0.0, 1.0).round().x.is_nan()); }); glam_test!(test_floor, { assert_eq!( $vec4::new(1.35, 1.5, -1.5, 1.999).floor(), $vec4::new(1.0, 1.0, -2.0, 1.0) ); assert_eq!( $vec4::new($t::INFINITY, $t::NEG_INFINITY, 0.0, 0.0).floor(), $vec4::new($t::INFINITY, $t::NEG_INFINITY, 0.0, 0.0) ); assert!($vec4::new(0.0, $t::NAN, 0.0, 0.0).floor().y.is_nan()); assert_eq!( $vec4::new(-0.0, -2000000.123, 10000000.123, 1000.9).floor(), $vec4::new(-0.0, -2000001.0, 10000000.0, 1000.0) ); }); glam_test!(test_fract_gl, { assert_approx_eq!( $vec4::new(1.35, 1.5, -1.5, 1.999).fract_gl(), $vec4::new(0.35, 0.5, 0.5, 0.999) ); assert_approx_eq!( $vec4::new(-0.0, -200000.123, 1000000.123, 1000.9).fract_gl(), $vec4::new(0.0, 0.877, 0.123, 0.9), 0.002 ); }); glam_test!(test_fract, { assert_approx_eq!( $vec4::new(1.35, 1.5, -1.5, 1.999).fract(), $vec4::new(0.35, 0.5, -0.5, 0.999) ); assert_approx_eq!( $vec4::new(-0.0, -200000.123, 1000000.123, 1000.9).fract(), $vec4::new(0.0, -0.123, 0.123, 0.9), 0.002 ); }); glam_test!(test_ceil, { assert_eq!( $vec4::new(1.35, 1.5, -1.5, 1234.1234).ceil(), $vec4::new(2.0, 2.0, -1.0, 1235.0) ); assert_eq!( $vec4::new($t::INFINITY, $t::NEG_INFINITY, 0.0, 0.0).ceil(), $vec4::new($t::INFINITY, $t::NEG_INFINITY, 0.0, 0.0) ); assert!($vec4::new(0.0, 0.0, $t::NAN, 0.0).ceil().z.is_nan()); assert_eq!( $vec4::new(-1234.1234, -2000000.123, 1000000.123, 1000.9).ceil(), $vec4::new(-1234.0, -2000000.0, 1000001.0, 1001.0) ); }); 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($t::INFINITY, $t::NEG_INFINITY, 0.0, 0.0).trunc(), $vec4::new($t::INFINITY, $t::NEG_INFINITY, 0.0, 0.0) ); assert!($vec4::new(0.0, $t::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); assert_approx_eq!(v0, v0.lerp(v1, 0.0)); assert_approx_eq!(v1, v0.lerp(v1, 1.0)); assert_approx_eq!($vec4::ZERO, v0.lerp(v1, 0.5)); }); glam_test!(test_lerp_big_difference, { let v0 = $vec4::new(-1e30, -1e30, -1e30, -1e30); let v1 = $vec4::new(16.0, 16.0, 16.0, 16.0); assert_approx_eq!(v0, v0.lerp(v1, 0.0)); assert_approx_eq!(v1, v0.lerp(v1, 1.0)); }); glam_test!(test_move_towards, { let v0 = $vec4::new(-1.0, -1.0, -1.0, -1.0); let v1 = $vec4::new(1.0, 1.0, 1.0, 1.0); assert_approx_eq!(v0, v0.move_towards(v1, 0.0)); assert_approx_eq!(v1, v0.move_towards(v1, v0.distance(v1))); assert_approx_eq!(v1, v0.move_towards(v1, v0.distance(v1) + 1.0)); }); glam_test!(test_midpoint, { let v0 = $vec4::new(-1.0, -1.0, -1.0, -1.0); let v1 = $vec4::new(1.0, 1.0, 1.0, 1.0); let v2 = $vec4::new(-1.5, 0.0, 1.0, 0.5); assert_approx_eq!($vec4::ZERO, v0.midpoint(v1)); assert_approx_eq!($vec4::new(-0.25, 0.5, 1.0, 0.75), v1.midpoint(v2)); }); glam_test!(test_is_finite, { assert!($vec4::new(0.0, 0.0, 0.0, 0.0).is_finite()); assert!($vec4::new(-1e-10, 1.0, 1e10, 42.0).is_finite()); assert!(!$vec4::new($t::INFINITY, 0.0, 0.0, 0.0).is_finite()); assert!(!$vec4::new(0.0, $t::NAN, 0.0, 0.0).is_finite()); assert!(!$vec4::new(0.0, 0.0, $t::NEG_INFINITY, 0.0).is_finite()); assert!(!$vec4::new(0.0, 0.0, 0.0, $t::NAN).is_finite()); assert!(!$vec4::INFINITY.is_finite()); assert!(!$vec4::NEG_INFINITY.is_finite()); }); glam_test!(test_powf, { assert_eq!( $vec4::new(2.0, 4.0, 8.0, 16.0).powf(2.0), $vec4::new(4.0, 16.0, 64.0, 256.0) ); }); glam_test!(test_exp, { assert_approx_eq!( $vec4::new(1.0, 2.0, 3.0, 4.0).exp(), $vec4::new( (1.0 as $t).exp(), (2.0 as $t).exp(), (3.0 as $t).exp(), (4.0 as $t).exp() ), 1e-5 ); }); glam_test!(test_clamp_length, { // Too long gets shortened assert_eq!( $vec4::new(12.0, 16.0, 0.0, 0.0).clamp_length(7.0, 10.0), $vec4::new(6.0, 8.0, 0.0, 0.0) // shortened to length 10.0 ); // In the middle is unchanged assert_eq!( $vec4::new(2.0, 1.0, 0.0, 0.0).clamp_length(0.5, 5.0), $vec4::new(2.0, 1.0, 0.0, 0.0) // unchanged ); // Too short gets lengthened assert_eq!( $vec4::new(0.6, 0.8, 0.0, 0.0).clamp_length(10.0, 20.0), $vec4::new(6.0, 8.0, 0.0, 0.0) // lengthened to length 10.0 ); should_glam_assert!({ $vec4::ONE.clamp_length(1.0, 0.0) }); }); glam_test!(test_clamp_length_max, { // Too long gets shortened assert_eq!( $vec4::new(12.0, 16.0, 0.0, 0.0).clamp_length_max(10.0), $vec4::new(6.0, 8.0, 0.0, 0.0) // shortened to length 10.0 ); // Not too long is unchanged assert_eq!( $vec4::new(2.0, 1.0, 0.0, 0.0).clamp_length_max(5.0), $vec4::new(2.0, 1.0, 0.0, 0.0) // unchanged ); }); glam_test!(test_clamp_length_min, { // Not too short is unchanged assert_eq!( $vec4::new(2.0, 1.0, 0.0, 0.0).clamp_length_min(0.5), $vec4::new(2.0, 1.0, 0.0, 0.0) // unchanged ); // Too short gets lengthened assert_eq!( $vec4::new(0.6, 0.8, 0.0, 0.0).clamp_length_min(10.0), $vec4::new(6.0, 8.0, 0.0, 0.0) // lengthened to length 10.0 ); }); glam_test!(test_mul_add, { assert_eq!( $vec4::new(1.0, 1.0, 1.0, 1.0).mul_add( $vec4::new(0.5, 2.0, -4.0, 0.0), $vec4::new(-1.0, -1.0, -1.0, -1.0) ), $vec4::new(-0.5, 1.0, -5.0, -1.0) ); }); glam_test!(test_fmt_float, { let a = $vec4::new(1.0, 2.0, 3.0, 4.0); assert_eq!(format!("{:.2}", a), "[1.00, 2.00, 3.00, 4.00]"); }); glam_test!(test_reflect, { let incident = $vec4::new(1.0, -1.0, 1.0, 1.0); let normal = $vec4::Y; assert_approx_eq!(incident.reflect(normal), $vec4::ONE); }); glam_test!(test_refract, { let incident = $vec4::NEG_ONE.normalize(); let normal = $vec4::ONE.normalize(); assert_approx_eq!(incident.refract(normal, 0.5), incident); let incident = $vec4::new(1.0, -1.0, 0.0, 0.0).normalize(); let normal = $vec4::Y; assert_approx_eq!(incident.refract(normal, 1.5), $vec4::ZERO); }); }; } macro_rules! impl_vec4_scalar_shift_op_test { ($vec4:ident, $t_min:literal, $t_max:literal, $rhs_min:literal, $rhs_max:literal) => { glam_test!(test_vec4_scalar_shift_ops, { for x in $t_min..$t_max { for y in $t_min..$t_max { for z in $t_min..$t_max { for w in $t_min..$t_max { for rhs in $rhs_min..$rhs_max { assert_eq!( $vec4::new(x, y, z, w) << rhs, $vec4::new(x << rhs, y << rhs, z << rhs, w << rhs) ); assert_eq!( $vec4::new(x, y, z, w) >> rhs, $vec4::new(x >> rhs, y >> rhs, z >> rhs, w >> rhs) ); } } } } } }); }; } macro_rules! impl_vec4_scalar_shift_op_tests { ($vec4:ident, $t_min:literal, $t_max:literal) => { mod shift_by_i8 { use glam::$vec4; impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0i8, 2); } mod shift_by_i16 { use glam::$vec4; impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0i16, 2); } mod shift_by_i32 { 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); } mod shift_by_u16 { use glam::$vec4; impl_vec4_scalar_shift_op_test!($vec4, $t_min, $t_max, 0u16, 2); } mod shift_by_u32 { 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); } }; } macro_rules! impl_vec4_shift_op_test { ($vec4:ident, $rhs:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec4_shift_ops, { for x1 in $t_min..$t_max { for y1 in $t_min..$t_max { for z1 in $t_min..$t_max { for w1 in $t_min..$t_max { for x2 in $t_min..$t_max { for y2 in $t_min..$t_max { for z2 in $t_min..$t_max { for w2 in $t_min..$t_max { assert_eq!( $vec4::new(x1, y1, z1, w1) << $rhs::new(x2, y2, z2, w2), $vec4::new(x1 << x2, y1 << y2, z1 << z2, w1 << w2) ); assert_eq!( $vec4::new(x1, y1, z1, w1) >> $rhs::new(x2, y2, z2, w2), $vec4::new(x1 >> x2, y1 >> y2, z1 >> z2, w1 >> w2) ); } } } } } } } } }); }; } macro_rules! impl_vec4_shift_op_tests { ($vec4:ident) => { mod shift_ivec4_by_ivec4 { use super::*; impl_vec4_shift_op_test!($vec4, IVec4, 0, 2); } mod shift_ivec4_by_uvec4 { use super::*; impl_vec4_shift_op_test!($vec4, UVec4, 0, 2); } }; } macro_rules! impl_vec4_scalar_bit_op_tests { ($vec4:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec4_scalar_bit_ops, { for x in $t_min..$t_max { for y in $t_min..$t_max { for z in $t_min..$t_max { for w in $t_min..$t_max { for rhs in $t_min..$t_max { assert_eq!( $vec4::new(x, y, z, w) & rhs, $vec4::new(x & rhs, y & rhs, z & rhs, w & rhs) ); assert_eq!( $vec4::new(x, y, z, w) | rhs, $vec4::new(x | rhs, y | rhs, z | rhs, w | rhs) ); assert_eq!( $vec4::new(x, y, z, w) ^ rhs, $vec4::new(x ^ rhs, y ^ rhs, z ^ rhs, w ^ rhs) ); } } } } } }); }; } macro_rules! impl_vec4_bit_op_tests { ($vec4:ident, $t_min:literal, $t_max:literal) => { glam_test!(test_vec4_bit_ops, { for x1 in $t_min..$t_max { for y1 in $t_min..$t_max { for z1 in $t_min..$t_max { for w1 in $t_min..$t_max { assert_eq!(!$vec4::new(x1, y1, z1, w1), $vec4::new(!x1, !y1, !z1, !w1)); for x2 in $t_min..$t_max { for y2 in $t_min..$t_max { for z2 in $t_min..$t_max { for w2 in $t_min..$t_max { assert_eq!( $vec4::new(x1, y1, z1, w1) & $vec4::new(x2, y2, z2, w2), $vec4::new(x1 & x2, y1 & y2, z1 & z2, w1 & w2) ); assert_eq!( $vec4::new(x1, y1, z1, w1) | $vec4::new(x2, y2, z2, w2), $vec4::new(x1 | x2, y1 | y2, z1 | z2, w1 | w2) ); assert_eq!( $vec4::new(x1, y1, z1, w1) ^ $vec4::new(x2, y2, z2, w2), $vec4::new(x1 ^ x2, y1 ^ y2, z1 ^ z2, w1 ^ w2) ); } } } } } } } } }); }; } mod bvec4 { use glam::{bvec4, BVec4}; glam_test!(test_mask_align, { use std::mem; assert_eq!(4, mem::size_of::()); assert_eq!(1, mem::align_of::()); }); impl_bvec4_tests!(BVec4, bvec4); } mod bvec4a { use glam::{bvec4a, BVec4A}; glam_test!(test_mask_align, { use std::mem; assert_eq!(16, mem::size_of::()); assert_eq!(16, mem::align_of::()); }); impl_bvec4_tests!(BVec4A, bvec4a); } mod vec4 { #[cfg(feature = "scalar-math")] use glam::BVec4; #[cfg(not(feature = "scalar-math"))] use glam::BVec4A; use glam::{vec4, Vec2, Vec3, Vec4}; glam_test!(test_align, { use std::mem; assert_eq!(16, mem::size_of::()); if cfg!(any(not(feature = "scalar-math"), feature = "cuda")) { assert_eq!(16, mem::align_of::()); } else { assert_eq!(4, mem::align_of::()); } }); #[cfg(all( target_feature = "sse2", not(any(feature = "core-simd", feature = "scalar-math")) ))] #[test] fn test_m128() { #[cfg(target_arch = "x86")] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::*; #[repr(C, align(16))] struct F32x4_A16([f32; 4]); let v0 = Vec4::new(1.0, 2.0, 3.0, 4.0); let m0: __m128 = v0.into(); let mut a0 = F32x4_A16([0.0, 0.0, 0.0, 0.0]); unsafe { _mm_store_ps(a0.0.as_mut_ptr(), m0); } assert_eq!([1.0, 2.0, 3.0, 4.0], a0.0); let v1 = Vec4::from(m0); assert_eq!(v0, v1); #[repr(C, align(16))] struct U32x4_A16([u32; 4]); let v0 = BVec4A::new(true, false, true, false); let m0: __m128 = v0.into(); let mut a0 = U32x4_A16([1, 2, 3, 4]); unsafe { _mm_store_ps(a0.0.as_mut_ptr() as *mut f32, m0); } assert_eq!([0xffffffff, 0, 0xffffffff, 0], a0.0); } glam_test!(test_as, { use glam::{ DVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, 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!( I8Vec4::new(-1, -2, -3, -4), Vec4::new(-1.0, -2.0, -3.0, -4.0).as_i8vec4() ); assert_eq!( U8Vec4::new(1, 2, 3, 4), Vec4::new(1.0, 2.0, 3.0, 4.0).as_u8vec4() ); 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() ); assert_eq!( 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!( USizeVec4::new(1, 2, 3, 4), Vec4::new(1.0, 2.0, 3.0, 4.0).as_usizevec4() ); 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!( I8Vec4::new(-1, -2, -3, -4), DVec4::new(-1.0, -2.0, -3.0, -4.0).as_i8vec4() ); assert_eq!( U8Vec4::new(1, 2, 3, 4), DVec4::new(1.0, 2.0, 3.0, 4.0).as_u8vec4() ); 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() ); assert_eq!( UVec4::new(1, 2, 3, 4), DVec4::new(1.0, 2.0, 3.0, 4.0).as_uvec4() ); assert_eq!( 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!( USizeVec4::new(1, 2, 3, 4), DVec4::new(1.0, 2.0, 3.0, 4.0).as_usizevec4() ); assert_eq!( Vec4::new(-1.0, -2.0, -3.0, -4.0), I8Vec4::new(-1, -2, -3, -4).as_vec4() ); assert_eq!( DVec4::new(-1.0, -2.0, -3.0, -4.0), I8Vec4::new(-1, -2, -3, -4).as_dvec4() ); assert_eq!(U8Vec4::new(1, 2, 3, 4), I8Vec4::new(1, 2, 3, 4).as_u8vec4()); assert_eq!( I16Vec4::new(-1, -2, -3, -4), I8Vec4::new(-1, -2, -3, -4).as_i16vec4() ); assert_eq!( U16Vec4::new(1, 2, 3, 4), I8Vec4::new(1, 2, 3, 4).as_u16vec4() ); assert_eq!( IVec4::new(-1, -2, -3, -4), I8Vec4::new(-1, -2, -3, -4).as_ivec4() ); assert_eq!(UVec4::new(1, 2, 3, 4), I8Vec4::new(1, 2, 3, 4).as_uvec4()); assert_eq!( I64Vec4::new(-1, -2, -3, -4), I8Vec4::new(-1, -2, -3, -4).as_i64vec4() ); assert_eq!( U64Vec4::new(1, 2, 3, 4), I8Vec4::new(1, 2, 3, 4).as_u64vec4() ); assert_eq!( USizeVec4::new(1, 2, 3, 4), I8Vec4::new(1, 2, 3, 4).as_usizevec4() ); assert_eq!( Vec4::new(1.0, 2.0, 3.0, 4.0), U8Vec4::new(1, 2, 3, 4).as_vec4() ); assert_eq!( DVec4::new(1.0, 2.0, 3.0, 4.0), U8Vec4::new(1, 2, 3, 4).as_dvec4() ); assert_eq!(I8Vec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_i8vec4()); assert_eq!( I16Vec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_i16vec4() ); assert_eq!( U16Vec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_u16vec4() ); assert_eq!(IVec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_ivec4()); assert_eq!(UVec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_uvec4()); assert_eq!( I64Vec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_i64vec4() ); assert_eq!( U64Vec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_u64vec4() ); assert_eq!( USizeVec4::new(1, 2, 3, 4), U8Vec4::new(1, 2, 3, 4).as_usizevec4() ); 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!( I8Vec4::new(-1, -2, -3, -4), I16Vec4::new(-1, -2, -3, -4).as_i8vec4() ); assert_eq!( U8Vec4::new(1, 2, 3, 4), I16Vec4::new(1, 2, 3, 4).as_u8vec4() ); 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!( USizeVec4::new(1, 2, 3, 4), I16Vec4::new(1, 2, 3, 4).as_usizevec4() ); 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!( I8Vec4::new(1, 2, 3, 4), U16Vec4::new(1, 2, 3, 4).as_i8vec4() ); assert_eq!( U8Vec4::new(1, 2, 3, 4), U16Vec4::new(1, 2, 3, 4).as_u8vec4() ); 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!( USizeVec4::new(1, 2, 3, 4), U16Vec4::new(1, 2, 3, 4).as_usizevec4() ); 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!( I8Vec4::new(-1, -2, -3, -4), IVec4::new(-1, -2, -3, -4).as_i8vec4() ); assert_eq!(U8Vec4::new(1, 2, 3, 4), IVec4::new(1, 2, 3, 4).as_u8vec4()); assert_eq!(UVec4::new(1, 2, 3, 4), IVec4::new(1, 2, 3, 4).as_uvec4()); assert_eq!( 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!( USizeVec4::new(1, 2, 3, 4), IVec4::new(1, 2, 3, 4).as_usizevec4() ); 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!(I8Vec4::new(1, 2, 3, 4), UVec4::new(1, 2, 3, 4).as_i8vec4()); assert_eq!(U8Vec4::new(1, 2, 3, 4), UVec4::new(1, 2, 3, 4).as_u8vec4()); 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!( USizeVec4::new(1, 2, 3, 4), UVec4::new(1, 2, 3, 4).as_usizevec4() ); 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!( U8Vec4::new(1, 2, 3, 4), I64Vec4::new(1, 2, 3, 4).as_u8vec4() ); assert_eq!( I8Vec4::new(-1, -2, -3, -4), I64Vec4::new(-1, -2, -3, -4).as_i8vec4() ); 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!( USizeVec4::new(1, 2, 3, 4), I64Vec4::new(1, 2, 3, 4).as_usizevec4() ); assert_eq!( Vec4::new(1.0, 2.0, 3.0, 4.0), 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!( I8Vec4::new(1, 2, 3, 4), U64Vec4::new(1, 2, 3, 4).as_i8vec4() ); assert_eq!( U8Vec4::new(1, 2, 3, 4), U64Vec4::new(1, 2, 3, 4).as_u8vec4() ); 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() ); assert_eq!( USizeVec4::new(1, 2, 3, 4), U64Vec4::new(1, 2, 3, 4).as_usizevec4() ); assert_eq!( Vec4::new(1.0, 2.0, 3.0, 4.0), USizeVec4::new(1, 2, 3, 4).as_vec4() ); assert_eq!( DVec4::new(1.0, 2.0, 3.0, 4.0), USizeVec4::new(1, 2, 3, 4).as_dvec4() ); assert_eq!( I8Vec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_i8vec4() ); assert_eq!( U8Vec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_u8vec4() ); assert_eq!( I16Vec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_i16vec4() ); assert_eq!( U16Vec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_u16vec4() ); assert_eq!( IVec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_ivec4() ); assert_eq!( UVec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_uvec4() ); assert_eq!( I64Vec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_i64vec4() ); assert_eq!( U64Vec4::new(1, 2, 3, 4), USizeVec4::new(1, 2, 3, 4).as_u64vec4() ); }); glam_test!(test_vec3a, { use glam::Vec3A; assert_eq!( Vec4::new(1.0, 2.0, 3.0, 4.0), Vec4::from((Vec3A::new(1.0, 2.0, 3.0), 4.0)) ); assert_eq!( Vec4::new(1.0, 2.0, 3.0, 4.0), Vec4::from((1.0, Vec3A::new(2.0, 3.0, 4.0))) ); }); #[cfg(not(feature = "scalar-math"))] impl_vec4_float_tests!(f32, vec4, Vec4, Vec3, Vec2, BVec4A); #[cfg(feature = "scalar-math")] impl_vec4_float_tests!(f32, vec4, Vec4, Vec3, Vec2, BVec4); } mod dvec4 { use glam::{dvec4, BVec4, DVec2, DVec3, DVec4, IVec4, UVec4, Vec4}; glam_test!(test_align, { use std::mem; assert_eq!(32, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(mem::align_of::(), mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); 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 i8vec4 { use glam::{ i8vec4, BVec4, I16Vec4, I64Vec4, I8Vec2, I8Vec3, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(4, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(1, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(4, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(U8Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(U8Vec4::new(u8::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(U8Vec4::new(1, u8::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(U8Vec4::new(1, 2, u8::MAX, 4)).is_err()); assert!(I8Vec4::try_from(U8Vec4::new(1, 2, 3, u8::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(I16Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(I16Vec4::new(i16::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(I16Vec4::new(1, i16::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(I16Vec4::new(1, 2, i16::MAX, 4)).is_err()); assert!(I8Vec4::try_from(I16Vec4::new(1, 2, 3, i16::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(U16Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(U16Vec4::new(u16::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(U16Vec4::new(1, u16::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(U16Vec4::new(1, 2, u16::MAX, 4)).is_err()); assert!(I8Vec4::try_from(U16Vec4::new(1, 2, 3, u16::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(IVec4::new(i32::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(IVec4::new(1, i32::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(IVec4::new(1, 2, i32::MAX, 4)).is_err()); assert!(I8Vec4::try_from(IVec4::new(1, 2, 3, i32::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(UVec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(UVec4::new(u32::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(UVec4::new(1, u32::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(UVec4::new(1, 2, u32::MAX, 4)).is_err()); assert!(I8Vec4::try_from(UVec4::new(1, 2, 3, u32::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(I64Vec4::new(i64::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(I64Vec4::new(1, i64::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(I64Vec4::new(1, 2, i64::MAX, 4)).is_err()); assert!(I8Vec4::try_from(I64Vec4::new(1, 2, 3, i64::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err()); assert!(I8Vec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err()); assert_eq!( I8Vec4::new(1, 2, 3, 4), I8Vec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); assert!(I8Vec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(I8Vec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(I8Vec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(I8Vec4::try_from(USizeVec4::new(1, 2, 3, usize::MAX)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( I8Vec4::new(i8::MAX, 5, i8::MIN, 0).wrapping_add(I8Vec4::new(1, 3, i8::MAX, 0)), I8Vec4::new(i8::MIN, 8, -1, 0), ); }); glam_test!(test_wrapping_sub, { assert_eq!( I8Vec4::new(i8::MAX, 5, i8::MIN, 0).wrapping_sub(I8Vec4::new(1, 3, i8::MAX, 0)), I8Vec4::new(126, 2, 1, 0) ); }); glam_test!(test_wrapping_mul, { assert_eq!( I8Vec4::new(i8::MAX, 5, i8::MIN, 0).wrapping_mul(I8Vec4::new(3, 3, 5, 1)), I8Vec4::new(125, 15, -128, 0) ); }); glam_test!(test_wrapping_div, { assert_eq!( I8Vec4::new(i8::MAX, 5, i8::MIN, 0).wrapping_div(I8Vec4::new(3, 3, 5, 1)), I8Vec4::new(42, 1, -25, 0) ); }); glam_test!(test_saturating_add, { assert_eq!( I8Vec4::new(i8::MAX, i8::MIN, 0, 0).saturating_add(I8Vec4::new(1, -1, 2, 3)), I8Vec4::new(i8::MAX, i8::MIN, 2, 3) ); }); glam_test!(test_saturating_sub, { assert_eq!( I8Vec4::new(i8::MIN, i8::MAX, 0, 0).saturating_sub(I8Vec4::new(1, -1, 2, 3)), I8Vec4::new(i8::MIN, i8::MAX, -2, -3) ); }); glam_test!(test_saturating_mul, { assert_eq!( I8Vec4::new(i8::MAX, i8::MIN, 0, 0).saturating_mul(I8Vec4::new(2, 2, 0, 0)), I8Vec4::new(i8::MAX, i8::MIN, 0, 0) ); }); glam_test!(test_saturating_div, { assert_eq!( I8Vec4::new(i8::MAX, i8::MIN, 0, 0).saturating_div(I8Vec4::new(2, 2, 3, 4)), I8Vec4::new(63, -64, 0, 0) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(I8Vec4::MAX.checked_add_unsigned(U8Vec4::ONE), None); assert_eq!( I8Vec4::NEG_ONE.checked_add_unsigned(U8Vec4::ONE), Some(I8Vec4::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I8Vec4::MIN.checked_sub_unsigned(U8Vec4::ONE), None); assert_eq!( I8Vec4::ZERO.checked_sub_unsigned(U8Vec4::ONE), Some(I8Vec4::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I8Vec4::new(i8::MAX, i8::MAX, i8::MAX, i8::MAX) .wrapping_add_unsigned(U8Vec4::new(1, 1, 1, 1)), I8Vec4::new(i8::MIN, i8::MIN, i8::MIN, i8::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I8Vec4::new(i8::MIN, i8::MIN, i8::MIN, i8::MIN) .wrapping_sub_unsigned(U8Vec4::new(1, 1, 1, 1)), I8Vec4::new(i8::MAX, i8::MAX, i8::MAX, i8::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I8Vec4::new(i8::MAX, i8::MAX, i8::MAX, i8::MAX) .saturating_add_unsigned(U8Vec4::new(1, 1, 1, 1)), I8Vec4::new(i8::MAX, i8::MAX, i8::MAX, i8::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I8Vec4::new(i8::MIN, i8::MIN, i8::MIN, i8::MIN) .saturating_sub_unsigned(U8Vec4::new(1, 1, 1, 1)), I8Vec4::new(i8::MIN, i8::MIN, i8::MIN, i8::MIN) ); }); impl_vec4_signed_integer_tests!(i8, i8vec4, I8Vec4, I8Vec3, I8Vec2, BVec4); impl_vec4_eq_hash_tests!(i8, i8vec4); impl_vec4_scalar_shift_op_tests!(I8Vec4, -2, 2); impl_vec4_shift_op_tests!(I8Vec4); impl_vec4_scalar_bit_op_tests!(I8Vec4, -2, 2); impl_vec4_bit_op_tests!(I8Vec4, -2, 2); } mod u8vec4 { use glam::{ u8vec4, BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec2, U8Vec3, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(4, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(1, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(4, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(I8Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(I8Vec4::new(-1, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I8Vec4::new(1, -2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I8Vec4::new(1, 2, -3, 4)).is_err()); assert!(U8Vec4::try_from(I8Vec4::new(1, 2, 3, -4)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(I16Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(I16Vec4::new(-1, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(1, -2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(1, 2, -3, 4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(1, 2, 3, -4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(i16::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(1, i16::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(1, 2, i16::MAX, 4)).is_err()); assert!(U8Vec4::try_from(I16Vec4::new(1, 2, 3, i16::MAX)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(U16Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(U16Vec4::new(u16::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(U16Vec4::new(1, u16::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(U16Vec4::new(1, 2, u16::MAX, 4)).is_err()); assert!(U8Vec4::try_from(U16Vec4::new(1, 2, 3, u16::MAX)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(IVec4::new(-1, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(1, -2, 3, 4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(1, 2, -3, 4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(1, 2, 3, -4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(i32::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(1, i32::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(1, 2, i32::MAX, 4)).is_err()); assert!(U8Vec4::try_from(IVec4::new(1, 2, 3, i32::MAX)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(UVec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(UVec4::new(u32::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(UVec4::new(1, u32::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(UVec4::new(1, 2, u32::MAX, 4)).is_err()); assert!(U8Vec4::try_from(UVec4::new(1, 2, 3, u32::MAX)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(I64Vec4::new(-1, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(1, -2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(1, 2, -3, 4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(1, 2, 3, -4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(i64::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(1, i64::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(1, 2, i64::MAX, 4)).is_err()); assert!(U8Vec4::try_from(I64Vec4::new(1, 2, 3, i64::MAX)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(U64Vec4::new(u64::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(U64Vec4::new(1, u64::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(U64Vec4::new(1, 2, u64::MAX, 4)).is_err()); assert!(U8Vec4::try_from(U64Vec4::new(1, 2, 3, u64::MAX)).is_err()); assert_eq!( U8Vec4::new(1, 2, 3, 4), U8Vec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); assert!(U8Vec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(U8Vec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(U8Vec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(U8Vec4::try_from(USizeVec4::new(1, 2, 3, usize::MAX)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( U8Vec4::new(u8::MAX, 5, u8::MAX, 0).wrapping_add(U8Vec4::new(1, 3, u8::MAX, 0)), U8Vec4::new(0, 8, 254, 0), ); }); glam_test!(test_wrapping_sub, { assert_eq!( U8Vec4::new(u8::MAX, 5, u8::MAX - 1, 0).wrapping_sub(U8Vec4::new(1, 3, u8::MAX, 0)), U8Vec4::new(254, 2, 255, 0) ); }); glam_test!(test_wrapping_mul, { assert_eq!( U8Vec4::new(u8::MAX, 5, u8::MAX, 0).wrapping_mul(U8Vec4::new(3, 3, 5, 1)), U8Vec4::new(253, 15, 251, 0) ); }); glam_test!(test_wrapping_div, { assert_eq!( U8Vec4::new(u8::MAX, 5, u8::MAX, 0).wrapping_div(U8Vec4::new(3, 3, 5, 1)), U8Vec4::new(85, 1, 51, 0) ); }); glam_test!(test_saturating_add, { assert_eq!( U8Vec4::new(u8::MAX, u8::MAX, 0, 0).saturating_add(U8Vec4::new(1, u8::MAX, 2, 3)), U8Vec4::new(u8::MAX, u8::MAX, 2, 3) ); }); glam_test!(test_saturating_sub, { assert_eq!( U8Vec4::new(0, u8::MAX, 0, 0).saturating_sub(U8Vec4::new(1, 1, 2, 3)), U8Vec4::new(0, 254, 0, 0) ); }); glam_test!(test_saturating_mul, { assert_eq!( U8Vec4::new(u8::MAX, u8::MAX, 0, 0).saturating_mul(U8Vec4::new(2, u8::MAX, 0, 0)), U8Vec4::new(u8::MAX, u8::MAX, 0, 0) ); }); glam_test!(test_saturating_div, { assert_eq!( U8Vec4::new(u8::MAX, u8::MAX, 0, 0).saturating_div(U8Vec4::new(2, u8::MAX, 3, 4)), U8Vec4::new(127, 1, 0, 0) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U8Vec4::new(u8::MAX, u8::MAX, u8::MAX, u8::MAX) .wrapping_add_signed(I8Vec4::new(1, 1, 1, 1)), U8Vec4::new(u8::MIN, u8::MIN, u8::MIN, u8::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U8Vec4::new(u8::MAX, u8::MAX, u8::MAX, u8::MAX) .saturating_add_signed(I8Vec4::new(1, 1, 1, 1)), U8Vec4::new(u8::MAX, u8::MAX, u8::MAX, u8::MAX) ); }); impl_vec4_unsigned_integer_tests!(u8, u8vec4, U8Vec4, U8Vec3, U8Vec2, BVec4); impl_vec4_eq_hash_tests!(u8, u8vec4); impl_vec4_scalar_shift_op_tests!(U8Vec4, 0, 2); impl_vec4_shift_op_tests!(U8Vec4); impl_vec4_scalar_bit_op_tests!(U8Vec4, 0, 2); impl_vec4_bit_op_tests!(U8Vec4, 0, 2); } mod i16vec4 { use glam::{ i16vec4, BVec4, I16Vec2, I16Vec3, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(8, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(2, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(8, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( I16Vec4::new(1, 2, 3, 4), I16Vec4::from(U8Vec4::new(1, 2, 3, 4)) ); assert_eq!( I16Vec4::new(1, 2, 3, 4), I16Vec4::from(I8Vec4::new(1, 2, 3, 4)) ); 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()); assert_eq!( I16Vec4::new(1, 2, 3, 4), I16Vec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); assert!(I16Vec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(I16Vec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(I16Vec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(I16Vec4::try_from(USizeVec4::new(1, 2, 3, usize::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) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(I16Vec4::MAX.checked_add_unsigned(U16Vec4::ONE), None); assert_eq!( I16Vec4::NEG_ONE.checked_add_unsigned(U16Vec4::ONE), Some(I16Vec4::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I16Vec4::MIN.checked_sub_unsigned(U16Vec4::ONE), None); assert_eq!( I16Vec4::ZERO.checked_sub_unsigned(U16Vec4::ONE), Some(I16Vec4::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX) .wrapping_add_unsigned(U16Vec4::new(1, 1, 1, 1)), I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN) .wrapping_sub_unsigned(U16Vec4::new(1, 1, 1, 1)), I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX) .saturating_add_unsigned(U16Vec4::new(1, 1, 1, 1)), I16Vec4::new(i16::MAX, i16::MAX, i16::MAX, i16::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN) .saturating_sub_unsigned(U16Vec4::new(1, 1, 1, 1)), I16Vec4::new(i16::MIN, i16::MIN, i16::MIN, i16::MIN) ); }); 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, I8Vec4, IVec4, U16Vec2, U16Vec3, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(8, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(2, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(8, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U16Vec4::new(1, 2, 3, 4), U16Vec4::try_from(I8Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U16Vec4::try_from(I8Vec4::new(-1, 2, 3, 4)).is_err()); assert!(U16Vec4::try_from(I8Vec4::new(1, -2, 3, 4)).is_err()); assert!(U16Vec4::try_from(I8Vec4::new(1, 2, -3, 4)).is_err()); assert!(U16Vec4::try_from(I8Vec4::new(1, 2, 3, -4)).is_err()); assert_eq!( U16Vec4::new(1, 2, 3, 4), U16Vec4::from(U8Vec4::new(1, 2, 3, 4)) ); 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()); assert_eq!( U16Vec4::new(1, 2, 3, 4), U16Vec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); assert!(U16Vec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(U16Vec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(U16Vec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(U16Vec4::try_from(USizeVec4::new(1, 2, 3, usize::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) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U16Vec4::new(u16::MAX, u16::MAX, u16::MAX, u16::MAX) .wrapping_add_signed(I16Vec4::new(1, 1, 1, 1)), U16Vec4::new(u16::MIN, u16::MIN, u16::MIN, u16::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U16Vec4::new(u16::MAX, u16::MAX, u16::MAX, u16::MAX) .saturating_add_signed(I16Vec4::new(1, 1, 1, 1)), U16Vec4::new(u16::MAX, u16::MAX, u16::MAX, u16::MAX) ); }); impl_vec4_unsigned_integer_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, I16Vec4, I64Vec4, I8Vec4, IVec2, IVec3, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(16, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(4, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!(IVec4::new(1, 2, 3, 4), IVec4::from(U8Vec4::new(1, 2, 3, 4))); assert_eq!(IVec4::new(1, 2, 3, 4), IVec4::from(I8Vec4::new(1, 2, 3, 4))); 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()); assert_eq!( IVec4::new(1, 2, 3, 4), IVec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); assert!(IVec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(IVec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(IVec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(IVec4::try_from(USizeVec4::new(1, 2, 3, usize::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) ); }); glam_test!(test_checked_add_unsigned, { assert_eq!(IVec4::MAX.checked_add_unsigned(UVec4::ONE), None); assert_eq!( IVec4::NEG_ONE.checked_add_unsigned(UVec4::ONE), Some(IVec4::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(IVec4::MIN.checked_sub_unsigned(UVec4::ONE), None); assert_eq!( IVec4::ZERO.checked_sub_unsigned(UVec4::ONE), Some(IVec4::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX) .wrapping_add_unsigned(UVec4::new(1, 1, 1, 1)), IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN) .wrapping_sub_unsigned(UVec4::new(1, 1, 1, 1)), IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX) .saturating_add_unsigned(UVec4::new(1, 1, 1, 1)), IVec4::new(i32::MAX, i32::MAX, i32::MAX, i32::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN) .saturating_sub_unsigned(UVec4::new(1, 1, 1, 1)), IVec4::new(i32::MIN, i32::MIN, i32::MIN, i32::MIN) ); }); 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); impl_vec4_shift_op_tests!(IVec4); impl_vec4_scalar_bit_op_tests!(IVec4, -2, 2); impl_vec4_bit_op_tests!(IVec4, -2, 2); } mod uvec4 { use glam::{ uvec4, BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec2, UVec3, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(16, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(4, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( UVec4::new(1, 2, 3, 4), UVec4::try_from(I8Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(UVec4::try_from(I8Vec4::new(-1, 2, 3, 4)).is_err()); assert!(UVec4::try_from(I8Vec4::new(1, -2, 3, 4)).is_err()); assert!(UVec4::try_from(I8Vec4::new(1, 2, -3, 4)).is_err()); assert!(UVec4::try_from(I8Vec4::new(1, 2, 3, -4)).is_err()); assert_eq!(UVec4::new(1, 2, 3, 4), UVec4::from(U8Vec4::new(1, 2, 3, 4))); 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()); assert_eq!( UVec4::new(1, 2, 3, 4), UVec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); if core::mem::size_of::() > 4 { assert!(UVec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(UVec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(UVec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(UVec4::try_from(USizeVec4::new(1, 2, 3, usize::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) ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( UVec4::new(u32::MAX, u32::MAX, u32::MAX, u32::MAX) .wrapping_add_signed(IVec4::new(1, 1, 1, 1)), UVec4::new(u32::MIN, u32::MIN, u32::MIN, u32::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( UVec4::new(u32::MAX, u32::MAX, u32::MAX, u32::MAX) .saturating_add_signed(IVec4::new(1, 1, 1, 1)), UVec4::new(u32::MAX, u32::MAX, u32::MAX, u32::MAX) ); }); impl_vec4_unsigned_integer_tests!(u32, uvec4, UVec4, UVec3, UVec2, BVec4); impl_vec4_eq_hash_tests!(u32, uvec4); impl_vec4_scalar_shift_op_tests!(UVec4, 0, 2); impl_vec4_shift_op_tests!(UVec4); 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, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(32, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(8, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( I64Vec4::new(1, 2, 3, 4), I64Vec4::from(I8Vec4::new(1, 2, 3, 4)) ); assert_eq!( I64Vec4::new(1, 2, 3, 4), I64Vec4::from(U8Vec4::new(1, 2, 3, 4)) ); 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()); assert_eq!( I64Vec4::new(1, 2, 3, 4), I64Vec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); if core::mem::size_of::() > 4 { assert!(I64Vec4::try_from(USizeVec4::new(usize::MAX, 2, 3, 4)).is_err()); assert!(I64Vec4::try_from(USizeVec4::new(1, usize::MAX, 3, 4)).is_err()); assert!(I64Vec4::try_from(USizeVec4::new(1, 2, usize::MAX, 4)).is_err()); assert!(I64Vec4::try_from(USizeVec4::new(1, 2, 3, usize::MAX)).is_err()); } }); glam_test!(test_checked_add_unsigned, { assert_eq!(I64Vec4::MAX.checked_add_unsigned(U64Vec4::ONE), None); assert_eq!( I64Vec4::NEG_ONE.checked_add_unsigned(U64Vec4::ONE), Some(I64Vec4::ZERO) ); }); glam_test!(test_checked_sub_unsigned, { assert_eq!(I64Vec4::MIN.checked_sub_unsigned(U64Vec4::ONE), None); assert_eq!( I64Vec4::ZERO.checked_sub_unsigned(U64Vec4::ONE), Some(I64Vec4::NEG_ONE) ); }); glam_test!(test_wrapping_add_unsigned, { assert_eq!( I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX) .wrapping_add_unsigned(U64Vec4::new(1, 1, 1, 1)), I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN) ); }); glam_test!(test_wrapping_sub_unsigned, { assert_eq!( I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN) .wrapping_sub_unsigned(U64Vec4::new(1, 1, 1, 1)), I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX) ); }); glam_test!(test_saturating_add_unsigned, { assert_eq!( I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX) .saturating_add_unsigned(U64Vec4::new(1, 1, 1, 1)), I64Vec4::new(i64::MAX, i64::MAX, i64::MAX, i64::MAX) ); }); glam_test!(test_saturating_sub_unsigned, { assert_eq!( I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN) .saturating_sub_unsigned(U64Vec4::new(1, 1, 1, 1)), I64Vec4::new(i64::MIN, i64::MIN, i64::MIN, i64::MIN) ); }); 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, I8Vec4, IVec4, U16Vec4, U64Vec2, U64Vec3, U64Vec4, U8Vec4, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(32, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(8, mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( U64Vec4::new(1, 2, 3, 4), U64Vec4::try_from(I8Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(U64Vec4::try_from(I8Vec4::new(-1, 2, 3, 4)).is_err()); assert!(U64Vec4::try_from(I8Vec4::new(1, -2, 3, 4)).is_err()); assert!(U64Vec4::try_from(I8Vec4::new(1, 2, -3, 4)).is_err()); assert!(U64Vec4::try_from(I8Vec4::new(1, 2, 3, -4)).is_err()); assert_eq!( U64Vec4::new(1, 2, 3, 4), U64Vec4::from(U8Vec4::new(1, 2, 3, 4)) ); 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()); assert_eq!( U64Vec4::new(1, 2, 3, 4), U64Vec4::try_from(USizeVec4::new(1, 2, 3, 4)).unwrap() ); }); glam_test!(test_wrapping_add_signed, { assert_eq!( U64Vec4::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX) .wrapping_add_signed(I64Vec4::new(1, 1, 1, 1)), U64Vec4::new(u64::MIN, u64::MIN, u64::MIN, u64::MIN) ); }); glam_test!(test_saturating_add_signed, { assert_eq!( U64Vec4::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX) .saturating_add_signed(I64Vec4::new(1, 1, 1, 1)), U64Vec4::new(u64::MAX, u64::MAX, u64::MAX, u64::MAX) ); }); impl_vec4_unsigned_integer_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); } mod usizevec4 { use glam::{ usizevec4, BVec4, I16Vec4, I64Vec4, I8Vec4, IVec4, U16Vec4, U64Vec4, U8Vec4, USizeVec2, USizeVec3, USizeVec4, UVec4, }; glam_test!(test_align, { use std::mem; assert_eq!(mem::size_of::() * 4, mem::size_of::()); #[cfg(not(feature = "cuda"))] assert_eq!(mem::align_of::(), mem::align_of::()); #[cfg(feature = "cuda")] assert_eq!(16, mem::align_of::()); }); glam_test!(test_try_from, { assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::try_from(I8Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(USizeVec4::try_from(I8Vec4::new(-1, 2, 3, 4)).is_err()); assert!(USizeVec4::try_from(I8Vec4::new(1, -2, 3, 4)).is_err()); assert!(USizeVec4::try_from(I8Vec4::new(1, 2, -3, 4)).is_err()); assert!(USizeVec4::try_from(I8Vec4::new(1, 2, 3, -4)).is_err()); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::from(U8Vec4::new(1, 2, 3, 4)) ); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::try_from(I16Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(USizeVec4::try_from(I16Vec4::new(-1, 2, 3, 4)).is_err()); assert!(USizeVec4::try_from(I16Vec4::new(1, -2, 3, 4)).is_err()); assert!(USizeVec4::try_from(I16Vec4::new(1, 2, -3, 4)).is_err()); assert!(USizeVec4::try_from(I16Vec4::new(1, 2, 3, -4)).is_err()); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::from(U16Vec4::new(1, 2, 3, 4)) ); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::try_from(IVec4::new(1, 2, 3, 4)).unwrap() ); assert!(USizeVec4::try_from(IVec4::new(-1, 2, 3, 4)).is_err()); assert!(USizeVec4::try_from(IVec4::new(1, -2, 3, 4)).is_err()); assert!(USizeVec4::try_from(IVec4::new(1, 2, -3, 4)).is_err()); assert!(USizeVec4::try_from(IVec4::new(1, 2, 3, -4)).is_err()); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::try_from(UVec4::new(1, 2, 3, 4)).unwrap() ); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::try_from(U64Vec4::new(1, 2, 3, 4)).unwrap() ); assert_eq!( USizeVec4::new(1, 2, 3, 4), USizeVec4::try_from(I64Vec4::new(1, 2, 3, 4)).unwrap() ); assert!(USizeVec4::try_from(I64Vec4::new(-1, 2, 3, 4)).is_err()); assert!(USizeVec4::try_from(I64Vec4::new(1, -2, 3, 4)).is_err()); assert!(USizeVec4::try_from(I64Vec4::new(1, 2, -3, 4)).is_err()); assert!(USizeVec4::try_from(I64Vec4::new(1, 2, 3, -4)).is_err()); }); glam_test!(test_wrapping_add, { assert_eq!( USizeVec4::new(usize::MAX, 5, usize::MAX, 0).wrapping_add(USizeVec4::new( 1, 3, usize::MAX, 0 )), USizeVec4::new(0, 8, usize::MAX.wrapping_add(usize::MAX), 0), ); }); glam_test!(test_wrapping_sub, { assert_eq!( USizeVec4::new(usize::MAX, 5, usize::MAX - 1, 0).wrapping_sub(USizeVec4::new( 1, 3, usize::MAX, 0 )), USizeVec4::new( usize::MAX.wrapping_sub(1), 2, (usize::MAX - 1).wrapping_sub(usize::MAX), 0 ) ); }); glam_test!(test_wrapping_mul, { assert_eq!( USizeVec4::new(usize::MAX, 5, usize::MAX, 0).wrapping_mul(USizeVec4::new(3, 3, 5, 1)), USizeVec4::new( usize::MAX.wrapping_mul(3), 15, usize::MAX.wrapping_mul(5), 0 ) ); }); glam_test!(test_wrapping_div, { assert_eq!( USizeVec4::new(usize::MAX, 5, usize::MAX, 0).wrapping_div(USizeVec4::new(3, 3, 5, 1)), USizeVec4::new(usize::MAX.wrapping_div(3), 1, usize::MAX.wrapping_div(5), 0) ); }); glam_test!(test_saturating_add, { assert_eq!( USizeVec4::new(usize::MAX, usize::MAX, 0, 0).saturating_add(USizeVec4::new( 1, usize::MAX, 2, 3 )), USizeVec4::new(usize::MAX, usize::MAX, 2, 3) ); }); glam_test!(test_saturating_sub, { assert_eq!( USizeVec4::new(0, usize::MAX, 0, 0).saturating_sub(USizeVec4::new(1, 1, 2, 3)), USizeVec4::new(0, usize::MAX.saturating_sub(1), 0, 0) ); }); glam_test!(test_saturating_mul, { assert_eq!( USizeVec4::new(usize::MAX, usize::MAX, 0, 0).saturating_mul(USizeVec4::new( 2, usize::MAX, 0, 0 )), USizeVec4::new(usize::MAX, usize::MAX, 0, 0) ); }); glam_test!(test_saturating_div, { assert_eq!( USizeVec4::new(usize::MAX, usize::MAX, 0, 0).saturating_div(USizeVec4::new( 2, usize::MAX, 3, 4 )), USizeVec4::new(usize::MAX.saturating_div(2), 1, 0, 0) ); }); impl_vec4_unsigned_integer_tests!(usize, usizevec4, USizeVec4, USizeVec3, USizeVec2, BVec4); impl_vec4_eq_hash_tests!(usize, usizevec4); impl_vec4_scalar_shift_op_tests!(USizeVec4, 0, 2); impl_vec4_shift_op_tests!(USizeVec4); impl_vec4_scalar_bit_op_tests!(USizeVec4, 0, 2); impl_vec4_bit_op_tests!(USizeVec4, 0, 2); }