#![allow(dead_code)]
use std::ops::{Add, Sub, Neg, Mul, Div};
use std::cmp::{PartialEq, PartialOrd, Ordering};
pub use num::{Zero, One, Num};
use num;
use super::float::Float;
use super::{Vec2, Vec3};
use std::fmt;
use clamp::Clamp;
use std::iter::IntoIterator;
#[derive(Copy, Clone, Debug)]
pub struct Vec4<T>(pub T, pub T, pub T, pub T);
impl<T: Copy> IntoIterator for Vec4<T> {
type Item = T;
type IntoIter = Vec4Iterator<T>;
fn into_iter(self) -> Self::IntoIter {
Vec4Iterator {
v: self,
index: 0,
}
}
}
pub struct Vec4Iterator<T> {
v: Vec4<T>,
index: usize,
}
impl<T: Copy> Iterator for Vec4Iterator<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
let result = match self.index {
0 => Some(self.v.0),
1 => Some(self.v.1),
2 => Some(self.v.2),
3 => Some(self.v.3),
_ => return None,
};
self.index += 1;
result
}
}
impl<T: fmt::Display> fmt::Display for Vec4<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Vec4({}, {}, {}, {})", self.0, self.1, self.2, self.3)
}
}
impl<T: One> One for Vec4<T> {
fn one() -> Self {
Vec4(T::one(), T::one(), T::one(), T::one())
}
}
impl<T: Float> Vec4<T> {
pub fn almost_equal<N: num::Float>(self, other: Self, abs_tol: N) -> bool {
self.0.almost_equal(other.0, abs_tol) && self.1.almost_equal(other.1, abs_tol) &&
self.2.almost_equal(other.2, abs_tol) && self.3.almost_equal(other.3, abs_tol)
}
pub fn is_nan(self) -> bool {
self.0.is_nan() && self.1.is_nan() && self.2.is_nan() && self.3.is_nan()
}
pub fn round(&self) -> Self {
Vec4(self.0.round(),
self.1.round(),
self.2.round(),
self.3.round())
}
}
impl<T: Add<Output = T>> Add for Vec4<T> {
type Output = Self;
fn add(self, _rhs: Self) -> Self {
Vec4(self.0 + _rhs.0,
self.1 + _rhs.1,
self.2 + _rhs.2,
self.3 + _rhs.3)
}
}
impl<T: Add<Output = T> + Copy> Vec4<T> {
pub fn add_scalar(self, _rhs: T) -> Self {
Vec4(self.0 + _rhs, self.1 + _rhs, self.2 + _rhs, self.3 + _rhs)
}
}
impl<T: Neg<Output = T>> Neg for Vec4<T> {
type Output = Self;
fn neg(self) -> Self {
Vec4(-self.0, -self.1, -self.2, -self.3)
}
}
impl<T: Sub<Output = T>> Sub for Vec4<T> {
type Output = Self;
fn sub(self, _rhs: Self) -> Self {
Vec4(self.0 - _rhs.0,
self.1 - _rhs.1,
self.2 - _rhs.2,
self.3 - _rhs.3)
}
}
impl<T: Sub<Output = T> + Copy> Vec4<T> {
pub fn sub_scalar(self, _rhs: T) -> Self {
Vec4(self.0 - _rhs, self.1 - _rhs, self.2 - _rhs, self.3 - _rhs)
}
}
impl<T: Mul<Output = T>> Mul for Vec4<T> {
type Output = Self;
fn mul(self, _rhs: Self) -> Self {
Vec4(self.0 * _rhs.0,
self.1 * _rhs.1,
self.2 * _rhs.2,
self.3 * _rhs.3)
}
}
impl<T: Mul<Output = T> + Copy> Vec4<T> {
pub fn mul_scalar(self, _rhs: T) -> Self {
Vec4(self.0 * _rhs, self.1 * _rhs, self.2 * _rhs, self.3 * _rhs)
}
}
impl<T: Div<Output = T>> Div for Vec4<T> {
type Output = Self;
fn div(self, _rhs: Self) -> Self {
Vec4(self.0 / _rhs.0,
self.1 / _rhs.1,
self.2 / _rhs.2,
self.3 / _rhs.3)
}
}
impl<T: Div<Output = T> + Copy> Vec4<T> {
pub fn div_scalar(self, _rhs: T) -> Self {
Vec4(self.0 / _rhs, self.1 / _rhs, self.2 / _rhs, self.3 / _rhs)
}
}
impl<T: Clamp<Elem = T> + Copy> Clamp for Vec4<T> {
type Elem = T;
fn clamp(self, min: T, max: T) -> Self {
Vec4(self.0.clamp(min, max),
self.1.clamp(min, max),
self.2.clamp(min, max),
self.3.clamp(min, max))
}
}
impl<T> AsRef<Vec4<T>> for Vec4<T> {
fn as_ref(&self) -> &Self {
self
}
}
impl<T: PartialOrd> Vec4<T> {
pub fn any_less<O: AsRef<Self>>(&self, other: O) -> bool {
let o = other.as_ref();
self.0 < o.0 || self.1 < o.1 || self.2 < o.2 || self.3 < o.3
}
pub fn any_greater<O: AsRef<Self>>(&self, other: O) -> bool {
let o = other.as_ref();
self.0 > o.0 || self.1 > o.1 || self.2 > o.2 || self.3 > o.3
}
}
impl<T: PartialEq> PartialEq for Vec4<T> {
fn eq(&self, _rhs: &Self) -> bool {
self.0 == _rhs.0 && self.1 == _rhs.1 && self.2 == _rhs.2 && self.3 == _rhs.3
}
}
impl<T: PartialOrd> PartialOrd for Vec4<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.0 < other.0 && self.1 < other.1 && self.2 < other.2 && self.3 < other.3 {
Some(Ordering::Less)
} else if self.0 > other.0 && self.1 > other.1 && self.2 > other.2 && self.3 > other.3 {
Some(Ordering::Greater)
} else if self == other {
Some(Ordering::Equal)
} else {
None
}
}
}
impl<T: PartialOrd> Vec4<T> {
pub fn min(self, other: Self) -> Self {
Vec4(if self.0 < other.0 {
self.0
} else {
other.0
},
if self.1 < other.1 {
self.1
} else {
other.1
},
if self.2 < other.2 {
self.2
} else {
other.2
},
if self.3 < other.3 {
self.3
} else {
other.3
})
}
pub fn max(self, other: Self) -> Self {
Vec4(if self.0 > other.0 {
self.0
} else {
other.0
},
if self.1 > other.1 {
self.1
} else {
other.1
},
if self.2 > other.2 {
self.2
} else {
other.2
},
if self.3 > other.3 {
self.3
} else {
other.3
})
}
}
impl<T: Zero> Zero for Vec4<T> {
fn zero() -> Self {
Vec4(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
}
fn is_zero(&self) -> bool {
self.0.is_zero() && self.1.is_zero() && self.2.is_zero() && self.3.is_zero()
}
}
impl<T: Num + Copy> Vec4<T> {
pub fn dot(self, b: Self) -> T {
self.0 * b.0 + self.1 * b.1 + self.2 * b.2 + self.3 * b.3
}
pub fn length_sq(self) -> T {
self.dot(self)
}
pub fn project(self, other: Self) -> Self {
other.mul_scalar(self.dot(other) / other.length_sq())
}
}
impl<T: Float> Vec4<T> {
pub fn length(self) -> T {
self.length_sq().sqrt()
}
pub fn normalize(self) -> Option<Self> {
let length = self.length();
if length == T::zero() {
None
} else {
Some(self.div_scalar(length))
}
}
pub fn lerp(self, other: Self, t: T) -> Self {
self * other.mul_scalar(t)
}
}
swizzle!(x, Vec4);
swizzle!(y, Vec4);
swizzle!(z, Vec4);
swizzle!(w, Vec4);
swizzle!(2, Vec4);
swizzle!(3, Vec4);
swizzle!(4, Vec4);