Implement AsRef, AsMut, Into, From.

This commit is contained in:
Sébastien Crozet 2017-02-18 13:28:22 +01:00 committed by Sébastien Crozet
parent a4089a7ee0
commit d6285e1165
2 changed files with 248 additions and 3 deletions

View File

@ -1,7 +1,11 @@
use std::ptr;
use std::mem;
use std::convert::{From, Into, AsRef, AsMut};
use typenum::{self, Cmp, Equal};
use alga::general::{SubsetOf, SupersetOf};
use core::{Scalar, Matrix};
use core::dimension::Dim;
use core::dimension::{Dim, DimName, DimNameMul, DimNameProd, U1, U2, U3, U4, U5, U6};
use core::constraint::{ShapeConstraint, SameNumberOfRows, SameNumberOfColumns};
use core::storage::OwnedStorage;
use core::allocator::{OwnedAllocator, SameShapeAllocator};
@ -57,3 +61,155 @@ impl<N1, N2, R1, C1, R2, C2, SA, SB> SubsetOf<Matrix<N2, R2, C2, SB>> for Matrix
res
}
}
macro_rules! impl_from_into_asref_1D(
($($Dim: ident => $SZ: expr);* $(;)*) => {$(
impl<N, R, C, S> From<[N; $SZ]> for Matrix<N, R, C, S>
where N: Scalar,
R: DimName + DimNameMul<C>,
C: DimName,
S: OwnedStorage<N, R, C>,
S::Alloc: OwnedAllocator<N, R, C, S>,
<DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
#[inline]
fn from(arr: [N; $SZ]) -> Self {
unsafe {
let mut res = Self::new_uninitialized();
ptr::copy_nonoverlapping(&arr[0], res.data.ptr_mut(), $SZ);
res
}
}
}
impl<N, R, C, S> Into<[N; $SZ]> for Matrix<N, R, C, S>
where N: Scalar,
R: DimName + DimNameMul<C>,
C: DimName,
S: OwnedStorage<N, R, C>,
S::Alloc: OwnedAllocator<N, R, C, S>,
<DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
#[inline]
fn into(self) -> [N; $SZ] {
unsafe {
let mut res: [N; $SZ] = mem::uninitialized();
ptr::copy_nonoverlapping(self.data.ptr(), &mut res[0], $SZ);
res
}
}
}
impl<N, R, C, S> AsRef<[N; $SZ]> for Matrix<N, R, C, S>
where N: Scalar,
R: DimName + DimNameMul<C>,
C: DimName,
S: OwnedStorage<N, R, C>,
S::Alloc: OwnedAllocator<N, R, C, S>,
<DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
#[inline]
fn as_ref(&self) -> &[N; $SZ] {
unsafe {
mem::transmute(self.data.ptr())
}
}
}
impl<N, R, C, S> AsMut<[N; $SZ]> for Matrix<N, R, C, S>
where N: Scalar,
R: DimName + DimNameMul<C>,
C: DimName,
S: OwnedStorage<N, R, C>,
S::Alloc: OwnedAllocator<N, R, C, S>,
<DimNameProd<R, C> as DimName>::Value: Cmp<typenum::$Dim, Output = Equal> {
#[inline]
fn as_mut(&mut self) -> &mut [N; $SZ] {
unsafe {
mem::transmute(self.data.ptr_mut())
}
}
}
)*}
);
// Implement for vectors of dimension 1 .. 36 and matrices with shape 1x1 .. 6x6.
impl_from_into_asref_1D!(
U1 => 1; U2 => 2; U3 => 3; U4 => 4; U5 => 5; U6 => 6;
U7 => 7; U8 => 8; U9 => 9; U10 => 10; U11 => 11; U12 => 12;
U13 => 13; U14 => 14; U15 => 15; U16 => 16; U17 => 17; U18 => 18;
U19 => 19; U20 => 20; U21 => 21; U22 => 22; U23 => 23; U24 => 24;
U25 => 25; U26 => 26; U27 => 27; U28 => 28; U29 => 29; U30 => 30;
U31 => 31; U32 => 32; U33 => 33; U34 => 34; U35 => 35; U36 => 36;
);
macro_rules! impl_from_into_asref_2D(
($(($NRows: ty, $NCols: ty) => ($SZRows: expr, $SZCols: expr));* $(;)*) => {$(
impl<N, S> From<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
where N: Scalar,
S: OwnedStorage<N, $NRows, $NCols>,
S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
#[inline]
fn from(arr: [[N; $SZRows]; $SZCols]) -> Self {
unsafe {
let mut res = Self::new_uninitialized();
ptr::copy_nonoverlapping(&arr[0][0], res.data.ptr_mut(), $SZRows * $SZCols);
res
}
}
}
impl<N, S> Into<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
where N: Scalar,
S: OwnedStorage<N, $NRows, $NCols>,
S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
#[inline]
fn into(self) -> [[N; $SZRows]; $SZCols] {
unsafe {
let mut res: [[N; $SZRows]; $SZCols] = mem::uninitialized();
ptr::copy_nonoverlapping(self.data.ptr(), &mut res[0][0], $SZRows * $SZCols);
res
}
}
}
impl<N, S> AsRef<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
where N: Scalar,
S: OwnedStorage<N, $NRows, $NCols>,
S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
#[inline]
fn as_ref(&self) -> &[[N; $SZRows]; $SZCols] {
unsafe {
mem::transmute(self.data.ptr())
}
}
}
impl<N, S> AsMut<[[N; $SZRows]; $SZCols]> for Matrix<N, $NRows, $NCols, S>
where N: Scalar,
S: OwnedStorage<N, $NRows, $NCols>,
S::Alloc: OwnedAllocator<N, $NRows, $NCols, S> {
#[inline]
fn as_mut(&mut self) -> &mut [[N; $SZRows]; $SZCols] {
unsafe {
mem::transmute(self.data.ptr_mut())
}
}
}
)*}
);
// Implement for matrices with shape 1x1 .. 4x4.
impl_from_into_asref_2D!(
(U1, U1) => (1, 1); (U1, U2) => (1, 2); (U1, U3) => (1, 3); (U1, U4) => (1, 4); (U1, U5) => (1, 5); (U1, U6) => (1, 6);
(U2, U1) => (2, 1); (U2, U2) => (2, 2); (U2, U3) => (2, 3); (U2, U4) => (2, 4); (U2, U5) => (2, 5); (U2, U6) => (2, 6);
(U3, U1) => (3, 1); (U3, U2) => (3, 2); (U3, U3) => (3, 3); (U3, U4) => (3, 4); (U3, U5) => (3, 5); (U3, U6) => (3, 6);
(U4, U1) => (4, 1); (U4, U2) => (4, 2); (U4, U3) => (4, 3); (U4, U4) => (4, 4); (U4, U5) => (4, 5); (U4, U6) => (4, 6);
(U5, U1) => (5, 1); (U5, U2) => (5, 2); (U5, U3) => (5, 3); (U5, U4) => (5, 4); (U5, U5) => (5, 5); (U5, U6) => (5, 6);
(U6, U1) => (6, 1); (U6, U2) => (6, 2); (U6, U3) => (6, 3); (U6, U4) => (6, 4); (U6, U5) => (6, 5); (U6, U6) => (6, 6);
);

View File

@ -8,8 +8,16 @@ extern crate alga;
extern crate nalgebra as na;
use alga::linear::Transformation;
use na::{Vector3, Point3, Translation3, Isometry3, Similarity3, Affine3, Projective3, Transform3,
Rotation3, UnitQuaternion};
use na::{
Vector1, Vector2, Vector3, Vector4, Vector5, Vector6,
Matrix2, Matrix3, Matrix4, Matrix5, Matrix6,
Matrix2x3, Matrix2x4, Matrix2x5, Matrix2x6,
Matrix3x2, Matrix3x4, Matrix3x5, Matrix3x6,
Matrix4x2, Matrix4x3, Matrix4x5, Matrix4x6,
Matrix5x2, Matrix5x3, Matrix5x4, Matrix5x6,
Matrix6x2, Matrix6x3, Matrix6x4, Matrix6x5,
Point3, Translation3, Isometry3, Similarity3, Affine3,
Projective3, Transform3, Rotation3, UnitQuaternion};
#[cfg(feature = "arbitrary")]
@ -145,3 +153,84 @@ quickcheck!{
// XXX test TransformBase
}
macro_rules! array_vector_conversion(
($($array_vector_conversion_i: ident, $Vector: ident, $SZ: expr);* $(;)*) => {$(
#[test]
fn $array_vector_conversion_i() {
let v = $Vector::from_fn(|i, _| i);
let arr: [usize; $SZ] = v.into();
let arr_ref: &[usize; $SZ] = v.as_ref();
let v2 = $Vector::from(arr);
for i in 0 .. $SZ {
assert_eq!(arr[i], i);
assert_eq!(arr_ref[i], i);
}
assert_eq!(v, v2);
}
)*}
);
array_vector_conversion!(
array_vector_conversion_1, Vector1, 1;
array_vector_conversion_2, Vector2, 2;
array_vector_conversion_3, Vector3, 3;
array_vector_conversion_4, Vector4, 4;
array_vector_conversion_5, Vector5, 5;
array_vector_conversion_6, Vector6, 6;
);
macro_rules! array_matrix_conversion(
($($array_matrix_conversion_i_j: ident, $Matrix: ident, ($NRows: expr, $NCols: expr));* $(;)*) => {$(
#[test]
fn $array_matrix_conversion_i_j() {
let m = $Matrix::from_fn(|i, j| i * 10 + j);
let arr: [[usize; $NRows]; $NCols] = m.into();
let arr_ref: &[[usize; $NRows]; $NCols] = m.as_ref();
let m2 = $Matrix::from(arr);
for i in 0 .. $NRows {
for j in 0 .. $NCols {
assert_eq!(arr[j][i], i * 10 + j);
assert_eq!(arr_ref[j][i], i * 10 + j);
}
}
assert_eq!(m, m2);
}
)*}
);
array_matrix_conversion!(
array_matrix_conversion_2_2, Matrix2, (2, 2);
array_matrix_conversion_2_3, Matrix2x3, (2, 3);
array_matrix_conversion_2_4, Matrix2x4, (2, 4);
array_matrix_conversion_2_5, Matrix2x5, (2, 5);
array_matrix_conversion_2_6, Matrix2x6, (2, 6);
array_matrix_conversion_3_2, Matrix3x2, (3, 2);
array_matrix_conversion_3_3, Matrix3, (3, 3);
array_matrix_conversion_3_4, Matrix3x4, (3, 4);
array_matrix_conversion_3_5, Matrix3x5, (3, 5);
array_matrix_conversion_3_6, Matrix3x6, (3, 6);
array_matrix_conversion_4_2, Matrix4x2, (4, 2);
array_matrix_conversion_4_3, Matrix4x3, (4, 3);
array_matrix_conversion_4_4, Matrix4, (4, 4);
array_matrix_conversion_4_5, Matrix4x5, (4, 5);
array_matrix_conversion_4_6, Matrix4x6, (4, 6);
array_matrix_conversion_5_2, Matrix5x2, (5, 2);
array_matrix_conversion_5_3, Matrix5x3, (5, 3);
array_matrix_conversion_5_4, Matrix5x4, (5, 4);
array_matrix_conversion_5_5, Matrix5, (5, 5);
array_matrix_conversion_5_6, Matrix5x6, (5, 6);
array_matrix_conversion_6_2, Matrix6x2, (6, 2);
array_matrix_conversion_6_3, Matrix6x3, (6, 3);
array_matrix_conversion_6_4, Matrix6x4, (6, 4);
array_matrix_conversion_6_5, Matrix6x5, (6, 5);
array_matrix_conversion_6_6, Matrix6, (6, 6);
);