use core::f32;
use std::{
ops::{Add, Div, Mul, Sub},
slice::from_raw_parts,
};
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]
pub struct Vector {
x: f32,
y: f32,
z: f32,
w: f32,
}
impl Add for Vector {
type Output = Vector;
#[inline(always)]
fn add(self, rhs: Self) -> Self {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
w: self.w + rhs.w,
}
}
}
impl Default for Vector {
#[inline(always)]
fn default() -> Self {
Self {
x: 0f32,
y: 0f32,
z: 0f32,
w: 0f32,
}
}
}
impl Div for Vector {
type Output = Vector;
#[inline(always)]
fn div(self, rhs: Self) -> Self {
Self {
x: self.x / rhs.x,
y: self.y / rhs.y,
z: self.z / rhs.z,
w: self.w / rhs.w,
}
}
}
impl Div<f32> for Vector {
type Output = Vector;
#[inline(always)]
fn div(self, rhs: f32) -> Self {
Self {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
w: self.w / rhs,
}
}
}
impl Mul for Vector {
type Output = Vector;
#[inline(always)]
fn mul(self, rhs: Self) -> Self {
Self {
x: self.x * rhs.x,
y: self.y * rhs.y,
z: self.z * rhs.z,
w: self.w * rhs.w,
}
}
}
impl Mul<f32> for Vector {
type Output = Vector;
#[inline(always)]
fn mul(self, rhs: f32) -> Self {
Self {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
w: self.w * rhs,
}
}
}
impl Sub for Vector {
type Output = Vector;
#[inline(always)]
fn sub(self, rhs: Self) -> Self {
Self {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
w: self.w - rhs.w,
}
}
}
impl Vector {
#[inline(always)]
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self { Self { x, y, z, w } }
#[inline(always)]
pub fn x(self) -> f32 { self.x }
#[inline(always)]
pub fn y(self) -> f32 { self.y }
#[inline(always)]
pub fn z(self) -> f32 { self.z }
#[inline(always)]
pub fn w(self) -> f32 { self.w }
#[inline(always)]
pub fn set_x(&mut self, val: f32) { self.x = val }
#[inline(always)]
pub fn set_y(&mut self, val: f32) { self.y = val }
#[inline(always)]
pub fn set_z(&mut self, val: f32) { self.z = val }
#[inline(always)]
pub fn set_w(&mut self, val: f32) { self.w = val }
#[inline(always)]
pub fn shuffle<const X: u32, const Y: u32, const Z: u32, const W: u32>(self) -> Self {
let data = unsafe { from_raw_parts((&self as *const Vector) as *const f32, 4) };
Self {
x: data[X as usize],
y: data[Y as usize],
z: data[Z as usize],
w: data[W as usize],
}
}
#[inline(always)]
pub fn shuffle_merge<const X: u32, const Y: u32, const Z: u32, const W: u32>(vec1: Vector, vec2: Vector) -> Self {
let data = unsafe {
(
from_raw_parts((&vec1 as *const Vector) as *const f32, 4),
from_raw_parts((&vec2 as *const Vector) as *const f32, 4),
)
};
Self {
x: data.0[X as usize],
y: data.0[Y as usize],
z: data.1[Z as usize],
w: data.1[W as usize],
}
}
#[inline(always)]
pub fn get(self, idx: u8) -> f32 {
assert!(idx < 4, "Indexed out of Vector bounds");
unsafe { from_raw_parts((&self as *const Vector) as *const f32, 4)[idx as usize] }
}
#[inline(always)]
pub fn abs(self) -> Self {
Self {
x: self.x.abs(),
y: self.y.abs(),
z: self.z.abs(),
w: self.w.abs(),
}
}
#[inline(always)]
pub fn hsum(self) -> f32 { self.x + self.y + self.z + self.w }
#[inline(always)]
pub fn min(lhs: Self, rhs: Self) -> Self {
Self {
x: f32::min(lhs.x, rhs.x),
y: f32::min(lhs.y, rhs.y),
z: f32::min(lhs.z, rhs.z),
w: f32::min(lhs.w, rhs.w),
}
}
#[inline(always)]
pub fn max(lhs: Self, rhs: Self) -> Self {
Self {
x: f32::max(lhs.x, rhs.x),
y: f32::max(lhs.y, rhs.y),
z: f32::max(lhs.z, rhs.z),
w: f32::max(lhs.w, rhs.w),
}
}
#[inline(always)]
pub fn adj_add(lhs: Self, rhs: Self) -> Self {
Self {
x: lhs.x + lhs.y,
y: lhs.z + lhs.w,
z: rhs.x + rhs.y,
w: rhs.z + rhs.w,
}
}
#[inline(always)]
pub fn adj_sub(lhs: Self, rhs: Self) -> Self {
Self {
x: lhs.x - lhs.y,
y: lhs.z - lhs.w,
z: rhs.x - rhs.y,
w: rhs.z - rhs.w,
}
}
#[inline(always)]
pub fn add_sub(lhs: Self, rhs: Self) -> Self {
Self {
x: lhs.x - rhs.x,
y: lhs.y + rhs.y,
z: lhs.z - rhs.z,
w: lhs.w + rhs.w,
}
}
}