// High-performance 3D and 4D vector algebra for optical polarizations.

///|
/// 3D Double Vector
pub struct Vector3D {
  x : Double
  y : Double
  z : Double
} derive(Debug, Eq)

///|
/// Create 3D Vector
pub fn Vector3D::new(x : Double, y : Double, z : Double) -> Vector3D {
  { x, y, z }
}

///|
/// Zero 3D Vector
pub fn Vector3D::zero() -> Vector3D {
  { x: 0.0, y: 0.0, z: 0.0 }
}

///|
/// Dot product of two 3D vectors
pub fn dot_product_3d(v1 : Vector3D, v2 : Vector3D) -> Double {
  v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
}

///|
/// Cross product of two 3D vectors
pub fn cross_product_3d(v1 : Vector3D, v2 : Vector3D) -> Vector3D {
  {
    x: v1.y * v2.z - v1.z * v2.y,
    y: v1.z * v2.x - v1.x * v2.z,
    z: v1.x * v2.y - v1.y * v2.x,
  }
}

///|
/// Magnitude of 3D vector
pub fn magnitude_3d(v : Vector3D) -> Double {
  @math.pow(v.x * v.x + v.y * v.y + v.z * v.z, 0.5)
}

///|
/// Normalize 3D vector to unit length
pub fn normalize_3d(v : Vector3D) -> Vector3D {
  let mag = magnitude_3d(v)
  if mag == 0.0 {
    Vector3D::zero()
  } else {
    { x: v.x / mag, y: v.y / mag, z: v.z / mag }
  }
}

///|
/// 4D Double Vector
pub struct Vector4D {
  v0 : Double
  v1 : Double
  v2 : Double
  v3 : Double
} derive(Debug, Eq)

///|
/// Create 4D Vector
pub fn Vector4D::new(
  v0 : Double,
  v1 : Double,
  v2 : Double,
  v3 : Double,
) -> Vector4D {
  { v0, v1, v2, v3 }
}

///|
/// Dot product of two 4D vectors
pub fn dot_product_4d(a : Vector4D, b : Vector4D) -> Double {
  a.v0 * b.v0 + a.v1 * b.v1 + a.v2 * b.v2 + a.v3 * b.v3
}