Sat, 30 Aug 2025 22:25:28 -0500
wrap sketch
| src/convex.rs | file | annotate | diff | comparison | revisions | |
| src/euclidean.rs | file | annotate | diff | comparison | revisions | |
| src/euclidean/wrap.rs | file | annotate | diff | comparison | revisions |
--- a/src/convex.rs Sun May 18 23:31:48 2025 -0500 +++ b/src/convex.rs Sat Aug 30 22:25:28 2025 -0500 @@ -135,10 +135,7 @@ Self: 'a; fn conjugate(&self) -> Self::Conjugate<'_> { - NormConstraint { - radius: F::ONE, - norm: self.exponent.dual_exponent().as_mapping(), - } + NormConstraint { radius: F::ONE, norm: self.exponent.dual_exponent().as_mapping() } } } @@ -178,10 +175,7 @@ #[inline] fn prox_mapping(&self, _τ: Self::Codomain) -> Self::Prox<'_> { assert!(self.radius >= F::ZERO); - NormProjection { - radius: self.radius, - exponent: self.norm.exponent, - } + NormProjection { radius: self.radius, exponent: self.norm.exponent } } }
--- a/src/euclidean.rs Sun May 18 23:31:48 2025 -0500 +++ b/src/euclidean.rs Sat Aug 30 22:25:28 2025 -0500 @@ -8,6 +8,8 @@ use crate::types::*; use std::ops::{Add, AddAssign, Sub, SubAssign}; +pub mod wrap; + /// Space (type) with Euclidean and vector space structure /// /// The type should implement vector space operations (addition, subtraction, scalar
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/euclidean/wrap.rs Sat Aug 30 22:25:28 2025 -0500 @@ -0,0 +1,219 @@ +/*! +Wrappers for implemention [`Euclidean`] operations. +*/ + +use super::Euclidean; +use crate::instance::{Decomposition, DecompositionMut, Instance, InstanceMut, MyCow}; +use crate::linops::AXPY; +use crate::loc::Loc; +use crate::mapping::Space; +use crate::norms::{HasDual, Norm, NormExponent, Normed, PairNorm, L2}; +use crate::types::{Float, Num}; +use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; +use serde::{Deserialize, Serialize}; +use std::clone::Clone; + +macro_rules! impl_unary { + ($type:ty, $trait:ident, $fn:ident) => { + impl $trait for $type { + type Output = Self::WrappedOutput; + fn $fn(self) -> Self::Output { + $type::wrap(self.get_view().$fn()) + } + } + }; +} + +macro_rules! impl_binary { + ($type:ty, $trait:ident, $fn:ident) => { + impl $trait<$type> for $type { + type Output = Self::WrappedOutput; + fn $fn(self, other: $type) -> Self::Output { + $type::wrap(self.get_view().$fn(other.get_view())) + } + } + + impl<'a> $trait<$type> for &'a $type { + type Output = Self::WrappedOutput; + fn $fn(self, other: $type) -> Self::Output { + $type::wrap(self.get_view().$fn(other.get_view())) + } + } + + impl<'a, 'b> $trait<&'b $type> for &'a $type { + type Output = Self::WrappedOutput; + fn $fn(self, other: $type) -> Self::Output { + $type::wrap(self.get_view().$fn(other.get_view())) + } + } + + impl<'b> $trait<&'b $type> for $type { + type Output = Self::WrappedOutput; + fn $fn(self, other: $type) -> Self::Output { + $type::wrap(self.get_view().$fn(other.get_view())) + } + } + }; +} + +macro_rules! impl_scalar { + ($type:ty, $trait:ident, $fn:ident) => { + impl<F: Num> $trait<F> for $type, + where + $type::Unwrapped: $trait<F>, + { + type Output = Self::WrappedOutput; + fn $fn(self, t: F) -> Self::Output { + $type::wrap(self.get_view().$fn(t)) + } + } + + impl<'a, F: Num> $trait<F> for &'a $type, + where + $type::Unwrapped: $trait<F>, + { + type Output = Self::WrappedOutput; + fn $fn(self, t: F) -> Self::Output { + $type::wrap(self.get_view().$fn(t)) + } + } + + }; +} + +macro_rules! impl_scalar_lhs { + ($type:ty, $trait:ident, $fn:ident, $F:ty) => { + impl<A, B> $trait<$type> for $F + where + $F: $type::Unwrapped, + { + type Output = Self::WrappedOutput; + fn $fn(self, rhs: $type) -> Self::Output { + $type::wrap(self.$fn(rhs.get_view())) + } + } + }; +} + +macro_rules! impl_binary_mut { + ($type:ty, $trait:ident, $fn:ident) => { + impl $trait<$type> for $type { + fn $fn(&mut self, rhs: $type) { + self.get_view_mut().$fn(rhs.get_view()) + } + } + + impl<'b> $trait<&'b $type> for $type { + fn $fn(&mut self, rhs: $type) { + self.get_view_mut().$fn(rhs.get_view()) + } + } + }; +} + +macro_rules! impl_scalar_mut { + ($type:ty, $trait:ident, $fn:ident) => { + impl $trait<F> for $type + where + $type::UnwrappedMut: $trait<F>, + { + fn $fn(&mut self, t: F) { + self.unwrap_mut().$fn(t) + } + } + }; +} + +macro_rules! wrap { + ($type:ty) => { + impl_unary!($type, Neg, neg); + impl_binary!($type, Add, add); + impl_binary!($type, Sub, sub); + impl_scalar!($type, Mul, mul); + impl_scalar!($type, Div, div); + impl_scalar_lhs!($type, Mul, mul, f32); + impl_scalar_lhs!($type, Mul, mul, f64); + impl_scalar_lhs!($type, Div, div, f32); + impl_scalar_lhs!($type, Div, div, f64); + impl_binary_mut!($type, AddAssign, add_assign); + impl_binary_mut!($type, SubAssign, sub_assign); + impl_scalar_mut!($type, MulAssign, mul_assign); + impl_scalar_mut!($type, DivAssign, div_assign); + + /// We only support 'closed' `Euclidean` `Pair`s, as more general ones cause + /// compiler overflows. + impl<F: Float> Euclidean<F> for $type + where + //Pair<A, B>: Euclidean<F>, + Self: Sized + + Mul<F, Output = <Self as AXPY>::Owned> + + MulAssign<F> + + Div<F, Output = <Self as AXPY>::Owned> + + DivAssign<F> + + 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>, + { + fn dot<I: Instance<Self>>(&self, other: I) -> F { + other.eval_decompose(|x| self.get_view().dot(x.get_view())) + } + + fn norm2_squared(&self) -> F { + self.get_view().norm2_squared() + } + + fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { + other.eval_decompose(|x| self.get_view().dist2_squared(x.get_view())) + } + } + + impl<F> AXPY for $type + where + Self::Unwrapped : AXPY<Field = $F>, + F: Num, + Self: MulAssign<F> + DivAssign<F>, + Self::Unwrapped: MulAssign<F> + DivAssign<F>, + { + type Field = F; + type Owned = Pair<A::Owned, B::Owned>; + + fn axpy<I: Instance<Self>>(&mut self, α: F, x: I, β: F) { + x.eval_decompose(|v| { + self.get_mut_view().axpy(α, v.get_view(), β) + }) + } + + fn copy_from<I: Instance<Self>>(&mut self, x: I) { + x.eval_decompose(|Pair(u, v)| { + self.get_mut_view().copy_from(v.get_view()) + }) + } + + fn scale_from<I: Instance<Self>>(&mut self, α: F, x: I) { + x.eval_decompose(|v| { + self.get_mut_view().scale_from(α, v.get_view()) + }) + } + + /// Return a similar zero as `self`. + fn similar_origin(&self) -> Self::Owned { + $type::wrap(self.get_view().similar_origin()) + } + + /// Set self to zero. + fn set_zero(&mut self) { + self.get_mut_view().set_zero() + } + } + + impl<A: Space, B: Space> Space for $type { + type Decomp = $type::Unwrapped::Decomp + } + }; +}