mint-0.5.9/.cargo_vcs_info.json0000644000000001360000000000100120160ustar { "git": { "sha1": "8ea6a9f531e9c15f3d79c376e38ec422c21f36c9" }, "path_in_vcs": "" }mint-0.5.9/.github/workflows/check.yaml000064400000000000000000000007730072674642500162030ustar 00000000000000name: check on: [pull_request, push] jobs: build: runs-on: ubuntu-latest strategy: matrix: channel: [stable, nightly, 1.52.1] steps: - uses: actions/checkout@v2 - name: Select Rust channel uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.channel }} override: true - name: Rust Version Info run: | rustc --version cargo --version - name: Test All run: cargo test --verbose --all-features mint-0.5.9/.gitignore000064400000000000000000000000360072674642500126250ustar 00000000000000target/ **/*.rs.bk Cargo.lock mint-0.5.9/CHANGELOG.md000064400000000000000000000020410072674642500124440ustar 00000000000000# Change Log ### v0.5.9 (XX-XX-2022) - implement `AsMut` ### v0.5.8 (22-10-2021) - add `IntoMint` trait for unique conversions ([#68]) [#68]: https://github.com/kvark/mint/pull/68 ### v0.5.7 (25-09-2021) - update to rust2018 - implement `From` for fixed-size arrays ### v0.5.6 (04-11-2020) - add serde support ### v0.5.5 (13-04-2020) - fixed the `Quaternion` memory layout ### v0.5.4 (18-11-2019) - make it `[no_std]` ### v0.5.3 (30-09-2019) - removed executable flag from the crate files ### v0.5.2 (16-09-2019) - even more matrices ### v0.5.1 (23-07-2018) - more asymmetrical matrix types ## v0.5.0 (28-12-2017) - removed `LeftQuaternion` - implement `AsRef` ### v0.4.2 (08-06-2017) - derive traits for rotation types ### v0.4.1 (06-06-2017) - major refactor of Euler angles ## v0.3.0 (01-06-2017) - added strongly-typed Row/Column matrices - added points ## v0.2.0 (29-05-2017) - removed Row/Column matrix separation - added `QuatScalePos` ## v0.1.0 (26-05-2017) - basic matrices, vectors, quaternions, and Euler angles mint-0.5.9/Cargo.toml0000644000000022030000000000100100110ustar # 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 = "2018" name = "mint" version = "0.5.9" authors = ["Benjamin Saunders ", "Dzmitry Malyshau ", "Evgenii P. ", "George Burton ", "Ilya Bogdanov ", "Osspial ", "Pâris DOUADY ", "Rémi Lauzier "] description = "Math interoperability standard types" documentation = "https://docs.rs/mint" keywords = ["math"] license = "MIT" repository = "https://github.com/kvark/mint" [dependencies.serde] version = "1.0" optional = true default-features = false [dev-dependencies.serde_json] version = "1.0" mint-0.5.9/Cargo.toml.orig000064400000000000000000000012750072674642500135320ustar 00000000000000[package] name = "mint" version = "0.5.9" edition = "2018" authors = [ "Benjamin Saunders ", "Dzmitry Malyshau ", "Evgenii P. ", "George Burton ", "Ilya Bogdanov ", "Osspial ", "Pâris DOUADY ", "Rémi Lauzier ", ] description = "Math interoperability standard types" license = "MIT" repository = "https://github.com/kvark/mint" documentation = "https://docs.rs/mint" keywords = ["math"] [dependencies] serde = { version = "1.0", optional = true, default-features = false } [dev-dependencies] serde_json = "1.0" mint-0.5.9/LICENSE000064400000000000000000000020610072674642500116420ustar 00000000000000MIT License Copyright (c) 2017 Dzmitry Malyshau 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. mint-0.5.9/README.md000064400000000000000000000061340072674642500121210ustar 00000000000000# mint [![Build Status](https://github.com/kvark/mint/workflows/check/badge.svg)](https://github.com/kvark/mint/actions) [![Docs](https://docs.rs/mint/badge.svg)](https://docs.rs/mint) [![Crates.io](https://img.shields.io/crates/v/mint.svg?maxAge=2592000)](https://crates.io/crates/mint) **Math INteroperability Types** ![xkcd standard](https://imgs.xkcd.com/comics/standards.png) This library provides standard mathematical types used in computer graphics. Its only purpose is to serve as a standard and interoperability language between various components of [rust-gamedev](http://arewegameyet.com/categories/math/) ecosystem that happen to expose math-related types on their API. There are no operations defined for the types other than for the means of conversion from/into external types. Serde support is available through the `serde` feature. ## Types This crate offers the following types: ### Points * [`Point2`](https://docs.rs/mint/*/mint/struct.Point2.html) * [`Point3`](https://docs.rs/mint/*/mint/struct.Point3.html) ### Matrices #### Column Matrices * [`ColumnMatrix2`](https://docs.rs/mint/*/mint/struct.ColumnMatrix2.html) * [`ColumnMatrix3`](https://docs.rs/mint/*/mint/struct.ColumnMatrix3.html) * [`ColumnMatrix4`](https://docs.rs/mint/*/mint/struct.ColumnMatrix4.html) * [`ColumnMatrix2x3`](https://docs.rs/mint/*/mint/struct.ColumnMatrix2x3.html) * [`ColumnMatrix2x4`](https://docs.rs/mint/*/mint/struct.ColumnMatrix2x4.html) * [`ColumnMatrix3x2`](https://docs.rs/mint/*/mint/struct.ColumnMatrix3x2.html) * [`ColumnMatrix3x4`](https://docs.rs/mint/*/mint/struct.ColumnMatrix3x4.html) * [`ColumnMatrix4x2`](https://docs.rs/mint/*/mint/struct.ColumnMatrix4x2.html) * [`ColumnMatrix4x3`](https://docs.rs/mint/*/mint/struct.ColumnMatrix4x3.html) #### Row Matrices * [`RowMatrix2`](https://docs.rs/mint/*/mint/struct.RowMatrix2.html) * [`RowMatrix3`](https://docs.rs/mint/*/mint/struct.RowMatrix3.html) * [`RowMatrix4`](https://docs.rs/mint/*/mint/struct.RowMatrix4.html) * [`RowMatrix2x3`](https://docs.rs/mint/*/mint/struct.RowMatrix2x3.html) * [`RowMatrix2x4`](https://docs.rs/mint/*/mint/struct.RowMatrix2x4.html) * [`RowMatrix3x2`](https://docs.rs/mint/*/mint/struct.RowMatrix3x2.html) * [`RowMatrix3x4`](https://docs.rs/mint/*/mint/struct.RowMatrix3x4.html) * [`RowMatrix4x2`](https://docs.rs/mint/*/mint/struct.RowMatrix4x2.html) * [`RowMatrix4x3`](https://docs.rs/mint/*/mint/struct.RowMatrix4x3.html) ### Vectors * [`Vector2`](https://docs.rs/mint/*/mint/struct.Vector2.html) * [`Vector3`](https://docs.rs/mint/*/mint/struct.Vector3.html) * [`Vector4`](https://docs.rs/mint/*/mint/struct.Vector4.html) ### Quaternion * [`Quaternion`](https://docs.rs/mint/*/mint/struct.Quaternion.html) ### Euler Angles * [`EulerAngles`](https://docs.rs/mint/*/mint/struct.EulerAngles.html) ## MSRV mint supports Rust 1.52.1 and newer. From time to time, mint may increase the minimum supported Rust version in a minor version bump in order to take advantage of new Rust features. ## License mint is available under the terms of the MIT license. See [LICENSE](LICENSE) or for more information.mint-0.5.9/src/into_mint.rs000064400000000000000000000010200072674642500137640ustar 00000000000000/// Defines which mint type a given type is associated with. This trait enables /// converting a type into its mint equivalent without having to name the mint /// type. /// /// Implementing `IntoMint` on a type states that the type is semantically /// equivalent to the type given in `MintType`. /// /// All mint types implement `IntoMint` reflexively, i.e., they implement /// `IntoMint`. pub trait IntoMint: Into { /// The mint type that this type is associated with. type MintType; } mint-0.5.9/src/lib.rs000064400000000000000000000007410072674642500125430ustar 00000000000000/*! Mint - Math interoperability standard types. Defines basic math types useful for computer graphics. Designed to serve as an interoperability standard between libraries. */ #![no_std] #![deny( missing_docs, rust_2018_compatibility, rust_2018_idioms, future_incompatible, nonstandard_style, unused, clippy::all )] mod into_mint; mod matrix; mod rotation; mod vector; pub use into_mint::*; pub use matrix::*; pub use rotation::*; pub use vector::*; mint-0.5.9/src/matrix.rs000064400000000000000000000166230072674642500133070ustar 00000000000000use crate::vector::{Vector2, Vector3, Vector4}; use crate::IntoMint; macro_rules! matrix { ($name:ident : $vec:ident[ $($field:ident[$($sub:ident),*] = $index:expr),* ] = ($inner:expr, $outer:expr)) => { #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] #[repr(C)] #[allow(missing_docs)] //TODO: actually have docs pub struct $name { $( pub $field : $vec, )* } impl IntoMint for $name { type MintType = $name; } impl From<[[T; $inner]; $outer]> for $name { fn from([$($field),*]: [[T; $inner]; $outer]) -> Self { $name { $( $field: From::from($field), )* } } } impl From<$name> for [[T; $inner]; $outer] { fn from(name: $name) -> [[T; $inner]; $outer] { [$( name.$field.into() ),*] } } impl AsRef<[[T; $inner]; $outer]> for $name { fn as_ref(&self) -> &[[T; $inner]; $outer] { unsafe { ::core::mem::transmute(self) } } } impl AsMut<[[T; $inner]; $outer]> for $name { fn as_mut(&mut self) -> &mut [[T; $inner]; $outer] { unsafe { ::core::mem::transmute(self) } } } impl From<[T; $inner * $outer]> for $name { fn from(m: [T; $inner * $outer]) -> Self { $name { $( $field: $vec::from_slice(&m[$index*$inner..($index+1)*$inner]), )* } } } impl From<$name> for [T; $inner * $outer] { fn from(name: $name) -> [T; $inner * $outer] { let $name { $($field),* } = name; [ $( $( $field.$sub ),* ),* ] } } impl AsRef<[T; $inner * $outer]> for $name { fn as_ref(&self) -> &[T; $inner * $outer] { unsafe { ::core::mem::transmute(self) } } } impl AsMut<[T; $inner * $outer]> for $name { fn as_mut(&mut self) -> &mut [T; $inner * $outer] { unsafe { ::core::mem::transmute(self) } } } #[cfg(feature = "serde")] impl ::serde::Serialize for $name where T: ::serde::Serialize { fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer { AsRef::<[[T; $inner]; $outer]>::as_ref(self).serialize(serializer) } } #[cfg(feature = "serde")] impl<'de, T> ::serde::Deserialize<'de> for $name where T: ::serde::Deserialize<'de> { fn deserialize(deserializer: D) -> Result where D: ::serde::Deserializer<'de> { <[[T; $inner]; $outer]>::deserialize(deserializer).map($name::::from) } } }; } macro_rules! turn { ($name:ident : $vec:ident[$( $field:ident [ $($sub:ident),* ] ),* ] = $transposed:ident) => { impl From<$transposed> for $name { fn from(m: $transposed) -> Self { $name { $( $field: $vec { $( $sub: m.$sub.$field, )* }, )* } } } } } // 2x2 row-major matrix. matrix!( RowMatrix2 : Vector2[x[x,y]=0,y[x,y]=1] = (2, 2)); turn!( RowMatrix2 : Vector2[x[x,y],y[x,y]] = ColumnMatrix2 ); // 2x3 row-major matrix. // Useful for combining rotation, scale, and translation in 2D space. matrix!( RowMatrix2x3 : Vector3[x[x,y,z]=0,y[x,y,z]=1] = (3, 2)); turn!( RowMatrix2x3 : Vector3[x[x,y,z],y[x,y,z]] = ColumnMatrix2x3 ); // 2x4 row-major matrix. matrix!( RowMatrix2x4 : Vector4[x[x,y,z,w]=0,y[x,y,z,w]=1] = (4, 2)); turn!( RowMatrix2x4 : Vector4[x[x,y,z,w],y[x,y,z,w]] = ColumnMatrix2x4 ); // 3x2 row-major matrix. // Useful for combining rotation, scale, and translation in 2D space. matrix!( RowMatrix3x2 : Vector2[x[x,y]=0,y[x,y]=1,z[x,y]=2] = (2, 3)); turn!( RowMatrix3x2 : Vector2[x[x,y],y[x,y],z[x,y]] = ColumnMatrix3x2 ); // 3x3 row-major matrix. // Useful for representing rotation and scale in 3D space. matrix!( RowMatrix3 : Vector3[x[x,y,z]=0,y[x,y,z]=1,z[x,y,z]=2] = (3, 3)); turn!( RowMatrix3 : Vector3[x[x,y,z],y[x,y,z],z[x,y,z]] = ColumnMatrix3 ); // 3x4 row-major matrix. // Useful for combining rotation, scale, and translation in 3D space. matrix!( RowMatrix3x4 : Vector4[x[x,y,z,w]=0,y[x,y,z,w]=1,z[x,y,z,w]=2] = (4, 3)); turn!( RowMatrix3x4 : Vector4[x[x,y,z,w],y[x,y,z,w],z[x,y,z,w]] = ColumnMatrix3x4 ); // 4x3 row-major matrix. // Useful for combining rotation, scale, and translation in 3D space. matrix!( RowMatrix4x3 : Vector3[x[x,y,z]=0,y[x,y,z]=1,z[x,y,z]=2,w[x,y,z]=3] = (3, 4)); turn!( RowMatrix4x3 : Vector3[x[x,y,z],y[x,y,z],z[x,y,z],w[x,y,z]] = ColumnMatrix4x3 ); // 4x2 row-major matrix. matrix!( RowMatrix4x2 : Vector2[x[x,y]=0,y[x,y]=1,z[x,y]=2,w[x,y]=3] = (2, 4)); turn!( RowMatrix4x2 : Vector2[x[x,y],y[x,y],z[x,y],w[x,y]] = ColumnMatrix4x2 ); // 4x4 row-major matrix. matrix!( RowMatrix4 : Vector4[x[x,y,z,w]=0,y[x,y,z,w]=1,z[x,y,z,w]=2,w[x,y,z,w]=3] = (4, 4)); turn!( RowMatrix4 : Vector4[x[x,y,z,w],y[x,y,z,w],z[x,y,z,w],w[x,y,z,w]] = ColumnMatrix4 ); // 2x2 column-major matrix. matrix!( ColumnMatrix2 : Vector2[x[x,y]=0,y[x,y]=1] = (2, 2)); turn!( ColumnMatrix2 : Vector2[x[x,y],y[x,y]] = RowMatrix2 ); // 2x3 column-major matrix. // Useful for combining rotation, scale, and translation in 2D space. matrix!( ColumnMatrix2x3 : Vector2[x[x,y]=0,y[x,y]=1,z[x,y]=2] = (2, 3)); turn!( ColumnMatrix2x3 : Vector2[x[x,y],y[x,y],z[x,y]] = RowMatrix2x3 ); // 2x4 column-major matrix. matrix!( ColumnMatrix2x4 : Vector2[x[x,y]=0,y[x,y]=1,z[x,y]=2,w[x,y]=3] = (2, 4)); turn!( ColumnMatrix2x4 : Vector2[x[x,y],y[x,y],z[x,y],w[x,y]] = RowMatrix2x4 ); // 3x2 column-major matrix. // Useful for combining rotation, scale, and translation in 2D space. matrix!( ColumnMatrix3x2 : Vector3[x[x,y,z]=0,y[x,y,z]=1] = (3, 2)); turn!( ColumnMatrix3x2 : Vector3[x[x,y,z],y[x,y,z]] = RowMatrix3x2 ); // 3x3 column-major matrix. // Useful for representing rotation and scale in 3D space. matrix!( ColumnMatrix3 : Vector3[x[x,y,z]=0,y[x,y,z]=1,z[x,y,z]=2] = (3, 3)); turn!( ColumnMatrix3 : Vector3[x[x,y,z],y[x,y,z],z[x,y,z]] = RowMatrix3 ); // 3x4 column-major matrix. // Useful for combining rotation, scale, and translation in 3D space. matrix!( ColumnMatrix3x4 : Vector3[x[x,y,z]=0,y[x,y,z]=1,z[x,y,z]=2,w[x,y,z]=3] = (3, 4)); turn!( ColumnMatrix3x4 : Vector3[x[x,y,z],y[x,y,z],z[x,y,z],w[x,y,z]] = RowMatrix3x4 ); // 4x2 column-major matrix. matrix!( ColumnMatrix4x2 : Vector4[x[x,y,z,w]=0,y[x,y,z,w]=1] = (4, 2)); turn!( ColumnMatrix4x2 : Vector4[x[x,y,z,w],y[x,y,z,w]] = RowMatrix4x2 ); // 4x3 column-major matrix. // Useful for combining rotation, scale, and translation in 3D space. matrix!( ColumnMatrix4x3 : Vector4[x[x,y,z,w]=0,y[x,y,z,w]=1,z[x,y,z,w]=2] = (4, 3)); turn!( ColumnMatrix4x3 : Vector4[x[x,y,z,w],y[x,y,z,w],z[x,y,z,w]] = RowMatrix4x3 ); // 4x4 column-major matrix. matrix!( ColumnMatrix4 : Vector4[x[x,y,z,w]=0,y[x,y,z,w]=1,z[x,y,z,w]=2,w[x,y,z,w]=3] = (4, 4)); turn!( ColumnMatrix4 : Vector4[x[x,y,z,w],y[x,y,z,w],z[x,y,z,w],w[x,y,z,w]] = RowMatrix4 ); mint-0.5.9/src/rotation.rs000064400000000000000000000117700072674642500136400ustar 00000000000000use crate::vector::Vector3; use crate::IntoMint; use core::marker::PhantomData; /// Standard quaternion represented by the scalar and vector parts. /// Useful for representing rotation in 3D space. /// Corresponds to a right-handed rotation matrix. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] #[repr(C)] pub struct Quaternion { /// Vector part of a quaternion. pub v: Vector3, /// Scalar part of a quaternion. pub s: T, } impl IntoMint for Quaternion { type MintType = Quaternion; } impl From<[T; 4]> for Quaternion { fn from([x, y, z, s]: [T; 4]) -> Self { Quaternion { s, v: Vector3::from([x, y, z]), } } } impl From> for [T; 4] { fn from(quaternion: Quaternion) -> [T; 4] { [quaternion.v.x, quaternion.v.y, quaternion.v.z, quaternion.s] } } impl AsRef<[T; 4]> for Quaternion { fn as_ref(&self) -> &[T; 4] { unsafe { ::core::mem::transmute(self) } } } impl AsMut<[T; 4]> for Quaternion { fn as_mut(&mut self) -> &mut [T; 4] { unsafe { ::core::mem::transmute(self) } } } #[cfg(feature = "serde")] impl ::serde::Serialize for Quaternion where T: ::serde::Serialize, { fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer, { AsRef::<[T; 4]>::as_ref(self).serialize(serializer) } } #[cfg(feature = "serde")] impl<'de, T> ::serde::Deserialize<'de> for Quaternion where T: ::serde::Deserialize<'de>, { fn deserialize(deserializer: S) -> Result where S: ::serde::Deserializer<'de>, { <[T; 4]>::deserialize(deserializer).map(Quaternion::::from) } } /// Abstract set of Euler angles in 3D space. The basis of angles /// is defined by the generic parameter `B`. /// /// Note: there are multiple notations of Euler angles. They are /// split in two groups: /// - intrinsic (also known as "Tait-Bryan angles"): rotate around local axis /// - extrinsic (also known as "Proper Euler angles"): rotate around world axis /// For each interpretation, different axis may be chosen in different order. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] #[repr(C)] pub struct EulerAngles { /// First angle of rotation in range [-pi, pi] (_pitch_). pub a: T, /// Second angle of rotation around in range [-pi/2, pi/2] (_yaw_). pub b: T, /// Third angle of rotation in range [-pi, pi] (_roll_). pub c: T, /// Marker for the phantom basis. pub marker: PhantomData, } /// Intrinsic rotation around X, then Y, then Z axis. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub enum IntraXYZ {} /// Intrinsic rotation around Z, then X, then Z axis. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub enum IntraZXZ {} /// Intrinsic rotation around Z, then Y, then X axis. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub enum IntraZYX {} /// Extrinsic rotation around X, then Y, then Z axis. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub enum ExtraXYZ {} /// Extrinsic rotation around Z, then X, then Z axis. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub enum ExtraZXZ {} /// Extrinsic rotation around Z, then Y, then X axis. #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] pub enum ExtraZYX {} impl From<[T; 3]> for EulerAngles { fn from([a, b, c]: [T; 3]) -> Self { EulerAngles { a, b, c, marker: PhantomData, } } } impl From> for [T; 3] { fn from(euler: EulerAngles) -> [T; 3] { [euler.a, euler.b, euler.c] } } #[cfg(feature = "serde")] impl ::serde::Serialize for EulerAngles where T: ::serde::Serialize, { fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer, { [&self.a, &self.b, &self.c].serialize(serializer) } } #[cfg(feature = "serde")] impl<'de, T, B> ::serde::Deserialize<'de> for EulerAngles where T: ::serde::Deserialize<'de>, { fn deserialize(deserializer: S) -> Result where S: ::serde::Deserializer<'de>, { <[T; 3]>::deserialize(deserializer).map(EulerAngles::::from) } } macro_rules! reverse { ($from:ident -> $to:ident) => { impl From> for EulerAngles { fn from(other: EulerAngles) -> Self { EulerAngles { a: other.c, b: other.b, c: other.a, marker: PhantomData, } } } }; ($from:ident <-> $to:ident) => { reverse!($from -> $to); reverse!($to -> $from); }; } reverse!(IntraXYZ <-> ExtraZYX); reverse!(IntraZXZ <-> ExtraZXZ); reverse!(IntraZYX <-> ExtraXYZ); mint-0.5.9/src/vector.rs000064400000000000000000000056650072674642500133110ustar 00000000000000use crate::IntoMint; macro_rules! vec { ($name:ident [ $($field:ident),* ] = $fixed:ty) => { #[derive(Clone, Copy, Debug, Hash, PartialEq, PartialOrd, Eq, Ord)] #[repr(C)] #[allow(missing_docs)] //TODO: actually have docs pub struct $name { $( pub $field : T, )* } impl IntoMint for $name { type MintType = $name; } impl From<$fixed> for $name { fn from([$($field),*]: $fixed) -> Self { $name { $( $field, )* } } } impl From<$name> for $fixed { fn from(name: $name) -> $fixed { [$(name.$field.into() ),*] } } impl AsRef<$fixed> for $name { fn as_ref(&self) -> &$fixed { unsafe { ::core::mem::transmute(self) } } } impl AsMut<$fixed> for $name { fn as_mut(&mut self) -> &mut $fixed { unsafe { ::core::mem::transmute(self) } } } impl $name { #[allow(missing_docs)] pub fn from_slice(slice: &[T]) -> Self { let mut iter = slice.iter(); $name { $( $field: iter .next() .expect(&concat!("Missing ", stringify!($field), "-axis in slice.")) .clone() ),* } } } #[cfg(feature = "serde")] impl ::serde::Serialize for $name where T: ::serde::Serialize { fn serialize(&self, serializer: S) -> Result where S: ::serde::Serializer { AsRef::<$fixed>::as_ref(self).serialize(serializer) } } #[cfg(feature = "serde")] impl<'de, T> ::serde::Deserialize<'de> for $name where T: ::serde::Deserialize<'de>, { fn deserialize(deserializer: D) -> Result where D: ::serde::Deserializer<'de> { <$fixed>::deserialize(deserializer).map($name::::from) } } } } macro_rules! from { ($name:ident [ $($field:ident),* ] = $other:ident) => { impl From<$other> for $name { fn from(v: $other) -> Self { $name { $( $field: v.$field, )* } } } } } vec!( Vector2 [x, y] = [T; 2] ); from!( Vector2 [x,y] = Point2 ); vec!( Vector3 [x, y, z] = [T; 3] ); from!( Vector3 [x,y,z] = Point3 ); vec!( Vector4 [x, y, z, w] = [T; 4] ); vec!( Point2 [x, y] = [T; 2] ); from!( Point2 [x,y] = Vector2 ); vec!( Point3 [x, y, z] = [T; 3] ); from!( Point3 [x,y,z] = Vector3 ); mint-0.5.9/tests/tests.rs000064400000000000000000000230550072674642500135150ustar 00000000000000#![deny( missing_docs, rust_2018_compatibility, rust_2018_idioms, future_incompatible, nonstandard_style, unused, clippy::all )] use mint::{ ColumnMatrix2, ColumnMatrix2x3, ColumnMatrix2x4, ColumnMatrix3, ColumnMatrix3x2, ColumnMatrix3x4, ColumnMatrix4, ColumnMatrix4x2, ColumnMatrix4x3, }; use mint::{EulerAngles, Point2, Point3, Quaternion, Vector2, Vector3, Vector4}; use mint::{ RowMatrix2, RowMatrix2x3, RowMatrix2x4, RowMatrix3, RowMatrix3x2, RowMatrix3x4, RowMatrix4, RowMatrix4x2, RowMatrix4x3, }; macro_rules! transitive { ($name:ident [ $($field:ident = $value:expr),* ] = $fixed:ty) => ( let v1 = $name { $($field : $value,)* }; let a: $fixed = v1.into(); let v2 = $name::from(a); assert_eq!(v1, v2); ); ($name:ident [ $($field:ident = $value:expr),* ] = ref $fixed:ty) => ( transitive!($name [ $($field = $value),* ] = $fixed); let v1 = $name { $($field : $value,)* }; let a: $fixed = v1.into(); assert_eq!(AsRef::<$fixed>::as_ref(&v1), &a); ); } macro_rules! matrix_transitive { ($name:ident $vecType:ident[ $($field:ident = $value:expr),* ] = ($inner:expr, $outer:expr) : $elt:ty) => ( transitive!($name [ $($field = $vecType::from($value)),*] = ref [[$elt; $inner]; $outer]); transitive!($name [ $($field = $vecType::from($value)),*] = ref [$elt; $inner * $outer]); ) } macro_rules! turn { ($name1:ident [$($value1:expr),*] = $name2:ident [$($value2:expr),*]) => ( let transposed = [$($value2),*]; let m1 = $name1::from([$($value1),*]); let m2: $name2<_> = m1.into(); assert_eq!(m1, $name1::from(m2)); assert_eq!(m2, $name2::from(transposed)); ) } #[test] fn vector() { transitive!(Vector2 [x=1, y=3] = ref [i32; 2]); transitive!(Vector3 [x=1, y=3, z=5] = ref [i32; 3]); transitive!(Vector4 [x=1, y=3, z=5, w=7] = ref [i32; 4]); transitive!(Point2 [x=1, y=3] = ref [i32; 2]); transitive!(Point3 [x=1, y=3, z=5] = ref [i32; 3]); // Translation Vector <-> Point transitive!(Point2 [x=1, y=3] = Vector2); transitive!(Point3 [x=1, y=3, z=5] = Vector3); } #[test] fn rotation() { transitive!(Quaternion [s=1, v=Vector3{x: 1, y: 3, z: 5}] = [i32; 4]); // EulerAngles let a1: [i32; 3] = [1, 3, 5]; let e: EulerAngles<_, mint::ExtraXYZ> = EulerAngles::from(a1); let a2: [i32; 3] = e.into(); assert_eq!(a1, a2); } #[test] fn row_matrix() { matrix_transitive!(RowMatrix2 Vector2[ x=[1,2], y=[3,4]] = (2, 2): i32); matrix_transitive!(RowMatrix2x3 Vector3[ x=[1,2,3], y=[4,5,6]] = (3, 2): i32); matrix_transitive!(RowMatrix2x4 Vector4[ x=[1,2,3,4], y=[5,6,7,8]] = (4, 2): i32); matrix_transitive!(RowMatrix3x2 Vector2[ x=[1,2], y=[3,4], z=[5,6]] = (2, 3): i32); matrix_transitive!(RowMatrix3 Vector3[ x=[1,2,3], y=[4,5,6], z=[7,8,9]] = (3, 3): i32); matrix_transitive!(RowMatrix3x4 Vector4[ x=[1,2,3,4], y=[5,6,7,8], z=[9,10,11,12]] = (4, 3): i32); matrix_transitive!(RowMatrix4x2 Vector2[ x=[1,2], y=[3,4], z=[5,6], w=[7,8]] = (2, 4): i32); matrix_transitive!(RowMatrix4x3 Vector3[ x=[1,2,3], y=[4,5,6], z=[7,8,9], w=[10,11,12]] = (3, 4): i32); matrix_transitive!(RowMatrix4 Vector4[ x=[1,2,3,4], y=[5,6,7,8], z=[9,10,11,12], w=[13,14,15,16]] = (4, 4): i32); } #[test] fn column_matrix() { matrix_transitive!(ColumnMatrix2 Vector2[ x=[1,2], y=[3,4]] = (2, 2): i32); matrix_transitive!(ColumnMatrix2x3 Vector2[ x=[1,2], y=[3,4], z=[5,6]] = (2, 3): i32); matrix_transitive!(ColumnMatrix2x4 Vector2[ x=[1,2], y=[3,4], z=[5,6], w=[7,8]] = (2, 4): i32); matrix_transitive!(ColumnMatrix3x2 Vector3[ x=[1,2,3], y=[4,5,6]] = (3, 2): i32); matrix_transitive!(ColumnMatrix3 Vector3[ x=[1,2,3], y=[4,5,6], z=[7,8,9]] = (3, 3): i32); matrix_transitive!(ColumnMatrix3x4 Vector3[ x=[1,2,3], y=[4,5,6], z=[7,8,9], w=[10,11,12]] = (3, 4): i32); matrix_transitive!(ColumnMatrix4x2 Vector4[ x=[1,2,3,4], y=[5,6,7,8]] = (4, 2): i32); matrix_transitive!(ColumnMatrix4x3 Vector4[ x=[1,2,3,4], y=[5,6,7,8], z=[9,10,11,12]] = (4, 3): i32); matrix_transitive!(ColumnMatrix4 Vector4[ x=[1,2,3,4], y=[5,6,7,8], z=[9,10,11,12], w=[13,14,15,16]] = (4, 4): i32); } #[test] fn turn() { turn!(RowMatrix2 [ [1,2], [3,4]] = ColumnMatrix2 [ [1,3], [2,4]]); turn!(RowMatrix2x3 [ [1,3,5], [2,4,6]] = ColumnMatrix2x3 [ [1,2], [3,4], [5,6]]); turn!(RowMatrix2x4 [ [1,3,5,7], [2,4,6,8]] = ColumnMatrix2x4 [ [1,2], [3,4], [5,6], [7,8]]); turn!(RowMatrix3x2 [ [1,2], [3,4], [5,6]] = ColumnMatrix3x2 [ [1,3,5], [2,4,6]]); turn!(RowMatrix3 [ [1,2,3], [4,5,6], [7,8,9]] = ColumnMatrix3 [ [1,4,7], [2,5,8], [3,6,9]]); turn!(RowMatrix3x4 [ [1,4,7,10], [2,5,8,11], [3,6,9,12]] = ColumnMatrix3x4 [ [1,2,3], [4,5,6], [7,8,9], [10,11,12]]); turn!(RowMatrix4x2 [ [1,2], [3,4], [5,6], [7,8]] = ColumnMatrix4x2 [ [1,3,5,7], [2,4,6,8]]); turn!(RowMatrix4x3 [ [1,2,3], [4,5,6], [7,8,9], [10,11,12]] = ColumnMatrix4x3 [ [1,4,7,10], [2,5,8,11], [3,6,9,12]]); turn!(RowMatrix4 [ [1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16]] = ColumnMatrix4 [ [1,5,9,13], [2,6,10,14], [3,7,11,15], [4,8,12,16]]); } #[test] fn vector_from_slice_success() { let v = Vector3::from_slice(&[0.0f32, 1.0, 2.0, 3.0]); assert_eq!( v, Vector3 { x: 0.0, y: 1.0, z: 2.0 } ); } #[test] #[should_panic(expected = "Missing y-axis in slice.")] fn vector_from_slice_fail() { let _ = Vector4::from_slice(&[0.0]); } #[test] fn quaternion_layout() { let q = Quaternion { v: Vector3::from([0, 1, 2]), s: 3, }; let expected = [0, 1, 2, 3]; let a: [i32; 4] = q.into(); assert_eq!(a, expected); let b: &[i32; 4] = q.as_ref(); assert_eq!(b, &expected); let c: [i32; 4] = unsafe { core::mem::transmute(q) }; assert_eq!(c, expected); } macro_rules! representation_tests { ($module:ident => $name:ty : $fixed:ty ) => { #[cfg(all(feature = "serde", test))] mod $module { use super::*; use serde_json; #[test] fn serialize() { let fixed: $fixed = <$fixed as Default>::default(); let fixed_valid = serde_json::to_string(&fixed).unwrap(); // Should do the same things as the $fixed serialized representation. let this: $name = fixed.into(); let this_valid = serde_json::to_string(&this).unwrap(); assert_eq!(fixed_valid, this_valid); } #[test] fn deserialize() { // Should be able to create $name from the $fixed representation. let fixed: $fixed = <$fixed as Default>::default(); let fixed_valid = serde_json::to_string(&fixed).unwrap(); let from_string: $name = serde_json::from_str(&fixed_valid).unwrap(); let from_fixed: $name = fixed.into(); // Serializing the struct again should be the same as the $fixed representation. let into_string = serde_json::to_string(&from_string).unwrap(); assert_eq!(from_string, from_fixed); assert_eq!(into_string, fixed_valid); } } }; } representation_tests!( row_matrix_2_serde => RowMatrix2 : [[f32; 2]; 2] ); representation_tests!( row_matrix_2x3_serde => RowMatrix2x3 : [[f32; 3]; 2] ); representation_tests!( row_matrix_3_serde => RowMatrix3 : [[f32; 3]; 3] ); representation_tests!( row_matrix_3x4_serde => RowMatrix3x4 : [[f32; 4]; 3] ); representation_tests!( row_matrix_4_serde => RowMatrix4 : [[f32; 4]; 4] ); representation_tests!( column_matrix_2_serde => ColumnMatrix2 : [[f32; 2]; 2] ); representation_tests!( column_matrix_2x3_serde => ColumnMatrix2x3 : [[f32; 2]; 3] ); representation_tests!( column_matrix_3_serde => ColumnMatrix3 : [[f32; 3]; 3] ); representation_tests!( column_matrix_3x4_serde => ColumnMatrix3x4 : [[f32; 3]; 4] ); representation_tests!( column_matrix_4_serde => ColumnMatrix4 : [[f32; 4]; 4] ); representation_tests!( vector2_serde => Vector2 : [f32; 2] ); representation_tests!( vector3_serde => Vector3 : [f32; 3] ); representation_tests!( vector4_serde => Vector4 : [f32; 4] ); representation_tests!( point2_serde => Point2 : [f32; 2] ); representation_tests!( point3_serde => Point3 : [f32; 3] ); representation_tests!( euler_angles => EulerAngles : [f32; 3] ); representation_tests!( quaternions => Quaternion : [f32; 4] );