Add flatten trait.

This commit is contained in:
Sébastien Crozet 2013-06-10 00:09:36 +00:00
parent c02edb9d09
commit 4c65f793e8
12 changed files with 310 additions and 5 deletions

View File

@ -4,6 +4,7 @@ use std::cmp::ApproxEq;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::flatten::Flatten;
use traits::workarounds::rlmul::{RMul, LMul};
use dim1::vec1::Vec1;
@ -105,3 +106,18 @@ impl<N:Rand + Copy> Rand for Mat1<N>
fn rand<R: Rng>(rng: &mut R) -> Mat1<N>
{ Mat1::new(rng.gen()) }
}
impl<N: Copy> Flatten<N> for Mat1<N>
{
fn flat_size() -> uint
{ 1 }
fn from_flattened(l: &[N], off: uint) -> Mat1<N>
{ Mat1::new(l[off]) }
fn to_flattened(&self) -> ~[N]
{ ~[ self.m11 ] }
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{ l[off] = self.m11 }
}

View File

@ -7,6 +7,7 @@ use traits::dot::Dot;
use traits::norm::Norm;
use traits::translation::Translation;
use traits::sub_dot::SubDot;
use traits::flatten::Flatten;
use traits::workarounds::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
#[deriving(Eq, ToStr)]
@ -169,3 +170,18 @@ impl<N:Rand + Copy> Rand for Vec1<N>
fn rand<R: Rng>(rng: &mut R) -> Vec1<N>
{ Vec1::new(rng.gen()) }
}
impl<N: Copy> Flatten<N> for Vec1<N>
{
fn flat_size() -> uint
{ 1 }
fn from_flattened(l: &[N], off: uint) -> Vec1<N>
{ Vec1::new(l[off]) }
fn to_flattened(&self) -> ~[N]
{ ~[ self.x ] }
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{ l[off] = self.x }
}

View File

@ -5,6 +5,7 @@ use std::util::swap;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::flatten::Flatten;
use traits::workarounds::rlmul::{RMul, LMul};
use dim2::vec2::Vec2;
@ -158,3 +159,23 @@ impl<N:Rand + Copy> Rand for Mat2<N>
fn rand<R: Rng>(rng: &mut R) -> Mat2<N>
{ Mat2::new(rng.gen(), rng.gen(), rng.gen(), rng.gen()) }
}
impl<N: Copy> Flatten<N> for Mat2<N>
{
fn flat_size() -> uint
{ 4 }
fn from_flattened(l: &[N], off: uint) -> Mat2<N>
{ Mat2::new(l[off], l[off + 1], l[off + 2], l[off + 3]) }
fn to_flattened(&self) -> ~[N]
{ ~[ self.m11, self.m12, self.m21, self.m22 ] }
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{
l[off] = self.m11;
l[off + 1] = self.m12;
l[off + 2] = self.m21;
l[off + 3] = self.m22;
}
}

View File

@ -8,6 +8,7 @@ use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::flatten::Flatten;
use traits::translation::Translation;
use traits::workarounds::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
@ -203,3 +204,21 @@ impl<N:Rand + Copy> Rand for Vec2<N>
fn rand<R: Rng>(rng: &mut R) -> Vec2<N>
{ Vec2::new(rng.gen(), rng.gen()) }
}
impl<N: Copy> Flatten<N> for Vec2<N>
{
fn flat_size() -> uint
{ 2 }
fn from_flattened(l: &[N], off: uint) -> Vec2<N>
{ Vec2::new(l[off], l[off + 1]) }
fn to_flattened(&self) -> ~[N]
{ ~[ self.x, self.y ] }
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{
l[off] = self.x;
l[off + 1] = self.y;
}
}

View File

@ -5,6 +5,7 @@ use std::util::swap;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::flatten::Flatten;
use traits::workarounds::rlmul::{RMul, LMul};
use dim3::vec3::Vec3;
@ -212,3 +213,36 @@ impl<N:Rand + Copy> Rand for Mat3<N>
rng.gen(), rng.gen(), rng.gen())
}
}
impl<N: Copy> Flatten<N> for Mat3<N>
{
fn flat_size() -> uint
{ 9 }
fn from_flattened(l: &[N], off: uint) -> Mat3<N>
{ Mat3::new(l[off + 0], l[off + 1], l[off + 2],
l[off + 3], l[off + 4], l[off + 5],
l[off + 6], l[off + 7], l[off + 8]) }
fn to_flattened(&self) -> ~[N]
{
~[
self.m11, self.m12, self.m13,
self.m21, self.m22, self.m23,
self.m31, self.m32, self.m33
]
}
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{
l[off + 0] = self.m11;
l[off + 1] = self.m12;
l[off + 2] = self.m13;
l[off + 3] = self.m21;
l[off + 4] = self.m22;
l[off + 5] = self.m23;
l[off + 6] = self.m31;
l[off + 7] = self.m32;
l[off + 8] = self.m33;
}
}

View File

@ -7,6 +7,7 @@ use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::flatten::Flatten;
use traits::translation::Translation;
use traits::workarounds::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
@ -232,3 +233,22 @@ impl<N:Copy + Rand> Rand for Vec3<N>
fn rand<R: Rng>(rng: &mut R) -> Vec3<N>
{ Vec3::new(rng.gen(), rng.gen(), rng.gen()) }
}
impl<N: Copy> Flatten<N> for Vec3<N>
{
fn flat_size() -> uint
{ 3 }
fn from_flattened(l: &[N], off: uint) -> Vec3<N>
{ Vec3::new(l[off], l[off + 1], l[off + 2]) }
fn to_flattened(&self) -> ~[N]
{ ~[ self.x, self.y, self.z ] }
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{
l[off] = self.x;
l[off + 1] = self.y;
l[off + 2] = self.z;
}
}

View File

@ -69,6 +69,7 @@ pub mod traits
pub mod ring;
pub mod division_ring;
pub mod sub_dot;
pub mod flatten;
/// This package contains everything done because the current compiler either
/// crashes or miss features.

View File

@ -6,6 +6,7 @@ use traits::dim::Dim;
use traits::inv::Inv;
use traits::division_ring::DivisionRing;
use traits::transpose::Transpose;
use traits::flatten::Flatten;
use traits::workarounds::rlmul::{RMul, LMul};
use ndim::dmat::{DMat, one_mat_with_dim, zero_mat_with_dim, is_zero_mat};
use ndim::nvec::NVec;
@ -168,3 +169,39 @@ impl<D: Dim, N: Rand + Zero + Copy> Rand for NMat<D, N>
res
}
}
impl<D: Dim, N: Zero + Copy> Flatten<N> for NMat<D, N>
{
fn flat_size() -> uint
{ Dim::dim::<D>() * Dim::dim::<D>() }
fn from_flattened(l: &[N], off: uint) -> NMat<D, N>
{
let dim = Dim::dim::<D>();
let mut res = Zero::zero::<NMat<D, N>>();
for iterate(0u, dim * dim) |i|
{ res.mij.mij[i] = l[off + i] }
res
}
fn to_flattened(&self) -> ~[N]
{
let dim = Dim::dim::<D>();
let mut res = ~[];
for iterate(0u, dim * dim) |i|
{ res.push(self.mij.mij[i]) }
res
}
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{
let dim = Dim::dim::<D>();
for iterate(0u, dim * dim) |i|
{ l[off + i] = self.mij.mij[i] }
}
}

View File

@ -12,6 +12,7 @@ use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::Translation;
use traits::flatten::Flatten;
use traits::workarounds::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
// D is a phantom parameter, used only as a dimensional token.
@ -196,3 +197,39 @@ impl<D: Dim, N: Rand + Zero + Copy> Rand for NVec<D, N>
res
}
}
impl<D: Dim, N: Zero + Copy> Flatten<N> for NVec<D, N>
{
fn flat_size() -> uint
{ Dim::dim::<D>() }
fn from_flattened(l: &[N], off: uint) -> NVec<D, N>
{
let dim = Dim::dim::<D>();
let mut res = Zero::zero::<NVec<D, N>>();
for iterate(0u, dim) |i|
{ res.at.at[i] = l[off + i] }
res
}
fn to_flattened(&self) -> ~[N]
{
let dim = Dim::dim::<D>();
let mut res = ~[];
for iterate(0u, dim) |i|
{ res.push(self.at.at[i]) }
res
}
fn to_flattened_inplace(&self, l: &mut [N], off: uint)
{
let dim = Dim::dim::<D>();
for iterate(0u, dim) |i|
{ l[off + i] = self.at.at[i] }
}
}

View File

@ -1,5 +1,7 @@
#[test]
use std::num::{Real, One, abs};
use std::vec;
#[test]
use std::num::{Real, Zero, One, abs};
#[test]
use std::rand::{random};
#[test]
@ -8,8 +10,8 @@ use std::cmp::ApproxEq;
use traits::inv::Inv;
#[test]
use traits::rotation::Rotation;
// #[test]
// use traits::dim::d7;
#[test]
use traits::dim::d7;
#[test]
use dim1::vec1::Vec1;
#[test]
@ -18,10 +20,12 @@ use dim1::mat1::Mat1;
use dim2::mat2::Mat2;
#[test]
use dim3::mat3::Mat3;
// #[test]
// use ndim::nmat::NMat;
#[test]
use ndim::nmat::NMat;
#[test]
use adaptors::rotmat::Rotmat;
#[test]
use traits::flatten::Flatten;
macro_rules! test_inv_mat_impl(
($t: ty) => (
@ -34,6 +38,21 @@ macro_rules! test_inv_mat_impl(
);
)
macro_rules! test_flatten_impl(
($t: ty, $n: ty) => (
for 10000.times
{
let v: $t = random();
let mut l: ~[$n] = vec::from_elem(42 + Flatten::flat_size::<$n, $t>(), Zero::zero::<$n>());
v.to_flattened_inplace(l, 42);
assert!(Flatten::from_flattened::<$n, $t>(v.to_flattened(), 0) == v);
assert!(Flatten::from_flattened::<$n, $t>(l, 42) == v);
}
)
)
#[test]
fn test_inv_mat1()
{ test_inv_mat_impl!(Mat1<f64>); }
@ -51,6 +70,22 @@ fn test_inv_mat3()
// fn test_inv_nmat()
// { test_inv_mat_impl!(NMat<d7, f64>); }
#[test]
fn test_flatten_mat1()
{ test_flatten_impl!(Mat1<f64>, f64); }
#[test]
fn test_flatten_mat2()
{ test_flatten_impl!(Mat2<f64>, f64); }
#[test]
fn test_flatten_mat3()
{ test_flatten_impl!(Mat3<f64>, f64); }
#[test]
fn test_flatten_nmat()
{ test_flatten_impl!(NMat<d7, f64>, f64); }
#[test]
fn test_rotation2()
{

View File

@ -1,4 +1,6 @@
#[test]
use std::vec;
#[test]
use std::iterator::IteratorUtil;
#[test]
use std::num::{Zero, One};
@ -24,6 +26,8 @@ use traits::cross::Cross;
use traits::dot::Dot;
#[test]
use traits::norm::Norm;
#[test]
use traits::flatten::Flatten;
macro_rules! test_commut_dot_impl(
($t: ty) => (
@ -75,6 +79,21 @@ macro_rules! test_subspace_basis_impl(
);
)
macro_rules! test_flatten_impl(
($t: ty, $n: ty) => (
for 10000.times
{
let v: $t = random();
let mut l: ~[$n] = vec::from_elem(42 + Flatten::flat_size::<$n, $t>(), Zero::zero::<$n>());
v.to_flattened_inplace(l, 42);
assert!(Flatten::from_flattened::<$n, $t>(v.to_flattened(), 0) == v);
assert!(Flatten::from_flattened::<$n, $t>(l, 42) == v);
}
)
)
#[test]
fn test_cross_vec3()
{
@ -136,3 +155,19 @@ fn test_subspace_basis_vec3()
#[test]
fn test_subspace_basis_nvec()
{ test_subspace_basis_impl!(NVec<d7, f64>); }
#[test]
fn test_flatten_vec1()
{ test_flatten_impl!(Vec1<f64>, f64); }
#[test]
fn test_flatten_vec2()
{ test_flatten_impl!(Vec2<f64>, f64); }
#[test]
fn test_flatten_vec3()
{ test_flatten_impl!(Vec3<f64>, f64); }
#[test]
fn test_flatten_nvec()
{ test_flatten_impl!(NVec<d7, f64>, f64); }

34
src/traits/flatten.rs Normal file
View File

@ -0,0 +1,34 @@
/// Trait of objects which can be written as a list of values, and read from
/// that list.
pub trait Flatten<N>
{
/// The number of elements needed to flatten this object.
fn flat_size() -> uint;
/**
* Creates a new object from its flattened version. Its flattened version is
* a continuous list of values. It is assumet that `flat_size` elements will
* be read.
*
* - `l`: list from which the flat version must be read.
* - `off`: index from which (included) the flat version read must begin.
* It is assumed that the caller gives a valid input.
*/
fn from_flattened(l: &[N], off: uint) -> Self; // FIXME: keep (vector + index) or use an iterator?
/**
* Creates a flattened version of `self`. The result vector must be of size
* `flat_size`.
*/
fn to_flattened(&self) -> ~[N];
/**
* Creates a flattened version of `self` on a vector. It is assumed that
* `flat_size` elements will be written contiguously.
*
* - `l`: list to which the flat version must be written.
* - `off`: index from which (included) the flat version write must begin.
* It is assumed that the caller allocated a long enough list.
*/
fn to_flattened_inplace(&self, l: &mut [N], off: uint); // FIXME: keep (vector + index) or use an iterator (to a mutable value…)?
}