#![allow(non_snake_case)]

use std::ops::{Add, Sub, Mul, Div};

#[derive(Debug)]
pub struct Vector4D {
    pub X: f64,
    pub Y: f64,
    pub Z: f64,
    pub T: f64,
}

impl Vector4D {
    pub fn New(&self, nx: f64, ny: f64, nz: f64, nt: f64) -> Vector4D {
        Vector4D {
            X: nx,
            Y: ny,
            Z: nz,
            T: nt,
        }
    }

    pub fn Magnitude(&self) -> f64 {
        (((self.X * self.X) + (self.Y * self.Y) + (self.Z * self.Z) + (self.T * self.T))).sqrt()
    }

    pub fn Normalize(&mut self) {
        let temp_mag: f64 = self.Magnitude();
        self.X = self.X / temp_mag;
        self.Y = self.Y / temp_mag;
        self.Z = self.Z / temp_mag;
        self.T = self.T / temp_mag;
    }
}

impl Add for Vector4D {
    type Output = Vector4D;

    fn add(self, rhs: Vector4D) -> Vector4D {
        Vector4D {
            X: self.X + rhs.X,
            Y: self.Y + rhs.Y,
            Z: self.Z + rhs.Z,
            T: self.T + rhs.T,
        }
    }
}

impl Sub for Vector4D {
    type Output = Vector4D;

    fn sub(self, rhs: Vector4D) -> Vector4D {
        Vector4D {
            X: self.X - rhs.X,
            Y: self.Y - rhs.Y,
            Z: self.Z - rhs.Z,
            T: self.T - rhs.T,
        }
    }
}

impl Mul for Vector4D {
    type Output = Vector4D;

    fn mul(self, rhs: Vector4D) -> Vector4D {
        Vector4D {
            X: self.X * rhs.X,
            Y: self.Y * rhs.Y,
            Z: self.Z * rhs.Z,
            T: self.T * rhs.T,
        }
    }
}

impl Div for Vector4D {
    type Output = Vector4D;

    fn div(self, rhs: Vector4D) -> Vector4D {
        Vector4D {
            X: self.X / rhs.X,
            Y: self.Y / rhs.Y,
            Z: self.Z / rhs.Z,
            T: self.T / rhs.T,
        }
    }
}
