use crate::point::{p2, p3}; use crate::quaternion::Quat; use crate::Point; use std::ops::*; pub trait InnerSpace: std::fmt::Debug + Copy + Clone + Neg + Mul + Div + Add + Sub { fn dot(&self, other: &Self) -> f32; fn dist(&self, other: &Self) -> f32; fn angle(&self, other: &Self) -> f32; fn length(&self) -> f32; fn normalize(&self) -> Self; fn normalize_mut(&mut self); fn project_onto(&self, other: &Self) -> Self; fn reflect(&self, normal: &Self) -> Self; fn lerp(&self, other: &Self, t: f32) -> Self; fn to_point(&self) -> impl Point; } // ################################################## // # VECTOR 2D # // ################################################## /// Representation of a 2D vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v2 { x: f32, y: f32, } impl v2 { /// The unit vector along the x-axis. pub const X: v2 = v2 { x: 1.0, y: 0.0 }; /// The unit vector along the y-axis. pub const Y: v2 = v2 { x: 0.0, y: 1.0 }; /// The zero vector. pub const ZERO: v2 = v2 { x: 0.0, y: 0.0 }; /// Creates a new vector with the given components. pub const fn new(x: f32, y: f32) -> Self { v2 { x, y } } /// Creates a new vector from a point. pub fn from_point(p: p2) -> Self { Self { x: p.x(), y: p.y() } } /// Gets the x-component of the vector. pub fn x(&self) -> f32 { self.x } /// Gets the y-component of the vector. pub fn y(&self) -> f32 { self.y } /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: f32) { self.x = new_x; } /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: f32) { self.y = new_y; } } impl Add for v2 { type Output = v2; fn add(self, other: v2) -> v2 { v2 { x: self.x + other.x, y: self.y + other.y, } } } impl AddAssign for v2 { fn add_assign(&mut self, other: v2) { self.x += other.x; self.y += other.y; } } impl Sub for v2 { type Output = v2; fn sub(self, other: v2) -> v2 { v2 { x: self.x - other.x, y: self.y - other.y, } } } impl SubAssign for v2 { fn sub_assign(&mut self, other: v2) { self.x -= other.x; self.y -= other.y; } } impl Neg for v2 { type Output = Self; fn neg(self) -> Self::Output { Self { x: -self.x, y: -self.y, } } } impl Mul for v2 { type Output = v2; fn mul(self, other: f32) -> v2 { v2 { x: self.x * other, y: self.y * other, } } } impl Mul for f32 { type Output = v2; fn mul(self, other: v2) -> v2 { v2 { x: self * other.x, y: self * other.y, } } } impl Div for v2 { type Output = v2; fn div(self, other: f32) -> v2 { v2 { x: self.x / other, y: self.y / other, } } } impl Into<[f32; 2]> for v2 { fn into(self) -> [f32; 2] { [self.x, self.y] } } impl Into for [f32; 2] { fn into(self) -> v2 { v2 { x: self[0], y: self[1], } } } /// Representation of a 2D integer vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v2i { x: i64, y: i64, } impl v2i { /// The unit vector in the x direction. pub const X: v2i = v2i { x: 1, y: 0 }; /// The unit vector in the y direction. pub const Y: v2i = v2i { x: 0, y: 1 }; /// The zero vector. pub const ZERO: v2i = v2i { x: 0, y: 0 }; /// Creates a new vector with the given components. pub const fn new(x: i64, y: i64) -> Self { v2i { x, y } } /// Creates a new vector from a point. pub fn from_point(p: p2) -> Self { Self { x: p.x() as i64, y: p.y() as i64, } } /// Creates a 2D point from the vector. pub fn as_point(&self) -> p2 { p2::new(self.x as f32, self.y as f32) } /// Creates a integer 2D vector from a floating point 2D vector. pub fn from_vec2(v: v2) -> Self { Self { x: v.x as i64, y: v.y as i64, } } /// Creates a floating point 2D vector from the integer vector. pub fn as_vec2(&self) -> v2 { v2 { x: self.x as f32, y: self.y as f32, } } /// Gets the x component of the vector. pub fn x(&self) -> i64 { self.x } /// Gets the y component of the vector. pub fn y(&self) -> i64 { self.y } /// Sets the x component of the vector. pub fn set_x(&mut self, new_x: i64) { self.x = new_x; } /// Sets the y component of the vector. pub fn set_y(&mut self, new_y: i64) { self.y = new_y; } /// Gets the length of the vector. pub fn length(&self) -> i64 { ((self.x * self.x + self.y * self.y) as f32).sqrt() as i64 } /// Calculates the normalized version of the vector. pub fn normalize(&self) -> Self { let factor = 1.0 / self.length() as f32; v2i { x: (factor * self.x as f32) as i64, y: (factor * self.y as f32) as i64, } } /// Swizzles the vector components. /// (x,y) -> (x,x) pub fn xx(&self) -> Self { Self { x: self.x, y: self.x, } } /// Swizzles the vector components. /// (x,y) -> (x,y) pub fn xy(&self) -> Self { Self { x: self.x, y: self.y, } } /// Swizzles the vector components. /// (x,y) -> (y,x) pub fn yx(&self) -> Self { Self { x: self.y, y: self.x, } } /// Swizzles the vector components. /// (x,y) -> (y,y) pub fn yy(&self) -> Self { Self { x: self.y, y: self.y, } } } impl Add for v2i { type Output = v2i; fn add(self, other: v2i) -> v2i { v2i { x: self.x + other.x, y: self.y + other.y, } } } impl Add for v2 { type Output = v2; fn add(self, other: v2i) -> v2 { v2 { x: self.x + other.x as f32, y: self.y + other.y as f32, } } } impl Add for v2i { type Output = v2; fn add(self, other: v2) -> v2 { v2 { x: self.x as f32 + other.x, y: self.y as f32 + other.y, } } } impl AddAssign for v2i { fn add_assign(&mut self, other: v2i) { self.x += other.x; self.y += other.y; } } impl Sub for v2i { type Output = v2i; fn sub(self, other: v2i) -> v2i { v2i { x: self.x - other.x, y: self.y - other.y, } } } impl Sub for v2 { type Output = v2; fn sub(self, other: v2i) -> v2 { v2 { x: self.x - other.x as f32, y: self.y - other.y as f32, } } } impl Sub for v2i { type Output = v2; fn sub(self, other: v2) -> v2 { v2 { x: self.x as f32 - other.x, y: self.y as f32 - other.y, } } } impl SubAssign for v2i { fn sub_assign(&mut self, other: v2i) { self.x -= other.x; self.y -= other.y; } } impl Mul for v2i { type Output = v2i; fn mul(self, other: f32) -> v2i { v2i { x: self.x * other as i64, y: self.y * other as i64, } } } impl From for v2 { fn from(v: v2i) -> v2 { v2 { x: v.x as f32, y: v.y as f32, } } } impl From for v2i { fn from(v: v2) -> v2i { v2i { x: v.x as i64, y: v.y as i64, } } } impl Into<[i64; 2]> for v2i { fn into(self) -> [i64; 2] { [self.x, self.y] } } impl Into<[f32; 2]> for v2i { fn into(self) -> [f32; 2] { [self.x as f32, self.y as f32] } } // ################################################## // # VECTOR 3D # // ################################################## /// Representation of a 3D vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v3 { pub x: f32, pub y: f32, pub z: f32, } impl v3 { /// The unit vector along the x-axis. pub const X: v3 = v3 { x: 1.0, y: 0.0, z: 0.0, }; /// The unit vector along the y-axis. pub const Y: v3 = v3 { x: 0.0, y: 1.0, z: 0.0, }; /// The unit vector along the z-axis. pub const Z: v3 = v3 { x: 0.0, y: 0.0, z: 1.0, }; /// The zero vector. pub const ZERO: v3 = v3 { x: 0.0, y: 0.0, z: 0.0, }; /// Creates a new vector with the given components. pub const fn new(x: f32, y: f32, z: f32) -> Self { v3 { x, y, z } } /// Creates a new vector from a point. pub fn from_point(p: p3) -> Self { Self { x: p.x(), y: p.y(), z: p.z(), } } /// Creates a new point from a vector. pub fn as_point(&self) -> p3 { p3::new(self.x as f32, self.y as f32, self.z as f32) } /// Gets the x-component of the vector. pub fn x(&self) -> f32 { self.x } /// Gets the y-component of the vector. pub fn y(&self) -> f32 { self.y } /// Gets the z-component of the vector. pub fn z(&self) -> f32 { self.z } /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: f32) { self.x = new_x; } /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: f32) { self.y = new_y; } /// Sets the z-component of the vector. pub fn set_z(&mut self, new_z: f32) { self.z = new_z; } } impl Add for v3 { type Output = v3; fn add(self, other: v3) -> v3 { v3 { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z, } } } impl AddAssign for v3 { fn add_assign(&mut self, other: v3) { self.x += other.x; self.y += other.y; self.z += other.z; } } impl Sub for v3 { type Output = v3; fn sub(self, other: v3) -> v3 { v3 { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z, } } } impl SubAssign for v3 { fn sub_assign(&mut self, other: v3) { self.x -= other.x; self.y -= other.y; self.z -= other.z; } } impl Neg for v3 { type Output = v3; fn neg(self) -> v3 { v3 { x: -self.x, y: -self.y, z: -self.z, } } } impl Mul for v3 { type Output = v3; fn mul(self, other: f32) -> v3 { v3 { x: self.x * other, y: self.y * other, z: self.z * other, } } } impl Mul for f32 { type Output = v3; fn mul(self, other: v3) -> v3 { v3 { x: self * other.x, y: self * other.y, z: self * other.z, } } } impl Div for v3 { type Output = v3; fn div(self, other: f32) -> v3 { v3 { x: self.x / other, y: self.y / other, z: self.z / other, } } } impl Into for v3 { fn into(self) -> Quat { Quat::new(0.0, self) } } impl Into<[f32; 3]> for v3 { fn into(self) -> [f32; 3] { [self.x, self.y, self.z] } } impl Into for [f32; 3] { fn into(self) -> v3 { v3 { x: self[0], y: self[1], z: self[2], } } } /// Representation of a 3D integer vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v3i { pub x: i64, pub y: i64, pub z: i64, } impl v3i { /// The unit vector in the x-direction. pub const X: v3i = v3i { x: 1, y: 0, z: 0 }; /// The unit vector in the y-direction. pub const Y: v3i = v3i { x: 0, y: 1, z: 0 }; /// The unit vector in the z-direction. pub const Z: v3i = v3i { x: 0, y: 0, z: 1 }; /// The zero vector. pub const ZERO: v3i = v3i { x: 0, y: 0, z: 0 }; /// Creates a new vector with the given components. pub const fn new(x: i64, y: i64, z: i64) -> Self { v3i { x, y, z } } /// Creates a new vector from a point. pub fn from_point(p: p3) -> Self { Self { x: p.x() as i64, y: p.y() as i64, z: p.z() as i64, } } /// Gets the x-component of the vector. pub fn x(&self) -> i64 { self.x } /// Gets the y-component of the vector. pub fn y(&self) -> i64 { self.y } /// Gets the z-component of the vector. pub fn z(&self) -> i64 { self.z } /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: i64) { self.x = new_x; } /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: i64) { self.y = new_y; } /// Sets the z-component of the vector. pub fn set_z(&mut self, new_z: i64) { self.z = new_z; } /// Calculates the length of the vector. pub fn length(&self) -> i64 { ((self.x * self.x + self.y * self.y + self.z * self.z) as f32).sqrt() as i64 } /// Normalizes the vector. pub fn normalize(&self) -> Self { let factor = 1 / self.length(); v3i { x: factor * self.x, y: factor * self.y, z: factor * self.z, } } } impl Add for v3i { type Output = v3i; fn add(self, other: v3i) -> v3i { v3i { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z, } } } impl Add for v3 { type Output = v3; fn add(self, other: v3i) -> v3 { v3 { x: self.x + other.x as f32, y: self.y + other.y as f32, z: self.z + other.z as f32, } } } impl Add for v3i { type Output = v3; fn add(self, other: v3) -> v3 { v3 { x: self.x as f32 + other.x, y: self.y as f32 + other.y, z: self.z as f32 + other.z, } } } impl AddAssign for v3i { fn add_assign(&mut self, other: v3i) { self.x += other.x; self.y += other.y; self.z += other.z; } } impl Sub for v3i { type Output = v3i; fn sub(self, other: v3i) -> v3i { v3i { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z, } } } impl Sub for v3 { type Output = v3; fn sub(self, other: v3i) -> v3 { v3 { x: self.x - other.x as f32, y: self.y - other.y as f32, z: self.z - other.z as f32, } } } impl Sub for v3i { type Output = v3; fn sub(self, other: v3) -> v3 { v3 { x: self.x as f32 - other.x, y: self.y as f32 - other.y, z: self.z as f32 - other.z, } } } impl SubAssign for v3i { fn sub_assign(&mut self, other: v3i) { self.x -= other.x; self.y -= other.y; } } impl Mul for v3i { type Output = v3i; fn mul(self, other: f32) -> v3i { v3i { x: self.x * other as i64, y: self.y * other as i64, z: self.z * other as i64, } } } impl From for v3 { fn from(v: v3i) -> v3 { v3 { x: v.x as f32, y: v.y as f32, z: v.z as f32, } } } impl From for v3i { fn from(v: v3) -> v3i { v3i { x: v.x as i64, y: v.y as i64, z: v.z as i64, } } } // ################################################## // # VECTOR 4D # // ################################################## /// Representation of a 4D vector #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[allow(non_camel_case_types)] pub struct v4 { x: f32, y: f32, z: f32, w: f32, } impl v4 { /// The unit vector along the x-axis. pub const X: v4 = v4 { x: 1.0, y: 0.0, z: 0.0, w: 0.0, }; /// The unit vector along the y-axis. pub const Y: v4 = v4 { x: 0.0, y: 1.0, z: 0.0, w: 0.0, }; /// The unit vector along the z-axis. pub const Z: v4 = v4 { x: 0.0, y: 0.0, z: 1.0, w: 0.0, }; /// The unit vector along the w-axis. pub const W: v4 = v4 { x: 0.0, y: 0.0, z: 0.0, w: 1.0, }; /// The zero vector. pub const ZERO: v4 = v4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0, }; /// Creates a new vector with the given components. pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self { v4 { x, y, z, w } } /// Gets the x-component of the vector. pub fn x(&self) -> f32 { self.x } /// Gets the y-component of the vector. pub fn y(&self) -> f32 { self.y } /// Gets the z-component of the vector. pub fn z(&self) -> f32 { self.z } /// Gets the w-component of the vector. pub fn w(&self) -> f32 { self.w } /// Sets the x-component of the vector. pub fn set_x(&mut self, new_x: f32) { self.x = new_x; } /// Sets the y-component of the vector. pub fn set_y(&mut self, new_y: f32) { self.y = new_y; } /// Sets the z-component of the vector. pub fn set_z(&mut self, new_z: f32) { self.z = new_z; } /// Sets the w-component of the vector. pub fn set_w(&mut self, new_w: f32) { self.w = new_w; } } impl Add for v4 { type Output = v4; fn add(self, other: v4) -> v4 { v4 { x: self.x + other.x, y: self.y + other.y, z: self.z + other.z, w: self.w + other.w, } } } impl AddAssign for v4 { fn add_assign(&mut self, other: v4) { self.x += other.x; self.y += other.y; self.z += other.z; self.w += other.w; } } impl Sub for v4 { type Output = v4; fn sub(self, other: v4) -> v4 { v4 { x: self.x - other.x, y: self.y - other.y, z: self.z - other.z, w: self.w - other.w, } } } impl SubAssign for v4 { fn sub_assign(&mut self, other: v4) { self.x -= other.x; self.y -= other.y; self.z -= other.z; self.w -= other.w; } } impl Neg for v4 { type Output = Self; fn neg(self) -> Self::Output { Self { x: -self.x, y: -self.y, z: -self.z, w: -self.w, } } } impl Mul for v4 { type Output = v4; fn mul(self, other: f32) -> v4 { v4 { x: self.x * other, y: self.y * other, z: self.z * other, w: self.w * other, } } } impl Mul for f32 { type Output = v4; fn mul(self, other: v4) -> v4 { v4 { x: self * other.x, y: self * other.y, z: self * other.z, w: self * other.w, } } } impl MulAssign for v4 { fn mul_assign(&mut self, other: f32) { self.x *= other; self.y *= other; self.z *= other; self.w *= other; } } impl Div for v4 { type Output = v4; fn div(self, other: f32) -> v4 { v4 { x: self.x / other, y: self.y / other, z: self.z / other, w: self.w / other, } } } impl Into<[f32; 4]> for v4 { fn into(self) -> [f32; 4] { [self.x, self.y, self.z, self.w] } } impl InnerSpace for v2 { fn dot(&self, other: &Self) -> f32 { self.x * other.x + self.y * other.y } fn dist(&self, other: &Self) -> f32 { v2 { x: other.x - self.x, y: other.y - self.y, } .length() } fn angle(&self, other: &Self) -> f32 { (self.dot(other) / (self.length() * other.length())).acos() } fn length(&self) -> f32 { (self.x * self.x + self.y * self.y).sqrt() } fn normalize(&self) -> Self { let factor = 1.0 / self.length(); v2 { x: factor * self.x, y: factor * self.y, } } fn normalize_mut(&mut self) { let factor = 1.0 / self.length(); self.x *= factor; self.y *= factor; } fn project_onto(&self, other: &Self) -> Self { let factor = self.dot(other) / other.dot(other); *other * factor } fn reflect(&self, normal: &Self) -> Self { *self - *normal * 2.0 * self.dot(normal) } fn lerp(&self, other: &Self, t: f32) -> Self { *self * (1.0 - t) + *other * t } fn to_point(&self) -> impl Point { p2::new(self.x, self.y) } } impl InnerSpace for v3 { fn dot(&self, other: &Self) -> f32 { self.x * other.x + self.y * other.y + self.z * other.z } fn dist(&self, other: &Self) -> f32 { v3 { x: other.x - self.x, y: other.y - self.y, z: other.z - self.z, } .length() } fn angle(&self, other: &Self) -> f32 { (self.dot(other) / (self.length() * other.length())).acos() } fn length(&self) -> f32 { (self.x * self.x + self.y * self.y + self.z * self.z).sqrt() } fn normalize(&self) -> Self { let factor = 1.0 / self.length(); v3 { x: factor * self.x, y: factor * self.y, z: factor * self.z, } } fn normalize_mut(&mut self) { let factor = 1.0 / self.length(); self.x *= factor; self.y *= factor; self.z *= factor; } fn project_onto(&self, other: &Self) -> Self { let factor = self.dot(other) / other.dot(other); *other * factor } fn reflect(&self, normal: &Self) -> Self { *self - *normal * 2.0 * self.dot(normal) } fn lerp(&self, other: &Self, t: f32) -> Self { *self * (1.0 - t) + *other * t } fn to_point(&self) -> impl Point { p3::new(self.x, self.y, self.z) } } impl InnerSpace for v4 { fn dot(&self, other: &Self) -> f32 { self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w } fn dist(&self, other: &Self) -> f32 { v4 { x: other.x - self.x, y: other.y - self.y, z: other.z - self.z, w: other.w - self.w, } .length() } fn angle(&self, other: &Self) -> f32 { (self.dot(other) / (self.length() * other.length())).acos() } fn length(&self) -> f32 { (self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w).sqrt() } fn normalize(&self) -> Self { let factor = 1.0 / self.length(); v4 { x: factor * self.x, y: factor * self.y, z: factor * self.z, w: factor * self.w, } } fn normalize_mut(&mut self) { let factor = 1.0 / self.length(); self.x *= factor; self.y *= factor; self.z *= factor; self.w *= factor; } fn project_onto(&self, other: &Self) -> Self { let factor = self.dot(other) / other.dot(other); *other * factor } fn reflect(&self, normal: &Self) -> Self { *self - *normal * 2.0 * self.dot(normal) } fn lerp(&self, other: &Self, t: f32) -> Self { *self * (1.0 - t) + *other * t } fn to_point(&self) -> impl Point { p3::new(self.x / self.w, self.y / self.w, self.z / self.w) } } macro_rules! generate_swizzles2 { ($VecType:ident, $($name:ident => ($a:ident, $b:ident)),* $(,)?) => { impl $VecType { $( pub fn $name(&self) -> Self { Self { x: self.$a, y: self.$b, } } )* } }; } macro_rules! generate_swizzles3 { ($VecType:ident, $($name:ident => ($a:ident, $b:ident, $c:ident)),* $(,)?) => { impl $VecType { $( pub fn $name(&self) -> Self { Self { x: self.$a, y: self.$b, z: self.$c } } )* } }; } macro_rules! generate_swizzles4 { ($VecType:ident, $($name:ident => ($a:ident, $b:ident, $c:ident, $d:ident)),* $(,)?) => { impl $VecType { $( pub fn $name(&self) -> Self { Self { x: self.$a, y: self.$b, z: self.$c, w: self.$d } } )* } }; } generate_swizzles2!(v2, xx => (x, x), xy => (x, y), yx => (y, x), yy => (y, y) ); generate_swizzles3!(v3, xxx => (x, x, x), xxy => (x, x, y), xxz => (x, x, z), xyx => (x, y, x), xyy => (x, y, y), xyz => (x, y, z), xzx => (x, z, x), xzy => (x, z, y), xzz => (x, z, z), yxx => (y, x, x), yxy => (y, x, y), yxz => (y, x, z), yyx => (y, y, x), yyy => (y, y, y), yyz => (y, y, z), yzx => (y, z, x), yzy => (y, z, y), yzz => (y, z, z), zxx => (z, x, x), zxy => (z, x, y), zxz => (z, x, z), zyx => (z, y, x), zyy => (z, y, y), zyz => (z, y, z), zzx => (z, z, x), zzy => (z, z, y), zzz => (z, z, z) ); generate_swizzles4!(v4, xxxx => (x, x, x, x), xxxy => (x, x, x, y), xxxz => (x, x, x, z), xxxw => (x, x, x, w), xxyx => (x, x, y, x), xxyy => (x, x, y, y), xxyz => (x, x, y, z), xxyw => (x, x, y, w), xxzx => (x, x, z, x), xxzy => (x, x, z, y), xxzz => (x, x, z, z), xxzw => (x, x, z, w), xxwx => (x, x, w, x), xxwy => (x, x, w, y), xxwz => (x, x, w, z), xxww => (x, x, w, w), xyxx => (x, y, x, x), xyxy => (x, y, x, y), xyxz => (x, y, x, z), xyxw => (x, y, x, w), xyyx => (x, y, y, x), xyyy => (x, y, y, y), xyyz => (x, y, y, z), xyyw => (x, y, y, w), xyzx => (x, y, z, x), xyzy => (x, y, z, y), xyzz => (x, y, z, z), xyzw => (x, y, z, w), xywx => (x, y, w, x), xywy => (x, y, w, y), xywz => (x, y, w, z), xyww => (x, y, w, w), xzxx => (x, z, x, x), xzxy => (x, z, x, y), xzxz => (x, z, x, z), xzxw => (x, z, x, w), xzyx => (x, z, y, x), xzyy => (x, z, y, y), xzyz => (x, z, y, z), xzyw => (x, z, y, w), xzzx => (x, z, z, x), xzzy => (x, z, z, y), xzzz => (x, z, z, z), xzzw => (x, z, z, w), xzwx => (x, z, w, x), xzwy => (x, z, w, y), xzwz => (x, z, w, z), xzww => (x, z, w, w), xwxx => (x, w, x, x), xwxy => (x, w, x, y), xwxz => (x, w, x, z), xwxw => (x, w, x, w), xwyx => (x, w, y, x), xwyy => (x, w, y, y), xwyz => (x, w, y, z), xwyw => (x, w, y, w), xwzx => (x, w, z, x), xwzy => (x, w, z, y), xwzz => (x, w, z, z), xwzw => (x, w, z, w), xwwx => (x, w, w, x), xwwy => (x, w, w, y), xwwz => (x, w, w, z), xwww => (x, w, w, w), yxxx => (y, x, x, x), yxxy => (y, x, x, y), yxxz => (y, x, x, z), yxxw => (y, x, x, w), yxyx => (y, x, y, x), yxyy => (y, x, y, y), yxyz => (y, x, y, z), yxyw => (y, x, y, w), yxzx => (y, x, z, x), yxzy => (y, x, z, y), yxzz => (y, x, z, z), yxzw => (y, x, z, w), yxwx => (y, x, w, x), yxwy => (y, x, w, y), yxwz => (y, x, w, z), yxww => (y, x, w, w), yyxx => (y, y, x, x), yyxy => (y, y, x, y), yyxz => (y, y, x, z), yyxw => (y, y, x, w), yyyx => (y, y, y, x), yyyy => (y, y, y, y), yyyz => (y, y, y, z), yyyw => (y, y, y, w), yyzx => (y, y, z, x), yyzy => (y, y, z, y), yyzz => (y, y, z, z), yyzw => (y, y, z, w), yywx => (y, y, w, x), yywy => (y, y, w, y), yywz => (y, y, w, z), yyww => (y, y, w, w) );