use crate::{Vector, Vector3D};
macro_rules! binary_op {
{ $t:ty, $trait_op:ident, $op:ident, $binop:tt, $trait_assign_op:ident, $assign_op:ident, $assign_binop:tt } => {
impl std::ops::$trait_op<$t> for $t {
type Output = Self; fn $op(self, other: Self) -> Self { Self(self.0 $binop other.0) }
}
impl std::ops::$trait_assign_op<$t> for $t {
fn $assign_op(&mut self, other: Self) { self.0 $assign_binop other.0; }
}
impl std::ops::$trait_op<f32> for $t {
type Output = Self; fn $op(self, other:f32) -> Self { Self(self.0 $binop other) }
}
impl std::ops::$trait_assign_op<f32> for $t {
fn $assign_op(&mut self, other:f32) { self.0 $assign_binop other; }
}
}
}
macro_rules! binary_op_n {
{ $t:ty, $trait_op:ident, $op:ident, $binop:tt, $trait_assign_op:ident, $assign_op:ident, $assign_binop:tt } => {
impl std::ops::$trait_op<$t> for $t {
type Output = Self; fn $op(self, other: Self) -> Self { Self(self.0 $binop other.0) }
}
impl std::ops::$trait_assign_op<$t> for $t {
fn $assign_op(&mut self, other: Self) { self.0 $assign_binop other.0; }
}
impl std::ops::$trait_op<f32> for $t {
type Output = Self; fn $op(self, other:f32) -> Self { Self(self.0 $binop Self::of_float(other).0) }
}
impl std::ops::$trait_assign_op<f32> for $t {
fn $assign_op(&mut self, other:f32) { self.0 $assign_binop Self::of_float(other).0; }
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct F32x4Vec4(core_simd::f32x4);
binary_op! { F32x4Vec4, Add, add, +, AddAssign, add_assign, += }
binary_op! { F32x4Vec4, Sub, sub, -, SubAssign, sub_assign, -= }
binary_op! { F32x4Vec4, Mul, mul, *, MulAssign, mul_assign, *= }
binary_op! { F32x4Vec4, Div, div, /, DivAssign, div_assign, /= }
impl std::convert::AsRef<[f32; 4]> for F32x4Vec4 {
fn as_ref(&self) -> &[f32; 4] {
unsafe { std::mem::transmute::<&core_simd::f32x4, &[f32; 4]>(&self.0) }
}
}
impl std::convert::AsRef<[f32]> for F32x4Vec4 {
fn as_ref(&self) -> &[f32] {
unsafe { std::mem::transmute::<&core_simd::f32x4, &[f32; 4]>(&self.0) }
}
}
impl std::convert::AsMut<[f32; 4]> for F32x4Vec4 {
fn as_mut(&mut self) -> &mut [f32; 4] {
unsafe { std::mem::transmute::<&mut core_simd::f32x4, &mut [f32; 4]>(&mut self.0) }
}
}
impl std::convert::AsMut<[f32]> for F32x4Vec4 {
fn as_mut(&mut self) -> &mut [f32] {
unsafe { std::mem::transmute::<&mut core_simd::f32x4, &mut [f32; 4]>(&mut self.0) }
}
}
impl std::default::Default for F32x4Vec4 {
fn default() -> Self {
Self(core_simd::f32x4::default())
}
}
impl std::ops::Index<usize> for F32x4Vec4 {
type Output = f32;
fn index(&self, index: usize) -> &f32 {
let x: &[f32] = self.as_ref();
&x[index]
}
}
impl std::ops::IndexMut<usize> for F32x4Vec4 {
fn index_mut(&mut self, index: usize) -> &mut f32 {
let x: &mut [f32] = self.as_mut();
&mut x[index]
}
}
impl std::ops::Neg for F32x4Vec4 {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl Vector<f32, 4> for F32x4Vec4 {
fn from_array(data: [f32; 4]) -> Self {
Self(core_simd::f32x4::from_array(data))
}
fn zero() -> Self {
Self(core_simd::f32x4::splat(0.))
}
fn is_zero(&self) -> bool {
self.0.lanes_eq(core_simd::f32x4::splat(0.)).all()
}
fn set_zero(&mut self) {
self.0 = core_simd::f32x4::splat(0.)
}
fn mix(&self, other: &Self, t: f32) -> Self {
Self(self.0 * (1.0 - t) + other.0 * t)
}
fn reduce_sum(&self) -> f32 {
self.0.horizontal_sum()
}
fn dot(&self, other: &Self) -> f32 {
(self.0 * other.0).horizontal_sum()
}
}
#[derive(Clone, Copy, Debug)]
pub struct F32x4Vec3(core_simd::f32x4);
binary_op_n! { F32x4Vec3, Add, add, +, AddAssign, add_assign, += }
binary_op_n! { F32x4Vec3, Sub, sub, -, SubAssign, sub_assign, -= }
binary_op_n! { F32x4Vec3, Mul, mul, *, MulAssign, mul_assign, *= }
binary_op! { F32x4Vec3, Div, div, /, DivAssign, div_assign, /= }
impl std::convert::AsRef<[f32; 3]> for F32x4Vec3 {
fn as_ref(&self) -> &[f32; 3] {
unsafe { std::mem::transmute::<&core_simd::f32x4, &[f32; 3]>(&self.0) }
}
}
impl std::convert::AsRef<[f32]> for F32x4Vec3 {
fn as_ref(&self) -> &[f32] {
unsafe { std::mem::transmute::<&core_simd::f32x4, &[f32; 3]>(&self.0) }
}
}
impl std::convert::AsMut<[f32; 3]> for F32x4Vec3 {
fn as_mut(&mut self) -> &mut [f32; 3] {
unsafe { std::mem::transmute::<&mut core_simd::f32x4, &mut [f32; 3]>(&mut self.0) }
}
}
impl std::convert::AsMut<[f32]> for F32x4Vec3 {
fn as_mut(&mut self) -> &mut [f32] {
unsafe { std::mem::transmute::<&mut core_simd::f32x4, &mut [f32; 3]>(&mut self.0) }
}
}
impl std::default::Default for F32x4Vec3 {
fn default() -> Self {
Self(core_simd::f32x4::default())
}
}
impl std::ops::Index<usize> for F32x4Vec3 {
type Output = f32;
fn index(&self, index: usize) -> &f32 {
let x: &[f32] = self.as_ref();
&x[index]
}
}
impl std::ops::IndexMut<usize> for F32x4Vec3 {
fn index_mut(&mut self, index: usize) -> &mut f32 {
let x: &mut [f32] = self.as_mut();
&mut x[index]
}
}
impl std::ops::Neg for F32x4Vec3 {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl F32x4Vec3 {
fn of_float(f: f32) -> Self {
Self::from_array([f, f, f])
}
}
impl Vector<f32, 3> for F32x4Vec3 {
fn from_array(data: [f32; 3]) -> Self {
Self(core_simd::f32x4::from_array([
data[0], data[1], data[2], 0.,
]))
}
fn zero() -> Self {
Self(core_simd::f32x4::splat(0.))
}
fn is_zero(&self) -> bool {
self.0.lanes_eq(core_simd::f32x4::splat(0.)).all()
}
fn set_zero(&mut self) {
self.0 = core_simd::f32x4::splat(0.)
}
fn mix(&self, other: &Self, t: f32) -> Self {
Self(self.0 * (1.0 - t) + other.0 * t)
}
fn reduce_sum(&self) -> f32 {
self.0.horizontal_sum()
}
fn dot(&self, other: &Self) -> f32 {
(self.0 * other.0).horizontal_sum()
}
}
#[derive(Clone, Copy, Debug)]
pub struct F32x4Vec2(core_simd::f32x4);
binary_op_n! { F32x4Vec2, Add, add, +, AddAssign, add_assign, += }
binary_op_n! { F32x4Vec2, Sub, sub, -, SubAssign, sub_assign, -= }
binary_op_n! { F32x4Vec2, Mul, mul, *, MulAssign, mul_assign, *= }
binary_op! { F32x4Vec2, Div, div, /, DivAssign, div_assign, /= }
impl std::convert::AsRef<[f32; 2]> for F32x4Vec2 {
fn as_ref(&self) -> &[f32; 2] {
unsafe { std::mem::transmute::<&core_simd::f32x4, &[f32; 2]>(&self.0) }
}
}
impl std::convert::AsRef<[f32]> for F32x4Vec2 {
fn as_ref(&self) -> &[f32] {
unsafe { std::mem::transmute::<&core_simd::f32x4, &[f32; 2]>(&self.0) }
}
}
impl std::convert::AsMut<[f32; 2]> for F32x4Vec2 {
fn as_mut(&mut self) -> &mut [f32; 2] {
unsafe { std::mem::transmute::<&mut core_simd::f32x4, &mut [f32; 2]>(&mut self.0) }
}
}
impl std::convert::AsMut<[f32]> for F32x4Vec2 {
fn as_mut(&mut self) -> &mut [f32] {
unsafe { std::mem::transmute::<&mut core_simd::f32x4, &mut [f32; 2]>(&mut self.0) }
}
}
impl std::default::Default for F32x4Vec2 {
fn default() -> Self {
Self(core_simd::f32x4::default())
}
}
impl std::ops::Index<usize> for F32x4Vec2 {
type Output = f32;
fn index(&self, index: usize) -> &f32 {
let x: &[f32] = self.as_ref();
&x[index]
}
}
impl std::ops::IndexMut<usize> for F32x4Vec2 {
fn index_mut(&mut self, index: usize) -> &mut f32 {
let x: &mut [f32] = self.as_mut();
&mut x[index]
}
}
impl std::ops::Neg for F32x4Vec2 {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl F32x4Vec2 {
fn of_float(f: f32) -> Self {
Self::from_array([f, f])
}
}
impl Vector<f32, 2> for F32x4Vec2 {
fn from_array(data: [f32; 2]) -> Self {
Self(core_simd::f32x4::from_array([data[0], data[1], 0., 0.]))
}
fn zero() -> Self {
Self(core_simd::f32x4::splat(0.))
}
fn is_zero(&self) -> bool {
self.0.lanes_eq(core_simd::f32x4::splat(0.)).all()
}
fn set_zero(&mut self) {
self.0 = core_simd::f32x4::splat(0.)
}
fn mix(&self, other: &Self, t: f32) -> Self {
Self(self.0 * (1.0 - t) + other.0 * t)
}
fn reduce_sum(&self) -> f32 {
self.0.horizontal_sum()
}
fn dot(&self, other: &Self) -> f32 {
(self.0 * other.0).horizontal_sum()
}
}
#[derive(Clone, Copy, Debug)]
pub struct F32x2Vec2(core_simd::f32x2);
binary_op! { F32x2Vec2, Add, add, +, AddAssign, add_assign, += }
binary_op! { F32x2Vec2, Sub, sub, -, SubAssign, sub_assign, -= }
binary_op! { F32x2Vec2, Mul, mul, *, MulAssign, mul_assign, *= }
binary_op! { F32x2Vec2, Div, div, /, DivAssign, div_assign, /= }
impl std::convert::AsRef<[f32; 2]> for F32x2Vec2 {
fn as_ref(&self) -> &[f32; 2] {
unsafe { std::mem::transmute::<&core_simd::f32x2, &[f32; 2]>(&self.0) }
}
}
impl std::convert::AsRef<[f32]> for F32x2Vec2 {
fn as_ref(&self) -> &[f32] {
unsafe { std::mem::transmute::<&core_simd::f32x2, &[f32; 2]>(&self.0) }
}
}
impl std::convert::AsMut<[f32; 2]> for F32x2Vec2 {
fn as_mut(&mut self) -> &mut [f32; 2] {
unsafe { std::mem::transmute::<&mut core_simd::f32x2, &mut [f32; 2]>(&mut self.0) }
}
}
impl std::convert::AsMut<[f32]> for F32x2Vec2 {
fn as_mut(&mut self) -> &mut [f32] {
unsafe { std::mem::transmute::<&mut core_simd::f32x2, &mut [f32; 2]>(&mut self.0) }
}
}
impl std::default::Default for F32x2Vec2 {
fn default() -> Self {
Self(core_simd::f32x2::default())
}
}
impl std::ops::Index<usize> for F32x2Vec2 {
type Output = f32;
fn index(&self, index: usize) -> &f32 {
let x: &[f32] = self.as_ref();
&x[index]
}
}
impl std::ops::IndexMut<usize> for F32x2Vec2 {
fn index_mut(&mut self, index: usize) -> &mut f32 {
let x: &mut [f32] = self.as_mut();
&mut x[index]
}
}
impl std::ops::Neg for F32x2Vec2 {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl Vector<f32, 2> for F32x2Vec2 {
fn from_array(data: [f32; 2]) -> Self {
Self(core_simd::f32x2::from_array(data))
}
fn zero() -> Self {
Self(core_simd::f32x2::splat(0.))
}
fn is_zero(&self) -> bool {
self.0.lanes_eq(core_simd::f32x2::splat(0.)).all()
}
fn set_zero(&mut self) {
self.0 = core_simd::f32x2::splat(0.)
}
fn mix(&self, other: &Self, t: f32) -> Self {
Self(self.0 * (1.0 - t) + other.0 * t)
}
fn reduce_sum(&self) -> f32 {
self.0.horizontal_sum()
}
fn dot(&self, other: &Self) -> f32 {
(self.0 * other.0).horizontal_sum()
}
}