Sat, 30 Aug 2025 22:25:28 -0500
wrap sketch
/*! 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 } }; }