Merge pull request #844 from dimforge/cast

@sebcrozet Add "cast" methods to cast the type component types
This commit is contained in:
Sébastien Crozet 2021-03-06 12:19:41 +01:00 committed by GitHub
commit a798d1c4ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 303 additions and 26 deletions

View File

@ -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::<f32>()`.
## [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

View File

@ -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<N: Scalar, R: Dim, C: Dim, S: Storage<N, R, C>> Matrix<N, R, C, S> {
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::<f32>();
/// assert_eq!(q2, Vector3::new(1.0f32, 2.0, 3.0));
/// ```
pub fn cast<N2: Scalar>(self) -> MatrixMN<N2, R, C>
where
MatrixMN<N2, R, C>: SupersetOf<Self>,
DefaultAllocator: Allocator<N2, R, C>,
{
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:

View File

@ -5,6 +5,7 @@ use crate::{
use num::{One, Zero};
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
use simba::scalar::SupersetOf;
impl<N: Scalar> DualQuaternion<N> {
/// Creates a dual quaternion from its rotation and translation components.
@ -49,6 +50,22 @@ impl<N: Scalar> DualQuaternion<N> {
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::<f32>();
/// assert_eq!(q2, DualQuaternion::from_real(Quaternion::new(1.0f32, 2.0, 3.0, 4.0)));
/// ```
pub fn cast<To: Scalar>(self) -> DualQuaternion<To>
where
DualQuaternion<To>: SupersetOf<Self>,
{
crate::convert(self)
}
}
impl<N: SimdRealField> DualQuaternion<N>
@ -129,6 +146,22 @@ impl<N: SimdRealField> UnitDualQuaternion<N> {
pub fn identity() -> Self {
Self::new_unchecked(DualQuaternion::identity())
}
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::UnitDualQuaternion;
/// let q = UnitDualQuaternion::<f64>::identity();
/// let q2 = q.cast::<f32>();
/// assert_eq!(q2, UnitDualQuaternion::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> UnitDualQuaternion<To>
where
UnitDualQuaternion<To>: SupersetOf<Self>,
{
crate::convert(self)
}
}
impl<N: SimdRealField> UnitDualQuaternion<N>

View File

@ -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::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, IsometryMatrix2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> IsometryMatrix2<To>
where
IsometryMatrix2<To>: SupersetOf<Self>,
{
crate::convert(self)
}
}
impl<N: SimdRealField> Isometry2<N>
@ -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::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, Isometry2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Isometry2<To>
where
Isometry2<To>: SupersetOf<Self>,
{
crate::convert(self)
}
}
// 3D rotation.
@ -387,6 +420,22 @@ where
N::Element: SimdRealField,
{
basic_isometry_construction_impl!(UnitQuaternion<N>);
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Isometry3;
/// let iso = Isometry3::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, Isometry3::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Isometry3<To>
where
Isometry3<To>: SupersetOf<Self>,
{
crate::convert(self)
}
}
impl<N: SimdRealField> IsometryMatrix3<N>
@ -394,6 +443,22 @@ where
N::Element: SimdRealField,
{
basic_isometry_construction_impl!(Rotation3<N>);
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::IsometryMatrix3;
/// let iso = IsometryMatrix3::<f64>::identity();
/// let iso2 = iso.cast::<f32>();
/// assert_eq!(iso2, IsometryMatrix3::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> IsometryMatrix3<To>
where
IsometryMatrix3<To>: SupersetOf<Self>,
{
crate::convert(self)
}
}
/// # Construction from a 3D eye position and target point

View File

@ -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::<f32>();
/// assert_eq!(pt2, Point2::new(1.0f32, 2.0));
/// ```
pub fn cast<To: Scalar>(self) -> Point<To, D>
where
Point<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D>,
{
crate::convert(self)
}
}
/*

View File

@ -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<N: Scalar> Quaternion<N> {
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::<f32>();
/// assert_eq!(q2, Quaternion::new(1.0f32, 2.0, 3.0, 4.0));
/// ```
pub fn cast<To: Scalar>(self) -> Quaternion<To>
where
To: SupersetOf<N>,
{
crate::convert(self)
}
}
impl<N: SimdRealField> Quaternion<N> {
@ -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::<f32>();
/// assert_relative_eq!(q2, UnitQuaternion::from_euler_angles(1.0f32, 2.0, 3.0), epsilon = 1.0e-6);
/// ```
pub fn cast<To: Scalar>(self) -> UnitQuaternion<To>
where
To: SupersetOf<N>,
{
crate::convert(self)
}
/// Creates a new quaternion from a unit vector (the rotation axis) and an angle
/// (the rotation angle).
///

View File

@ -35,8 +35,8 @@ use crate::geometry::{
impl<N1, N2> SubsetOf<Quaternion<N2>> for Quaternion<N1>
where
N1: SimdRealField,
N2: SimdRealField + SupersetOf<N1>,
N1: Scalar,
N2: Scalar + SupersetOf<N1>,
{
#[inline]
fn to_superset(&self) -> Quaternion<N2> {
@ -58,8 +58,8 @@ where
impl<N1, N2> SubsetOf<UnitQuaternion<N2>> for UnitQuaternion<N1>
where
N1: SimdRealField,
N2: SimdRealField + SupersetOf<N1>,
N1: Scalar,
N2: Scalar + SupersetOf<N1>,
{
#[inline]
fn to_superset(&self) -> UnitQuaternion<N2> {

View File

@ -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<N: Scalar, D: DimName> Rotation<N, D>
where
DefaultAllocator: Allocator<N, D, D>,
{
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Rotation2;
/// let rot = Rotation2::<f64>::identity();
/// let rot2 = rot.cast::<f32>();
/// assert_eq!(rot2, Rotation2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Rotation<To, D>
where
Rotation<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D, D>,
{
crate::convert(self)
}
}
impl<N, D: DimName> One for Rotation<N, D>
where
N: Scalar + Zero + One + ClosedAdd + ClosedMul,

View File

@ -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<N: SimdRealField, D: DimName, R> Similarity<N, D, R>
@ -158,6 +159,22 @@ where
scaling,
)
}
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::SimilarityMatrix2;
/// let sim = SimilarityMatrix2::<f64>::identity();
/// let sim2 = sim.cast::<f32>();
/// assert_eq!(sim2, SimilarityMatrix2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Similarity<To, U2, Rotation2<To>>
where
Similarity<To, U2, Rotation2<To>>: SupersetOf<Self>,
{
crate::convert(self)
}
}
impl<N: SimdRealField> Similarity<N, U2, UnitComplex<N>>
@ -184,12 +201,28 @@ where
scaling,
)
}
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Similarity2;
/// let sim = Similarity2::<f64>::identity();
/// let sim2 = sim.cast::<f32>();
/// assert_eq!(sim2, Similarity2::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Similarity<To, U2, UnitComplex<To>>
where
Similarity<To, U2, UnitComplex<To>>: SupersetOf<Self>,
{
crate::convert(self)
}
}
// 3D rotation.
macro_rules! similarity_construction_impl(
($Rot: ty) => {
impl<N: SimdRealField> Similarity<N, U3, $Rot>
($Rot: ident) => {
impl<N: SimdRealField> Similarity<N, U3, $Rot<N>>
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<N>, axisangle: Vector3<N>, scaling: N) -> Self
{
Self::from_isometry(Isometry::<_, U3, $Rot>::new(translation, axisangle), scaling)
Self::from_isometry(Isometry::<_, U3, $Rot<N>>::new(translation, axisangle), scaling)
}
/// Cast the components of `self` to another type.
///
/// # Example
/// ```
/// # use nalgebra::Similarity3;
/// let sim = Similarity3::<f64>::identity();
/// let sim2 = sim.cast::<f32>();
/// assert_eq!(sim2, Similarity3::<f32>::identity());
/// ```
pub fn cast<To: Scalar>(self) -> Similarity<To, U3, $Rot<To>>
where
Similarity<To, U3, $Rot<To>>: SupersetOf<Self>,
{
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<N>,
scaling: N)
-> Self {
Self::from_isometry(Isometry::<_, U3, $Rot>::face_towards(eye, target, up), scaling)
Self::from_isometry(Isometry::<_, U3, $Rot<N>>::face_towards(eye, target, up), scaling)
}
/// Deprecated: Use [SimilarityMatrix3::face_towards] instead.
@ -308,7 +357,7 @@ macro_rules! similarity_construction_impl(
up: &Vector3<N>,
scaling: N)
-> Self {
Self::from_isometry(Isometry::<_, U3, $Rot>::look_at_rh(eye, target, up), scaling)
Self::from_isometry(Isometry::<_, U3, $Rot<N>>::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<N>,
scaling: N)
-> Self {
Self::from_isometry(Isometry::<_, _, $Rot>::look_at_lh(eye, target, up), scaling)
Self::from_isometry(Isometry::<_, _, $Rot<N>>::look_at_lh(eye, target, up), scaling)
}
}
}
);
similarity_construction_impl!(Rotation3<N>);
similarity_construction_impl!(UnitQuaternion<N>);
similarity_construction_impl!(Rotation3);
similarity_construction_impl!(UnitQuaternion);

View File

@ -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<N: Scalar + Zero, D: DimName> Translation<N, D>
impl<N: Scalar, D: DimName> Translation<N, D>
where
DefaultAllocator: Allocator<N, D>,
{
@ -37,9 +37,29 @@ where
/// assert_eq!(t * p, p);
/// ```
#[inline]
pub fn identity() -> Translation<N, D> {
pub fn identity() -> Translation<N, D>
where
N: Zero,
{
Self::from(VectorN::<N, D>::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::<f32>();
/// assert_eq!(tra2, Translation2::new(1.0f32, 2.0));
/// ```
pub fn cast<To: Scalar>(self) -> Translation<To, D>
where
Translation<To, D>: SupersetOf<Self>,
DefaultAllocator: Allocator<To, D>,
{
crate::convert(self)
}
}
impl<N: Scalar + Zero + ClosedAdd, D: DimName> One for Translation<N, D>

View File

@ -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<N: SimdRealField> UnitComplex<N>
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::<f32>();
/// assert_eq!(c2, UnitComplex::new(1.0f32));
/// ```
pub fn cast<To: Scalar>(self) -> UnitComplex<To>
where
UnitComplex<To>: SupersetOf<Self>,
{
crate::convert(self)
}
/// The underlying complex number.
///
/// Same as `self.as_ref()`.