Rework of the traits for Vectors.

The goal is to make traits less fine-grained for vectors, and reduce the amount of `use`.

- Scalar{Mul, Div} are removed, replaced by Mul<N, V> and Div<N, V>,
- Ring and DivisionRing are removed. Use Num instead.
- VectorSpace, Dot, and Norm are removed, replaced by the new, higher-level traits.

Add four traits:
- Vec: common operations on vectors. Replaces VectorSpace and Dot.
- AlgebraicVec: Vec + the old Norm trait.
- VecExt: Vec + every other traits vectors implement.
- AlgebraicVecExt: AlgebraicVec + VecExt.
This commit is contained in:
Sébastien Crozet 2013-08-18 18:33:25 +02:00
parent cead4f8410
commit 347883caa1
22 changed files with 166 additions and 285 deletions

View File

@ -1,7 +1,6 @@
use std::num::{One, Zero};
use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::ring::DivisionRing;
use traits::rlmul::{RMul, LMul};
use traits::cross::Cross;
use traits::dim::Dim;
@ -11,7 +10,7 @@ use traits::rotation::{Rotation, Rotate, Rotatable};
use traits::transformation::{Transform}; // FIXME: implement Transformation and Transformable
use traits::homogeneous::ToHomogeneous;
use traits::indexable::Indexable;
use traits::norm::Norm;
use traits::vector::AlgebraicVec;
use vec::Vec1;
use mat::{Mat2, Mat3};
use vec::Vec3;
@ -42,7 +41,7 @@ impl<N: Clone + Trigonometric + Neg<N>> Rotmat<Mat2<N>> {
}
}
impl<N: Clone + Trigonometric + DivisionRing + Algebraic> Rotmat<Mat3<N>> {
impl<N: Clone + Trigonometric + Num + Algebraic> Rotmat<Mat3<N>> {
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
///
/// # Arguments
@ -83,7 +82,7 @@ impl<N: Clone + Trigonometric + DivisionRing + Algebraic> Rotmat<Mat3<N>> {
}
}
impl<N: Clone + DivisionRing + Algebraic> Rotmat<Mat3<N>> {
impl<N: Clone + Num + Algebraic> Rotmat<Mat3<N>> {
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
/// for that.
@ -121,7 +120,7 @@ impl<N: Clone + DivisionRing + Algebraic> Rotmat<Mat3<N>> {
}
}
impl<N: Trigonometric + DivisionRing + Clone>
impl<N: Trigonometric + Num + Clone>
Rotation<Vec1<N>> for Rotmat<Mat2<N>> {
#[inline]
fn rotation(&self) -> Vec1<N> {
@ -139,7 +138,7 @@ Rotation<Vec1<N>> for Rotmat<Mat2<N>> {
}
}
impl<N: Trigonometric + DivisionRing + Clone>
impl<N: Trigonometric + Num + Clone>
Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> {
#[inline]
fn rotated(&self, rot: &Vec1<N>) -> Rotmat<Mat2<N>> {
@ -147,7 +146,7 @@ Rotatable<Vec1<N>, Rotmat<Mat2<N>>> for Rotmat<Mat2<N>> {
}
}
impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
impl<N: Clone + Trigonometric + Num + Algebraic>
Rotation<Vec3<N>> for Rotmat<Mat3<N>> {
#[inline]
fn rotation(&self) -> Vec3<N> {
@ -166,7 +165,7 @@ Rotation<Vec3<N>> for Rotmat<Mat3<N>> {
}
}
impl<N: Clone + Trigonometric + DivisionRing + Algebraic>
impl<N: Clone + Trigonometric + Num + Algebraic>
Rotatable<Vec3<N>, Rotmat<Mat3<N>>> for Rotmat<Mat3<N>> {
#[inline]
fn rotated(&self, axisangle: &Vec3<N>) -> Rotmat<Mat3<N>> {
@ -205,7 +204,7 @@ impl<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M> {
}
}
impl<N: Clone + Rand + Trigonometric + DivisionRing + Algebraic>
impl<N: Clone + Rand + Trigonometric + Num + Algebraic>
Rand for Rotmat<Mat3<N>> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rotmat<Mat3<N>> {

View File

@ -3,7 +3,6 @@ use std::rand::{Rand, Rng, RngUtil};
use std::cmp::ApproxEq;
use traits::dim::Dim;
use traits::inv::Inv;
use traits::ring::DivisionRing;
use traits::rotation::{Rotation, Rotate, Rotatable};
use traits::translation::{Translation, Translate, Translatable};
use Ts = traits::transformation::Transform;
@ -53,7 +52,7 @@ impl<M: Clone, V: Clone> Transform<M, V> {
}
}
impl<N: Clone + DivisionRing + Algebraic> Transform<Rotmat<Mat3<N>>, Vec3<N>> {
impl<N: Clone + Num + Algebraic> Transform<Rotmat<Mat3<N>>, Vec3<N>> {
/// Reorient and translate this transformation such that its local `x` axis points to a given
/// direction. Note that the usually known `look_at` function does the same thing but with the
/// `z` axis. See `look_at_z` for that.

View File

@ -2,7 +2,6 @@ use std::num::{One, Zero};
use std::vec::from_elem;
use std::cmp::ApproxEq;
use traits::inv::Inv;
use traits::ring::DivisionRing;
use traits::transpose::Transpose;
use traits::rlmul::{RMul, LMul};
use dvec::{DVec, zero_vec_with_dim};
@ -145,7 +144,7 @@ LMul<DVec<N>> for DMat<N> {
}
}
impl<N: Clone + Eq + DivisionRing>
impl<N: Clone + Num>
Inv for DMat<N> {
#[inline]
fn inverse(&self) -> Option<DMat<N>> {

View File

@ -3,13 +3,10 @@ use std::vec::{VecIterator, VecMutIterator};
use std::vec::from_elem;
use std::cmp::ApproxEq;
use std::iterator::FromIterator;
use traits::vector::{Vec, AlgebraicVec};
use traits::iterable::{Iterable, IterableMut};
use traits::ring::{Ring, DivisionRing};
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
use traits::scalar_op::{ScalarAdd, ScalarSub};
/// Vector with a dimension unknown at compile-time.
#[deriving(Eq, ToStr, Clone)]
@ -57,7 +54,7 @@ impl<N> FromIterator<N> for DVec<N> {
}
}
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> DVec<N> {
impl<N: Clone + Num + Algebraic + ApproxEq<N>> DVec<N> {
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
/// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal
/// to 1.0.
@ -94,10 +91,10 @@ impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> DVec<N> {
let mut elt = basis_element.clone();
elt = elt - self.scalar_mul(&basis_element.dot(self));
elt = elt - self * basis_element.dot(self);
for v in res.iter() {
elt = elt - v.scalar_mul(&elt.dot(v))
elt = elt - v * elt.dot(v)
};
if !elt.sqnorm().approx_eq(&Zero::zero()) {
@ -138,7 +135,7 @@ impl<N: Neg<N>> Neg<DVec<N>> for DVec<N> {
}
}
impl<N: Ring> Dot<N> for DVec<N> {
impl<N: Num> DVec<N> {
#[inline]
fn dot(&self, other: &DVec<N>) -> N {
assert!(self.at.len() == other.at.len());
@ -151,9 +148,7 @@ impl<N: Ring> Dot<N> for DVec<N> {
res
}
}
impl<N: Ring> SubDot<N> for DVec<N> {
#[inline]
fn sub_dot(&self, a: &DVec<N>, b: &DVec<N>) -> N {
let mut res = Zero::zero::<N>();
@ -166,33 +161,19 @@ impl<N: Ring> SubDot<N> for DVec<N> {
}
}
impl<N: Mul<N, N>> ScalarMul<N> for DVec<N> {
impl<N: Mul<N, N>> Mul<N, DVec<N>> for DVec<N> {
#[inline]
fn scalar_mul(&self, s: &N) -> DVec<N> {
fn mul(&self, s: &N) -> DVec<N> {
DVec { at: self.at.iter().map(|a| a * *s).collect() }
}
#[inline]
fn scalar_mul_inplace(&mut self, s: &N) {
for i in range(0u, self.at.len()) {
self.at[i] = self.at[i] * *s;
}
}
}
impl<N: Div<N, N>> ScalarDiv<N> for DVec<N> {
impl<N: Div<N, N>> Div<N, DVec<N>> for DVec<N> {
#[inline]
fn scalar_div(&self, s: &N) -> DVec<N> {
fn div(&self, s: &N) -> DVec<N> {
DVec { at: self.at.iter().map(|a| a / *s).collect() }
}
#[inline]
fn scalar_div_inplace(&mut self, s: &N) {
for i in range(0u, self.at.len()) {
self.at[i] = self.at[i] / *s;
}
}
}
impl<N: Add<N, N>> ScalarAdd<N> for DVec<N> {
@ -247,7 +228,7 @@ impl<N: Add<N, N> + Neg<N> + Clone> Translatable<DVec<N>, DVec<N>> for DVec<N> {
}
}
impl<N: DivisionRing + Algebraic + Clone> Norm<N> for DVec<N> {
impl<N: Num + Algebraic + Clone> DVec<N> {
#[inline]
fn sqnorm(&self) -> N {
self.dot(self)

View File

@ -6,7 +6,6 @@ use std::cmp::ApproxEq;
use std::vec::{VecIterator, VecMutIterator};
use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6};
use traits::dim::Dim;
use traits::ring::{Ring, DivisionRing};
use traits::inv::Inv;
use traits::transpose::Transpose;
use traits::rlmul::{RMul, LMul};
@ -16,7 +15,7 @@ use traits::indexable::Indexable;
use traits::column::Column;
use traits::iterable::{Iterable, IterableMut};
use traits::outer::Outer;
use traits::scalar_op::{ScalarMul, ScalarAdd, ScalarDiv, ScalarSub};
use traits::scalar_op::{ScalarAdd, ScalarSub};
pub use traits::mat_cast::*;
pub use traits::column::*;

View File

@ -49,34 +49,24 @@ macro_rules! sub_impl(
macro_rules! scalar_mul_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Mul<N, N>> ScalarMul<N> for $t<N> {
impl<N: Mul<N, N>> $t<N> {
#[inline]
fn scalar_mul(&self, other: &N) -> $t<N> {
/// Scalar multiplication of each component of this matrix by a scalar.
pub fn scalar_mul(&self, other: &N) -> $t<N> {
$t::new(self.$comp0 * *other $(, self.$compN * *other )*)
}
#[inline]
fn scalar_mul_inplace(&mut self, other: &N) {
self.$comp0 = self.$comp0 * *other;
$(self.$compN = self.$compN * *other; )*
}
}
)
)
macro_rules! scalar_div_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Div<N, N>> ScalarDiv<N> for $t<N> {
impl<N: Div<N, N>> $t<N> {
#[inline]
fn scalar_div(&self, other: &N) -> $t<N> {
/// Scalar division of each component of this matrix by a scalar.
pub fn scalar_div(&self, other: &N) -> $t<N> {
$t::new(self.$comp0 / *other $(, self.$compN / *other )*)
}
#[inline]
fn scalar_div_inplace(&mut self, other: &N) {
self.$comp0 = self.$comp0 / *other;
$(self.$compN = self.$compN / *other; )*
}
}
)
)
@ -226,7 +216,7 @@ macro_rules! column_impl(
macro_rules! mul_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + Ring> Mul<$t<N>, $t<N>> for $t<N> {
impl<N: Clone + Num> Mul<$t<N>, $t<N>> for $t<N> {
#[inline]
fn mul(&self, other: &$t<N>) -> $t<N> {
let mut res: $t<N> = Zero::zero();
@ -251,7 +241,7 @@ macro_rules! mul_impl(
macro_rules! rmul_impl(
($t: ident, $v: ident, $dim: expr) => (
impl<N: Clone + Ring> RMul<$v<N>> for $t<N> {
impl<N: Clone + Num> RMul<$v<N>> for $t<N> {
#[inline]
fn rmul(&self, other: &$v<N>) -> $v<N> {
let mut res : $v<N> = Zero::zero();
@ -271,7 +261,7 @@ macro_rules! rmul_impl(
macro_rules! lmul_impl(
($t: ident, $v: ident, $dim: expr) => (
impl<N: Clone + Ring> LMul<$v<N>> for $t<N> {
impl<N: Clone + Num> LMul<$v<N>> for $t<N> {
#[inline]
fn lmul(&self, other: &$v<N>) -> $v<N> {
let mut res : $v<N> = Zero::zero();
@ -291,7 +281,7 @@ macro_rules! lmul_impl(
macro_rules! transform_impl(
($t: ident, $v: ident) => (
impl<N: Clone + DivisionRing + Eq>
impl<N: Clone + Num + Eq>
Transform<$v<N>> for $t<N> {
#[inline]
fn transform(&self, v: &$v<N>) -> $v<N> {
@ -311,7 +301,7 @@ macro_rules! transform_impl(
macro_rules! inv_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + Eq + DivisionRing>
impl<N: Clone + Eq + Num>
Inv for $t<N> {
#[inline]
fn inverse(&self) -> Option<$t<N>> {

View File

@ -1,10 +1,9 @@
use std::num::{Zero, One};
use mat::{Mat1, Mat2, Mat3};
use traits::ring::DivisionRing;
use traits::inv::Inv;
// some specializations:
impl<N: DivisionRing + Clone>
impl<N: Num + Clone>
Inv for Mat1<N> {
#[inline]
fn inverse(&self) -> Option<Mat1<N>> {
@ -30,7 +29,7 @@ Inv for Mat1<N> {
}
}
impl<N: DivisionRing + Clone>
impl<N: Num + Clone>
Inv for Mat2<N> {
#[inline]
fn inverse(&self) -> Option<Mat2<N>> {
@ -61,7 +60,7 @@ Inv for Mat2<N> {
}
}
impl<N: DivisionRing + Clone>
impl<N: Num + Clone>
Inv for Mat3<N> {
#[inline]
fn inverse(&self) -> Option<Mat3<N>> {

View File

@ -47,24 +47,20 @@ pub mod types;
// FIXME: it would be better to hide all those from the outside!
pub mod traits
{
pub mod vector;
pub mod sample;
pub mod indexable;
pub mod column;
pub mod iterable;
pub mod dot;
pub mod outer;
pub mod cross;
pub mod inv;
pub mod transpose;
pub mod dim;
pub mod basis;
pub mod norm;
pub mod rotation;
pub mod translation;
pub mod transformation;
pub mod vector_space;
pub mod ring;
pub mod sub_dot;
pub mod rlmul;
pub mod scalar_op;
pub mod homogeneous;

View File

@ -5,10 +5,6 @@ use std::rand::random;
#[test]
use std::cmp::ApproxEq;
#[test]
use traits::norm::Norm;
#[test]
use traits::scalar_op::ScalarMul;
#[test]
use traits::inv::Inv;
#[test]
use traits::rotation::{Rotation, Rotatable};
@ -17,6 +13,8 @@ use traits::indexable::Indexable;
#[test]
use traits::transpose::Transpose;
#[test]
use traits::vector::AlgebraicVec;
#[test]
use vec::{Vec1, Vec3};
#[test]
use mat::{Mat1, Mat2, Mat3, Mat4, Mat5, Mat6};
@ -125,7 +123,7 @@ fn test_inv_rotation3() {
do 10000.times {
let randmat = One::one::<Rotmat<Mat3<f64>>>();
let dir: Vec3<f64> = random();
let ang = &dir.normalized().scalar_mul(&(abs::<f64>(random()) % Real::pi()));
let ang = &(dir.normalized() * (abs::<f64>(random()) % Real::pi()));
let rot = randmat.rotated(ang);
assert!((rot.transposed() * rot).approx_eq(&One::one()));

View File

@ -13,13 +13,11 @@ use traits::basis::Basis;
#[test]
use traits::cross::Cross;
#[test]
use traits::dot::Dot;
#[test]
use traits::norm::Norm;
use traits::vector::{Vec, AlgebraicVec};
#[test]
use traits::iterable::{Iterable, IterableMut};
#[test]
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
use traits::scalar_op::{ScalarAdd, ScalarSub};
#[test]
use traits::outer::Outer;
@ -36,7 +34,7 @@ macro_rules! test_iterator_impl(
*e = *e * n
}
assert!(nv == mv && nv == v.scalar_mul(&n));
assert!(nv == mv && nv == v * n);
}
)
)
@ -58,8 +56,8 @@ macro_rules! test_scalar_op_impl(
let v1 : $t = random();
let n : $n = random();
assert!(v1.scalar_mul(&n).scalar_div(&n).approx_eq(&v1));
assert!(v1.scalar_div(&n).scalar_mul(&n).approx_eq(&v1));
assert!(((v1 * n) / n).approx_eq(&v1));
assert!(((v1 / n) * n).approx_eq(&v1));
assert!(v1.scalar_sub(&n).scalar_add(&n).approx_eq(&v1));
assert!(v1.scalar_add(&n).scalar_sub(&n).approx_eq(&v1));
@ -67,8 +65,8 @@ macro_rules! test_scalar_op_impl(
let v0 : $t = v1.clone();
let n : $n = random();
v1.scalar_mul_inplace(&n);
v1.scalar_div_inplace(&n);
v1 = v1 * n;
v1 = v1 / n;
assert!(v1.approx_eq(&v0));
}

View File

@ -1,8 +0,0 @@
/**
* Trait of objects having a dot product (also called inner product).
*/
pub trait Dot<N>
{
/// Computes the dot (inner) product of two objects.
fn dot(&self, &Self) -> N;
}

View File

@ -1,19 +0,0 @@
/**
* Trait of objects having a L² norm and which can be normalized.
*/
pub trait Norm<N> {
/// Computes the norm a an object.
fn norm(&self) -> N;
/**
* Computes the squared norm of an object. Usually faster than computing the
* norm itself.
*/
fn sqnorm(&self) -> N;
/// Gets the normalized version of the argument.
fn normalized(&self) -> Self;
/// In-place version of `normalized`.
fn normalize(&mut self) -> N;
}

View File

@ -1,22 +0,0 @@
use std::num::{One, Zero};
/**
* Trait of elements of a ring. A rings is an algebraic structure, the
* elements of which have all the common numeric operation but the division:
* addition, subtraction, multiplication and distinct elements (`One` and
* `Zero`) respectively neutral and absorbant wrt the multiplication.
*/
pub trait Ring :
Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Mul<Self, Self> + One + Zero { }
impl<N: Sub<N, N> + Add<N, N> + Neg<N> + Mul<N, N> + One + Zero>
Ring for N;
/**
* Trait of elements of a division ring. A division ring is an algebraic
* structure like a ring, but with the division operator.
*/
pub trait DivisionRing : Ring + Div<Self, Self>
{ }
impl<N: Ring + Div<N, N>> DivisionRing for N;

View File

@ -2,8 +2,5 @@
/// approximate a sphere using support mapping functions.
pub trait UniformSphereSample {
/// Iterate throught the samples.
fn sample(&fn(&'static Self));
/// Gets the list of all samples.
fn sample_list() -> &[Self];
fn sample(&fn(Self));
}

View File

@ -1,25 +1,3 @@
/**
* Trait of objects having a multiplication with a scalar.
*/
pub trait ScalarMul<N> {
/// Gets the result of a multiplication by a scalar.
fn scalar_mul(&self, &N) -> Self;
/// In-place version of `scalar_mul`.
fn scalar_mul_inplace(&mut self, &N);
}
/**
* Trait of objects having a division with a scalar.
*/
pub trait ScalarDiv<N> {
/// Gets the result of a division by a scalar.
fn scalar_div(&self, &N) -> Self;
/// In-place version of `scalar_div`.
fn scalar_div_inplace(&mut self, &N);
}
/**
* Trait of objects having an addition with a scalar.
*/

View File

@ -1,14 +0,0 @@
use traits::dot::Dot;
/// Traits of objects with a subtract and a dot product. Exists only for optimization purpose.
pub trait SubDot<N> : Sub<Self, Self> + Dot<N> {
/**
* Short-cut to compute the projection of a point on a vector, but without
* computing intermediate vectors.
* This must be equivalent to:
*
* (a - b).dot(c)
*
*/
fn sub_dot(&self, b: &Self, c: &Self) -> N;
}

83
src/traits/vector.rs Normal file
View File

@ -0,0 +1,83 @@
use std::num::Zero;
use traits::dim::Dim;
use traits::basis::Basis;
use traits::indexable::Indexable;
use traits::iterable::Iterable;
use traits::sample::UniformSphereSample;
use traits::scalar_op::{ScalarAdd, ScalarSub};
// NOTE: cant call that `Vector` because it conflicts with std::Vector
/// Trait grouping most common operations on vectors.
pub trait Vec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + Eq + Mul<N, Self>
+ Div<N, Self>
{
/// Computes the dot (inner) product of two vectors.
#[inline]
fn dot(&self, &Self) -> N;
/**
* Short-cut to compute the projection of a point on a vector, but without
* computing intermediate vectors.
* This must be equivalent to:
*
* (a - b).dot(c)
*
*/
#[inline]
fn sub_dot(&self, b: &Self, c: &Self) -> N {
(*self - *b).dot(c)
}
}
/// Trait of vector with components implementing the `Algebraic` trait.
pub trait AlgebraicVec<N: Algebraic>: Vec<N> {
/// Computes the norm a an object.
#[inline]
fn norm(&self) -> N {
self.sqnorm().sqrt()
}
/**
* Computes the squared norm of an object. Usually faster than computing the
* norm itself.
*/
#[inline]
fn sqnorm(&self) -> N {
self.dot(self)
}
/// Gets the normalized version of the argument.
#[inline]
fn normalized(&self) -> Self {
self / self.norm()
}
/// In-place version of `normalized`.
#[inline]
fn normalize(&mut self) -> N {
let norm = self.norm();
*self = *self / norm;
norm
}
}
/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait VecExt<N>: Vec<N> + Basis + Indexable<uint, N> + Iterable<N> + Round +
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable
{ }
/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait AlgebraicVecExt<N: Algebraic>: AlgebraicVec<N> + VecExt<N>
{ }
impl<N,
V: Vec<N> + Basis + Indexable<uint, N> + Iterable<N> + Round +
UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded + Orderable>
VecExt<N> for V;
impl<N: Algebraic, V: AlgebraicVec<N> + VecExt<N>>
AlgebraicVecExt<N> for V;

View File

@ -1,13 +0,0 @@
use std::num::Zero;
use traits::ring::DivisionRing;
use traits::scalar_op::{ScalarMul, ScalarDiv};
/// Trait of elements of a vector space. A vector space is an algebraic
/// structure, the elements of which have addition, substraction, negation,
/// scalar multiplication (the scalar being a element of a `DivisionRing`), and
/// has a distinct element (`Zero`) neutral wrt the addition.
pub trait VectorSpace<N>
: Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + ScalarMul<N> + ScalarDiv<N> { }
impl<V: Sub<V, V> + Add<V, V> + Neg<V> + Zero + ScalarMul<N> + ScalarDiv<N>,
N: DivisionRing> VectorSpace<N> for V;

View File

@ -7,22 +7,12 @@ use std::cmp::ApproxEq;
use traits::basis::Basis;
use traits::dim::Dim;
use traits::translation::{Translation, Translatable};
use traits::ring::{Ring, DivisionRing};
use traits::homogeneous::{FromHomogeneous, ToHomogeneous};
use traits::indexable::Indexable;
pub use traits::vec_cast::*;
pub use traits::basis::*;
pub use traits::cross::*;
pub use traits::outer::*;
pub use traits::dot::*;
pub use traits::indexable::*;
pub use traits::iterable::*;
pub use traits::norm::*;
pub use traits::sample::*;
pub use traits::sub_dot::*;
pub use traits::vector_space::*;
pub use traits::scalar_op::*;
use traits::scalar_op::{ScalarAdd, ScalarSub};
use traits::iterable::{Iterable, IterableMut};
use traits::vec_cast::VecCast;
use traits::vector::{Vec, AlgebraicVec};
mod vec_macros;
@ -50,7 +40,6 @@ add_impl!(Vec1, x)
sub_impl!(Vec1, x)
neg_impl!(Vec1, x)
dot_impl!(Vec1, x)
sub_dot_impl!(Vec1, x)
scalar_mul_impl!(Vec1, x)
scalar_div_impl!(Vec1, x)
scalar_add_impl!(Vec1, x)
@ -90,7 +79,6 @@ add_impl!(Vec2, x, y)
sub_impl!(Vec2, x, y)
neg_impl!(Vec2, x, y)
dot_impl!(Vec2, x, y)
sub_dot_impl!(Vec2, x, y)
scalar_mul_impl!(Vec2, x, y)
scalar_div_impl!(Vec2, x, y)
scalar_add_impl!(Vec2, x, y)
@ -132,7 +120,6 @@ add_impl!(Vec3, x, y, z)
sub_impl!(Vec3, x, y, z)
neg_impl!(Vec3, x, y, z)
dot_impl!(Vec3, x, y, z)
sub_dot_impl!(Vec3, x, y, z)
scalar_mul_impl!(Vec3, x, y, z)
scalar_div_impl!(Vec3, x, y, z)
scalar_add_impl!(Vec3, x, y, z)
@ -176,7 +163,6 @@ add_impl!(Vec4, x, y, z, w)
sub_impl!(Vec4, x, y, z, w)
neg_impl!(Vec4, x, y, z, w)
dot_impl!(Vec4, x, y, z, w)
sub_dot_impl!(Vec4, x, y, z, w)
scalar_mul_impl!(Vec4, x, y, z, w)
scalar_div_impl!(Vec4, x, y, z, w)
scalar_add_impl!(Vec4, x, y, z, w)
@ -222,7 +208,6 @@ add_impl!(Vec5, x, y, z, w, a)
sub_impl!(Vec5, x, y, z, w, a)
neg_impl!(Vec5, x, y, z, w, a)
dot_impl!(Vec5, x, y, z, w, a)
sub_dot_impl!(Vec5, x, y, z, w, a)
scalar_mul_impl!(Vec5, x, y, z, w, a)
scalar_div_impl!(Vec5, x, y, z, w, a)
scalar_add_impl!(Vec5, x, y, z, w, a)
@ -270,7 +255,6 @@ add_impl!(Vec6, x, y, z, w, a, b)
sub_impl!(Vec6, x, y, z, w, a, b)
neg_impl!(Vec6, x, y, z, w, a, b)
dot_impl!(Vec6, x, y, z, w, a, b)
sub_dot_impl!(Vec6, x, y, z, w, a, b)
scalar_mul_impl!(Vec6, x, y, z, w, a, b)
scalar_div_impl!(Vec6, x, y, z, w, a, b)
scalar_add_impl!(Vec6, x, y, z, w, a, b)

View File

@ -6,13 +6,10 @@ use std::cmp::ApproxEq;
use traits::iterable::{Iterable, IterableMut};
use traits::basis::Basis;
use traits::dim::Dim;
use traits::dot::Dot;
use traits::sub_dot::SubDot;
use traits::norm::Norm;
use traits::translation::{Translation, Translatable};
use traits::scalar_op::{ScalarMul, ScalarDiv, ScalarAdd, ScalarSub};
use traits::ring::{Ring, DivisionRing};
use traits::scalar_op::{ScalarAdd, ScalarSub};
use traits::indexable::Indexable;
use traits::vector::{Vec, AlgebraicVec};
use vec;
impl<N> vec::Vec0<N> {
@ -69,7 +66,7 @@ impl<N> Dim for vec::Vec0<N> {
}
}
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for vec::Vec0<N> {
impl<N: Clone + Num + Algebraic + ApproxEq<N>> Basis for vec::Vec0<N> {
#[inline(always)]
fn canonical_basis(_: &fn(vec::Vec0<N>) -> bool) { }
@ -98,38 +95,30 @@ impl<N: Neg<N>> Neg<vec::Vec0<N>> for vec::Vec0<N> {
}
}
impl<N: Ring> Dot<N> for vec::Vec0<N> {
impl<N: Num + Clone> Vec<N> for vec::Vec0<N> {
#[inline]
fn dot(&self, _: &vec::Vec0<N>) -> N {
Zero::zero()
}
}
}
impl<N: Clone + Ring> SubDot<N> for vec::Vec0<N> {
#[inline]
fn sub_dot(&self, _: &vec::Vec0<N>, _: &vec::Vec0<N>) -> N {
Zero::zero()
}
}
impl<N: Mul<N, N>> ScalarMul<N> for vec::Vec0<N> {
impl<N: Mul<N, N>> Mul<N, vec::Vec0<N>> for vec::Vec0<N> {
#[inline]
fn scalar_mul(&self, _: &N) -> vec::Vec0<N> {
fn mul(&self, _: &N) -> vec::Vec0<N> {
vec::Vec0
}
#[inline]
fn scalar_mul_inplace(&mut self, _: &N) { }
}
impl<N: Div<N, N>> ScalarDiv<N> for vec::Vec0<N> {
impl<N: Div<N, N>> Div<N, vec::Vec0<N>> for vec::Vec0<N> {
#[inline]
fn scalar_div(&self, _: &N) -> vec::Vec0<N> {
fn div(&self, _: &N) -> vec::Vec0<N> {
vec::Vec0
}
#[inline]
fn scalar_div_inplace(&mut self, _: &N) { }
}
impl<N: Add<N, N>> ScalarAdd<N> for vec::Vec0<N> {
@ -176,7 +165,7 @@ impl<N: Add<N, N> + Neg<N> + Clone> Translatable<vec::Vec0<N>, vec::Vec0<N>> for
}
}
impl<N: Clone + DivisionRing + Algebraic> Norm<N> for vec::Vec0<N> {
impl<N: Clone + Num + Algebraic> AlgebraicVec<N> for vec::Vec0<N> {
#[inline]
fn sqnorm(&self) -> N {
self.dot(self)
@ -200,7 +189,7 @@ impl<N: Clone + DivisionRing + Algebraic> Norm<N> for vec::Vec0<N> {
fn normalize(&mut self) -> N {
let l = self.norm();
self.scalar_div_inplace(&l);
*self = *self / l;
l
}

View File

@ -183,7 +183,7 @@ macro_rules! dim_impl(
macro_rules! basis_impl(
($t: ident, $dim: expr) => (
impl<N: Clone + DivisionRing + Algebraic + ApproxEq<N>> Basis for $t<N> {
impl<N: Clone + Num + Algebraic + ApproxEq<N>> Basis for $t<N> {
#[inline]
fn canonical_basis(f: &fn($t<N>) -> bool) {
for i in range(0u, $dim) {
@ -212,10 +212,10 @@ macro_rules! basis_impl(
let mut elt = basis_element.clone();
elt = elt - self.scalar_mul(&basis_element.dot(self));
elt = elt - *self * basis_element.dot(self);
for v in basis.iter() {
elt = elt - v.scalar_mul(&elt.dot(v))
elt = elt - v * elt.dot(v)
};
if !elt.sqnorm().approx_eq(&Zero::zero()) {
@ -266,18 +266,12 @@ macro_rules! neg_impl(
macro_rules! dot_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Ring> Dot<N> for $t<N> {
impl<N: Num + Clone> Vec<N> for $t<N> {
#[inline]
fn dot(&self, other: &$t<N>) -> N {
self.$comp0 * other.$comp0 $(+ self.$compN * other.$compN )*
}
}
)
)
macro_rules! sub_dot_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Ring> SubDot<N> for $t<N> {
#[inline]
fn sub_dot(&self, a: &$t<N>, b: &$t<N>) -> N {
(self.$comp0 - a.$comp0) * b.$comp0 $(+ (self.$compN - a.$compN) * b.$compN )*
@ -288,34 +282,22 @@ macro_rules! sub_dot_impl(
macro_rules! scalar_mul_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Mul<N, N>> ScalarMul<N> for $t<N> {
impl<N: Mul<N, N>> Mul<N, $t<N>> for $t<N> {
#[inline]
fn scalar_mul(&self, s: &N) -> $t<N> {
fn mul(&self, s: &N) -> $t<N> {
$t::new(self.$comp0 * *s $(, self.$compN * *s)*)
}
#[inline]
fn scalar_mul_inplace(&mut self, s: &N) {
self.$comp0 = self.$comp0 * *s;
$(self.$compN = self.$compN * *s;)*
}
}
)
)
macro_rules! scalar_div_impl(
($t: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Div<N, N>> ScalarDiv<N> for $t<N> {
impl<N: Div<N, N>> Div<N, $t<N>> for $t<N> {
#[inline]
fn scalar_div(&self, s: &N) -> $t<N> {
fn div(&self, s: &N) -> $t<N> {
$t::new(self.$comp0 / *s $(, self.$compN / *s)*)
}
#[inline]
fn scalar_div_inplace(&mut self, s: &N) {
self.$comp0 = self.$comp0 / *s;
$(self.$compN = self.$compN / *s;)*
}
}
)
)
@ -388,7 +370,7 @@ macro_rules! translatable_impl(
macro_rules! norm_impl(
($t: ident) => (
impl<N: Clone + DivisionRing + Algebraic> Norm<N> for $t<N> {
impl<N: Clone + Num + Algebraic> AlgebraicVec<N> for $t<N> {
#[inline]
fn sqnorm(&self) -> N {
self.dot(self)
@ -412,7 +394,7 @@ macro_rules! norm_impl(
fn normalize(&mut self) -> N {
let l = self.norm();
self.scalar_div_inplace(&l);
*self = *self / l;
l
}
@ -529,7 +511,7 @@ macro_rules! from_homogeneous_impl(
res.$comp0 = v.$comp0.clone();
$( res.$compN = v.$compN.clone(); )*
res.scalar_div(&v.$extra);
res = res / v.$extra;
res
}

View File

@ -1,9 +1,9 @@
use std::num::{Zero, One};
use traits::basis::Basis;
use traits::cross::Cross;
use traits::ring::DivisionRing;
use traits::norm::Norm;
use traits::sample::UniformSphereSample;
use traits::vec_cast::VecCast;
use traits::vector::{AlgebraicVec};
use vec::{Vec1, Vec2, Vec3};
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
@ -47,7 +47,7 @@ impl<N: Clone + One + Zero + Neg<N>> Basis for Vec2<N> {
}
}
impl<N: Clone + DivisionRing + Ord + Algebraic + Signed>
impl<N: Clone + Ord + Algebraic + Signed>
Basis for Vec3<N> {
#[inline(always)]
fn canonical_basis(f: &fn(Vec3<N>) -> bool) {
@ -142,34 +142,20 @@ static SAMPLES_3_F64: [Vec3<f64>, ..42] = [
Vec3 { x: 0.162456 , y: 0.499995 , z: 0.850654 }
];
impl UniformSphereSample for Vec2<f64> {
impl<N: NumCast> UniformSphereSample for Vec2<N> {
#[inline(always)]
fn sample(f: &fn(&'static Vec2<f64>)) {
fn sample(f: &fn(Vec2<N>)) {
for sample in SAMPLES_2_F64.iter() {
f(sample)
f(VecCast::from(*sample))
}
}
#[inline]
fn sample_list() -> &[Vec2<f64>] {
let res: &[Vec2<f64>] = SAMPLES_2_F64;
res
}
}
impl UniformSphereSample for Vec3<f64> {
impl<N: NumCast> UniformSphereSample for Vec3<N> {
#[inline(always)]
fn sample(f: &fn(&'static Vec3<f64>)) {
fn sample(f: &fn(Vec3<N>)) {
for sample in SAMPLES_3_F64.iter() {
f(sample)
f(VecCast::from(*sample))
}
}
#[inline]
fn sample_list() -> &[Vec3<f64>] {
let res: &[Vec3<f64>] = SAMPLES_3_F64;
res
}
}