use std::fmt;
use num::{Float, Zero, Num};
use std::ops::{Deref, DerefMut};
use std::ops::{Add, Mul, Sub};
use crate::errors::VectorErrors;
use crate::matrix3x3::M33;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct V3<T>([T; 3]);
impl<T> V3<T> {
pub fn new(input: [T; 3]) -> V3<T> {
V3(input)
}
}
impl<T: Num + Copy> V3<T> {
pub fn zeros() -> V3<T> {
<V3<T> as Zero>::zero()
}
pub fn cross(&self, rhs: Self) -> Self {
let u_x = rhs[0];
let u_y = rhs[1];
let u_z = rhs[2];
Self::new([u_y * self[2] - u_z * self[1],
u_z * self[0] - u_x * self[2],
u_x * self[1] - u_y * self[0]])
}
}
impl<T: Float> V3<T> {
pub fn norm2(&self) -> T {
let a = self[0];
let b = self[1];
let c = self[2];
T::sqrt(a * a + b * b + c * c)
}
pub fn normalize(&self) -> Result<Self, VectorErrors> {
let n = self.norm2();
if n != T::zero() {
let mut result = Self::zeros();
for i in 0..self.len() {
result[i] = self[i] / n;
}
Ok(result)
} else {
Err(VectorErrors::Norm2IsZero)
}
}
}
impl<T: Num + Copy> Mul<T> for V3<T> {
type Output = V3<T>;
fn mul(self, rhs: T) -> Self::Output {
let a0 = self[0] * rhs;
let a1 = self[1] * rhs;
let a2 = self[2] * rhs;
V3::new([a0, a1, a2])
}
}
impl Mul<V3<f32>> for f32 {
type Output = V3<f32>;
fn mul(self, rhs: V3<f32>) -> Self::Output {
let a0 = rhs[0] * self;
let a1 = rhs[1] * self;
let a2 = rhs[2] * self;
V3::new([a0, a1, a2])
}
}
impl<T: Num + Copy> Mul for V3<T> {
type Output = T;
fn mul(self, rhs: Self) -> T {
let a1 = self[0];
let a2 = self[1];
let a3 = self[2];
let b1 = rhs[0];
let b2 = rhs[1];
let b3 = rhs[2];
a1 * b1 + a2 * b2 + a3 * b3
}
}
impl<T: Num + Copy> Mul<M33<T>> for V3<T> {
type Output = V3<T>;
fn mul(self, rhs: M33<T>) -> V3<T> {
let a11 = rhs[(0, 0)];
let a12 = rhs[(0, 1)];
let a13 = rhs[(0, 2)];
let a21 = rhs[(1, 0)];
let a22 = rhs[(1, 1)];
let a23 = rhs[(1, 2)];
let a31 = rhs[(2, 0)];
let a32 = rhs[(2, 1)];
let a33 = rhs[(2, 2)];
let v1 = self[0];
let v2 = self[1];
let v3 = self[2];
V3::new([
a11 * v1 + a12 * v2 + a13 * v3,
a21 * v1 + a22 * v2 + a23 * v3,
a31 * v1 + a32 * v2 + a33 * v3,
])
}
}
impl<T: Num + Copy> Sub for V3<T> {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
let v0 = self[0];
let v1 = self[1];
let v2 = self[2];
let a0 = rhs[0];
let a1 = rhs[1];
let a2 = rhs[2];
V3::new([v0 - a0, v1 - a1, v2 - a2])
}
}
impl<T: Num + Copy> Add for V3<T> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
let v1 = self[0];
let v2 = self[1];
let v3 = self[2];
let a1 = rhs[0];
let a2 = rhs[1];
let a3 = rhs[2];
V3::new([v1 + a1, v2 + a2, v3 + a3])
}
}
impl<T: Num + Copy> Zero for V3<T> {
fn zero() -> V3<T> {
V3::new([T::zero(); 3])
}
fn is_zero(&self) -> bool {
*self == V3::zero()
}
}
impl<T> Deref for V3<T> {
type Target = [T; 3];
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for V3<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> From<[T; 3]> for V3<T> {
fn from(data: [T; 3]) -> V3<T> {
V3(data)
}
}
impl<T: Num + fmt::Display> fmt::Display for V3<T> {
fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
println!("");
write!(dest, "[{0:^3.2} {1:^3.2} {2:^3.2}]\n", self[0], self[1], self[2])
}
}
#[cfg(test)]
mod vector3_test {
use crate::vector3::V3;
#[test]
fn create_vector3_test() {
let v = V3::new([1.0, 1.0, 1.0]);
assert_eq!(v[0], 1.0);
assert_eq!(v[1], 1.0);
assert_eq!(v[2], 1.0);
}
#[test]
fn zero_vector3_test() {
let result: V3<f64> = V3::zeros();
let expected = V3::new([0.0, 0.0, 0.0]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
#[test]
fn product_test() {
let v1 = V3::new([1.0, 2.0, 3.0]);
let v2 = V3::new([4.0, 5.0, 6.0]);
let result = v1 * v2;
let expected = 32.0;
assert_eq!(result, expected);
}
#[test]
fn add_test() {
let v1 = V3::new([1.0, 2.0, 3.0]);
let v2 = V3::new([4.0, 5.0, 6.0]);
let result = v1 + v2;
let expected = V3::new([5.0, 7.0, 9.0]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
#[test]
fn norm2_test() {
let v1 = V3::new([1.0, 2.0, 3.0]);
let expected = 3.7416573867739413;
let result = v1.norm2();
assert_eq!(result, expected);
}
#[test]
fn mul_const_rhs() {
let v = V3::new([1.0, 2.0, 3.0]);
let result = 2.0 * v;
let expected = V3::new([2.0, 4.0, 6.0]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
#[test]
fn mul_const() {
let v = V3::new([1.0, 2.0, 3.0]);
let result = v * 2.0;
let expected = V3::new([2.0, 4.0, 6.0]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
#[test]
fn sub_test() {
let v1 = V3::new([1.0, 1.0, 1.0]);
let v2 = V3::new([2.0, 3.0, 4.0]);
let result = v1 - v2;
let expected = V3::new([-1.0, -2.0, -3.0]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
#[test]
fn normalize_test() {
let result = V3::new([1.0, 1.0, 1.0]).normalize().unwrap();
let expected = V3::new([0.5773502691896258, 0.5773502691896258, 0.5773502691896258]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
#[test]
fn cross_test() {
let x = V3::new([1.0, 0.0, 0.0]);
let y = V3::new([0.0, 1.0, 0.0]);
let result = y.cross(x);
let expected = V3::new([0.0, 0.0, 1.0]);
assert_eq!(
&result[..],
&expected[..],
"\nExpected\n{:?}\nfound\n{:?}",
&result[..],
&expected[..]
);
}
}