vector-traits 0.6.2

Rust traits for 2D and 3D vector types.
Documentation
// SPDX-License-Identifier: MIT OR Apache-2.0
// Copyright (c) 2023, 2025 lacklustr@protonmail.com https://github.com/eadf

// This file is part of vector-traits.

use super::Aabb2A;
use crate::{macaw, prelude::*};
use std::{
    fmt,
    fmt::Debug,
    ops::{Add, AddAssign, Div, Index, IndexMut, Mul, Neg, Sub},
};

/// A wrapper around `Vec2` with zero runtime cost. Created to facilitate the implementation of the trait
/// `GenericVector3` for `Vec3A`. While not an ideal solution, it is the most suitable one identified.
/// Note that this type is only as aligned as `macaw::Vec2` is.
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq)]
pub struct Vec2A(pub macaw::Vec2);

// Implement necessary traits and delegate to inner macaw::Vec2
impl std::ops::Deref for Vec2A {
    type Target = macaw::Vec2;

    #[inline(always)]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl std::ops::DerefMut for Vec2A {
    #[inline(always)]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
impl std::ops::SubAssign for Vec2A {
    fn sub_assign(&mut self, rhs: Self) {
        self.0 -= rhs.0;
    }
}

impl AddAssign for Vec2A {
    #[inline(always)]
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
    }
}

impl std::ops::MulAssign<f32> for Vec2A {
    #[inline(always)]
    fn mul_assign(&mut self, rhs: f32) {
        self.0 *= rhs;
    }
}

impl std::ops::DivAssign<f32> for Vec2A {
    #[inline(always)]
    fn div_assign(&mut self, rhs: f32) {
        self.0 /= rhs;
    }
}

impl std::ops::MulAssign for Vec2A {
    #[inline(always)]
    fn mul_assign(&mut self, rhs: Self) {
        self.0 *= rhs.0;
    }
}

impl std::ops::DivAssign for Vec2A {
    #[inline(always)]
    fn div_assign(&mut self, rhs: Self) {
        self.0 /= rhs.0;
    }
}

impl Add for Vec2A {
    type Output = Self;

    #[inline(always)]
    fn add(self, rhs: Self) -> Self::Output {
        Vec2A(self.0 + rhs.0)
    }
}

impl Sub for Vec2A {
    type Output = Self;

    #[inline(always)]
    fn sub(self, rhs: Self) -> Self::Output {
        Vec2A(self.0 - rhs.0)
    }
}

impl Neg for Vec2A {
    type Output = Self;

    #[inline(always)]
    fn neg(self) -> Self::Output {
        Vec2A(-self.0)
    }
}

// Scalar multiplication (Vec2A * f32 and f32 * Vec2A)
impl Mul<f32> for Vec2A {
    type Output = Self;

    #[inline(always)]
    fn mul(self, rhs: f32) -> Self::Output {
        Vec2A(self.0 * rhs)
    }
}

impl Mul<Vec2A> for f32 {
    type Output = Vec2A;

    #[inline(always)]
    fn mul(self, rhs: Vec2A) -> Self::Output {
        Vec2A(self * rhs.0)
    }
}

// Scalar division (Vec2A / f32)
impl Div<f32> for Vec2A {
    type Output = Self;

    #[inline(always)]
    fn div(self, rhs: f32) -> Self::Output {
        Vec2A(self.0 / rhs)
    }
}

impl Vec2A {
    pub const fn new(x: f32, y: f32) -> Self {
        Self(macaw::Vec2::new(x, y))
    }
}

impl From<macaw::Vec2> for Vec2A {
    fn from(v: macaw::Vec2) -> Self {
        Self(v)
    }
}

impl From<Vec2A> for macaw::Vec2 {
    #[inline(always)]
    fn from(v: Vec2A) -> Self {
        v.0
    }
}

impl From<(f32, f32)> for Vec2A {
    #[inline(always)]
    fn from(tuple: (f32, f32)) -> Self {
        Vec2A(macaw::Vec2::new(tuple.0, tuple.1))
    }
}

impl From<[f32; 2]> for Vec2A {
    #[inline(always)]
    fn from(array: [f32; 2]) -> Self {
        Self(macaw::Vec2::from(array))
    }
}

impl From<Vec2A> for [f32; 2] {
    #[inline(always)]
    fn from(val: Vec2A) -> Self {
        val.0.into()
    }
}

impl Debug for Vec2A {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Vec2A({},{})", self.0.x, self.0.y)
    }
}

impl Index<usize> for Vec2A {
    type Output = f32;

    #[inline(always)]
    fn index(&self, index: usize) -> &Self::Output {
        &self.0[index]
    }
}

impl IndexMut<usize> for Vec2A {
    #[inline(always)]
    fn index_mut(&mut self, index: usize) -> &mut f32 {
        &mut self.0[index]
    }
}

impl HasXY for Vec2A {
    type Scalar = f32;
    #[inline(always)]
    fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self {
        Self(macaw::Vec2::new(x, y))
    }

    #[inline(always)]
    fn x(self) -> Self::Scalar {
        self.0.x
    }

    #[inline(always)]
    fn x_mut(&mut self) -> &mut Self::Scalar {
        &mut self.0.x
    }

    #[inline(always)]
    fn set_x(&mut self, val: Self::Scalar) {
        self.0.x = val;
    }

    #[inline(always)]
    fn y(self) -> Self::Scalar {
        self.0.y
    }

    #[inline(always)]
    fn y_mut(&mut self) -> &mut Self::Scalar {
        &mut self.0.y
    }

    #[inline(always)]
    fn set_y(&mut self, val: Self::Scalar) {
        self.0.y = val
    }
}

impl GenericVector2 for Vec2A {
    const ZERO: Self = Vec2A(macaw::Vec2::ZERO);
    const ONE: Self = Vec2A(macaw::Vec2::ONE);
    type Vector3 = macaw::Vec3A;
    type Affine = macaw::Mat3A;
    type Aabb = Aabb2A;
    #[inline(always)]
    fn new(x: Self::Scalar, y: Self::Scalar) -> Self {
        Vec2A::new(x, y)
    }
    #[inline(always)]
    fn splat(value: Self::Scalar) -> Self {
        Self::new(value, value)
    }
    #[inline(always)]
    fn to_3d(self, z: Self::Scalar) -> Self::Vector3 {
        macaw::vec3a(self.0.x, self.0.y, z)
    }

    #[inline(always)]
    fn magnitude(self) -> Self::Scalar {
        self.0.length()
    }

    #[inline(always)]
    fn magnitude_sq(self) -> Self::Scalar {
        self.0.length_squared()
    }

    #[inline(always)]
    fn dot(self, other: Self) -> Self::Scalar {
        self.0.dot(other.0)
    }

    #[inline(always)]
    fn perp_dot(self, rhs: Self) -> Self::Scalar {
        self.0.perp_dot(rhs.0)
    }

    #[inline(always)]
    fn distance(self, rhs: Self) -> Self::Scalar {
        self.0.distance(rhs.0)
    }

    #[inline(always)]
    fn distance_sq(self, rhs: Self) -> Self::Scalar {
        self.0.distance_squared(rhs.0)
    }

    #[inline(always)]
    fn normalize(self) -> Self {
        Vec2A(self.0.normalize())
    }

    #[inline(always)]
    fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self> {
        let l_sq = self.0.length_squared();
        (l_sq > epsilon * epsilon).then(|| self / l_sq.sqrt())
    }
    #[inline(always)]
    fn min(self, rhs: Self) -> Self {
        self.0.min(rhs.0).into()
    }
    #[inline(always)]
    fn max(self, rhs: Self) -> Self {
        self.0.max(rhs.0).into()
    }
    #[inline(always)]
    fn clamp(self, min: Self, max: Self) -> Self {
        self.0.clamp(min.0, max.0).into()
    }
    #[inline(always)]
    fn is_finite(self) -> bool {
        self.0.x.is_finite() && self.0.y.is_finite()
    }
}

#[allow(dead_code)] // it is used, promise
#[cfg(feature = "macaw")]
#[inline(always)]
#[must_use]
pub const fn vec2a(x: f32, y: f32) -> Vec2A {
    Vec2A::new(x, y)
}