nalgebra/src/structs/mat_macros.rs

527 lines
14 KiB
Rust
Raw Normal View History

2013-07-22 16:26:20 +08:00
#[macro_escape];
macro_rules! mat_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
2013-08-05 16:13:44 +08:00
impl<N> $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
pub fn new($comp0: N $(, $compN: N )*) -> $t<N> {
2013-08-05 15:44:56 +08:00
$t {
$comp0: $comp0
$(, $compN: $compN )*
}
2013-07-22 16:26:20 +08:00
}
}
)
)
macro_rules! at_fast_impl(
($t: ident, $dim: expr) => (
impl<N: Clone> $t<N> {
#[inline]
unsafe fn at_fast(&self, (i, j): (uint, uint)) -> N {
(*cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)
.unsafe_ref(i + j * $dim)).clone()
}
#[inline]
unsafe fn set_fast(&mut self, (i, j): (uint, uint), val: N) {
(*cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)
.unsafe_mut_ref(i + j * $dim)) = val
}
}
)
)
macro_rules! mat_cast_impl(
($t: ident, $tcast: ident, $comp0: ident $(,$compN: ident)*) => (
impl<Nin: Clone, Nout: Clone + Cast<Nin>> $tcast<Nout> for $t<Nin> {
#[inline]
fn to(v: $t<Nin>) -> $t<Nout> {
$t::new(Cast::from(v.$comp0.clone()) $(, Cast::from(v.$compN.clone()))*)
}
2013-08-05 16:13:44 +08:00
}
)
)
macro_rules! add_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Add<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.$comp0 + right.$comp0 $(, left.$compN + right.$compN)*)
}
}
)
)
macro_rules! sub_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Sub<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*)
}
}
)
)
macro_rules! scalar_mul_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 * *right $(, left.$compN * *right)*)
}
}
)
)
macro_rules! scalar_div_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 / *right $(, left.$compN / *right)*)
}
}
)
)
macro_rules! scalar_add_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 + *right $(, left.$compN + *right)*)
}
}
)
)
macro_rules! scalar_sub_impl(
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl $trhs<$n, $t<$n>> for $n {
#[inline]
fn binop(left: &$t<$n>, right: &$n) -> $t<$n> {
$t::new(left.$comp0 - *right $(, left.$compN - *right)*)
}
}
)
)
macro_rules! absolute_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Signed> Absolute<$t<N>> for $t<N> {
#[inline]
fn abs(m: &$t<N>) -> $t<N> {
$t::new(m.$comp0.abs() $(, m.$compN.abs() )*)
}
}
)
)
2013-07-22 16:26:20 +08:00
macro_rules! iterable_impl(
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N> Iterable<N> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn iter<'l>(&'l self) -> VecIterator<'l, N> {
unsafe {
cast::transmute::<&'l $t<N>, &'l [N, ..$dim * $dim]>(self).iter()
}
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! iterable_mut_impl(
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N> IterableMut<N> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> {
unsafe {
cast::transmute::<&'l mut $t<N>, &'l mut [N, ..$dim * $dim]>(self).mut_iter()
}
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! one_impl(
2013-09-07 23:26:05 +08:00
($t: ident, $value0: expr $(, $valueN: expr)* ) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone + One + Zero> One for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn one() -> $t<N> {
2013-09-07 23:26:05 +08:00
$t::new($value0() $(, $valueN() )*)
2013-08-05 15:44:56 +08:00
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! dim_impl(
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N> Dim for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn dim(_: Option<$t<N>>) -> uint {
2013-08-05 16:13:44 +08:00
$dim
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! indexable_impl(
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone> Indexable<(uint, uint), N> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
fn at(&self, (i, j): (uint, uint)) -> N {
2013-08-05 16:13:44 +08:00
unsafe {
cast::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self)[i + j * $dim].clone()
2013-08-05 16:13:44 +08:00
}
}
2013-08-05 15:44:56 +08:00
#[inline]
fn set(&mut self, (i, j): (uint, uint), val: N) {
2013-08-05 16:13:44 +08:00
unsafe {
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)[i + j * $dim] = val
2013-08-05 16:13:44 +08:00
}
}
2013-08-05 15:44:56 +08:00
#[inline]
fn swap(&mut self, (i1, j1): (uint, uint), (i2, j2): (uint, uint)) {
2013-08-05 15:44:56 +08:00
unsafe {
cast::transmute::<&mut $t<N>, &mut [N, ..$dim * $dim]>(self)
.swap(i1 + j1 * $dim, i2 + j2 * $dim)
2013-08-05 15:44:56 +08:00
}
2013-07-22 16:26:20 +08:00
}
}
)
)
macro_rules! row_impl(
($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
#[inline]
fn nrows(&self) -> uint {
Dim::dim(None::<$t<N>>)
}
#[inline]
fn set_row(&mut self, row: uint, v: $tv<N>) {
for (i, e) in v.iter().enumerate() {
self.set((row, i), e.clone());
}
}
#[inline]
fn row(&self, row: uint) -> $tv<N> {
let mut res: $tv<N> = Zero::zero();
for (i, e) in res.mut_iter().enumerate() {
*e = self.at((row, i));
}
res
}
}
)
)
macro_rules! col_impl(
($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
#[inline]
fn ncols(&self) -> uint {
Dim::dim(None::<$t<N>>)
}
#[inline]
fn set_col(&mut self, col: uint, v: $tv<N>) {
for (i, e) in v.iter().enumerate() {
self.set((i, col), e.clone());
}
}
#[inline]
fn col(&self, col: uint) -> $tv<N> {
let mut res: $tv<N> = Zero::zero();
for (i, e) in res.mut_iter().enumerate() {
*e = self.at((i, col));
}
res
}
}
)
)
macro_rules! mat_mul_mat_impl(
($t: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Num> $trhs<N, $t<N>> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
// careful! we need to comute other * self here (self is the rhs).
2013-08-05 15:44:56 +08:00
let mut res: $t<N> = Zero::zero();
2013-08-08 02:53:51 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim) {
for j in range(0u, $dim) {
let mut acc: N = Zero::zero();
2013-08-08 02:53:51 +08:00
unsafe {
for k in range(0u, $dim) {
acc = acc + left.at_fast((i, k)) * right.at_fast((k, j));
}
2013-08-08 02:53:51 +08:00
res.set_fast((i, j), acc);
}
2013-08-05 15:44:56 +08:00
}
}
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! vec_mul_mat_impl(
($t: ident, $v: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Num> $trhs<N, $v<N>> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn binop(left: &$v<N>, right: &$t<N>) -> $v<N> {
2013-08-05 15:44:56 +08:00
let mut res : $v<N> = Zero::zero();
2013-08-08 02:53:51 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim) {
for j in range(0u, $dim) {
unsafe {
let val = res.at_fast(i) + left.at_fast(j) * right.at_fast((j, i));
res.set_fast(i, val)
}
2013-08-05 15:44:56 +08:00
}
}
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! mat_mul_vec_impl(
($t: ident, $v: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Num> $trhs<N, $v<N>> for $v<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn binop(left: &$t<N>, right: &$v<N>) -> $v<N> {
2013-08-05 15:44:56 +08:00
let mut res : $v<N> = Zero::zero();
2013-08-08 02:53:51 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim) {
for j in range(0u, $dim) {
unsafe {
let val = res.at_fast(i) + left.at_fast((i, j)) * right.at_fast(j);
res.set_fast(i, val)
}
2013-08-05 15:44:56 +08:00
}
}
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
res
2013-07-22 16:26:20 +08:00
}
}
)
)
macro_rules! inv_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + Eq + Num>
2013-08-05 16:13:44 +08:00
Inv for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn inv_cpy(m: &$t<N>) -> Option<$t<N>> {
let mut res : $t<N> = m.clone();
2013-08-08 02:53:51 +08:00
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
if res.inv() {
2013-08-05 16:13:44 +08:00
Some(res)
}
else {
None
}
2013-08-05 15:44:56 +08:00
}
2013-08-08 02:53:51 +08:00
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn inv(&mut self) -> bool {
2013-08-05 15:44:56 +08:00
let mut res: $t<N> = One::one();
let _0N: N = Zero::zero();
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
// inversion using Gauss-Jordan elimination
2013-08-05 16:13:44 +08:00
for k in range(0u, $dim) {
2013-08-05 15:44:56 +08:00
// search a non-zero value on the k-th column
// FIXME: would it be worth it to spend some more time searching for the
// max instead?
let mut n0 = k; // index of a non-zero entry
2013-08-05 16:13:44 +08:00
while (n0 != $dim) {
if self.at((n0, k)) != _0N {
break;
}
2013-08-05 15:44:56 +08:00
n0 = n0 + 1;
}
2013-08-05 16:13:44 +08:00
if n0 == $dim {
return false
}
2013-08-05 15:44:56 +08:00
// swap pivot line
2013-08-05 16:13:44 +08:00
if n0 != k {
for j in range(0u, $dim) {
2013-08-05 15:44:56 +08:00
self.swap((n0, j), (k, j));
res.swap((n0, j), (k, j));
}
}
let pivot = self.at((k, k));
2013-08-05 16:13:44 +08:00
for j in range(k, $dim) {
2013-08-05 15:44:56 +08:00
let selfval = self.at((k, j)) / pivot;
self.set((k, j), selfval);
}
2013-08-05 16:13:44 +08:00
for j in range(0u, $dim) {
2013-08-05 15:44:56 +08:00
let resval = res.at((k, j)) / pivot;
res.set((k, j), resval);
}
2013-08-05 16:13:44 +08:00
for l in range(0u, $dim) {
if l != k {
2013-08-05 15:44:56 +08:00
let normalizer = self.at((l, k));
2013-08-05 16:13:44 +08:00
for j in range(k, $dim) {
2013-08-05 15:44:56 +08:00
let selfval = self.at((l, j)) - self.at((k, j)) * normalizer;
self.set((l, j), selfval);
}
2013-08-05 16:13:44 +08:00
for j in range(0u, $dim) {
2013-08-05 15:44:56 +08:00
let resval = res.at((l, j)) - res.at((k, j)) * normalizer;
res.set((l, j), resval);
}
}
}
2013-07-22 16:26:20 +08:00
}
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
*self = res;
2013-07-22 16:26:20 +08:00
2013-08-05 15:44:56 +08:00
true
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! transpose_impl(
($t: ident, $dim: expr) => (
2013-08-05 16:13:44 +08:00
impl<N: Clone> Transpose for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
Api change: deal with inplace/out of place methods. Before, it was too easy to use an out of place method instead of the inplace one since they name were pretty mutch the same. This kind of confusion may lead to silly bugs very hard to understand. Thus the following changes have been made when a method is available both inplace and out-of-place: * inplace version keep a short name. * out-of-place version are suffixed by `_cpy` (meaning `copy`), and are static methods. Methods applying transformations (rotation, translation or general transform) are now prefixed by `append`, and a `prepend` version is available too. Also, free functions doing in-place modifications dont really make sense. They have been removed. Here are the naming changes: * `invert` -> `inv` * `inverted` -> `Inv::inv_cpy` * `transpose` -> `transpose` * `transposed` -> `Transpose::transpose_cpy` * `transform_by` -> `append_transformation` * `transformed` -> `Transform::append_transformation_cpy` * `rotate_by` -> `apppend_rotation` * `rotated` -> `Rotation::append_rotation_cpy` * `translate_by` -> `apppend_translation` * `translate` -> `Translation::append_translation_cpy` * `normalized` -> `Norm::normalize_cpy` * `rotated_wrt_point` -> `RotationWithTranslation::append_rotation_wrt_point_cpy` * `rotated_wrt_center` -> `RotationWithTranslation::append_rotation_wrt_center_cpy` Note that using those static methods is very verbose, and using in-place methods require an explicit import of the related trait. This is a way to convince the user to use free functions most of the time.
2013-10-14 16:22:32 +08:00
fn transpose_cpy(m: &$t<N>) -> $t<N> {
let mut res = m.clone();
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
res.transpose();
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
res
}
2013-08-08 02:53:51 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn transpose(&mut self) {
for i in range(1u, $dim) {
for j in range(0u, i) {
self.swap((i, j), (j, i))
}
2013-08-05 15:44:56 +08:00
}
2013-07-22 16:26:20 +08:00
}
}
)
)
macro_rules! approx_eq_impl(
($t: ident) => (
2013-08-05 16:13:44 +08:00
impl<N: ApproxEq<N>> ApproxEq<N> for $t<N> {
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn approx_epsilon() -> N {
fail!("approx_epsilon is broken since rust revision 8693943676487c01fa09f5f3daf0df6a1f71e24d.")
// ApproxEq::<N>::approx_epsilon()
2013-08-05 16:13:44 +08:00
}
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn approx_eq(&self, other: &$t<N>) -> bool {
2013-08-05 15:44:56 +08:00
let mut zip = self.iter().zip(other.iter());
2013-08-08 02:53:51 +08:00
2013-08-05 16:13:44 +08:00
do zip.all |(a, b)| {
a.approx_eq(b)
}
2013-08-05 15:44:56 +08:00
}
2013-08-08 02:53:51 +08:00
2013-08-05 15:44:56 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn approx_eq_eps(&self, other: &$t<N>, epsilon: &N) -> bool {
2013-08-05 15:44:56 +08:00
let mut zip = self.iter().zip(other.iter());
2013-08-08 02:53:51 +08:00
2013-08-05 16:13:44 +08:00
do zip.all |(a, b)| {
a.approx_eq_eps(b, epsilon)
}
2013-08-05 15:44:56 +08:00
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! to_homogeneous_impl(
($t: ident, $t2: ident, $dim: expr, $dim2: expr) => (
2013-08-05 16:13:44 +08:00
impl<N: One + Zero + Clone> ToHomogeneous<$t2<N>> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
fn to_homogeneous(m: &$t<N>) -> $t2<N> {
2013-08-05 15:44:56 +08:00
let mut res: $t2<N> = One::one();
2013-07-22 16:26:20 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim) {
for j in range(0u, $dim) {
res.set((i, j), m.at((i, j)))
2013-08-05 16:13:44 +08:00
}
2013-08-05 15:44:56 +08:00
}
res
}
2013-07-22 16:26:20 +08:00
}
)
)
macro_rules! from_homogeneous_impl(
($t: ident, $t2: ident, $dim: expr, $dim2: expr) => (
2013-08-05 16:13:44 +08:00
impl<N: One + Zero + Clone> FromHomogeneous<$t2<N>> for $t<N> {
2013-08-08 02:53:51 +08:00
#[inline]
2013-08-05 16:13:44 +08:00
fn from(m: &$t2<N>) -> $t<N> {
2013-08-05 15:44:56 +08:00
let mut res: $t<N> = One::one();
2013-07-22 16:26:20 +08:00
2013-08-05 16:13:44 +08:00
for i in range(0u, $dim2) {
for j in range(0u, $dim2) {
res.set((i, j), m.at((i, j)))
}
2013-08-05 15:44:56 +08:00
}
2013-07-22 16:26:20 +08:00
2013-08-05 15:44:56 +08:00
// FIXME: do we have to deal the lost components
// (like if the 1 is not a 1… do we have to divide?)
res
}
2013-07-22 16:26:20 +08:00
}
)
)
2013-08-12 22:45:31 +08:00
macro_rules! outer_impl(
($t: ident, $m: ident) => (
impl<N: Mul<N, N> + Zero + Clone> Outer<$m<N>> for $t<N> {
2013-08-12 22:45:31 +08:00
#[inline]
fn outer(a: &$t<N>, b: &$t<N>) -> $m<N> {
let mut res: $m<N> = Zero::zero();
2013-08-12 22:45:31 +08:00
for i in range(0u, Dim::dim(None::<$t<N>>)) {
for j in range(0u, Dim::dim(None::<$t<N>>)) {
res.set((i, j), a.at(i) * b.at(j))
2013-08-12 22:45:31 +08:00
}
}
res
}
}
)
)