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 crate::prelude::*;

/// A basic three-dimensional vector trait, designed for flexibility in precision.
///
/// The `HasXYZ` trait abstracts over three-dimensional vectors, allowing for easy
/// transition between different precisions (e.g., `f32` and `f64`) without necessitating
/// significant codebase modifications. It only provides the most basic vector interface.
/// It is intended to be used in situations where you need a custom storage type of vectors.
/// For example an FFI type.
///
/// Implementors of this trait can benefit from the ability to switch between different
/// precision representations seamlessly, making it ideal for applications where varying
/// precision levels might be desirable at different stages or configurations.
///
pub trait HasXYZ: HasXY {
    fn new_3d(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self;
    fn z(self) -> Self::Scalar;
    fn z_mut(&mut self) -> &mut Self::Scalar;
    fn set_z(&mut self, val: Self::Scalar);
}

/// A generic three-dimensional vector trait.
///
/// The `GenericVector3` trait abstracts over three-dimensional vectors, allowing for easy
/// transition between different precisions (e.g., `f32` and `f64`) without necessitating
/// significant codebase modifications. It provides the common operations one would expect
/// for 3D vectors, such as dot products, cross products, and normalization.
///
/// Implementors of this trait can benefit from the ability to switch between different
/// precision representations seamlessly, making it ideal for applications where varying
/// precision levels might be desirable at different stages or configurations.
///
/// The associated `Scalar` type represents the scalar type (e.g., `f32` or `f64`) used
/// by the vector, and `Vector2` is the corresponding two-dimensional vector type.
///
/// Note: The actual trait functionality might vary based on the concrete implementations.
pub trait GenericVector3:
    HasXYZ
    + Copy
    + Approx
    + PartialEq
    + std::ops::AddAssign
    + std::ops::SubAssign
    + std::ops::Index<usize, Output = Self::Scalar>
    + std::ops::IndexMut<usize, Output = Self::Scalar>
    + std::ops::Neg<Output = Self>
    + std::ops::Add<Self, Output = Self>
    + std::ops::Sub<Self, Output = Self>
    + std::ops::Mul<Self::Scalar, Output = Self>
    + std::ops::Div<Self::Scalar, Output = Self>
    + Into<[Self::Scalar; 3]>
    + From<[Self::Scalar; 3]>
{
    // Associated constants
    const ZERO: Self;
    const ONE: Self;

    type Affine: Affine3D<Vector3 = Self>;
    type Aabb: Aabb3<Vector = Self>;
    type Vector2: GenericVector2<Scalar = Self::Scalar, Vector3 = Self>;
    fn new(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self;
    fn splat(value: Self::Scalar) -> Self;
    fn to_2d(self) -> Self::Vector2;
    fn magnitude(self) -> Self::Scalar;
    fn magnitude_sq(self) -> Self::Scalar;
    fn dot(self, other: Self) -> Self::Scalar;
    fn cross(self, rhs: Self) -> Self;
    fn normalize(self) -> Self;
    fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self>;
    fn distance(self, other: Self) -> Self::Scalar;
    fn distance_sq(self, rhs: Self) -> Self::Scalar;
    fn min(self, rhs: Self) -> Self;
    fn max(self, rhs: Self) -> Self;
    /// Clamps the vector's components to be within the range defined by `min` and `max`.
    ///
    /// # Note
    /// This implementation does **not** follow `nalgebra`'s convention for `clamp`.
    /// In `nalgebra`, `clamp` is symmetric around zero.
    /// In this implementation, `clamp` ensures that `self` is bounded by `min` and `max`
    /// in a non-symmetric way: `self.min(max).max(min)`.
    fn clamp(self, min: Self, max: Self) -> Self;
    /// returns false on all inf or NaN values
    fn is_finite(self) -> bool;
}

/// Trait for vector types that can be upgraded to a SIMD-optimized variant
/// for computation, then downgraded back.
pub trait SimdUpgradable: GenericVector3
where
    Self::Simd: GenericVector3<Scalar = Self::Scalar>,
{
    /// The SIMD-optimized version of this vector type.
    /// For glam::Vec3, this is glam::Vec3A. For glam::DVec3, this is glam::DVec3 itself (no-op).
    type Simd;

    /// Convert to the SIMD-optimized variant
    fn to_simd(self) -> Self::Simd;

    /// Convert from the SIMD-optimized variant
    fn from_simd(simd: Self::Simd) -> Self;
}