vector-space 0.7.0

Generic vector space trait for compatibility across various libraries
Documentation
#![no_std]
#![deny(missing_docs)]
/*!
Minimal `VectorSpace` trait for generic vector math.

Defines `Scalar` type and core operation bounds. Use as compatibility layer across vector libraries (math, physics, rendering).

Implement once, use everywhere.
*/

use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use scalars::{Real, Zero};

/// This trait specifies some type to be a vector type.
/// It specifies the scalar type and is required for other vector types.
pub trait VectorSpace: Sized + Zero + PartialEq
where
    Self: Add<Output = Self>
        + Sub<Output = Self>
        + Mul<<Self as VectorSpace>::Scalar, Output = Self>
        + Div<<Self as VectorSpace>::Scalar, Output = Self>
        + Neg<Output = Self>,
{
    /// The scalar type of the vector space.
    type Scalar: Real;
}

impl VectorSpace for f32 {
    type Scalar = Self;
}
impl VectorSpace for f64 {
    type Scalar = Self;
}

/// This trait is automatically implemented for vector spaces, which also implement assignment operations.
pub trait VectorSpaceAssign:
    VectorSpace + AddAssign + SubAssign + MulAssign<Self::Scalar> + DivAssign<Self::Scalar>
{
}
impl<T> VectorSpaceAssign for T where
    T: VectorSpace + AddAssign + SubAssign + MulAssign<Self::Scalar> + DivAssign<Self::Scalar>
{
}

/// Marker trait for affine spaces, types whose differences are vectors.
pub trait AffineSpace: Sub<Output = Self::Diff> + Sized {
    /// The difference type.
    type Diff: VectorSpace;
}

impl<T, D> AffineSpace for T
where
    T: Sub<Output = D>,
    D: VectorSpace,
{
    type Diff = D;
}

/// A transformation that maps vectors to vectors.
///
/// Math libraries can implement this for their transform types
/// (matrices, quaternions, rotors, etc.) to enable generic transform support
/// across libraries that depend on `vector-space`.
pub trait Transform<V> {
    /// Applies this transformation to a point.
    fn apply_point(&self, point: V) -> V;
}

/// Linear interpolation of two points.
#[inline]
pub fn interpolate<T>(a: T, b: T, ratio: <T::Diff as VectorSpace>::Scalar) -> T
where
    T: Clone + AffineSpace + Add<T::Diff, Output = T>,
{
    a.clone() + (b - a) * ratio
}