--- a/src/kernels/ball_indicator.rs Thu Aug 29 00:00:00 2024 -0500 +++ b/src/kernels/ball_indicator.rs Tue Dec 31 09:25:45 2024 -0500 @@ -1,6 +1,6 @@ //! Implementation of the indicator function of a ball with respect to various norms. -use float_extras::f64::{tgamma as gamma}; +use float_extras::f64::tgamma as gamma; use numeric_literals::replace_float_literals; use serde::Serialize; use alg_tools::types::*; @@ -14,10 +14,16 @@ LocalAnalysis, GlobalAnalysis, }; -use alg_tools::mapping::Apply; +use alg_tools::mapping::{ + Mapping, + Differential, + DifferentiableImpl, +}; +use alg_tools::instance::Instance; +use alg_tools::euclidean::StaticEuclidean; use alg_tools::maputil::array_init; use alg_tools::coefficients::factorial; - +use crate::types::*; use super::base::*; /// Representation of the indicator of the ball $𝔹_q = \\{ x ∈ ℝ^N \mid \\|x\\|\_q ≤ r \\}$, @@ -36,14 +42,17 @@ #[replace_float_literals(C::Type::cast_from(literal))] impl<'a, F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> -Apply<&'a Loc<C::Type, N>> +Mapping<Loc<C::Type, N>> for BallIndicator<C, Exponent, N> -where Loc<F, N> : Norm<F, Exponent> { - type Output = C::Type; +where + Loc<F, N> : Norm<F, Exponent> +{ + type Codomain = C::Type; + #[inline] - fn apply(&self, x : &'a Loc<C::Type, N>) -> Self::Output { + fn apply<I : Instance<Loc<C::Type, N>>>(&self, x : I) -> Self::Codomain { let r = self.r.value(); - let n = x.norm(self.exponent); + let n = x.eval(|x| x.norm(self.exponent)); if n <= r { 1.0 } else { @@ -52,14 +61,79 @@ } } +impl<'a, F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> +DifferentiableImpl<Loc<C::Type, N>> +for BallIndicator<C, Exponent, N> +where + C : Constant, + Loc<F, N> : Norm<F, Exponent> +{ + type Derivative = Loc<C::Type, N>; + + #[inline] + fn differential_impl<I : Instance<Loc<C::Type, N>>>(&self, _x : I) -> Self::Derivative { + Self::Derivative::origin() + } +} + impl<F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> -Apply<Loc<C::Type, N>> +Lipschitz<L2> for BallIndicator<C, Exponent, N> -where Loc<F, N> : Norm<F, Exponent> { - type Output = C::Type; - #[inline] - fn apply(&self, x : Loc<C::Type, N>) -> Self::Output { - self.apply(&x) +where C : Constant, + Loc<F, N> : Norm<F, Exponent> { + type FloatType = C::Type; + + fn lipschitz_factor(&self, _l2 : L2) -> Option<C::Type> { + None + } +} + +impl<'b, F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> +Lipschitz<L2> +for Differential<'b, Loc<F, N>, BallIndicator<C, Exponent, N>> +where C : Constant, + Loc<F, N> : Norm<F, Exponent> { + type FloatType = C::Type; + + fn lipschitz_factor(&self, _l2 : L2) -> Option<C::Type> { + None + } +} + +impl<'a, 'b, F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> +Lipschitz<L2> +for Differential<'b, Loc<F, N>, &'a BallIndicator<C, Exponent, N>> +where C : Constant, + Loc<F, N> : Norm<F, Exponent> { + type FloatType = C::Type; + + fn lipschitz_factor(&self, _l2 : L2) -> Option<C::Type> { + None + } +} + + +impl<'b, F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> +NormBounded<L2> +for Differential<'b, Loc<F, N>, BallIndicator<C, Exponent, N>> +where C : Constant, + Loc<F, N> : Norm<F, Exponent> { + type FloatType = C::Type; + + fn norm_bound(&self, _l2 : L2) -> C::Type { + F::INFINITY + } +} + +impl<'a, 'b, F : Float, C : Constant<Type=F>, Exponent : NormExponent, const N : usize> +NormBounded<L2> +for Differential<'b, Loc<F, N>, &'a BallIndicator<C, Exponent, N>> +where C : Constant, + Loc<F, N> : Norm<F, Exponent> { + type FloatType = C::Type; + + fn norm_bound(&self, _l2 : L2) -> C::Type { + F::INFINITY } } @@ -188,32 +262,21 @@ #[replace_float_literals(F::cast_from(literal))] -impl<'a, F : Float, R, const N : usize> Apply<&'a Loc<F, N>> +impl<'a, F : Float, R, const N : usize> Mapping<Loc<F, N>> for AutoConvolution<CubeIndicator<R, N>> where R : Constant<Type=F> { - type Output = F; + type Codomain = F; #[inline] - fn apply(&self, y : &'a Loc<F, N>) -> F { + fn apply<I : Instance<Loc<F, N>>>(&self, y : I) -> F { let two_r = 2.0 * self.0.r.value(); // This is just a product of one-dimensional versions - y.iter().map(|&x| { + y.cow().iter().map(|&x| { 0.0.max(two_r - x.abs()) }).product() } } -impl<F : Float, R, const N : usize> Apply<Loc<F, N>> -for AutoConvolution<CubeIndicator<R, N>> -where R : Constant<Type=F> { - type Output = F; - - #[inline] - fn apply(&self, y : Loc<F, N>) -> F { - self.apply(&y) - } -} - #[replace_float_literals(F::cast_from(literal))] impl<F : Float, R, const N : usize> Support<F, N> for AutoConvolution<CubeIndicator<R, N>>