nalgebra/src/core/conversion.rs
2017-02-18 13:44:03 +01:00

216 lines
7.9 KiB
Rust
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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, DimName, DimNameMul, DimNameProd, U1, U2, U3, U4, U5, U6};
use core::constraint::{ShapeConstraint, SameNumberOfRows, SameNumberOfColumns};
use core::storage::OwnedStorage;
use core::allocator::{OwnedAllocator, SameShapeAllocator};
// FIXME: too bad this won't work allo slice conversions.
impl<N1, N2, R1, C1, R2, C2, SA, SB> SubsetOf<Matrix<N2, R2, C2, SB>> for Matrix<N1, R1, C1, SA>
where R1: Dim, C1: Dim, R2: Dim, C2: Dim,
N1: Scalar,
N2: Scalar + SupersetOf<N1>,
SA: OwnedStorage<N1, R1, C1>,
SB: OwnedStorage<N2, R2, C2>,
SB::Alloc: OwnedAllocator<N2, R2, C2, SB>,
SA::Alloc: OwnedAllocator<N1, R1, C1, SA> +
SameShapeAllocator<N1, R1, C1, R2, C2, SA>,
ShapeConstraint: SameNumberOfRows<R1, R2> + SameNumberOfColumns<C1, C2> {
#[inline]
fn to_superset(&self) -> Matrix<N2, R2, C2, SB> {
let (nrows, ncols) = self.shape();
let nrows2 = R2::from_usize(nrows);
let ncols2 = C2::from_usize(ncols);
let mut res = unsafe { Matrix::<N2, R2, C2, SB>::new_uninitialized_generic(nrows2, ncols2) };
for i in 0 .. nrows {
for j in 0 .. ncols {
unsafe {
*res.get_unchecked_mut(i, j) = N2::from_subset(self.get_unchecked(i, j))
}
}
}
res
}
#[inline]
fn is_in_subset(m: &Matrix<N2, R2, C2, SB>) -> bool {
m.iter().all(|e| e.is_in_subset())
}
#[inline]
unsafe fn from_superset_unchecked(m: &Matrix<N2, R2, C2, SB>) -> Self {
let (nrows2, ncols2) = m.shape();
let nrows = R1::from_usize(nrows2);
let ncols = C1::from_usize(ncols2);
let mut res = Self::new_uninitialized_generic(nrows, ncols);
for i in 0 .. nrows2 {
for j in 0 .. ncols2 {
*res.get_unchecked_mut(i, j) = m.get_unchecked(i, j).to_subset_unchecked()
}
}
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);
);