# HG changeset patch # User Tuomo Valkonen # Date 1756752663 18000 # Node ID c4e394a9c84ca6f0523592b8e142a4e90176ea32 # Parent 2f1798c65fd6cdbfb9b098b9b597786bb6cba0ac fubar diff -r 2f1798c65fd6 -r c4e394a9c84c src/bisection_tree/btfn.rs --- a/src/bisection_tree/btfn.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/bisection_tree/btfn.rs Mon Sep 01 13:51:03 2025 -0500 @@ -1,6 +1,5 @@ -use crate::mapping::{ - BasicDecomposition, DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space, -}; +use crate::instance::{ClosedSpace, Instance, Ownable, Space}; +use crate::mapping::{BasicDecomposition, DifferentiableImpl, DifferentiableMapping, Mapping}; use crate::types::Float; use numeric_literals::replace_float_literals; use std::iter::Sum; @@ -37,12 +36,31 @@ _phantoms: PhantomData, } +impl Ownable for BTFN +where + G: SupportGenerator, + G::SupportType: LocalAnalysis, + BT: BTImpl, +{ + type OwnedVariant = Self; + + fn into_owned(self) -> Self::OwnedVariant { + self + } + + /// Returns an owned instance of a reference. + fn clone_owned(&self) -> Self::OwnedVariant { + self.clone() + } +} + impl Space for BTFN where G: SupportGenerator, G::SupportType: LocalAnalysis, BT: BTImpl, { + type OwnedSpace = Self; type Decomp = BasicDecomposition; } @@ -64,11 +82,7 @@ } fn new_arc(bt: BT, generator: Arc) -> Self { - BTFN { - bt: bt, - generator: generator, - _phantoms: std::marker::PhantomData, - } + BTFN { bt, generator, _phantoms: std::marker::PhantomData } } /// Create a new BTFN support generator and a pre-initialised bisection tree, @@ -161,11 +175,7 @@ { /// Create a new [`PreBTFN`] with no bisection tree. pub fn new_pre(generator: G) -> Self { - BTFN { - bt: (), - generator: Arc::new(generator), - _phantoms: std::marker::PhantomData, - } + BTFN { bt: (), generator: Arc::new(generator), _phantoms: std::marker::PhantomData } } } @@ -188,11 +198,7 @@ bt.insert(d, &support); } - BTFN { - bt: bt, - generator: Arc::new(both), - _phantoms: std::marker::PhantomData, - } + BTFN { bt: bt, generator: Arc::new(both), _phantoms: std::marker::PhantomData } } } @@ -411,7 +417,7 @@ BT: BTImpl, G: SupportGenerator, G::SupportType: LocalAnalysis + Mapping, Codomain = V>, - V: Sum + Space, + V: Sum + ClosedSpace, { type Codomain = V; @@ -430,7 +436,7 @@ G: SupportGenerator, G::SupportType: LocalAnalysis + DifferentiableMapping, DerivativeDomain = V>, - V: Sum + Space, + V: Sum + ClosedSpace, { type Derivative = V; @@ -846,12 +852,7 @@ Cube: P2Minimise, F>, { fn maximise(&mut self, tolerance: F, max_steps: usize) -> (Loc, F) { - let refiner = P2Refiner { - tolerance, - max_steps, - how: RefineMax, - bound: None, - }; + let refiner = P2Refiner { tolerance, max_steps, how: RefineMax, bound: None }; self.bt .search_and_refine(refiner, &self.generator) .expect("Refiner failure.") @@ -864,24 +865,14 @@ tolerance: F, max_steps: usize, ) -> Option<(Loc, F)> { - let refiner = P2Refiner { - tolerance, - max_steps, - how: RefineMax, - bound: Some(bound), - }; + let refiner = P2Refiner { tolerance, max_steps, how: RefineMax, bound: Some(bound) }; self.bt .search_and_refine(refiner, &self.generator) .expect("Refiner failure.") } fn minimise(&mut self, tolerance: F, max_steps: usize) -> (Loc, F) { - let refiner = P2Refiner { - tolerance, - max_steps, - how: RefineMin, - bound: None, - }; + let refiner = P2Refiner { tolerance, max_steps, how: RefineMin, bound: None }; self.bt .search_and_refine(refiner, &self.generator) .expect("Refiner failure.") @@ -894,36 +885,21 @@ tolerance: F, max_steps: usize, ) -> Option<(Loc, F)> { - let refiner = P2Refiner { - tolerance, - max_steps, - how: RefineMin, - bound: Some(bound), - }; + let refiner = P2Refiner { tolerance, max_steps, how: RefineMin, bound: Some(bound) }; self.bt .search_and_refine(refiner, &self.generator) .expect("Refiner failure.") } fn has_upper_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { - let refiner = BoundRefiner { - bound, - tolerance, - max_steps, - how: RefineMax, - }; + let refiner = BoundRefiner { bound, tolerance, max_steps, how: RefineMax }; self.bt .search_and_refine(refiner, &self.generator) .expect("Refiner failure.") } fn has_lower_bound(&mut self, bound: F, tolerance: F, max_steps: usize) -> bool { - let refiner = BoundRefiner { - bound, - tolerance, - max_steps, - how: RefineMin, - }; + let refiner = BoundRefiner { bound, tolerance, max_steps, how: RefineMin }; self.bt .search_and_refine(refiner, &self.generator) .expect("Refiner failure.") diff -r 2f1798c65fd6 -r c4e394a9c84c src/bisection_tree/either.rs --- a/src/bisection_tree/either.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/bisection_tree/either.rs Mon Sep 01 13:51:03 2025 -0500 @@ -3,7 +3,9 @@ use crate::iter::{MapF, MapZ, Mappable}; use crate::loc::Loc; -use crate::mapping::{DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space}; +use crate::mapping::{ + ClosedSpace, DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space, +}; use crate::sets::Cube; use crate::types::*; @@ -192,7 +194,7 @@ impl Mapping for EitherSupport where - F: Space, + F: ClosedSpace, X: Space, S1: Mapping, S2: Mapping, @@ -210,8 +212,8 @@ impl DifferentiableImpl for EitherSupport where - O: Space, - X: Space, + O: ClosedSpace, + X: ClosedSpace, S1: DifferentiableMapping, S2: DifferentiableMapping, { diff -r 2f1798c65fd6 -r c4e394a9c84c src/bisection_tree/support.rs --- a/src/bisection_tree/support.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/bisection_tree/support.rs Mon Sep 01 13:51:03 2025 -0500 @@ -4,7 +4,9 @@ use super::aggregator::Bounds; pub use crate::bounds::{GlobalAnalysis, LocalAnalysis}; use crate::loc::Loc; -use crate::mapping::{DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space}; +use crate::mapping::{ + ClosedSpace, DifferentiableImpl, DifferentiableMapping, Instance, Mapping, Space, +}; use crate::maputil::map2; use crate::norms::{Linfinity, Norm, L1, L2}; pub use crate::operator_arithmetic::{Constant, Weighted}; @@ -46,10 +48,7 @@ /// Translate `self` by `x`. #[inline] fn shift(self, x: Loc) -> Shift { - Shift { - shift: x, - base_fn: self, - } + Shift { shift: x, base_fn: self } } } @@ -60,7 +59,7 @@ base_fn: T, } -impl<'a, T, V: Space, F: Float, const N: usize> Mapping> for Shift +impl<'a, T, V: ClosedSpace, F: Float, const N: usize> Mapping> for Shift where T: Mapping, Codomain = V>, { @@ -72,7 +71,8 @@ } } -impl<'a, T, V: Space, F: Float, const N: usize> DifferentiableImpl> for Shift +impl<'a, T, V: ClosedSpace, F: Float, const N: usize> DifferentiableImpl> + for Shift where T: DifferentiableMapping, DerivativeDomain = V>, { @@ -226,10 +226,7 @@ type Output = Weighted; #[inline] fn $fn(self, t: F) -> Self::Output { - Weighted { - weight: self.weight.$fn(t), - base_fn: self.base_fn.clone(), - } + Weighted { weight: self.weight.$fn(t), base_fn: self.base_fn.clone() } } } }; diff -r 2f1798c65fd6 -r c4e394a9c84c src/convex.rs --- a/src/convex.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/convex.rs Mon Sep 01 13:51:03 2025 -0500 @@ -4,7 +4,7 @@ use crate::error::DynResult; use crate::euclidean::Euclidean; -use crate::instance::{DecompositionMut, Instance, InstanceMut}; +use crate::instance::{ClosedSpace, DecompositionMut, Instance}; use crate::linops::{IdOp, Scaled, SimpleZeroOp, AXPY}; use crate::mapping::{DifferentiableImpl, LipschitzDifferentiableImpl, Mapping, Space}; use crate::norms::*; @@ -57,7 +57,7 @@ /// The conjugate type has to implement [`ConvexMapping`], but a `Conjugable` mapping need /// not be convex. pub trait Prox: Mapping { - type Prox<'a>: Mapping + type Prox<'a>: Mapping where Self: 'a; @@ -65,16 +65,15 @@ fn prox_mapping(&self, τ: Self::Codomain) -> Self::Prox<'_>; /// Calculate the proximal mapping with weight τ - fn prox>(&self, τ: Self::Codomain, z: I) -> Domain { + fn prox>(&self, τ: Self::Codomain, z: I) -> Domain::OwnedSpace { self.prox_mapping(τ).apply(z) } /// Calculate the proximal mapping with weight τ in-place - fn prox_mut<'b>(&self, τ: Self::Codomain, y: &'b mut Domain) + fn prox_mut<'b>(&self, τ: Self::Codomain, y: &'b mut Domain::OwnedSpace) where - &'b mut Domain: InstanceMut, Domain::Decomp: DecompositionMut, - for<'a> &'a Domain: Instance, + for<'a> &'a Domain::OwnedSpace: Instance, { *y = self.prox(τ, &*y); } @@ -165,7 +164,7 @@ Domain: Space + Norm, E: NormExponent, F: Float, - NormProjection: Mapping, + NormProjection: Mapping, { type Prox<'a> = NormProjection @@ -203,12 +202,13 @@ impl Mapping for NormProjection where Domain: Normed + Projection, + Domain::OwnedSpace: ClosedSpace, F: Float, E: NormExponent, { - type Codomain = Domain; + type Codomain = Domain::OwnedSpace; - fn apply>(&self, d: I) -> Domain { + fn apply>(&self, d: I) -> Self::Codomain { d.own().proj_ball(self.radius, self.exponent) } } @@ -262,7 +262,7 @@ } } -impl Prox for Zero { +impl Prox for Zero { type Prox<'a> = IdOp where @@ -395,7 +395,7 @@ impl Prox for Norm222 where F: Float, - X: Euclidean, + X: Euclidean + ClosedMul, { type Prox<'a> = Scaled @@ -410,11 +410,11 @@ impl DifferentiableImpl for Norm222 where F: Float, - X: Euclidean, + X: Euclidean, { - type Derivative = X; + type Derivative = X::Owned; - fn differential_impl>(&self, x: I) -> X { + fn differential_impl>(&self, x: I) -> Self::Derivative { x.own() } } @@ -422,7 +422,7 @@ impl LipschitzDifferentiableImpl for Norm222 where F: Float, - X: Euclidean, + X: Euclidean, { type FloatType = F; diff -r 2f1798c65fd6 -r c4e394a9c84c src/direct_product.rs --- a/src/direct_product.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/direct_product.rs Mon Sep 01 13:51:03 2025 -0500 @@ -6,8 +6,10 @@ */ use crate::euclidean::Euclidean; -use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; -use crate::linops::AXPY; +use crate::instance::{ + ClosedSpace, Decomposition, DecompositionMut, Instance, InstanceMut, MyCow, Ownable, +}; +use crate::linops::{VectorSpace, AXPY}; use crate::loc::Loc; use crate::mapping::Space; use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; @@ -262,6 +264,25 @@ impl_scalar_mut!(MulAssign, mul_assign); impl_scalar_mut!(DivAssign, div_assign); +/// Trait for ownable-by-consumption objects +impl Ownable for Pair +where + A: Ownable, + B: Ownable, +{ + type OwnedVariant = Pair; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + Pair(self.0.into_owned(), self.1.into_owned()) + } + + /// Returns an owned instance of a reference. + fn clone_owned(&self) -> Self::OwnedVariant { + Pair(self.0.clone_owned(), self.1.clone_owned()) + } +} + /// We only support 'closed' `Euclidean` `Pair`s, as more general ones cause /// compiler overflows. impl Euclidean for Pair @@ -270,19 +291,19 @@ B: Euclidean, //Pair: Euclidean, Self: Sized - + Mul::Owned> + + Mul::Owned> + MulAssign - + Div::Owned> + + Div::Owned> + DivAssign - + Add::Owned> - + Sub::Owned> - + for<'b> Add<&'b Self, Output = ::Owned> - + for<'b> Sub<&'b Self, Output = ::Owned> + + Add::Owned> + + Sub::Owned> + + for<'b> Add<&'b Self, Output = ::Owned> + + for<'b> Sub<&'b Self, Output = ::Owned> + AddAssign + for<'b> AddAssign<&'b Self> + SubAssign + for<'b> SubAssign<&'b Self> - + Neg::Owned>, + + Neg::Owned>, { fn dot>(&self, other: I) -> F { other.eval_decompose(|Pair(u, v)| self.0.dot(u) + self.1.dot(v)) @@ -297,6 +318,28 @@ } } +impl VectorSpace for Pair +where + A: VectorSpace, + B: VectorSpace, + O: ClosedSpace + AXPY, + P: ClosedSpace + AXPY, + F: Num, +{ + type Field = F; + type Owned = Pair; + + /// Return a similar zero as `self`. + fn similar_origin(&self) -> Self::Owned { + Pair(self.0.similar_origin(), self.1.similar_origin()) + } + + // #[inline] + // fn into_owned(self) -> Self::Owned { + // Pair(self.0.into_owned(), self.1.into_owned()) + // } +} + impl AXPY> for Pair where U: Space, @@ -306,13 +349,7 @@ F: Num, Self: MulAssign + DivAssign, Pair: MulAssign + DivAssign, - //A::Owned: MulAssign, - //B::Owned: MulAssign, - //Pair: AXPY, Field = F>, { - type Field = F; - type Owned = Pair; - fn axpy>>(&mut self, α: F, x: I, β: F) { x.eval_decompose(|Pair(u, v)| { self.0.axpy(α, u, β); @@ -334,11 +371,6 @@ }) } - /// Return a similar zero as `self`. - fn similar_origin(&self) -> Self::Owned { - Pair(self.0.similar_origin(), self.1.similar_origin()) - } - /// Set self to zero. fn set_zero(&mut self) { self.0.set_zero(); @@ -562,7 +594,7 @@ { type DualSpace = Pair; - fn dual_origin(&self) -> ::Owned { + fn dual_origin(&self) -> ::Owned { Pair(self.0.dual_origin(), self.1.dual_origin()) } } diff -r 2f1798c65fd6 -r c4e394a9c84c src/euclidean.rs --- a/src/euclidean.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/euclidean.rs Mon Sep 01 13:51:03 2025 -0500 @@ -3,13 +3,15 @@ */ use crate::instance::Instance; -use crate::linops::AXPY; +use crate::linops::{VectorSpace, AXPY}; use crate::norms::{HasDual, Reflexive}; use crate::types::*; use std::ops::{Add, AddAssign, Sub, SubAssign}; pub mod wrap; +// TODO: Euclidean & EuclideanMut +// /// Space (type) with Euclidean and vector space structure /// /// The type should implement vector space operations (addition, subtraction, scalar @@ -18,11 +20,11 @@ // TODO: remove F parameter, use AXPY::Field pub trait Euclidean: HasDual - + AXPY + + VectorSpace + Reflexive // TODO: move the following to AXPY - + for<'b> Add<&'b Self, Output = ::Owned> - + for<'b> Sub<&'b Self, Output = ::Owned> + + for<'b> Add<&'b Self, Output = ::Owned> + + for<'b> Sub<&'b Self, Output = ::Owned> + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self> { @@ -59,11 +61,20 @@ /// Projection to the 2-ball. #[inline] - fn proj_ball2(mut self, ρ: F) -> Self { - self.proj_ball2_mut(ρ); - self + fn proj_ball2(self, ρ: F) -> Self::Owned { + let r = self.norm2(); + if r > ρ { + self * (ρ / r) + } else { + self.into_owned() + } } +} +// TODO: remove F parameter, use AXPY::Field +pub trait EuclideanMut: + Euclidean + AXPY + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self> +{ /// In-place projection to the 2-ball. #[inline] fn proj_ball2_mut(&mut self, ρ: F) { @@ -74,8 +85,13 @@ } } +impl EuclideanMut for X where + X: Euclidean + AXPY + for<'b> AddAssign<&'b Self> + for<'b> SubAssign<&'b Self> +{ +} + /// Trait for [`Euclidean`] spaces with dimensions known at compile time. pub trait StaticEuclidean: Euclidean { /// Returns the origin - fn origin() -> ::Owned; + fn origin() -> ::Owned; } diff -r 2f1798c65fd6 -r c4e394a9c84c src/instance.rs --- a/src/instance.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/instance.rs Mon Sep 01 13:51:03 2025 -0500 @@ -23,35 +23,117 @@ } } -impl<'b, X> MyCow<'b, X> { +/// Trait for ownable-by-consumption objects +pub trait Ownable { + type OwnedVariant: Clone; + + /// Returns an owned instance, possibly consuming the original, + /// avoiding cloning when possible. + fn into_owned(self) -> Self::OwnedVariant; + + /// Returns an owned instance of a reference. + fn clone_owned(&self) -> Self::OwnedVariant; +} + +impl<'a, X: Ownable> Ownable for &'a X { + type OwnedVariant = X::OwnedVariant; + + #[inline] + /// Returns an owned instance. + fn into_owned(self) -> Self::OwnedVariant { + self.clone_owned() + } + #[inline] - pub fn into_owned(self) -> X - where - X: Clone, - { + /// Returns an owned instance. + fn clone_owned(&self) -> Self::OwnedVariant { + (*self).into_owned() + } +} + +impl<'a, X: Ownable> Ownable for &'a mut X { + type OwnedVariant = X::OwnedVariant; + + #[inline] + /// Returns an owned instance. + fn into_owned(self) -> Self::OwnedVariant { + self.clone_owned() + } + + #[inline] + /// Returns an owned instance. + fn clone_owned(&self) -> Self::OwnedVariant { + (&**self).into_owned() + } +} + +impl<'a, X: Ownable> Ownable for MyCow<'a, X> { + type OwnedVariant = X::OwnedVariant; + + #[inline] + /// Returns an owned instance. + fn into_owned(self) -> Self::OwnedVariant { match self { - EitherDecomp::Owned(x) => x, - EitherDecomp::Borrowed(x) => x.clone(), + EitherDecomp::Owned(x) => x.into_owned(), + EitherDecomp::Borrowed(x) => x.into_owned(), + } + } + + #[inline] + /// Returns an owned instance. + fn clone_owned(&self) -> Self::OwnedVariant { + match self { + EitherDecomp::Owned(x) => x.into_owned(), + EitherDecomp::Borrowed(x) => x.into_owned(), } } } /// Trait for abitrary mathematical spaces. -pub trait Space: Instance { +pub trait Space: Ownable + Sized { + type OwnedSpace: ClosedSpace; + /// Default decomposition for the space type Decomp: Decomposition; } +mod private { + pub trait Sealed {} +} + +/// Helper trait for working with own types. +pub trait Owned: Ownable + private::Sealed {} +impl> private::Sealed for X {} +impl> Owned for X {} + +/// Helper trait for working with closed spaces, operations in which should +/// return members of the same space +pub trait ClosedSpace: Space + Owned + Instance {} +impl + Owned + Instance> ClosedSpace for X {} + #[macro_export] macro_rules! impl_basic_space { - ($($type:ty)*) => { $( - impl $crate::instance::Space for $type { + ($($type:ty)*) => { + $( $crate::impl_basic_space!($type where ); )* + }; + ($type:ty where $($where:tt)*) => { + impl<$($where)*> $crate::instance::Space for $type { + type OwnedSpace = Self; type Decomp = $crate::instance::BasicDecomposition; } - )* }; - ($type:ty where $($where:tt)*) => { - impl<$($where)*> $crate::instance::Space for $type { - type Decomp = $crate::instance::BasicDecomposition; + + impl<$($where)*> $crate::instance::Ownable for $type { + type OwnedVariant = Self; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + self + } + + #[inline] + fn clone_owned(&self) -> Self::OwnedVariant { + *self + } } }; } @@ -83,7 +165,7 @@ #[derive(Copy, Clone, Debug)] pub struct BasicDecomposition; -impl Decomposition for BasicDecomposition { +impl Decomposition for BasicDecomposition { type Decomposition<'b> = MyCow<'b, X> where @@ -104,8 +186,9 @@ /// generalises [`std::borrow::ToOwned`], [`std::borrow::Borrow`], and [`std::borrow::Cow`]. /// /// This is used, for example, by [`crate::mapping::Mapping::apply`]. -pub trait Instance::Decomp>: Sized +pub trait Instance::Decomp>: Sized + Ownable where + X: Space, D: Decomposition, { /// Decomposes self according to `decomposer`, and evaluate `f` on the result. @@ -164,7 +247,7 @@ } } -impl Instance for X { +impl Instance for X { #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where @@ -197,7 +280,7 @@ } } -impl<'a, X: Space + Clone> Instance for &'a X { +impl<'a, X: Space> Instance for &'a X { #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where @@ -218,7 +301,7 @@ #[inline] fn own(self) -> X { - self.clone() + self.into_owned() } #[inline] @@ -230,7 +313,7 @@ } } -impl<'a, X: Space + Clone> Instance for &'a mut X { +impl<'a, X: Space> Instance for &'a mut X { #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where @@ -251,20 +334,19 @@ #[inline] fn own(self) -> X { - self.clone() + self.into_owned() } #[inline] fn cow<'b>(self) -> MyCow<'b, X> where Self: 'b, - X: Clone, { EitherDecomp::Borrowed(self) } } -impl<'a, X: Space + Clone> Instance for MyCow<'a, X> { +impl<'a, X: Space> Instance for MyCow<'a, X> { #[inline] fn eval_decompose<'b, R>(self, f: impl FnOnce(MyCow<'b, X>) -> R) -> R where diff -r 2f1798c65fd6 -r c4e394a9c84c src/linops.rs --- a/src/linops.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/linops.rs Mon Sep 01 13:51:03 2025 -0500 @@ -5,7 +5,7 @@ use crate::direct_product::Pair; use crate::error::DynResult; use crate::instance::Instance; -pub use crate::mapping::{Composition, DifferentiableImpl, Mapping, Space}; +pub use crate::mapping::{ClosedSpace, Composition, DifferentiableImpl, Mapping, Space}; use crate::norms::{HasDual, Linfinity, Norm, NormExponent, PairNorm, L1, L2}; use crate::types::*; use numeric_literals::replace_float_literals; @@ -25,16 +25,10 @@ // } // } -/// Efficient in-place summation. +/// Vector spaces #[replace_float_literals(Self::Field::cast_from(literal))] -pub trait AXPY: - Space - + MulAssign - + DivAssign - + AddAssign - + AddAssign - + SubAssign - + SubAssign +pub trait VectorSpace: + Space + Mul + Div + Add @@ -42,12 +36,42 @@ + Sub + Sub + Neg +{ + type Field: Num; + type Owned: ClosedSpace + + AXPY< + Self, + Field = Self::Field, + Owned = Self::Owned, + OwnedVariant = Self::Owned, + OwnedSpace = Self::Owned, + >; + + /// Return a similar zero as `self`. + fn similar_origin(&self) -> Self::Owned; + // { + // self.make_origin_generator().make_origin() + // } + + /// Return a similar zero as `x`. + fn similar_origin_inst>(x: I) -> Self::Owned { + x.eval(|xr| xr.similar_origin()) + } +} + +/// Efficient in-place summation. +#[replace_float_literals(Self::Field::cast_from(literal))] +pub trait AXPY: + VectorSpace + + MulAssign + + DivAssign + + AddAssign + + AddAssign + + SubAssign + + SubAssign where X: Space, { - type Field: Num; - type Owned: AXPY; - /// Computes `y = βy + αx`, where `y` is `Self`. fn axpy>(&mut self, α: Self::Field, x: I, β: Self::Field); @@ -61,21 +85,8 @@ self.axpy(α, x, 0.0) } - /// Return a similar zero as `self`. - fn similar_origin(&self) -> Self::Owned; - // { - // self.make_origin_generator().make_origin() - // } - - /// Return a similar zero as `x`. - fn similar_origin_inst>(x: I) -> Self::Owned { - x.eval(|xr| xr.similar_origin()) - } - /// Set self to zero. fn set_zero(&mut self); - - //fn make_origin_generator(&self) -> Self::OriginGen<'_>; } /// Efficient in-place application for [`Linear`] operators. @@ -178,21 +189,21 @@ } } -impl Mapping for IdOp { - type Codomain = X; +impl Mapping for IdOp { + type Codomain = X::OwnedVariant; fn apply>(&self, x: I) -> X { x.own() } } -impl Linear for IdOp {} +impl Linear for IdOp {} #[replace_float_literals(F::cast_from(literal))] impl GEMV for IdOp where Y: AXPY, - X: Clone + Space, + X: Space, { // Computes `y = αAx + βy`, where `A` is `Self`. fn gemv>(&self, y: &mut Y, α: F, x: I, β: F) { @@ -243,10 +254,7 @@ #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] pub struct SimpleZeroOp; -impl Mapping for SimpleZeroOp -where - X: AXPY + Instance, -{ +impl Mapping for SimpleZeroOp { type Codomain = X::Owned; fn apply>(&self, x: I) -> X::Owned { @@ -254,14 +262,14 @@ } } -impl Linear for SimpleZeroOp where X: AXPY + Instance {} +impl Linear for SimpleZeroOp {} #[replace_float_literals(F::cast_from(literal))] impl GEMV for SimpleZeroOp where F: Num, Y: AXPY, - X: AXPY + Instance, + X: VectorSpace + Instance, { // Computes `y = αAx + βy`, where `A` is `Self`. fn gemv>(&self, y: &mut Y, _α: F, _x: I, β: F) { @@ -276,7 +284,7 @@ impl BoundedLinear for SimpleZeroOp where F: Num, - X: AXPY + Instance + Norm, + X: VectorSpace + Norm, E1: NormExponent, E2: NormExponent, { @@ -288,8 +296,8 @@ impl Adjointable for SimpleZeroOp where F: Num, - X: AXPY + Instance + HasDual, - X::DualSpace: AXPY, + X: VectorSpace + HasDual, + X::DualSpace: VectorSpace, { type AdjointCodomain = X::DualSpace; type Adjoint<'b> @@ -303,7 +311,7 @@ } } -pub trait OriginGenerator { +pub trait OriginGenerator { type Ref<'b>: OriginGenerator where Self: 'b; @@ -312,7 +320,7 @@ fn as_ref(&self) -> Self::Ref<'_>; } -impl OriginGenerator for Y { +impl OriginGenerator for Y { type Ref<'b> = &'b Y where @@ -329,7 +337,7 @@ } } -impl<'b, Y: AXPY> OriginGenerator for &'b Y { +impl<'b, Y: VectorSpace> OriginGenerator for &'b Y { type Ref<'c> = Self where @@ -348,7 +356,7 @@ /// A zero operator that can be eitherh dualised or predualised (once). /// This is achieved by storing an oppropriate zero. -pub struct ZeroOp, OY: OriginGenerator, O, F: Float = f64> { +pub struct ZeroOp, OY: OriginGenerator, O, F: Float = f64> { codomain_origin_generator: OY, other_origin_generator: O, _phantoms: PhantomData<(X, Y, F)>, @@ -357,8 +365,8 @@ impl ZeroOp where OY: OriginGenerator, - X: AXPY, - Y: AXPY, + X: VectorSpace, + Y: VectorSpace, F: Float, { pub fn new(y_og: OY) -> Self { @@ -377,7 +385,7 @@ X: HasDual, Y: HasDual, F: Float, - Xprime: AXPY, + Xprime: VectorSpace, Xprime::Owned: AXPY, Yprime: Space + Instance, { @@ -392,8 +400,8 @@ impl Mapping for ZeroOp where - X: Space + Instance, - Y: AXPY, + X: Space, + Y: VectorSpace, F: Float, OY: OriginGenerator, { @@ -406,8 +414,8 @@ impl Linear for ZeroOp where - X: Space + Instance, - Y: AXPY, + X: Space, + Y: VectorSpace, F: Float, OY: OriginGenerator, { @@ -416,7 +424,7 @@ #[replace_float_literals(F::cast_from(literal))] impl GEMV for ZeroOp where - X: Space + Instance, + X: Space, Y: AXPY, F: Float, OY: OriginGenerator, @@ -434,7 +442,7 @@ impl BoundedLinear for ZeroOp where X: Space + Instance + Norm, - Y: AXPY, + Y: VectorSpace, Y::Owned: Clone, F: Float, E1: NormExponent, @@ -452,7 +460,7 @@ X: HasDual, Y: HasDual, F: Float, - Xprime: AXPY, + Xprime: VectorSpace, Xprime::Owned: AXPY, Yprime: Space + Instance, OY: OriginGenerator, diff -r 2f1798c65fd6 -r c4e394a9c84c src/loc.rs --- a/src/loc.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/loc.rs Mon Sep 01 13:51:03 2025 -0500 @@ -4,8 +4,8 @@ */ use crate::euclidean::*; -use crate::instance::{BasicDecomposition, Instance}; -use crate::linops::{Linear, Mapping, AXPY}; +use crate::instance::{BasicDecomposition, Instance, Ownable}; +use crate::linops::{Linear, Mapping, VectorSpace, AXPY}; use crate::mapping::Space; use crate::maputil::{map1, map1_mut, map2, map2_mut, FixedLength, FixedLengthMut}; use crate::norms::*; @@ -27,6 +27,21 @@ pub [F; N], ); +/// Trait for ownable-by-consumption objects +impl Ownable for Loc { + type OwnedVariant = Self; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + self + } + + /// Returns an owned instance of a reference. + fn clone_owned(&self) -> Self::OwnedVariant { + self.clone() + } +} + impl Display for Loc { // Required method fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -648,6 +663,14 @@ impl Projection for Loc { #[inline] + fn proj_ball(mut self, ρ: F, exp: Linfinity) -> Self { + self.proj_ball_mut(ρ, exp); + self + } +} + +impl ProjectionMut for Loc { + #[inline] fn proj_ball_mut(&mut self, ρ: F, _: Linfinity) { self.iter_mut() .for_each(|v| *v = num_traits::clamp(*v, -ρ, ρ)) @@ -706,6 +729,7 @@ } impl Space for Loc { + type OwnedSpace = Self; type Decomp = BasicDecomposition; } @@ -719,10 +743,32 @@ impl Linear> for Loc {} -impl AXPY> for Loc { +impl VectorSpace for Loc { type Field = F; type Owned = Self; + // #[inline] + // fn make_origin_generator(&self) -> StaticEuclideanOriginGenerator { + // StaticEuclideanOriginGenerator + // } + + #[inline] + fn similar_origin(&self) -> Self::Owned { + Self::ORIGIN + } + + #[inline] + fn similar_origin_inst>(_: I) -> Self::Owned { + Self::ORIGIN + } + + // #[inline] + // fn into_owned(self) -> Self::Owned { + // self + // } +} + +impl AXPY> for Loc { #[inline] fn axpy>>(&mut self, α: F, x: I, β: F) { x.eval(|x̃| { @@ -739,21 +785,6 @@ x.eval(|x̃| map2_mut(self, x̃, |yi, xi| *yi = *xi)) } - // #[inline] - // fn make_origin_generator(&self) -> StaticEuclideanOriginGenerator { - // StaticEuclideanOriginGenerator - // } - - #[inline] - fn similar_origin(&self) -> Self::Owned { - Self::ORIGIN - } - - #[inline] - fn similar_origin_inst>(_: I) -> Self::Owned { - Self::ORIGIN - } - #[inline] fn set_zero(&mut self) { *self = Self::ORIGIN; diff -r 2f1798c65fd6 -r c4e394a9c84c src/mapping.rs --- a/src/mapping.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/mapping.rs Mon Sep 01 13:51:03 2025 -0500 @@ -4,7 +4,7 @@ use crate::error::DynResult; use crate::instance::MyCow; -pub use crate::instance::{BasicDecomposition, Decomposition, Instance, Space}; +pub use crate::instance::{BasicDecomposition, ClosedSpace, Decomposition, Instance, Space}; use crate::loc::Loc; use crate::norms::{Norm, NormExponent}; use crate::operator_arithmetic::{Constant, Weighted}; @@ -14,7 +14,7 @@ /// A mapping from `Domain` to `Self::Codomain`. pub trait Mapping { - type Codomain: Space; + type Codomain: ClosedSpace; /// Compute the value of `self` at `x`. fn apply>(&self, x: I) -> Self::Codomain; @@ -25,11 +25,7 @@ where Self: Sized, { - Composition { - outer: self, - inner: other, - intermediate_norm_exponent: (), - } + Composition { outer: self, inner: other, intermediate_norm_exponent: () } } #[inline] @@ -43,11 +39,7 @@ Domain: Norm, F: Num, { - Composition { - outer: self, - inner: other, - intermediate_norm_exponent: norm, - } + Composition { outer: self, inner: other, intermediate_norm_exponent: norm } } /// Multiply `self` by the scalar `a`. @@ -58,10 +50,7 @@ C: Constant, Self::Codomain: ClosedMul, { - Weighted { - weight: a, - base_fn: self, - } + Weighted { weight: a, base_fn: self } } } @@ -86,7 +75,7 @@ /// /// This is automatically implemented when [`DifferentiableImpl`] is. pub trait DifferentiableMapping: Mapping { - type DerivativeDomain: Space; + type DerivativeDomain: ClosedSpace; type Differential<'b>: Mapping where Self: 'b; @@ -115,7 +104,7 @@ /// Helper trait for implementing [`DifferentiableMapping`] pub trait DifferentiableImpl: Sized { - type Derivative: Space; + type Derivative: ClosedSpace; /// Compute the differential of `self` at `x`, consuming the input. fn differential_impl>(&self, x: I) -> Self::Derivative; @@ -138,17 +127,11 @@ } fn diff(self) -> Differential<'static, Domain, Self> { - Differential { - g: MyCow::Owned(self), - _space: PhantomData, - } + Differential { g: MyCow::Owned(self), _space: PhantomData } } fn diff_ref(&self) -> Differential<'_, Domain, Self> { - Differential { - g: MyCow::Borrowed(self), - _space: PhantomData, - } + Differential { g: MyCow::Borrowed(self), _space: PhantomData } } } @@ -201,10 +184,7 @@ pub trait FlattenCodomain: Mapping> + Sized { /// Flatten the codomain from [`Loc`]`` to `F`. fn flatten_codomain(self) -> FlattenedCodomain { - FlattenedCodomain { - g: self, - _phantoms: PhantomData, - } + FlattenedCodomain { g: self, _phantoms: PhantomData } } } @@ -241,21 +221,13 @@ /// Flatten the codomain from [`Loc`]`` to `F`. fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> { assert!(slice < N); - SlicedCodomain { - g: MyCow::Owned(self), - slice, - _phantoms: PhantomData, - } + SlicedCodomain { g: MyCow::Owned(self), slice, _phantoms: PhantomData } } /// Flatten the codomain from [`Loc`]`` to `F`. fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> { assert!(slice < N); - SlicedCodomain { - g: MyCow::Borrowed(self), - slice, - _phantoms: PhantomData, - } + SlicedCodomain { g: MyCow::Borrowed(self), slice, _phantoms: PhantomData } } } @@ -294,7 +266,7 @@ E: Copy, //Composition: Space, S::Derivative: Mul, - Y: Space, + Y: ClosedSpace, { //type Derivative = Composition; type Derivative = Y; diff -r 2f1798c65fd6 -r c4e394a9c84c src/mapping/dataterm.rs --- a/src/mapping/dataterm.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/mapping/dataterm.rs Mon Sep 01 13:51:03 2025 -0500 @@ -8,7 +8,7 @@ use super::{DifferentiableImpl, DifferentiableMapping, LipschitzDifferentiableImpl, Mapping}; use crate::convex::ConvexMapping; use crate::error::DynResult; -use crate::instance::{Instance, Space}; +use crate::instance::{ClosedSpace, Instance, Space}; use crate::linops::{BoundedLinear, Linear, Preadjointable}; use crate::norms::{Normed, L2}; use crate::types::Float; @@ -41,11 +41,7 @@ G: Mapping + Clone, { fn clone(&self) -> Self { - DataTerm { - opA: self.opA.clone(), - b: self.b.clone(), - g: self.g.clone(), - } + DataTerm { opA: self.opA.clone(), b: self.b.clone(), g: self.g.clone() } } } @@ -78,7 +74,7 @@ X: Space, A: Mapping, G: Mapping, - A::Codomain: for<'a> Sub<&'a A::Codomain, Output = A::Codomain>, + A::Codomain: ClosedSpace + for<'a> Sub<&'a A::Codomain, Output = A::Codomain>, { type Codomain = F; @@ -97,7 +93,7 @@ X: Normed, A: Linear, G: ConvexMapping, - A::Codomain: Normed + for<'a> Sub<&'a A::Codomain, Output = A::Codomain>, + A::Codomain: ClosedSpace + Normed + for<'a> Sub<&'a A::Codomain, Output = A::Codomain>, { } @@ -105,9 +101,11 @@ where F: Float, X: Space, - Y: Space + for<'a> Sub<&'a Y, Output = Y>, + Y: Space + Instance + for<'a> Sub<&'a Y, Output = Y>, //>::Codomain: Euclidean, A: Linear + Preadjointable, + G::DerivativeDomain: Instance, + A::PreadjointCodomain: ClosedSpace, //<>::Codomain as Euclidean>::Output: Instance<>::Codomain>, G: DifferentiableMapping, { diff -r 2f1798c65fd6 -r c4e394a9c84c src/nalgebra_support.rs --- a/src/nalgebra_support.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/nalgebra_support.rs Mon Sep 01 13:51:03 2025 -0500 @@ -9,7 +9,7 @@ */ use crate::euclidean::*; -use crate::instance::Instance; +use crate::instance::{Instance, Ownable}; use crate::linops::*; use crate::mapping::{BasicDecomposition, Space}; use crate::norms::*; @@ -24,14 +24,36 @@ use num_traits::identities::{One, Zero}; use std::ops::Mul; +impl Ownable for Matrix +where + S: Storage, + M: Dim, + N: Dim, + E: Scalar + Zero + One, + DefaultAllocator: Allocator, +{ + type OwnedVariant = OMatrix; + + #[inline] + fn into_owned(self) -> Self::OwnedVariant { + Matrix::into_owned(self) + } + + /// Returns an owned instance of a reference. + fn clone_owned(&self) -> Self::OwnedVariant { + Matrix::clone_owned(self) + } +} + impl Space for Matrix where - SM: Storage + Clone, + SM: Storage, N: Dim, M: Dim, - E: Scalar + Zero + One + ClosedAddAssign + ClosedMulAssign, + E: Scalar + Zero + One, DefaultAllocator: Allocator, { + type OwnedSpace = OMatrix; type Decomp = BasicDecomposition; } @@ -103,10 +125,9 @@ } } -impl AXPY> for Matrix +impl VectorSpace for Matrix where - SM: StorageMut + Clone, - SV1: Storage + Clone, + S: Storage, M: Dim, N: Dim, E: Scalar + Zero + One + Float, @@ -116,6 +137,22 @@ type Owned = OMatrix; #[inline] + fn similar_origin(&self) -> Self::Owned { + let (n, m) = self.shape_generic(); + OMatrix::zeros_generic(n, m) + } +} + +impl AXPY> for Matrix +where + SM: StorageMut, + SV1: Storage, + M: Dim, + N: Dim, + E: Scalar + Zero + One + Float, + DefaultAllocator: Allocator, +{ + #[inline] fn axpy>>(&mut self, α: E, x: I, β: E) { x.eval(|x̃| { assert_eq!(self.ncols(), x̃.ncols()); @@ -136,12 +173,6 @@ fn set_zero(&mut self) { self.iter_mut().for_each(|e| *e = E::ZERO); } - - #[inline] - fn similar_origin(&self) -> Self::Owned { - let (n, m) = self.shape_generic(); - OMatrix::zeros_generic(n, m) - } } /* Implemented automatically as Euclidean. @@ -160,6 +191,21 @@ impl Projection for Vector where + SM: Storage + Clone, + M: Dim, + E: Scalar + Zero + One + Float + RealField, + DefaultAllocator: Allocator, +{ + #[inline] + fn proj_ball(self, ρ: E, exp: Linfinity) -> ::OwnedSpace { + let mut owned = self.into_owned(); + owned.proj_ball_mut(ρ, exp); + owned + } +} + +impl ProjectionMut for Vector +where SM: StorageMut + Clone, M: Dim, E: Scalar + Zero + One + Float + RealField, diff -r 2f1798c65fd6 -r c4e394a9c84c src/norms.rs --- a/src/norms.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/norms.rs Mon Sep 01 13:51:03 2025 -0500 @@ -3,7 +3,8 @@ */ use crate::euclidean::*; -use crate::linops::AXPY; +use crate::instance::Ownable; +use crate::linops::VectorSpace; use crate::mapping::{Instance, Mapping, Space}; use crate::types::*; use serde::{Deserialize, Serialize}; @@ -123,16 +124,12 @@ /// /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); /// ``` -pub trait Projection: Norm + Sized -where - F: Float, -{ +pub trait Projection: Ownable + Norm { /// Projection of `self` to the `q`-norm-ball of radius ρ. - fn proj_ball(mut self, ρ: F, q: Exponent) -> Self { - self.proj_ball_mut(ρ, q); - self - } + fn proj_ball(self, ρ: F, q: Exponent) -> Self::OwnedVariant; +} +pub trait ProjectionMut: Projection { /// In-place projection of `self` to the `q`-norm-ball of radius ρ. fn proj_ball_mut(&mut self, ρ: F, q: Exponent); } @@ -146,10 +143,12 @@ impl + Norm> Projection for E { #[inline] - fn proj_ball(self, ρ: F, _p: L2) -> Self { + fn proj_ball(self, ρ: F, _p: L2) -> Self::OwnedVariant { self.proj_ball2(ρ) } +} +impl + Norm> ProjectionMut for E { #[inline] fn proj_ball_mut(&mut self, ρ: F, _p: L2) { self.proj_ball2_mut(ρ) @@ -229,10 +228,10 @@ } } -pub trait HasDual: Normed + AXPY { - type DualSpace: Normed + AXPY; +pub trait HasDual: Normed + VectorSpace { + type DualSpace: Normed + VectorSpace; - fn dual_origin(&self) -> ::Owned; + fn dual_origin(&self) -> ::Owned; } /// Automatically implemented trait for reflexive spaces diff -r 2f1798c65fd6 -r c4e394a9c84c src/operator_arithmetic.rs --- a/src/operator_arithmetic.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/operator_arithmetic.rs Mon Sep 01 13:51:03 2025 -0500 @@ -2,7 +2,7 @@ Arithmetic of [`Mapping`]s. */ -use crate::instance::{Instance, Space}; +use crate::instance::{ClosedSpace, Instance, Space}; use crate::mapping::{DifferentiableImpl, DifferentiableMapping, Mapping}; use crate::types::*; use serde::Serialize; @@ -63,7 +63,7 @@ F: Float, D: Space, T: DifferentiableMapping, - V: Space + std::ops::Mul, + V: ClosedSpace + std::ops::Mul, C: Constant, { type Derivative = V; diff -r 2f1798c65fd6 -r c4e394a9c84c src/types.rs --- a/src/types.rs Mon Sep 01 00:04:22 2025 -0500 +++ b/src/types.rs Mon Sep 01 13:51:03 2025 -0500 @@ -10,15 +10,12 @@ */ //use trait_set::trait_set; +pub use num_traits::cast::AsPrimitive; pub use num_traits::Float as NumTraitsFloat; // needed to re-export functions. -pub use num_traits::cast::AsPrimitive; pub use simba::scalar::{ - ClosedAdd, ClosedAddAssign, + ClosedAdd, ClosedAddAssign, ClosedDiv, ClosedDivAssign, ClosedMul, ClosedMulAssign, ClosedNeg, ClosedSub, ClosedSubAssign, - ClosedMul, ClosedMulAssign, - ClosedDiv, ClosedDivAssign, - ClosedNeg }; /// Typical integer type @@ -34,8 +31,8 @@ pub type float = f64; /// Casts of abstract numerical types to others via the standard `as` keyword. -pub trait CastFrom : num_traits::cast::AsPrimitive { - fn cast_from(other : T) -> Self; +pub trait CastFrom: num_traits::cast::AsPrimitive { + fn cast_from(other: T) -> Self; } macro_rules! impl_casts { @@ -58,53 +55,71 @@ f32 f64); /// Trait for general numeric types -pub trait Num : 'static + Copy + Sync + Send + num::Num + num_traits::NumAssign - + std::iter::Sum + std::iter::Product - + std::fmt::Debug + std::fmt::Display + serde::Serialize - + CastFrom + CastFrom + CastFrom + CastFrom - + CastFrom + CastFrom - + CastFrom + CastFrom + CastFrom + CastFrom - + CastFrom + CastFrom - + CastFrom + CastFrom - + crate::instance::Space { - - const ZERO : Self; - const ONE : Self; - const TWO : Self; +pub trait Num: + 'static + + Copy + + Sync + + Send + + num::Num + + num_traits::NumAssign + + std::iter::Sum + + std::iter::Product + + std::fmt::Debug + + std::fmt::Display + + serde::Serialize + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + CastFrom + + crate::instance::ClosedSpace +{ + const ZERO: Self; + const ONE: Self; + const TWO: Self; /// Generic version of `Self::MAX` - const RANGE_MAX : Self; + const RANGE_MAX: Self; /// Generic version of `Self::MIN` - const RANGE_MIN : Self; + const RANGE_MIN: Self; } /// Trait for signed numeric types -pub trait SignedNum : Num + num::Signed + std::ops::Neg {} -impl> SignedNum for U { } +pub trait SignedNum: Num + num::Signed + std::ops::Neg {} +impl> SignedNum for U {} /// Trait for floating point numbers -pub trait Float : SignedNum + num::Float /*+ From*/ { +pub trait Float: SignedNum + num::Float /*+ From*/ { // An unsigned integer that can be used for indexing operations and // converted to F without loss. //type CompatibleSize : CompatibleUnsigned; - const PI : Self; - const E : Self; - const EPSILON : Self; - const SQRT_2 : Self; - const INFINITY : Self; - const NEG_INFINITY : Self; - const NAN : Self; - const FRAC_2_SQRT_PI : Self; + const PI: Self; + const E: Self; + const EPSILON: Self; + const SQRT_2: Self; + const INFINITY: Self; + const NEG_INFINITY: Self; + const NAN: Self; + const FRAC_2_SQRT_PI: Self; } /// Trait for integers -pub trait Integer : Num + num::Integer {} +pub trait Integer: Num + num::Integer {} /// Trait for unsigned integers -pub trait Unsigned : Num + Integer + num::Unsigned {} +pub trait Unsigned: Num + Integer + num::Unsigned {} /// Trait for signed integers -pub trait Signed : SignedNum + Integer {} +pub trait Signed: SignedNum + Integer {} macro_rules! impl_num_consts { ($($type:ty)*) => { $( @@ -137,14 +152,14 @@ #[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))] type CompatibleSize = usize;*/ - const PI : Self = std::f64::consts::PI; - const E : Self = std::f64::consts::E; - const EPSILON : Self = std::f64::EPSILON; - const SQRT_2 : Self = std::f64::consts::SQRT_2; - const INFINITY : Self = std::f64::INFINITY; - const NEG_INFINITY : Self = std::f64::NEG_INFINITY; - const NAN : Self = std::f64::NAN; - const FRAC_2_SQRT_PI : Self = std::f64::consts::FRAC_2_SQRT_PI; + const PI: Self = std::f64::consts::PI; + const E: Self = std::f64::consts::E; + const EPSILON: Self = std::f64::EPSILON; + const SQRT_2: Self = std::f64::consts::SQRT_2; + const INFINITY: Self = std::f64::INFINITY; + const NEG_INFINITY: Self = std::f64::NEG_INFINITY; + const NAN: Self = std::f64::NAN; + const FRAC_2_SQRT_PI: Self = std::f64::consts::FRAC_2_SQRT_PI; } impl Float for f32 { @@ -155,14 +170,14 @@ type CompatibleSize = usize; */ - const PI : Self = std::f32::consts::PI; - const E : Self = std::f32::consts::E; - const EPSILON : Self = std::f32::EPSILON; - const SQRT_2 : Self = std::f32::consts::SQRT_2; - const INFINITY : Self = std::f32::INFINITY; - const NEG_INFINITY : Self = std::f32::NEG_INFINITY; - const NAN : Self = std::f32::NAN; - const FRAC_2_SQRT_PI : Self = std::f32::consts::FRAC_2_SQRT_PI; + const PI: Self = std::f32::consts::PI; + const E: Self = std::f32::consts::E; + const EPSILON: Self = std::f32::EPSILON; + const SQRT_2: Self = std::f32::consts::SQRT_2; + const INFINITY: Self = std::f32::INFINITY; + const NEG_INFINITY: Self = std::f32::NEG_INFINITY; + const NAN: Self = std::f32::NAN; + const FRAC_2_SQRT_PI: Self = std::f32::consts::FRAC_2_SQRT_PI; } /* @@ -171,4 +186,3 @@ pub trait CompatibleSigned = Signed + Into; } */ -