src/euclidean.rs

Mon, 12 May 2025 17:10:39 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 12 May 2025 17:10:39 -0500
branch
dev
changeset 131
8264d72aa347
parent 124
6aa955ad8122
permissions
-rw-r--r--

euclidean simplify fail

/*!
Euclidean spaces.
*/

use crate::instance::Instance;
use crate::linops::AXPY;
use crate::norms::{HasDual, NormExponent, Normed, Reflexive, L2};
use crate::types::*;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};

/// 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 an inner product.
pub trait Euclidean:
    AXPY<Owned = Self::Owned_>
    + HasDual<Self::Field, DualSpace = Self>
    //+ Normed<Self::Field, NormExp = L2>
    + Reflexive<Self::Field>
    + Mul<Self::Field, Output = <Self as AXPY>::Owned>
    + MulAssign<Self::Field>
    + Div<Self::Field, Output = <Self as AXPY>::Owned>
    + DivAssign<Self::Field>
    + Add<Self, Output = <Self as AXPY>::Owned>
    + Sub<Self, Output = <Self as AXPY>::Owned>
    + for<'b> Add<&'b Self, Output = <Self as AXPY>::Owned>
    + for<'b> Sub<&'b Self, Output = <Self as AXPY>::Owned>
    + AddAssign<Self>
    + for<'b> AddAssign<&'b Self>
    + SubAssign<Self>
    + for<'b> SubAssign<&'b Self>
    + Neg<Output = <Self as AXPY>::Owned>
{
    type Owned_: Euclidean<Field = Self::Field>;

    // Inner product
    fn dot<I: Instance<Self>>(&self, other: I) -> Self::Field;

    /// Calculate the square of the 2-norm, $\frac{1}{2}\\|x\\|_2^2$, where `self` is $x$.
    ///
    /// This is not automatically implemented to avoid imposing
    /// `for <'a> &'a Self : Instance<Self>` trait bound bloat.
    fn norm2_squared(&self) -> Self::Field;

    /// 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<I: Instance<Self>>(&self, y: I) -> Self::Field;

    /// Calculate the 2-distance $\\|x-y\\|_2$, where `self` is $x$.
    #[inline]
    fn dist2<I: Instance<Self>>(&self, y: I) -> 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 AXPY>::Owned;
}

mercurial