diff --git a/CHANGELOG.md b/CHANGELOG.md index e65ed971..2224a62a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ documented here. This project adheres to [Semantic Versioning](https://semver.org/). +## [0.25.2] - WIP +### Added +- A `cast` method has been added to most types. This can be used to change the + type of the components of a given entity. Example: `vector.cast::()`. + ## [0.25.1] This release replaces the version 0.25.0 which has been yanked. The 0.25.0 version added significant complication to build `nalgebra` targeting a `#[no-std]` platform diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 89d24dcc..ee426227 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -16,7 +16,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; -use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, Field}; +use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, Field, SupersetOf}; use simba::simd::SimdPartialOrd; use crate::base::allocator::{Allocator, SameShapeAllocator, SameShapeC, SameShapeR}; @@ -610,6 +610,23 @@ impl> Matrix { res } + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Vector3; + /// let q = Vector3::new(1.0f64, 2.0, 3.0); + /// let q2 = q.cast::(); + /// assert_eq!(q2, Vector3::new(1.0f32, 2.0, 3.0)); + /// ``` + pub fn cast(self) -> MatrixMN + where + MatrixMN: SupersetOf, + DefaultAllocator: Allocator, + { + crate::convert(self) + } + /// Similar to `self.iter().fold(init, f)` except that `init` is replaced by a closure. /// /// The initialization closure is given the first component of this matrix: diff --git a/src/geometry/dual_quaternion_construction.rs b/src/geometry/dual_quaternion_construction.rs index 739972a9..047a9a2b 100644 --- a/src/geometry/dual_quaternion_construction.rs +++ b/src/geometry/dual_quaternion_construction.rs @@ -5,6 +5,7 @@ use crate::{ use num::{One, Zero}; #[cfg(feature = "arbitrary")] use quickcheck::{Arbitrary, Gen}; +use simba::scalar::SupersetOf; impl DualQuaternion { /// Creates a dual quaternion from its rotation and translation components. @@ -49,6 +50,22 @@ impl DualQuaternion { Quaternion::from_real(N::zero()), ) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::{Quaternion, DualQuaternion}; + /// let q = DualQuaternion::from_real(Quaternion::new(1.0f64, 2.0, 3.0, 4.0)); + /// let q2 = q.cast::(); + /// assert_eq!(q2, DualQuaternion::from_real(Quaternion::new(1.0f32, 2.0, 3.0, 4.0))); + /// ``` + pub fn cast(self) -> DualQuaternion + where + DualQuaternion: SupersetOf, + { + crate::convert(self) + } } impl DualQuaternion @@ -129,6 +146,22 @@ impl UnitDualQuaternion { pub fn identity() -> Self { Self::new_unchecked(DualQuaternion::identity()) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::UnitDualQuaternion; + /// let q = UnitDualQuaternion::::identity(); + /// let q2 = q.cast::(); + /// assert_eq!(q2, UnitDualQuaternion::::identity()); + /// ``` + pub fn cast(self) -> UnitDualQuaternion + where + UnitDualQuaternion: SupersetOf, + { + crate::convert(self) + } } impl UnitDualQuaternion diff --git a/src/geometry/isometry_construction.rs b/src/geometry/isometry_construction.rs index 00138573..1edf269b 100644 --- a/src/geometry/isometry_construction.rs +++ b/src/geometry/isometry_construction.rs @@ -10,15 +10,16 @@ use rand::{ Rng, }; +use simba::scalar::SupersetOf; use simba::simd::SimdRealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U2}; use crate::base::{DefaultAllocator, Vector2, Vector3}; -use crate::geometry::{ +use crate::{ AbstractRotation, Isometry, Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, Point, - Point3, Rotation, Rotation3, Translation, Translation2, Translation3, UnitComplex, + Point3, Rotation, Rotation3, Scalar, Translation, Translation2, Translation3, UnitComplex, UnitQuaternion, }; @@ -153,6 +154,22 @@ where pub fn rotation(angle: N) -> Self { Self::new(Vector2::zeros(), angle) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::IsometryMatrix2; + /// let iso = IsometryMatrix2::::identity(); + /// let iso2 = iso.cast::(); + /// assert_eq!(iso2, IsometryMatrix2::::identity()); + /// ``` + pub fn cast(self) -> IsometryMatrix2 + where + IsometryMatrix2: SupersetOf, + { + crate::convert(self) + } } impl Isometry2 @@ -191,6 +208,22 @@ where pub fn rotation(angle: N) -> Self { Self::new(Vector2::zeros(), angle) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Isometry2; + /// let iso = Isometry2::::identity(); + /// let iso2 = iso.cast::(); + /// assert_eq!(iso2, Isometry2::::identity()); + /// ``` + pub fn cast(self) -> Isometry2 + where + Isometry2: SupersetOf, + { + crate::convert(self) + } } // 3D rotation. @@ -387,6 +420,22 @@ where N::Element: SimdRealField, { basic_isometry_construction_impl!(UnitQuaternion); + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Isometry3; + /// let iso = Isometry3::::identity(); + /// let iso2 = iso.cast::(); + /// assert_eq!(iso2, Isometry3::::identity()); + /// ``` + pub fn cast(self) -> Isometry3 + where + Isometry3: SupersetOf, + { + crate::convert(self) + } } impl IsometryMatrix3 @@ -394,6 +443,22 @@ where N::Element: SimdRealField, { basic_isometry_construction_impl!(Rotation3); + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::IsometryMatrix3; + /// let iso = IsometryMatrix3::::identity(); + /// let iso2 = iso.cast::(); + /// assert_eq!(iso2, IsometryMatrix3::::identity()); + /// ``` + pub fn cast(self) -> IsometryMatrix3 + where + IsometryMatrix3: SupersetOf, + { + crate::convert(self) + } } /// # Construction from a 3D eye position and target point diff --git a/src/geometry/point_construction.rs b/src/geometry/point_construction.rs index 26ee8a8c..bf88ece0 100644 --- a/src/geometry/point_construction.rs +++ b/src/geometry/point_construction.rs @@ -15,7 +15,7 @@ use crate::{ Point1, Point2, Point3, Point4, Point5, Point6, Vector1, Vector2, Vector3, Vector4, Vector5, Vector6, }; -use simba::scalar::ClosedDiv; +use simba::scalar::{ClosedDiv, SupersetOf}; use crate::geometry::Point; @@ -119,6 +119,23 @@ where None } } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Point2; + /// let pt = Point2::new(1.0f64, 2.0); + /// let pt2 = pt.cast::(); + /// assert_eq!(pt2, Point2::new(1.0f32, 2.0)); + /// ``` + pub fn cast(self) -> Point + where + Point: SupersetOf, + DefaultAllocator: Allocator, + { + crate::convert(self) + } } /* diff --git a/src/geometry/quaternion_construction.rs b/src/geometry/quaternion_construction.rs index 6b40fe49..89911b91 100644 --- a/src/geometry/quaternion_construction.rs +++ b/src/geometry/quaternion_construction.rs @@ -13,7 +13,7 @@ use rand::{ use num::{One, Zero}; -use simba::scalar::RealField; +use simba::scalar::{RealField, SupersetOf}; use simba::simd::SimdBool; use crate::base::dimension::U3; @@ -49,6 +49,22 @@ impl Quaternion { pub fn new(w: N, i: N, j: N, k: N) -> Self { Self::from(Vector4::new(i, j, k, w)) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Quaternion; + /// let q = Quaternion::new(1.0f64, 2.0, 3.0, 4.0); + /// let q2 = q.cast::(); + /// assert_eq!(q2, Quaternion::new(1.0f32, 2.0, 3.0, 4.0)); + /// ``` + pub fn cast(self) -> Quaternion + where + To: SupersetOf, + { + crate::convert(self) + } } impl Quaternion { @@ -199,6 +215,23 @@ where Self::new_unchecked(Quaternion::identity()) } + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::UnitQuaternion; + /// # use approx::assert_relative_eq; + /// let q = UnitQuaternion::from_euler_angles(1.0f64, 2.0, 3.0); + /// let q2 = q.cast::(); + /// assert_relative_eq!(q2, UnitQuaternion::from_euler_angles(1.0f32, 2.0, 3.0), epsilon = 1.0e-6); + /// ``` + pub fn cast(self) -> UnitQuaternion + where + To: SupersetOf, + { + crate::convert(self) + } + /// Creates a new quaternion from a unit vector (the rotation axis) and an angle /// (the rotation angle). /// diff --git a/src/geometry/quaternion_conversion.rs b/src/geometry/quaternion_conversion.rs index 2707419e..c597603b 100644 --- a/src/geometry/quaternion_conversion.rs +++ b/src/geometry/quaternion_conversion.rs @@ -35,8 +35,8 @@ use crate::geometry::{ impl SubsetOf> for Quaternion where - N1: SimdRealField, - N2: SimdRealField + SupersetOf, + N1: Scalar, + N2: Scalar + SupersetOf, { #[inline] fn to_superset(&self) -> Quaternion { @@ -58,8 +58,8 @@ where impl SubsetOf> for UnitQuaternion where - N1: SimdRealField, - N2: SimdRealField + SupersetOf, + N1: Scalar, + N2: Scalar + SupersetOf, { #[inline] fn to_superset(&self) -> UnitQuaternion { diff --git a/src/geometry/rotation_construction.rs b/src/geometry/rotation_construction.rs index c351f373..f198fc92 100644 --- a/src/geometry/rotation_construction.rs +++ b/src/geometry/rotation_construction.rs @@ -1,6 +1,6 @@ use num::{One, Zero}; -use simba::scalar::{ClosedAdd, ClosedMul}; +use simba::scalar::{ClosedAdd, ClosedMul, SupersetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::DimName; @@ -31,6 +31,28 @@ where } } +impl Rotation +where + DefaultAllocator: Allocator, +{ + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Rotation2; + /// let rot = Rotation2::::identity(); + /// let rot2 = rot.cast::(); + /// assert_eq!(rot2, Rotation2::::identity()); + /// ``` + pub fn cast(self) -> Rotation + where + Rotation: SupersetOf, + DefaultAllocator: Allocator, + { + crate::convert(self) + } +} + impl One for Rotation where N: Scalar + Zero + One + ClosedAdd + ClosedMul, diff --git a/src/geometry/similarity_construction.rs b/src/geometry/similarity_construction.rs index c24e09b2..4501bdb7 100644 --- a/src/geometry/similarity_construction.rs +++ b/src/geometry/similarity_construction.rs @@ -10,15 +10,16 @@ use rand::{ Rng, }; +use simba::scalar::SupersetOf; use simba::simd::SimdRealField; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U2, U3}; use crate::base::{DefaultAllocator, Vector2, Vector3}; -use crate::geometry::{ - AbstractRotation, Isometry, Point, Point3, Rotation2, Rotation3, Similarity, Translation, - UnitComplex, UnitQuaternion, +use crate::{ + AbstractRotation, Isometry, Point, Point3, Rotation2, Rotation3, Scalar, Similarity, + Translation, UnitComplex, UnitQuaternion, }; impl Similarity @@ -158,6 +159,22 @@ where scaling, ) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::SimilarityMatrix2; + /// let sim = SimilarityMatrix2::::identity(); + /// let sim2 = sim.cast::(); + /// assert_eq!(sim2, SimilarityMatrix2::::identity()); + /// ``` + pub fn cast(self) -> Similarity> + where + Similarity>: SupersetOf, + { + crate::convert(self) + } } impl Similarity> @@ -184,12 +201,28 @@ where scaling, ) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Similarity2; + /// let sim = Similarity2::::identity(); + /// let sim2 = sim.cast::(); + /// assert_eq!(sim2, Similarity2::::identity()); + /// ``` + pub fn cast(self) -> Similarity> + where + Similarity>: SupersetOf, + { + crate::convert(self) + } } // 3D rotation. macro_rules! similarity_construction_impl( - ($Rot: ty) => { - impl Similarity + ($Rot: ident) => { + impl Similarity> where N::Element: SimdRealField { /// Creates a new similarity from a translation, rotation axis-angle, and scaling /// factor. @@ -219,7 +252,23 @@ macro_rules! similarity_construction_impl( #[inline] pub fn new(translation: Vector3, axisangle: Vector3, scaling: N) -> Self { - Self::from_isometry(Isometry::<_, U3, $Rot>::new(translation, axisangle), scaling) + Self::from_isometry(Isometry::<_, U3, $Rot>::new(translation, axisangle), scaling) + } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Similarity3; + /// let sim = Similarity3::::identity(); + /// let sim2 = sim.cast::(); + /// assert_eq!(sim2, Similarity3::::identity()); + /// ``` + pub fn cast(self) -> Similarity> + where + Similarity>: SupersetOf, + { + crate::convert(self) } /// Creates an similarity that corresponds to a scaling factor and a local frame of @@ -260,7 +309,7 @@ macro_rules! similarity_construction_impl( up: &Vector3, scaling: N) -> Self { - Self::from_isometry(Isometry::<_, U3, $Rot>::face_towards(eye, target, up), scaling) + Self::from_isometry(Isometry::<_, U3, $Rot>::face_towards(eye, target, up), scaling) } /// Deprecated: Use [SimilarityMatrix3::face_towards] instead. @@ -308,7 +357,7 @@ macro_rules! similarity_construction_impl( up: &Vector3, scaling: N) -> Self { - Self::from_isometry(Isometry::<_, U3, $Rot>::look_at_rh(eye, target, up), scaling) + Self::from_isometry(Isometry::<_, U3, $Rot>::look_at_rh(eye, target, up), scaling) } /// Builds a left-handed look-at view matrix including a scaling factor. @@ -346,11 +395,11 @@ macro_rules! similarity_construction_impl( up: &Vector3, scaling: N) -> Self { - Self::from_isometry(Isometry::<_, _, $Rot>::look_at_lh(eye, target, up), scaling) + Self::from_isometry(Isometry::<_, _, $Rot>::look_at_lh(eye, target, up), scaling) } } } ); -similarity_construction_impl!(Rotation3); -similarity_construction_impl!(UnitQuaternion); +similarity_construction_impl!(Rotation3); +similarity_construction_impl!(UnitQuaternion); diff --git a/src/geometry/translation_construction.rs b/src/geometry/translation_construction.rs index 3dd14a34..964cd105 100644 --- a/src/geometry/translation_construction.rs +++ b/src/geometry/translation_construction.rs @@ -10,7 +10,7 @@ use rand::{ Rng, }; -use simba::scalar::ClosedAdd; +use simba::scalar::{ClosedAdd, SupersetOf}; use crate::base::allocator::Allocator; use crate::base::dimension::{DimName, U1, U2, U3, U4, U5, U6}; @@ -18,7 +18,7 @@ use crate::base::{DefaultAllocator, Scalar, VectorN}; use crate::geometry::Translation; -impl Translation +impl Translation where DefaultAllocator: Allocator, { @@ -37,9 +37,29 @@ where /// assert_eq!(t * p, p); /// ``` #[inline] - pub fn identity() -> Translation { + pub fn identity() -> Translation + where + N: Zero, + { Self::from(VectorN::::from_element(N::zero())) } + + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::Translation2; + /// let tra = Translation2::new(1.0f64, 2.0); + /// let tra2 = tra.cast::(); + /// assert_eq!(tra2, Translation2::new(1.0f32, 2.0)); + /// ``` + pub fn cast(self) -> Translation + where + Translation: SupersetOf, + DefaultAllocator: Allocator, + { + crate::convert(self) + } } impl One for Translation diff --git a/src/geometry/unit_complex_construction.rs b/src/geometry/unit_complex_construction.rs index 21f56562..9a24a57d 100644 --- a/src/geometry/unit_complex_construction.rs +++ b/src/geometry/unit_complex_construction.rs @@ -12,9 +12,9 @@ use num_complex::Complex; use crate::base::dimension::{U1, U2}; use crate::base::storage::Storage; -use crate::base::{Matrix2, Unit, Vector, Vector2}; +use crate::base::{Matrix2, Scalar, Unit, Vector, Vector2}; use crate::geometry::{Rotation2, UnitComplex}; -use simba::scalar::RealField; +use simba::scalar::{RealField, SupersetOf}; use simba::simd::SimdRealField; /// # Identity @@ -118,6 +118,22 @@ impl UnitComplex where N::Element: SimdRealField, { + /// Cast the components of `self` to another type. + /// + /// # Example + /// ``` + /// # use nalgebra::UnitComplex; + /// let c = UnitComplex::new(1.0f64); + /// let c2 = c.cast::(); + /// assert_eq!(c2, UnitComplex::new(1.0f32)); + /// ``` + pub fn cast(self) -> UnitComplex + where + UnitComplex: SupersetOf, + { + crate::convert(self) + } + /// The underlying complex number. /// /// Same as `self.as_ref()`.