#[cfg(feature = "num-traits")]
use num_traits::Float;
use crate::f32::{Vec2Mask, Vec3};
#[cfg(not(target_arch = "spirv"))]
use core::fmt;
use core::{f32, ops::*};
#[cfg(feature = "std")]
use std::iter::{Product, Sum};
const ZERO: Vec2 = const_vec2!([0.0; 2]);
const ONE: Vec2 = const_vec2!([1.0; 2]);
const X_AXIS: Vec2 = const_vec2!([1.0, 0.0]);
const Y_AXIS: Vec2 = const_vec2!([0.0, 1.0]);
#[derive(Clone, Copy, PartialEq, PartialOrd, Default)]
#[cfg_attr(not(target_arch = "spirv"), repr(C))]
#[cfg_attr(target_arch = "spirv", repr(simd))]
pub struct Vec2 {
pub x: f32,
pub y: f32,
}
#[inline]
pub fn vec2(x: f32, y: f32) -> Vec2 {
Vec2 { x, y }
}
impl Vec2 {
#[inline]
pub fn is_nan_mask(self) -> Vec2Mask {
Vec2Mask::new(self.x.is_nan(), self.y.is_nan())
}
#[inline]
pub fn signum(self) -> Self {
Self {
x: self.x.signum(),
y: self.y.signum(),
}
}
#[inline]
pub fn recip(self) -> Self {
Self {
x: self.x.recip(),
y: self.y.recip(),
}
}
#[inline]
pub fn lerp(self, other: Self, s: f32) -> Self {
self + ((other - self) * s)
}
#[inline]
pub fn is_normalized(self) -> bool {
is_normalized!(self)
}
#[inline]
pub fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite()
}
#[inline]
pub fn is_nan(self) -> bool {
self.x.is_nan() || self.y.is_nan()
}
#[inline]
pub fn abs_diff_eq(self, other: Self, max_abs_diff: f32) -> bool {
abs_diff_eq!(self, other, max_abs_diff)
}
#[inline]
pub fn new(x: f32, y: f32) -> Vec2 {
Vec2 { x, y }
}
#[inline]
pub const fn zero() -> Vec2 {
ZERO
}
#[inline]
pub const fn one() -> Vec2 {
ONE
}
#[inline]
pub const fn unit_x() -> Vec2 {
X_AXIS
}
#[inline]
pub const fn unit_y() -> Vec2 {
Y_AXIS
}
#[inline]
pub fn splat(v: f32) -> Vec2 {
Self { x: v, y: v }
}
#[inline]
pub fn extend(self, z: f32) -> Vec3 {
Vec3::new(self.x, self.y, z)
}
#[inline]
pub fn dot(self, other: Vec2) -> f32 {
(self.x * other.x) + (self.y * other.y)
}
#[inline]
pub fn length(self) -> f32 {
self.dot(self).sqrt()
}
#[inline]
pub fn length_squared(self) -> f32 {
self.dot(self)
}
#[inline]
pub fn length_recip(self) -> f32 {
self.length().recip()
}
#[inline]
pub fn distance(self, other: Vec2) -> f32 {
(self - other).length()
}
#[inline]
pub fn distance_squared(self, other: Vec2) -> f32 {
(self - other).length_squared()
}
#[inline]
pub fn normalize(self) -> Vec2 {
self * self.length_recip()
}
#[inline]
pub fn min(self, other: Vec2) -> Vec2 {
Self {
x: self.x.min(other.x),
y: self.y.min(other.y),
}
}
#[inline]
pub fn max(self, other: Vec2) -> Vec2 {
Self {
x: self.x.max(other.x),
y: self.y.max(other.y),
}
}
#[inline]
pub fn min_element(self) -> f32 {
self.x.min(self.y)
}
#[inline]
pub fn max_element(self) -> f32 {
self.x.max(self.y)
}
#[inline]
pub fn cmpeq(self, other: Vec2) -> Vec2Mask {
Vec2Mask::new(self.x.eq(&other.x), self.y.eq(&other.y))
}
#[inline]
pub fn cmpne(self, other: Vec2) -> Vec2Mask {
Vec2Mask::new(self.x.ne(&other.x), self.y.ne(&other.y))
}
#[inline]
pub fn cmpge(self, other: Vec2) -> Vec2Mask {
Vec2Mask::new(self.x.ge(&other.x), self.y.ge(&other.y))
}
#[inline]
pub fn cmpgt(self, other: Vec2) -> Vec2Mask {
Vec2Mask::new(self.x.gt(&other.x), self.y.gt(&other.y))
}
#[inline]
pub fn cmple(self, other: Vec2) -> Vec2Mask {
Vec2Mask::new(self.x.le(&other.x), self.y.le(&other.y))
}
#[inline]
pub fn cmplt(self, other: Vec2) -> Vec2Mask {
Vec2Mask::new(self.x.lt(&other.x), self.y.lt(&other.y))
}
#[inline]
pub fn from_slice_unaligned(slice: &[f32]) -> Self {
Self {
x: slice[0],
y: slice[1],
}
}
#[inline]
pub fn write_to_slice_unaligned(self, slice: &mut [f32]) {
slice[0] = self.x;
slice[1] = self.y;
}
#[inline]
pub fn abs(self) -> Self {
Self {
x: self.x.abs(),
y: self.y.abs(),
}
}
#[inline]
pub fn round(self) -> Self {
Self {
x: self.x.round(),
y: self.y.round(),
}
}
#[inline]
pub fn floor(self) -> Self {
Self {
x: self.x.floor(),
y: self.y.floor(),
}
}
#[inline]
pub fn ceil(self) -> Self {
Self {
x: self.x.ceil(),
y: self.y.ceil(),
}
}
#[inline]
pub fn exp(self) -> Self {
Self {
x: self.x.exp(),
y: self.y.exp(),
}
}
#[inline]
pub fn powf(self, n: f32) -> Self {
Self {
x: self.x.powf(n),
y: self.y.powf(n),
}
}
#[inline]
pub fn perp(self) -> Self {
Self {
x: -self.y,
y: self.x,
}
}
#[inline]
pub fn perp_dot(self, other: Vec2) -> f32 {
(self.x * other.y) - (self.y * other.x)
}
#[inline]
pub fn angle_between(self, other: Self) -> f32 {
let angle = crate::f32::funcs::scalar_acos(
self.dot(other) / (self.dot(self) * other.dot(other)).sqrt(),
);
if self.perp_dot(other) < 0.0 {
-angle
} else {
angle
}
}
}
#[cfg(not(target_arch = "spirv"))]
impl fmt::Display for Vec2 {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}, {}]", self.x, self.y)
}
}
impl Div<Vec2> for Vec2 {
type Output = Self;
#[inline]
fn div(self, other: Vec2) -> Self {
Self {
x: self.x / other.x,
y: self.y / other.y,
}
}
}
impl DivAssign<Vec2> for Vec2 {
#[inline]
fn div_assign(&mut self, other: Vec2) {
self.x /= other.x;
self.y /= other.y;
}
}
impl Div<f32> for Vec2 {
type Output = Self;
#[inline]
fn div(self, other: f32) -> Self {
Self {
x: self.x / other,
y: self.y / other,
}
}
}
impl DivAssign<f32> for Vec2 {
#[inline]
fn div_assign(&mut self, other: f32) {
self.x /= other;
self.y /= other;
}
}
impl Div<Vec2> for f32 {
type Output = Vec2;
#[inline]
fn div(self, other: Vec2) -> Vec2 {
Vec2 {
x: self / other.x,
y: self / other.y,
}
}
}
impl Mul<Vec2> for Vec2 {
type Output = Self;
#[inline]
fn mul(self, other: Vec2) -> Self {
Self {
x: self.x * other.x,
y: self.y * other.y,
}
}
}
impl MulAssign<Vec2> for Vec2 {
#[inline]
fn mul_assign(&mut self, other: Vec2) {
self.x *= other.x;
self.y *= other.y;
}
}
impl Mul<f32> for Vec2 {
type Output = Self;
#[inline]
fn mul(self, other: f32) -> Self {
Self {
x: self.x * other,
y: self.y * other,
}
}
}
impl MulAssign<f32> for Vec2 {
#[inline]
fn mul_assign(&mut self, other: f32) {
self.x *= other;
self.y *= other;
}
}
impl Mul<Vec2> for f32 {
type Output = Vec2;
#[inline]
fn mul(self, other: Vec2) -> Vec2 {
Vec2 {
x: self * other.x,
y: self * other.y,
}
}
}
impl Add for Vec2 {
type Output = Self;
#[inline]
fn add(self, other: Self) -> Self {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl AddAssign for Vec2 {
#[inline]
fn add_assign(&mut self, other: Self) {
self.x += other.x;
self.y += other.y;
}
}
impl Sub for Vec2 {
type Output = Self;
#[inline]
fn sub(self, other: Vec2) -> Self {
Self {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
impl SubAssign for Vec2 {
#[inline]
fn sub_assign(&mut self, other: Vec2) {
self.x -= other.x;
self.y -= other.y;
}
}
impl Neg for Vec2 {
type Output = Self;
#[inline]
fn neg(self) -> Self {
Self {
x: -self.x,
y: -self.y,
}
}
}
impl AsRef<[f32; 2]> for Vec2 {
#[inline]
fn as_ref(&self) -> &[f32; 2] {
unsafe { &*(self as *const Vec2 as *const [f32; 2]) }
}
}
impl AsMut<[f32; 2]> for Vec2 {
#[inline]
fn as_mut(&mut self) -> &mut [f32; 2] {
unsafe { &mut *(self as *mut Vec2 as *mut [f32; 2]) }
}
}
#[cfg(not(target_arch = "spirv"))]
impl fmt::Debug for Vec2 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_tuple("Vec2")
.field(&self.x)
.field(&self.y)
.finish()
}
}
impl Index<usize> for Vec2 {
type Output = f32;
#[inline]
fn index(&self, index: usize) -> &Self::Output {
&self.as_ref()[index]
}
}
impl IndexMut<usize> for Vec2 {
#[inline]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.as_mut()[index]
}
}
impl From<(f32, f32)> for Vec2 {
#[inline]
fn from(t: (f32, f32)) -> Self {
Self { x: t.0, y: t.1 }
}
}
impl From<Vec2> for (f32, f32) {
#[inline]
fn from(v: Vec2) -> Self {
(v.x, v.y)
}
}
impl From<[f32; 2]> for Vec2 {
#[inline]
fn from(a: [f32; 2]) -> Self {
Self { x: a[0], y: a[1] }
}
}
impl From<Vec2> for [f32; 2] {
#[inline]
fn from(v: Vec2) -> Self {
[v.x, v.y]
}
}
#[cfg(feature = "std")]
impl<'a> Sum<&'a Self> for Vec2 {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(ZERO, |a, &b| Self::add(a, b))
}
}
#[cfg(feature = "std")]
impl<'a> Product<&'a Self> for Vec2 {
fn product<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Self>,
{
iter.fold(ONE, |a, &b| Self::mul(a, b))
}
}