use std::fmt;
use std::mem;
use std::ops::*;
use rand::{Rand, Rng};
use rust_num::{NumCast, Zero, One, zero, one};
use angle::{Rad, atan2, acos};
use approx::ApproxEq;
use array::{Array1, FixedArray};
use num::{BaseNum, BaseFloat};
pub trait Vector<S: BaseNum>: Array1<S> + Zero + One {
fn from_value(s: S) -> Self;
#[must_use]
fn add_s(&self, s: S) -> Self;
#[must_use]
fn sub_s(&self, s: S) -> Self;
#[must_use]
fn mul_s(&self, s: S) -> Self;
#[must_use]
fn div_s(&self, s: S) -> Self;
#[must_use]
fn rem_s(&self, s: S) -> Self;
#[must_use]
fn add_v(&self, v: &Self) -> Self;
#[must_use]
fn sub_v(&self, v: &Self) -> Self;
#[must_use]
fn mul_v(&self, v: &Self) -> Self;
#[must_use]
fn div_v(&self, v: &Self) -> Self;
#[must_use]
fn rem_v(&self, v: &Self) -> Self;
fn add_self_s(&mut self, s: S);
fn sub_self_s(&mut self, s: S);
fn mul_self_s(&mut self, s: S);
fn div_self_s(&mut self, s: S);
fn rem_self_s(&mut self, s: S);
fn add_self_v(&mut self, v: &Self);
fn sub_self_v(&mut self, v: &Self);
fn mul_self_v(&mut self, v: &Self);
fn div_self_v(&mut self, v: &Self);
fn rem_self_v(&mut self, v: &Self);
fn comp_add(&self) -> S;
fn comp_mul(&self) -> S;
#[inline]
fn dot(&self, v: &Self) -> S { self.mul_v(v).comp_add() }
fn comp_min(&self) -> S;
fn comp_max(&self) -> S;
}
#[inline] pub fn dot<S: BaseNum, V: Vector<S>>(a: V, b: V) -> S { a.dot(&b) }
macro_rules! vec(
($Self_:ident <$S:ident> { $($field:ident),+ }, $n:expr, $constructor:ident) => (
#[derive(PartialEq, Eq, Copy, Clone, Hash, RustcEncodable, RustcDecodable)]
pub struct $Self_<S> { $(pub $field: S),+ }
impl<$S> $Self_<$S> {
#[inline]
pub fn new($($field: $S),+) -> $Self_<$S> {
$Self_ { $($field: $field),+ }
}
}
impl<$S: Copy + Neg<Output = $S>> $Self_<$S> {
#[inline]
pub fn neg_self(&mut self) {
$(self.$field = -self.$field);+
}
}
#[inline]
pub fn $constructor<S>($($field: S),+) -> $Self_<S> {
$Self_::new($($field),+)
}
impl<$S: Zero + BaseNum> Zero for $Self_<$S> {
#[inline]
fn zero() -> $Self_<S> { $Self_ { $($field: zero()),+ } }
#[inline]
fn is_zero(&self) -> bool { $((self.$field.is_zero()) )&&+ }
}
impl<$S: One + BaseNum> One for $Self_<$S> {
#[inline]
fn one() -> $Self_<$S> { $Self_ { $($field: one()),+ } }
}
impl<$S: NumCast + Copy> $Self_<$S> {
#[inline]
pub fn cast<T: NumCast>(&self) -> $Self_<T> {
$Self_ { $($field: NumCast::from(self.$field).unwrap()),+ }
}
}
impl<$S> FixedArray<[$S; $n]> for $Self_<$S> {
#[inline]
fn into_fixed(self) -> [$S; $n] {
match self { $Self_ { $($field),+ } => [$($field),+] }
}
#[inline]
fn as_fixed<'a>(&'a self) -> &'a [$S; $n] {
unsafe { mem::transmute(self) }
}
#[inline]
fn as_mut_fixed<'a>(&'a mut self) -> &'a mut [$S; $n] {
unsafe { mem::transmute(self) }
}
#[inline]
fn from_fixed(_v: [$S; $n]) -> $Self_<$S> {
panic!("Unimplemented, pending a fix for rust-lang/rust#16418");
}
#[inline]
fn from_fixed_ref<'a>(v: &'a [$S; $n]) -> &'a $Self_<$S> {
unsafe { mem::transmute(v) }
}
#[inline]
fn from_fixed_mut<'a>(v: &'a mut [$S; $n]) -> &'a mut $Self_<$S> {
unsafe { mem::transmute(v) }
}
}
impl<$S: Copy> Index<usize> for $Self_<$S> {
type Output = S;
#[inline]
fn index<'a>(&'a self, i: usize) -> &'a $S {
&self.as_fixed()[i]
}
}
impl<$S: Copy> IndexMut<usize> for $Self_<$S> {
#[inline]
fn index_mut<'a>(&'a mut self, i: usize) -> &'a mut $S {
&mut self.as_mut_fixed()[i]
}
}
impl<$S: Copy> Array1<$S> for $Self_<$S> {
#[inline]
fn map<F>(&mut self, mut op: F) -> $Self_<$S> where F: FnMut($S) -> $S {
$(self.$field = op(self.$field);)+ *self
}
}
impl<S: BaseNum> Vector<S> for $Self_<S> {
#[inline] fn from_value(s: S) -> $Self_<S> { $Self_ { $($field: s),+ } }
#[inline] fn add_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field + s),+) }
#[inline] fn sub_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field - s),+) }
#[inline] fn mul_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field * s),+) }
#[inline] fn div_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field / s),+) }
#[inline] fn rem_s(&self, s: S) -> $Self_<S> { $Self_::new($(self.$field % s),+) }
#[inline] fn add_v(&self, v: &$Self_<S>) -> $Self_<S> { $Self_::new($(self.$field + v.$field),+) }
#[inline] fn sub_v(&self, v: &$Self_<S>) -> $Self_<S> { $Self_::new($(self.$field - v.$field),+) }
#[inline] fn mul_v(&self, v: &$Self_<S>) -> $Self_<S> { $Self_::new($(self.$field * v.$field),+) }
#[inline] fn div_v(&self, v: &$Self_<S>) -> $Self_<S> { $Self_::new($(self.$field / v.$field),+) }
#[inline] fn rem_v(&self, v: &$Self_<S>) -> $Self_<S> { $Self_::new($(self.$field % v.$field),+) }
#[inline] fn add_self_s(&mut self, s: S) { $(self.$field = self.$field + s;)+ }
#[inline] fn sub_self_s(&mut self, s: S) { $(self.$field = self.$field - s;)+ }
#[inline] fn mul_self_s(&mut self, s: S) { $(self.$field = self.$field * s;)+ }
#[inline] fn div_self_s(&mut self, s: S) { $(self.$field = self.$field / s;)+ }
#[inline] fn rem_self_s(&mut self, s: S) { $(self.$field = self.$field % s;)+ }
#[inline] fn add_self_v(&mut self, v: &$Self_<S>) { $(self.$field = self.$field + v.$field;)+ }
#[inline] fn sub_self_v(&mut self, v: &$Self_<S>) { $(self.$field = self.$field - v.$field;)+ }
#[inline] fn mul_self_v(&mut self, v: &$Self_<S>) { $(self.$field = self.$field * v.$field;)+ }
#[inline] fn div_self_v(&mut self, v: &$Self_<S>) { $(self.$field = self.$field / v.$field;)+ }
#[inline] fn rem_self_v(&mut self, v: &$Self_<S>) { $(self.$field = self.$field % v.$field;)+ }
#[inline] fn comp_add(&self) -> S { fold!(add, { $(self.$field),+ }) }
#[inline] fn comp_mul(&self) -> S { fold!(mul, { $(self.$field),+ }) }
#[inline] fn comp_min(&self) -> S { fold!(partial_min, { $(self.$field),+ }) }
#[inline] fn comp_max(&self) -> S { fold!(partial_max, { $(self.$field),+ }) }
}
impl<S: BaseNum> Add for $Self_<S> {
type Output = $Self_<S>;
#[inline]
fn add(self, v: $Self_<S>) -> $Self_<S> { self.add_v(&v) }
}
impl<S: BaseNum> Sub for $Self_<S> {
type Output = $Self_<S>;
#[inline]
fn sub(self, v: $Self_<S>) -> $Self_<S> { self.sub_v(&v) }
}
impl<S: Neg<Output = S>> Neg for $Self_<S> {
type Output = $Self_<S>;
#[inline]
fn neg(self) -> $Self_<S> { $Self_::new($(-self.$field),+) }
}
impl<S: BaseNum> Mul for $Self_<S> {
type Output = $Self_<S>;
#[inline]
fn mul(self, v: $Self_<S>) -> $Self_<S> { self.mul_v(&v) }
}
impl<S: BaseNum> Div for $Self_<S> {
type Output = $Self_<S>;
#[inline]
fn div(self, v: $Self_<S>) -> $Self_<S> { self.div_v(&v) }
}
impl<S: BaseNum> Rem for $Self_<S> {
type Output = $Self_<S>;
#[inline]
fn rem(self, v: $Self_<S>) -> $Self_<S> { self.rem_v(&v) }
}
impl<S: BaseFloat> ApproxEq<S> for $Self_<S> {
#[inline]
fn approx_eq_eps(&self, other: &$Self_<S>, epsilon: &S) -> bool {
$(self.$field.approx_eq_eps(&other.$field, epsilon))&&+
}
}
impl<S: BaseFloat + Rand> Rand for $Self_<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> $Self_<S> {
$Self_ { $($field: rng.gen()),+ }
}
}
)
);
macro_rules! fold {
(&$method:ident, { $x:expr, $y:expr }) => { $x.$method(&$y) };
(&$method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method(&$y).$method(&$z) };
(&$method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method(&$y).$method(&$z).$method(&$w) };
($method:ident, { $x:expr, $y:expr }) => { $x.$method($y) };
($method:ident, { $x:expr, $y:expr, $z:expr }) => { $x.$method($y).$method($z) };
($method:ident, { $x:expr, $y:expr, $z:expr, $w:expr }) => { $x.$method($y).$method($z).$method($w) };
}
vec!(Vector2<S> { x, y }, 2, vec2);
vec!(Vector3<S> { x, y, z }, 3, vec3);
vec!(Vector4<S> { x, y, z, w }, 4, vec4);
impl<S: BaseNum> Vector2<S> {
#[inline] pub fn unit_x() -> Vector2<S> { Vector2::new(one(), zero()) }
#[inline] pub fn unit_y() -> Vector2<S> { Vector2::new(zero(), one()) }
#[inline]
pub fn perp_dot(&self, other: &Vector2<S>) -> S {
(self.x * other.y) - (self.y * other.x)
}
#[inline]
pub fn extend(&self, z: S)-> Vector3<S> {
Vector3::new(self.x, self.y, z)
}
}
impl<S: BaseNum> Vector3<S> {
#[inline] pub fn unit_x() -> Vector3<S> { Vector3::new(one(), zero(), zero()) }
#[inline] pub fn unit_y() -> Vector3<S> { Vector3::new(zero(), one(), zero()) }
#[inline] pub fn unit_z() -> Vector3<S> { Vector3::new(zero(), zero(), one()) }
#[inline]
#[must_use]
pub fn cross(&self, other: &Vector3<S>) -> Vector3<S> {
Vector3::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))
}
#[inline]
pub fn cross_self(&mut self, other: &Vector3<S>) {
*self = self.cross(other)
}
#[inline]
pub fn extend(&self, w: S)-> Vector4<S> {
Vector4::new(self.x, self.y, self.z, w)
}
#[inline]
pub fn truncate(&self)-> Vector2<S> {
Vector2::new(self.x, self.y)
}
}
impl<S: BaseNum> Vector4<S> {
#[inline] pub fn unit_x() -> Vector4<S> { Vector4::new(one(), zero(), zero(), zero()) }
#[inline] pub fn unit_y() -> Vector4<S> { Vector4::new(zero(), one(), zero(), zero()) }
#[inline] pub fn unit_z() -> Vector4<S> { Vector4::new(zero(), zero(), one(), zero()) }
#[inline] pub fn unit_w() -> Vector4<S> { Vector4::new(zero(), zero(), zero(), one()) }
#[inline]
pub fn truncate(&self)-> Vector3<S> {
Vector3::new(self.x, self.y, self.z)
}
#[inline]
pub fn truncate_n(&self, n: isize)-> Vector3<S> {
match n {
0 => Vector3::new(self.y, self.z, self.w),
1 => Vector3::new(self.x, self.z, self.w),
2 => Vector3::new(self.x, self.y, self.w),
3 => Vector3::new(self.x, self.y, self.z),
_ => panic!("{:?} is out of range", n)
}
}
}
pub trait EuclideanVector<S: BaseFloat>: Vector<S>
+ ApproxEq<S>
+ Sized {
fn is_perpendicular(&self, other: &Self) -> bool {
self.dot(other).approx_eq(&zero())
}
#[inline]
fn length2(&self) -> S {
self.dot(self)
}
#[inline]
fn length(&self) -> S {
self.dot(self).sqrt()
}
fn angle(&self, other: &Self) -> Rad<S>;
#[inline]
#[must_use]
fn normalize(&self) -> Self {
self.normalize_to(one::<S>())
}
#[inline]
#[must_use]
fn normalize_to(&self, length: S) -> Self {
self.mul_s(length / self.length())
}
#[inline]
#[must_use]
fn lerp(&self, other: &Self, amount: S) -> Self {
self.add_v(&other.sub_v(self).mul_s(amount))
}
#[inline]
fn normalize_self(&mut self) {
let rlen = self.length().recip();
self.mul_self_s(rlen);
}
#[inline]
fn normalize_self_to(&mut self, length: S) {
let n = length / self.length();
self.mul_self_s(n);
}
fn lerp_self(&mut self, other: &Self, amount: S) {
let v = other.sub_v(self).mul_s(amount);
self.add_self_v(&v);
}
}
impl<S: BaseFloat> EuclideanVector<S> for Vector2<S> {
#[inline]
fn angle(&self, other: &Vector2<S>) -> Rad<S> {
atan2(self.perp_dot(other), self.dot(other))
}
}
impl<S: BaseFloat> EuclideanVector<S> for Vector3<S> {
#[inline]
fn angle(&self, other: &Vector3<S>) -> Rad<S> {
atan2(self.cross(other).length(), self.dot(other))
}
}
impl<S: BaseFloat> EuclideanVector<S> for Vector4<S> {
#[inline]
fn angle(&self, other: &Vector4<S>) -> Rad<S> {
acos(self.dot(other) / (self.length() * other.length()))
}
}
impl<S: BaseNum> fmt::Debug for Vector2<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{:?}, {:?}]", self.x, self.y)
}
}
impl<S: BaseNum> fmt::Debug for Vector3<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{:?}, {:?}, {:?}]", self.x, self.y, self.z)
}
}
impl<S: BaseNum> fmt::Debug for Vector4<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{:?}, {:?}, {:?}, {:?}]", self.x, self.y, self.z, self.w)
}
}