src/euclidean.rs

Tue, 31 Dec 2024 09:12:43 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 31 Dec 2024 09:12:43 -0500
branch
dev
changeset 81
d2acaaddd9af
parent 5
59dc4c5883f4
permissions
-rw-r--r--

Try to have Field as member type in Mappings etc.

/*!
Euclidean spaces.
*/

use crate::types::*;
use std::ops::{Mul, MulAssign, Div, DivAssign, Add, Sub, AddAssign, SubAssign, Neg};
pub use crate::types::{HasScalarField, HasRealField};

/// Space (type) with a defined dot product.
///
/// `U` is the space of the multiplier, and `F` the space of scalars.
/// Since `U` ≠ `Self`, this trait can also implement dual products.
pub trait Dot<U> : HasScalarField {
    fn dot(&self, other : U) -> Self::Field;
}

/// Space (type) with Euclidean and vector space structure
///
/// The type should implement vector space operations (addition, subtraction, scalar
/// multiplication and scalar division) along with their assignment versions, as well
/// as the [`Dot`] product with respect to `Self`.
pub trait Euclidean : Sized
        + HasRealField
        + Dot<Self> + for<'a> Dot<&'a Self>
        + Mul<Self::Field, Output=<Self as Euclidean>::Output>
        + MulAssign<Self::Field>
        + Div<Self::Field, Output=<Self as Euclidean>::Output>
        + DivAssign<Self::Field>
        + Add<Self, Output=<Self as Euclidean>::Output>
        + Sub<Self, Output=<Self as Euclidean>::Output>
        + for<'b> Add<&'b Self, Output=<Self as Euclidean>::Output>
        + for<'b> Sub<&'b Self, Output=<Self as Euclidean>::Output>
        + AddAssign<Self> + for<'b> AddAssign<&'b Self>
        + SubAssign<Self> + for<'b> SubAssign<&'b Self>
        + Neg<Output=<Self as Euclidean>::Output> {

    type Output : Euclidean<Field = Self::Field>;

    /// Returns origin of same dimensions as `self`.
    fn similar_origin(&self) -> <Self as Euclidean>::Output;

    /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$.
    #[inline]
    fn norm2_squared(&self) -> Self::Field {
        self.dot(self)
    }

    /// Calculate the square of the 2-norm divided by 2, $\frac{1}{2}\\|x\\|_2^2$,
    /// where `self` is $x$.
    #[inline]
    fn norm2_squared_div2(&self) -> Self::Field {
        self.norm2_squared()/Self::Field::TWO
    }

    /// Calculate the 2-norm $‖x‖_2$, where `self` is $x$.
    #[inline]
    fn norm2(&self) -> Self::Field {
        self.norm2_squared().sqrt()
    }

    /// Calculate the 2-distance squared $\\|x-y\\|_2^2$, where `self` is $x$.
    fn dist2_squared(&self, y : &Self) -> Self::Field;

    /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$.
    #[inline]
    fn dist2(&self, y : &Self) -> Self::Field {
        self.dist2_squared(y).sqrt()
    }

    /// Projection to the 2-ball.
    #[inline]
    fn proj_ball2(mut self, ρ : Self::Field) -> Self {
        self.proj_ball2_mut(ρ);
        self
    }

    /// In-place projection to the 2-ball.
    #[inline]
    fn proj_ball2_mut(&mut self, ρ : Self::Field) {
        let r = self.norm2();
        if r>ρ {
            *self *= ρ/r
        }
    }
}

/// Trait for [`Euclidean`] spaces with dimensions known at compile time.
pub trait StaticEuclidean : Euclidean {
    /// Returns the origin
    fn origin() -> <Self as Euclidean>::Output;
}

mercurial