Overhaul library, rename to cgmath

Moved the old source code temporarily to src-old. This will be removed once the functionality has been transferred over into the new system.

The new design is based on algebraic principles. Thanks goes to sebcrozet and his nalgebra library for providing the inspiration for the algebraic traits: https://github.com/sebcrozet/nalgebra
This commit is contained in:
Brendan Zabarauskas 2013-08-26 15:08:25 +10:00
parent c429ed839d
commit 3673c4db6d
49 changed files with 1112 additions and 100 deletions

View file

@ -11,3 +11,8 @@ Erick Tryzelaar
Luqman Aden
Maik Klein
Mikko Perttunen
With thanks to:
sebcrozet and his nalgebra library for providing the inspiration for the
algebraic traits: https://github.com/sebcrozet/nalgebra

View file

@ -1,49 +0,0 @@
# Copyright 2013 The Lmath Developers. For a full listing of the authors,
# refer to the AUTHORS file at the top-level directory of this distribution.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
TARGET = lmath
ROOT_DIR = .
SRC_DIR = $(ROOT_DIR)/src
SRC_CRATE = $(TARGET).rs
EXTERN_DIR = $(ROOT_DIR)/extern
BUILD_DIR = $(ROOT_DIR)/lib
CFG = --cfg=bounds --cfg=transform --cfg=space
TEST = $(TARGET)
TEST_BUILD_DIR = $(ROOT_DIR)/test
.PHONY: test
$(TARGET):
@echo "Building $(TARGET)..."
@mkdir -p $(BUILD_DIR)
@rustc $(CFG) $(SRC_DIR)/$(SRC_CRATE) --out-dir=$(BUILD_DIR)
@echo "Success"
all: $(TARGET)
test:
@echo "Building unit tests for $(TARGET)..."
@mkdir -p $(TEST_BUILD_DIR)
@rustc $(CFG) $(SRC_DIR)/$(SRC_CRATE) --test --out-dir=$(TEST_BUILD_DIR)
@echo "Success"
@$(TEST_BUILD_DIR)/$(TARGET)
clean:
rm -R -f $(BUILD_DIR)
rm -R -f $(TEST_BUILD_DIR)

View file

@ -1,11 +1,3 @@
# Lmath-rs
# cgmath-rs
A mathematics library for computer graphics.
## Examples
- [luqmana/rray](https://github.com/luqmana/rray) - Raytracer written in rust.
~B☼
A linear algebra and mathematics library for computer graphics.

View file

@ -67,4 +67,6 @@ impl<T:Clone + Float> AABB3<T> {
size: mx - mn,
}
}
// pub fn intersects_aabb3(&self, other: &AABB3<T>) -> bool {}
}

View file

@ -17,10 +17,11 @@
pub use self::aabb::{AABB2, AABB3};
pub use self::frustum::{Frustum, FrustumPoints};
pub use self::obb::{OBB2, OBB3};
pub use self::sphere::Sphere;
pub mod aabb;
pub mod box;
pub mod cylinder;
pub mod frustum;
pub mod obb;
pub mod sphere;

View file

@ -18,14 +18,14 @@
use math::*;
#[deriving(Clone, Eq)]
pub struct Box2<T> {
pub struct OBB2<T> {
center: Point2<T>,
axis: Vec2<T>,
extents: Vec2<T>,
}
#[deriving(Clone, Eq)]
pub struct Box3<T> {
pub struct OBB3<T> {
center: Point3<T>,
axis: Vec3<T>,
extents: Vec3<T>,

View file

@ -75,6 +75,7 @@ pub type Mat2f32 = Mat2<f32>;
pub type Mat2f64 = Mat2<f64>;
impl_dimensioned!(Mat2, Vec2<T>, 2)
impl_swap_components!(Mat2)
impl_approx!(Mat3 { x, y, z })
pub trait ToMat2<T> {
@ -288,7 +289,7 @@ impl<T:Clone + Float> Mat2<T> {
}
}
impl<T:Clone + Float> FloatMat<T,Vec3<T>,[Vec3<T>,..3]> for Mat2<T> {
impl<T:Clone + Float> FloatMat<T,Vec2<T>,[Vec2<T>,..2]> for Mat2<T> {
#[inline]
pub fn inverse(&self) -> Option<Mat2<T>> {
let d = self.determinant();
@ -539,6 +540,7 @@ pub type Mat3f32 = Mat3<f32>;
pub type Mat3f64 = Mat3<f64>;
impl_dimensioned!(Mat3, Vec3<T>, 3)
impl_swap_components!(Mat3)
impl_approx!(Mat2 { x, y })
pub trait ToMat3<T> {
@ -761,7 +763,7 @@ impl<T:Clone + Num> Neg<Mat3<T>> for Mat3<T> {
}
}
impl<T:Float> Mat3<T> {
impl<T: Clone + Float> Mat3<T> {
pub fn look_at(dir: &Vec3<T>, up: &Vec3<T>) -> Mat3<T> {
let dir_ = dir.normalize();
let side = dir_.cross(&up.normalize());
@ -823,7 +825,7 @@ impl<T:Clone + Float> ToQuat<T> for Mat3<T> {
}
}
impl<T:Clone + Float> FloatMat<T,Vec4<T>,[Vec4<T>,..4]> for Mat3<T> {
impl<T:Clone + Float> FloatMat<T,Vec3<T>,[Vec3<T>,..3]> for Mat3<T> {
#[inline]
pub fn inverse(&self) -> Option<Mat3<T>> {
let d = self.determinant();
@ -1111,6 +1113,7 @@ pub type Mat4f32 = Mat4<f32>;
pub type Mat4f64 = Mat4<f64>;
impl_dimensioned!(Mat4, Vec4<T>, 4)
impl_swap_components!(Mat4)
impl_approx!(Mat4 { x, y, z, w })
pub trait ToMat4<T> {

View file

@ -22,7 +22,7 @@ pub trait Vec<T,Slice>: Dimensioned<T,Slice>
+ SwapComponents {}
/// Vectors with numeric components
pub trait NumVec<T,Slice>: Neg<T> {
pub trait NumVec<T,Slice>: Neg<Self> {
pub fn add_s(&self, value: T) -> Self;
pub fn sub_s(&self, value: T) -> Self;
pub fn mul_s(&self, value: T) -> Self;
@ -209,9 +209,9 @@ impl<T:Num> Vec2<T> {
}
}
impl<T> Vec<T,[T,..2]> for Vec2<T> {}
impl<T: Clone> Vec<T,[T,..2]> for Vec2<T> {}
impl<T:Num> NumVec<T,[T,..2]> for Vec2<T> {
impl<T: Clone + Num> NumVec<T,[T,..2]> for Vec2<T> {
/// Returns a new vector with `value` added to each component.
#[inline]
pub fn add_s(&self, value: T) -> Vec2<T> {
@ -371,7 +371,7 @@ impl<T:Num> NumVec<T,[T,..2]> for Vec2<T> {
}
}
impl<T:Num> Neg<Vec2<T>> for Vec2<T> {
impl<T: Clone + Num> Neg<Vec2<T>> for Vec2<T> {
/// Returns the vector with each component negated.
#[inline]
pub fn neg(&self) -> Vec2<T> {
@ -380,7 +380,7 @@ impl<T:Num> Neg<Vec2<T>> for Vec2<T> {
}
}
impl<T:Float> FloatVec<T,[T,..2]> for Vec2<T> {
impl<T: Clone + Float> FloatVec<T,[T,..2]> for Vec2<T> {
/// Returns the squared magnitude of the vector. This does not perform a
/// square root operation like in the `magnitude` method and can therefore
/// be more efficient for comparing the magnitudes of two vectors.
@ -442,7 +442,7 @@ impl<T:Float> FloatVec<T,[T,..2]> for Vec2<T> {
}
}
impl<T:Orderable> OrdVec<T,[T,..2],Vec2<bool>> for Vec2<T> {
impl<T: Clone + Orderable> OrdVec<T,[T,..2],Vec2<bool>> for Vec2<T> {
#[inline]
pub fn lt_s(&self, value: T) -> Vec2<bool> {
Vec2::new(*self.i(0) < value,
@ -857,9 +857,9 @@ impl<T:Num> Vec3<T> {
}
}
impl<T> Vec<T,[T,..3]> for Vec3<T> {}
impl<T: Clone> Vec<T,[T,..3]> for Vec3<T> {}
impl<T:Num> NumVec<T,[T,..3]> for Vec3<T> {
impl<T: Clone + Num> NumVec<T,[T,..3]> for Vec3<T> {
/// Returns a new vector with `value` added to each component.
#[inline]
pub fn add_s(&self, value: T) -> Vec3<T> {
@ -1041,7 +1041,7 @@ impl<T:Num> NumVec<T,[T,..3]> for Vec3<T> {
}
}
impl<T:Num> Neg<Vec3<T>> for Vec3<T> {
impl<T: Clone + Num> Neg<Vec3<T>> for Vec3<T> {
/// Returns the vector with each component negated.
#[inline]
pub fn neg(&self) -> Vec3<T> {
@ -1051,7 +1051,7 @@ impl<T:Num> Neg<Vec3<T>> for Vec3<T> {
}
}
impl<T:Float> FloatVec<T,[T,..3]> for Vec3<T> {
impl<T: Clone + Float> FloatVec<T,[T,..3]> for Vec3<T> {
/// Returns the squared magnitude of the vector. This does not perform a
/// square root operation like in the `magnitude` method and can therefore
/// be more efficient for comparing the magnitudes of two vectors.
@ -1113,7 +1113,7 @@ impl<T:Float> FloatVec<T,[T,..3]> for Vec3<T> {
}
}
impl<T:Orderable> OrdVec<T,[T,..3],Vec3<bool>> for Vec3<T> {
impl<T: Clone + Orderable> OrdVec<T,[T,..3],Vec3<bool>> for Vec3<T> {
#[inline]
pub fn lt_s(&self, value: T) -> Vec3<bool> {
Vec3::new(*self.i(0) < value,
@ -1541,9 +1541,9 @@ impl<T:Num> Vec4<T> {
}
}
impl<T> Vec<T,[T,..4]> for Vec4<T> {}
impl<T: Clone> Vec<T,[T,..4]> for Vec4<T> {}
impl<T:Num> NumVec<T,[T,..4]> for Vec4<T> {
impl<T: Clone + Num> NumVec<T,[T,..4]> for Vec4<T> {
/// Returns a new vector with `value` added to each component.
#[inline]
pub fn add_s(&self, value: T) -> Vec4<T> {
@ -1747,7 +1747,7 @@ impl<T:Num> NumVec<T,[T,..4]> for Vec4<T> {
}
}
impl<T:Num> Neg<Vec4<T>> for Vec4<T> {
impl<T: Clone + Num> Neg<Vec4<T>> for Vec4<T> {
/// Returns the vector with each component negated.
#[inline]
pub fn neg(&self) -> Vec4<T> {
@ -1758,7 +1758,7 @@ impl<T:Num> Neg<Vec4<T>> for Vec4<T> {
}
}
impl<T:Float> FloatVec<T,[T,..4]> for Vec4<T> {
impl<T: Clone + Float> FloatVec<T,[T,..4]> for Vec4<T> {
/// Returns the squared magnitude of the vector. This does not perform a
/// square root operation like in the `magnitude` method and can therefore
/// be more efficient for comparing the magnitudes of two vectors.
@ -1820,7 +1820,7 @@ impl<T:Float> FloatVec<T,[T,..4]> for Vec4<T> {
}
}
impl<T:Orderable> OrdVec<T,[T,..4],Vec4<bool>> for Vec4<T> {
impl<T: Clone + Orderable> OrdVec<T,[T,..4],Vec4<bool>> for Vec4<T> {
#[inline]
pub fn lt_s(&self, value: T) -> Vec4<bool> {
Vec4::new(*self.i(0) < value,

View file

@ -15,4 +15,9 @@
// http://gameprogrammingpatterns.com/spatial-partition.html
pub struct Octree;
use bounds::AABB3;
pub struct Octree<Elem,T> {
bounds: AABB3<T>,
octants: [Option<~Octree<Elem,T>>, ..8],
}

View file

@ -52,7 +52,7 @@ pub trait Rotation3<T>: Eq
+ ToMat3<T>
+ ToMat4<T>
+ ToQuat<T> {
pub fn rotate_point3(&self, point: Point3<T>) -> Point3<T>;
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T>;
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T>;
pub fn rotate_ray3(&self, ray: &Ray3<T>) -> Ray3<T>;
pub fn to_rotation_mat3(&self) -> RotationMat3<T>;
@ -80,7 +80,7 @@ impl<T> RotationMat2<T> {
impl<T:Clone + Float> Rotation2<T> for RotationMat2<T> {
pub fn rotate_point2(&self, point: Point2<T>) -> Point2<T> {
Point2::from_vec2(self.mat.mul_v(point.as_vec2()))
point.with_vec2(|vec| self.rotate_vec2(vec))
}
pub fn rotate_vec2(&self, vec: &Vec2<T>) -> Vec2<T> {
@ -121,8 +121,8 @@ impl<T:Clone + Num> Neg<RotationMat2<T>> for RotationMat2<T> {
}
impl<T:Clone + Float> Rotation3<T> for Quat<T> {
pub fn rotate_point3(&self, point: Point3<T>) -> Point3<T> {
Point3::from_vec3(self.mul_v(point.as_vec3()))
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T> {
point.with_vec3(|vec| self.rotate_vec3(vec))
}
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T> {
@ -160,8 +160,8 @@ impl<T> RotationMat3<T> {
}
impl<T:Clone + Float> Rotation3<T> for RotationMat3<T> {
pub fn rotate_point3(&self, point: Point3<T>) -> Point3<T> {
Point3::from_vec3(self.mat.mul_v(point.as_vec3()))
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T> {
point.with_vec3(|vec| self.rotate_vec3(vec))
}
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T> {
@ -243,7 +243,7 @@ impl<T:Float> Euler<T> {
}
impl<T:Clone + Float> Rotation3<T> for Euler<T> {
pub fn rotate_point3(&self, _point: Point3<T>) -> Point3<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
@ -337,12 +337,27 @@ impl<T:Float> AxisAngle<T> {
}
impl<T:Float> Rotation3<T> for AxisAngle<T> {
pub fn rotate_point3(&self, _point: Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
pub fn rotate_point3(&self, point: &Point3<T>) -> Point3<T> {
point.with_vec3(|vec| self.rotate_vec3(vec))
}
pub fn rotate_vec3(&self, _vec: &Vec3<T>) -> Vec3<T> {
fail!("Not yet implemented.")
pub fn rotate_vec3(&self, vec: &Vec3<T>) -> Vec3<T> {
// Rodrigues' rotation formula
// http://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
//
// ~~~
// v cos θ + (k × v) sin θ + k(k ⋅ v)(1 - cos θ)
// ~~~
//
// Where:
// - `v` = vec
// - `k` = self.axis
// - `θ` = self.angle
vec.mul_s(self.angle.cos())
.add_v(&self.axis.cross(vec)).mul_s(self.angle.sin())
.add_v(&self.axis.mul_s(self.axis.dot(vec))
.mul_s(one!(T) - self.angle.cos()))
}
pub fn rotate_ray3(&self, _ray: &Ray3<T>) -> Ray3<T> {
@ -434,7 +449,7 @@ pub struct AngleX<T>(T);
impl_approx!(AngleX)
impl<T:Clone + Float> Rotation3<T> for AngleX<T> {
pub fn rotate_point3(&self, _point: Point3<T>) -> Point3<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
@ -495,7 +510,7 @@ pub struct AngleY<T>(T);
impl_approx!(AngleY)
impl<T:Clone + Float> Rotation3<T> for AngleY<T> {
pub fn rotate_point3(&self, _point: Point3<T>) -> Point3<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}
@ -575,7 +590,7 @@ impl<T:Float> Rotation2<T> for AngleZ<T> {
}
impl<T:Clone + Float> Rotation3<T> for AngleZ<T> {
pub fn rotate_point3(&self, _point: Point3<T>) -> Point3<T> {
pub fn rotate_point3(&self, _point: &Point3<T>) -> Point3<T> {
fail!("Not yet implemented.")
}

26
src/cgmath.rs Normal file
View file

@ -0,0 +1,26 @@
// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[link(name = "cgmath",
vers = "0.1",
author = "Brendan Zabarauskas",
url = "https://github.com/bjz/cgmath-rs")];
#[comment = "A mathematics library for computer graphics."];
#[license = "ASL2"];
#[crate_type = "lib"];
pub mod traits;
pub mod types;

View file

@ -0,0 +1,25 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num::Zero;
use traits::alg::ScalarMul;
/// An affine space is a set of points closed under affine combinations.
pub trait AffineSpace<S,V>: Eq
+ Zero
+ ScalarMul<S>
+ Add<V, Self>
+ Sub<Self, V> {}

View file

@ -0,0 +1,20 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub use traits::util::Indexable;
pub use traits::util::Swappable;
pub trait Coordinate<S, Slice>: Indexable<S, Slice>
+ Swappable<S, Slice> {}

View file

@ -0,0 +1,37 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::alg::Ring;
/// A ring that also requires the multiplicative inverse operation (division).
pub trait DivisionRing: Ring
+ Div<Self,Self>
+ Rem<Self,Self> {}
// impls for concrete types
impl DivisionRing for u8;
impl DivisionRing for u16;
impl DivisionRing for u32;
impl DivisionRing for u64;
impl DivisionRing for uint;
impl DivisionRing for i8;
impl DivisionRing for i16;
impl DivisionRing for i32;
impl DivisionRing for i64;
impl DivisionRing for int;
impl DivisionRing for f32;
impl DivisionRing for f64;
impl DivisionRing for float;

View file

@ -0,0 +1,64 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num;
use traits::alg::Ring;
use traits::alg::InnerProductSpace;
/// The Euclidean space is a vector space over the Real numbers.
pub trait EuclideanSpace<S:Real + Ring>: InnerProductSpace<S> {
fn dot(&self, other: &Self) -> S {
self.inner(other)
}
/// Returns `true` if the vector is perpendicular (at right angles to)
/// the other vector.
fn is_perpendicular(&self, other: &Self) -> bool {
self.is_orthogonal(other)
}
/// Returns the squared length of the vector. This does not perform an
/// expensive square root operation like in the `length` method and can
/// therefore be more efficient for comparing the lengths of two vectors.
fn length2(&self) -> S {
self.dot(self)
}
/// The norm of the vector.
fn length(&self) -> S {
num::sqrt(self.dot(self))
}
/// The angle between the vector and `other`.
fn angle(&self, other: &Self) -> S;
/// Returns a vector with the same direction, but with a `length` (or
/// `norm`) of `1`.
fn normalize(&self) -> Self {
self.normalize_to(num::one::<S>())
}
/// Returns a vector with the same direction and a given `length`.
fn normalize_to(&self, length: S) -> Self {
*self * (length / self.length())
}
/// Returns the result of linarly interpolating the length of the vector
/// to the length of `other` by the specified amount.
fn lerp(&self, other: &Self, amount: S) -> Self {
*self + (*other - *self) * amount
}
}

View file

@ -0,0 +1,24 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::alg::Ring;
use traits::alg::VectorSpace;
/// A vector space with the inner product operation.
pub trait InnerProductSpace<S: Ring>: VectorSpace<S> {
fn norm(&self) -> S;
fn inner(&self, other: &Self) -> S;
fn is_orthogonal(&self, other: &Self) -> bool;
}

36
src/traits/alg/mod.rs Normal file
View file

@ -0,0 +1,36 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub use self::affine_space::AffineSpace;
pub use self::coordinate::Coordinate;
pub use self::division_ring::DivisionRing;
pub use self::euclidean_space::EuclideanSpace;
pub use self::inner_product_space::InnerProductSpace;
pub use self::module::Module;
pub use self::ordered_ring::OrderedRing;
pub use self::ring::Ring;
pub use self::scalar_mul::ScalarMul;
pub use self::vector_space::VectorSpace;
pub mod affine_space;
pub mod coordinate;
pub mod division_ring;
pub mod euclidean_space;
pub mod inner_product_space;
pub mod module;
pub mod ordered_ring;
pub mod ring;
pub mod scalar_mul;
pub mod vector_space;

40
src/traits/alg/module.rs Normal file
View file

@ -0,0 +1,40 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num::Zero;
use traits::alg::ScalarMul;
/// An algebraic structure that generalizes the notion of a vector space.
pub trait Module<S>: Eq
+ Add<Self,Self>
+ ScalarMul<S>
+ Zero {}
// impls for concrete types
impl Module<u8> for u8;
impl Module<u16> for u16;
impl Module<u32> for u32;
impl Module<u64> for u64;
impl Module<uint> for uint;
impl Module<i8> for i8;
impl Module<i16> for i16;
impl Module<i32> for i32;
impl Module<i64> for i64;
impl Module<int> for int;
impl Module<f32> for f32;
impl Module<f64> for f64;
impl Module<float> for float;

View file

@ -0,0 +1,36 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::alg::Ring;
/// A ring that can also be ordered.
pub trait OrderedRing: Ring
+ Orderable {}
// impls for concrete types
impl OrderedRing for u8;
impl OrderedRing for u16;
impl OrderedRing for u32;
impl OrderedRing for u64;
impl OrderedRing for uint;
impl OrderedRing for i8;
impl OrderedRing for i16;
impl OrderedRing for i32;
impl OrderedRing for i64;
impl OrderedRing for int;
impl OrderedRing for f32;
impl OrderedRing for f64;
impl OrderedRing for float;

41
src/traits/alg/ring.rs Normal file
View file

@ -0,0 +1,41 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num::One;
use traits::alg::Module;
/// A module that also requires the additive inverse operation (subtraction)
/// and the additive inverse.
pub trait Ring: Module<Self>
+ Neg<Self>
+ Sub<Self,Self>
+ One {}
// impls for concrete types
impl Ring for u8;
impl Ring for u16;
impl Ring for u32;
impl Ring for u64;
impl Ring for uint;
impl Ring for i8;
impl Ring for i16;
impl Ring for i32;
impl Ring for i64;
impl Ring for int;
impl Ring for f32;
impl Ring for f64;
impl Ring for float;

View file

@ -0,0 +1,35 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/// Enforces the multiplication of an type by a scalar.
pub trait ScalarMul<S>: Mul<S, Self>
+ Div<S, Self>
+ Rem<S, Self> {}
// impls for concrete types
impl ScalarMul<u8> for u8;
impl ScalarMul<u16> for u16;
impl ScalarMul<u32> for u32;
impl ScalarMul<u64> for u64;
impl ScalarMul<uint> for uint;
impl ScalarMul<i8> for i8;
impl ScalarMul<i16> for i16;
impl ScalarMul<i32> for i32;
impl ScalarMul<i64> for i64;
impl ScalarMul<int> for int;
impl ScalarMul<f32> for f32;
impl ScalarMul<f64> for f64;
impl ScalarMul<float> for float;

View file

@ -0,0 +1,22 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::alg::Module;
/// A vector space is a set that is closed under vector addition and
/// scalar multiplication.
pub trait VectorSpace<S>: Module<S>
+ Neg<Self>
+ Sub<Self,Self> {}

View file

@ -1,4 +1,4 @@
// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@ -13,6 +13,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#[pkg_crate(file = "src/lmath.rs")];
#[pkg(id = "lmath", vers = "0.1.0")];
#[pkg_dep(url = "git://github.com/bjz/numeric-rs")];
pub use self::vector_ext::VectorExt;
pub mod vector_ext;

View file

@ -0,0 +1,49 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::alg::Ring;
use traits::alg::VectorSpace;
use traits::util::Indexable;
pub trait VectorExt<S: Ring, Slice>: VectorSpace<S>
+ Indexable<S, Slice> {
#[inline] fn add_s(&self, s: S) -> Self { self.map(|x| x.add(&s)) }
#[inline] fn sub_s(&self, s: S) -> Self { self.map(|x| x.sub(&s)) }
#[inline] fn mul_s(&self, s: S) -> Self { self.map(|x| x.mul(&s)) }
#[inline] fn div_s(&self, s: S) -> Self { self.map(|x| x.div(&s)) }
#[inline] fn rem_s(&self, s: S) -> Self { self.map(|x| x.rem(&s)) }
#[inline] fn add_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.add(b) ) }
#[inline] fn sub_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.sub(b) ) }
#[inline] fn mul_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.mul(b) ) }
#[inline] fn div_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.div(b) ) }
#[inline] fn rem_v(&self, other: &Self) -> Self { self.bimap(other, |a, b| a.rem(b) ) }
#[inline] fn neg_self(&mut self) { self.map_mut(|x| *x = -*x); }
#[inline] fn add_self_s(&mut self, s: S) { self.map_mut(|x| *x = x.add(&s)); }
#[inline] fn sub_self_s(&mut self, s: S) { self.map_mut(|x| *x = x.sub(&s)); }
#[inline] fn mul_self_s(&mut self, s: S) { self.map_mut(|x| *x = x.mul(&s)); }
#[inline] fn div_self_s(&mut self, s: S) { self.map_mut(|x| *x = x.div(&s)); }
#[inline] fn rem_self_s(&mut self, s: S) { self.map_mut(|x| *x = x.rem(&s)); }
#[inline] fn add_self_v(&mut self, other: &Self) { self.bimap_mut::<S, Slice, Self>(other, |a, b| *a = a.add(b)) }
#[inline] fn sub_self_v(&mut self, other: &Self) { self.bimap_mut::<S, Slice, Self>(other, |a, b| *a = a.sub(b)) }
#[inline] fn mul_self_v(&mut self, other: &Self) { self.bimap_mut::<S, Slice, Self>(other, |a, b| *a = a.mul(b)) }
#[inline] fn div_self_v(&mut self, other: &Self) { self.bimap_mut::<S, Slice, Self>(other, |a, b| *a = a.div(b)) }
#[inline] fn rem_self_v(&mut self, other: &Self) { self.bimap_mut::<S, Slice, Self>(other, |a, b| *a = a.rem(b)) }
#[inline] fn comp_add(&self) -> S { fail!() }
#[inline] fn comp_mul(&self) -> S { fail!() }
}

45
src/traits/mod.rs Normal file
View file

@ -0,0 +1,45 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_escape];
/// Import this module for the strict, algebraic trait heirachy.
///
/// # Example
///
/// ~~~rust
/// use lmath::traits::alg::*;
/// ~~~
pub mod alg;
/// Import this module to access utility traits that do not neccsarily match
/// up with the strict algebraic properties of the respective types, and yet
/// still may be useful for computer graphics work.
///
/// # Example
///
/// ~~~rust
/// use lmath::traits::ext::*;
/// ~~~
pub mod ext;
/// TODO
///
/// # Example
///
/// ~~~rust
/// use lmath::traits::util::*;
/// ~~~
pub mod util;

View file

@ -0,0 +1,105 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_escape];
/// Types that can be accessed via an unsigned index.
pub trait Indexable<T, Slice> {
fn len(&self) -> uint;
fn i<'a>(&'a self, i: uint) -> &'a T;
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T;
fn as_slice<'a>(&'a self) -> &'a Slice;
fn as_mut_slice<'a>(&'a mut self) -> &'a mut Slice;
fn from_slice(slice: Slice) -> Self;
fn build(builder: &fn(i: uint) -> T) -> Self;
#[inline]
fn map<U, SliceU, UU: Indexable<U, SliceU>>(&self, f: &fn(&T) -> U) -> UU {
Indexable::build(|i| f(self.i(i)))
}
#[inline]
fn map_mut(&mut self, f: &fn(&mut T)) {
for i in range(0, self.len()) {
f(self.mut_i(i));
}
}
#[inline]
fn bimap<U, SliceU, UU: Indexable<U, SliceU>,
V, SliceV, VV: Indexable<V, SliceV>>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV {
Indexable::build(|i| f(self.i(i), other.i(i)))
}
#[inline]
fn bimap_mut<U, SliceU, UU: Indexable<U, Slice>>(&mut self, other: &UU, f: &fn(&mut T, &U)) {
for i in range(0, self.len()) {
f(self.mut_i(i), other.i(i));
}
}
#[inline]
fn fold<U>(&self, init: U, f: &fn(acc: &U, x: &T) -> U) -> U {
let mut acc = init;
for i in range(0, self.len()) {
acc = f(&acc, self.i(i));
}
acc
}
}
macro_rules! impl_indexable(
($Self:ty, [$T:ident, ..$n:expr]) => (
impl<$T> Indexable<$T, [$T,..$n]> for $Self {
#[inline]
fn len(&self) -> uint { $n }
#[inline]
fn i<'a>(&'a self, i: uint) -> &'a $T {
&'a self.as_slice()[i]
}
#[inline]
fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut $T {
&'a mut self.as_mut_slice()[i]
}
#[inline]
fn as_slice<'a>(&'a self) -> &'a [$T,..$n] {
unsafe { ::std::cast::transmute(self) }
}
#[inline]
fn as_mut_slice<'a>(&'a mut self) -> &'a mut [$T,..$n] {
unsafe { ::std::cast::transmute(self) }
}
#[inline]
fn from_slice(slice: [$T,..$n]) -> $Self {
unsafe { ::std::cast::transmute(slice) }
}
#[inline]
fn build(builder: &fn(i: uint) -> $T) -> $Self {
use std::unstable::intrinsics;
let mut s: [$T,..$n] = unsafe { intrinsics::uninit() };
for i in range::<uint>(0, $n) {
s[i] = builder(i);
}
Indexable::from_slice(s)
}
}
)
)

22
src/traits/util/mod.rs Normal file
View file

@ -0,0 +1,22 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_escape];
pub use self::indexable::Indexable;
pub use self::swappable::Swappable;
pub mod indexable;
pub mod swappable;

View file

@ -0,0 +1,26 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::util::Indexable;
pub trait Swappable<T: Clone, Slice>: Indexable<T, Slice> {
/// Swap two elements of the type in place.
#[inline]
fn swap(&mut self, a: uint, b: uint) {
let tmp = self.i(a).clone();
*self.mut_i(a) = self.i(b).clone();
*self.mut_i(b) = tmp;
}
}

14
src/types/matrix.rs Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

19
src/types/mod.rs Normal file
View file

@ -0,0 +1,19 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod matrix;
pub mod point;
pub mod quaternion;
pub mod vector;

76
src/types/point.rs Normal file
View file

@ -0,0 +1,76 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Points are fixed positions in affine space with no length or direction. This
//! disinguishes them from vectors, which have a length and direction, but do
//! not have a fixed position.
use traits::alg::*;
use traits::util::*;
use types::vector::{Vec2, Vec3};
#[deriving(Eq, Zero, Clone)]
struct Point2<S> { x: S, y: S }
#[deriving(Eq, Zero, Clone)]
struct Point3<S> { x: S, y: S, z: S }
impl<S> Point2<S> {
#[inline]
pub fn new(x: S, y: S) -> Point2<S> {
Point2 { x: x, y: y }
}
}
impl<S> Point3<S> {
#[inline]
pub fn new(x: S, y: S, z: S) -> Point3<S> {
Point3 { x: x, y: y, z: z }
}
}
// Operator impls
impl<S:Ring> Mul<S, Point2<S>> for Point2<S> { #[inline(always)] fn mul(&self, s: &S) -> Point2<S> { self.map(|x| x.mul(s)) } }
impl<S:Ring> Mul<S, Point3<S>> for Point3<S> { #[inline(always)] fn mul(&self, s: &S) -> Point3<S> { self.map(|x| x.mul(s)) } }
impl<S:Ring> Div<S, Point2<S>> for Point2<S> { #[inline(always)] fn div(&self, s: &S) -> Point2<S> { self.map(|x| x.div(s)) } }
impl<S:Ring> Div<S, Point3<S>> for Point3<S> { #[inline(always)] fn div(&self, s: &S) -> Point3<S> { self.map(|x| x.div(s)) } }
impl<S:Ring> Rem<S, Point2<S>> for Point2<S> { #[inline(always)] fn rem(&self, s: &S) -> Point2<S> { self.map(|x| x.rem(s)) } }
impl<S:Ring> Rem<S, Point3<S>> for Point3<S> { #[inline(always)] fn rem(&self, s: &S) -> Point3<S> { self.map(|x| x.rem(s)) } }
impl<S:Ring> Add<Vec2<S>, Point2<S>> for Point2<S> { #[inline(always)] fn add(&self, other: &Vec2<S>) -> Point2<S> { self.bimap(other, |a, b| a.add(b)) } }
impl<S:Ring> Add<Vec3<S>, Point3<S>> for Point3<S> { #[inline(always)] fn add(&self, other: &Vec3<S>) -> Point3<S> { self.bimap(other, |a, b| a.add(b)) } }
impl<S:Ring> Sub<Point2<S>, Vec2<S>> for Point2<S> { #[inline(always)] fn sub(&self, other: &Point2<S>) -> Vec2<S> { self.bimap(other, |a, b| a.sub(b)) } }
impl<S:Ring> Sub<Point3<S>, Vec3<S>> for Point3<S> { #[inline(always)] fn sub(&self, other: &Point3<S>) -> Vec3<S> { self.bimap(other, |a, b| a.sub(b)) } }
// Trait impls
impl_indexable!(Point2<T>, [T, ..2])
impl_indexable!(Point3<T>, [T, ..3])
impl<S: Clone> Swappable<S, [S, ..2]> for Point2<S>;
impl<S: Clone> Swappable<S, [S, ..3]> for Point3<S>;
impl<S: Clone> Coordinate<S, [S, ..2]> for Point2<S>;
impl<S: Clone> Coordinate<S, [S, ..3]> for Point3<S>;
impl<S: Ring> ScalarMul<S> for Point2<S>;
impl<S: Ring> ScalarMul<S> for Point3<S>;
impl<S: Ring> AffineSpace<S, Vec2<S>> for Point2<S>;
impl<S: Ring> AffineSpace<S, Vec3<S>> for Point3<S>;

36
src/types/quaternion.rs Normal file
View file

@ -0,0 +1,36 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use traits::alg::*;
use types::vector::Vec3;
/// A quaternion in scalar/vector form
#[deriving(Clone, Eq)]
pub struct Quat<T> { s: T, v: Vec3<T> }
impl<T: Ring> Quat<T> {
/// Construct a new quaternion from one scalar component and three
/// imaginary components
#[inline]
pub fn new(w: T, xi: T, yj: T, zk: T) -> Quat<T> {
Quat::from_sv(w, Vec3::new(xi, yj, zk))
}
/// Construct a new quaternion from a scalar and a vector
#[inline]
pub fn from_sv(s: T, v: Vec3<T>) -> Quat<T> {
Quat { s: s, v: v }
}
}

240
src/types/vector.rs Normal file
View file

@ -0,0 +1,240 @@
// Copyright 2013 The OMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::num;
use std::num::{Zero, zero};
use std::num::{sqrt, atan2};
use traits::alg::*;
use traits::ext::*;
use traits::util::*;
#[deriving(Eq, Zero, Clone)] pub struct Vec1<S> { x: S }
#[deriving(Eq, Zero, Clone)] pub struct Vec2<S> { x: S, y: S }
#[deriving(Eq, Zero, Clone)] pub struct Vec3<S> { x: S, y: S, z: S }
#[deriving(Eq, Zero, Clone)] pub struct Vec4<S> { x: S, y: S, z: S, w: S }
#[deriving(Eq, Zero, Clone)] pub struct Vec5<S> { x: S, y: S, z: S, w: S, a: S }
#[deriving(Eq, Zero, Clone)] pub struct Vec6<S> { x: S, y: S, z: S, w: S, a: S, b: S }
macro_rules! impl_vec(
($Self:ident <$S:ident> { $($field:ident),+ }) => (
impl<$S> $Self<$S> {
#[inline]
pub fn new($($field: $S),+) -> $Self<$S> {
$Self { $($field: $field),+ }
}
}
)
)
impl_vec!(Vec1<S> { x })
impl_vec!(Vec2<S> { x, y })
impl_vec!(Vec3<S> { x, y, z })
impl_vec!(Vec4<S> { x, y, z, w })
impl_vec!(Vec5<S> { x, y, z, w, a })
impl_vec!(Vec6<S> { x, y, z, w, a, b })
macro_rules! impl_vec_clonable(
($Self:ident <$S:ident>) => (
impl<$S:Clone> $Self<$S> {
/// Construct a vector from a single value.
#[inline]
pub fn from_value(value: $S) -> $Self<$S> {
Indexable::build(|_| value.clone())
}
}
)
)
impl_vec_clonable!(Vec1<S>)
impl_vec_clonable!(Vec2<S>)
impl_vec_clonable!(Vec3<S>)
impl_vec_clonable!(Vec4<S>)
impl_vec_clonable!(Vec5<S>)
impl_vec_clonable!(Vec6<S>)
macro_rules! impl_vec_ring(
($Self:ident <$S:ident>) => (
impl<$S:Ring> $Self<$S> {
/// The additive identity of the vector.
#[inline]
pub fn zero() -> $Self<$S> { zero() }
}
)
)
impl_vec_ring!(Vec1<S>)
impl_vec_ring!(Vec2<S>)
impl_vec_ring!(Vec3<S>)
impl_vec_ring!(Vec4<S>)
impl_vec_ring!(Vec5<S>)
impl_vec_ring!(Vec6<S>)
// Operator impls
macro_rules! impl_vec_ops(
($vec_ops_mod:ident, $Self:ident <$S:ident>) => (
pub mod $vec_ops_mod {
use super::*;
use super::super::super::traits::alg::*;
impl<$S:Ring> Mul<$S, $Self<$S>> for $Self<$S> {
#[inline(always)]
fn mul(&self, s: &$S) -> $Self<$S> { self.map(|x| x.mul(s)) }
}
impl<$S:Ring> Div<$S, $Self<$S>> for $Self<$S> {
#[inline(always)]
fn div(&self, s: &$S) -> $Self<$S> { self.map(|x| x.div(s)) }
}
impl<$S:Ring> Rem<$S, $Self<$S>> for $Self<$S> {
#[inline(always)]
fn rem(&self, s: &$S) -> $Self<$S> { self.map(|x| x.rem(s)) }
}
impl<$S:Ring> Add<$Self<$S>, $Self<$S>> for $Self<$S> {
#[inline(always)]
fn add(&self, other: &$Self<$S>) -> $Self<$S> { self.bimap(other, |a, b| a.add(b)) }
}
impl<$S:Ring> Sub<$Self<$S>, $Self<$S>> for $Self<$S> {
#[inline(always)]
fn sub(&self, other: &$Self<$S>) -> $Self<$S> { self.bimap(other, |a, b| a.sub(b)) }
}
impl<$S:Ring> Neg<$Self<$S>> for $Self<$S> {
#[inline(always)]
fn neg(&self) -> $Self<$S> { self.map(|x| x.neg()) }
}
}
)
)
impl_vec_ops!(vec1_ops, Vec1<S>)
impl_vec_ops!(vec2_ops, Vec2<S>)
impl_vec_ops!(vec3_ops, Vec3<S>)
impl_vec_ops!(vec4_ops, Vec4<S>)
impl_vec_ops!(vec5_ops, Vec5<S>)
impl_vec_ops!(vec6_ops, Vec6<S>)
/// Operations specific to two-dimensional vectors.
impl<S: Ring> Vec2<S> {
/// The perpendicular dot product of the vector and `other`.
pub fn perp_dot(&self, other: &Vec2<S>) -> S {
(self.x * other.y) - (self.y * other.x)
}
}
/// Operations specific to three-dimensional vectors.
impl<S: Ring> Vec3<S> {
/// Returns the cross product of the vector and `other`.
pub fn cross(&self, other: &Vec3<S>) -> Vec3<S> {
Vec3::new((self.y * other.z) - (self.z * other.y),
(self.z * other.x) - (self.x * other.z),
(self.x * other.y) - (self.y * other.x))
}
}
// Trait impls
impl_indexable!(Vec1<S>, [S, ..1])
impl_indexable!(Vec2<S>, [S, ..2])
impl_indexable!(Vec3<S>, [S, ..3])
impl_indexable!(Vec4<S>, [S, ..4])
impl_indexable!(Vec5<S>, [S, ..5])
impl_indexable!(Vec6<S>, [S, ..6])
impl<S: Clone> Swappable<S, [S, ..1]> for Vec1<S>;
impl<S: Clone> Swappable<S, [S, ..2]> for Vec2<S>;
impl<S: Clone> Swappable<S, [S, ..3]> for Vec3<S>;
impl<S: Clone> Swappable<S, [S, ..4]> for Vec4<S>;
impl<S: Clone> Swappable<S, [S, ..5]> for Vec5<S>;
impl<S: Clone> Swappable<S, [S, ..6]> for Vec6<S>;
impl<S: Clone> Coordinate<S, [S, ..1]> for Vec1<S>;
impl<S: Clone> Coordinate<S, [S, ..2]> for Vec2<S>;
impl<S: Clone> Coordinate<S, [S, ..3]> for Vec3<S>;
impl<S: Clone> Coordinate<S, [S, ..4]> for Vec4<S>;
impl<S: Clone> Coordinate<S, [S, ..5]> for Vec5<S>;
impl<S: Clone> Coordinate<S, [S, ..6]> for Vec6<S>;
impl<S: Ring> ScalarMul<S> for Vec1<S>;
impl<S: Ring> ScalarMul<S> for Vec2<S>;
impl<S: Ring> ScalarMul<S> for Vec3<S>;
impl<S: Ring> ScalarMul<S> for Vec4<S>;
impl<S: Ring> ScalarMul<S> for Vec5<S>;
impl<S: Ring> ScalarMul<S> for Vec6<S>;
impl<S: Ring> Module<S> for Vec1<S>;
impl<S: Ring> Module<S> for Vec2<S>;
impl<S: Ring> Module<S> for Vec3<S>;
impl<S: Ring> Module<S> for Vec4<S>;
impl<S: Ring> Module<S> for Vec5<S>;
impl<S: Ring> Module<S> for Vec6<S>;
impl<S: Ring> VectorSpace<S> for Vec1<S>;
impl<S: Ring> VectorSpace<S> for Vec2<S>;
impl<S: Ring> VectorSpace<S> for Vec3<S>;
impl<S: Ring> VectorSpace<S> for Vec4<S>;
impl<S: Ring> VectorSpace<S> for Vec5<S>;
impl<S: Ring> VectorSpace<S> for Vec6<S>;
macro_rules! impl_vec_inner_product(
($Self:ident <$S:ident>) => (
impl<$S:Real + Ring + ApproxEq<$S>> InnerProductSpace<$S> for $Self<$S> {
fn norm(&self) -> $S {
num::sqrt(self.inner(self))
}
fn inner(&self, other: &$Self<$S>) -> $S {
let comp_sum: $Self<$S> = self.bimap(other, |a, b| a.mul(b));
comp_sum.fold(num::zero::<$S>(), |a, b| a.add(b))
}
fn is_orthogonal(&self, other: &$Self<$S>) -> bool {
self.inner(other).approx_eq(&num::zero())
}
}
)
)
impl_vec_inner_product!(Vec1<S>)
impl_vec_inner_product!(Vec2<S>)
impl_vec_inner_product!(Vec3<S>)
impl_vec_inner_product!(Vec4<S>)
impl_vec_inner_product!(Vec5<S>)
impl_vec_inner_product!(Vec6<S>)
// Euclidean spaces only really make sense for 2D and 3D vector spaces
impl<S:Real + Ring + ApproxEq<S>> EuclideanSpace<S> for Vec2<S> {
fn angle(&self, other: &Vec2<S>) -> S {
atan2(self.perp_dot(other), self.dot(other))
}
}
impl<S:Real + Ring + ApproxEq<S>> EuclideanSpace<S> for Vec3<S> {
fn angle(&self, other: &Vec3<S>) -> S {
atan2(self.cross(other).length(), self.dot(other))
}
}
impl<S: Ring> VectorExt<S, [S, ..1]> for Vec1<S>;
impl<S: Ring> VectorExt<S, [S, ..2]> for Vec2<S>;
impl<S: Ring> VectorExt<S, [S, ..3]> for Vec3<S>;
impl<S: Ring> VectorExt<S, [S, ..4]> for Vec4<S>;
impl<S: Ring> VectorExt<S, [S, ..5]> for Vec5<S>;
impl<S: Ring> VectorExt<S, [S, ..6]> for Vec6<S>;