--- a/src/bisection_tree/support.rs Thu May 01 08:40:33 2025 -0500 +++ b/src/bisection_tree/support.rs Thu May 01 13:06:58 2025 -0500 @@ -16,14 +16,14 @@ /// A trait for working with the supports of [`Mapping`]s. /// /// `Mapping` is not a super-trait to allow more general use. -pub trait Support<F: Num, const N: usize>: Sized + Sync + Send + 'static { +pub trait Support<const N: usize, F: Num>: Sized + Sync + Send + 'static { /// Return a cube containing the support of the function represented by `self`. /// /// The hint may be larger than the actual support, but must contain it. - fn support_hint(&self) -> Cube<F, N>; + fn support_hint(&self) -> Cube<N, F>; /// Indicate whether `x` is in the support of the function represented by `self`. - fn in_support(&self, x: &Loc<F, N>) -> bool; + fn in_support(&self, x: &Loc<N, F>) -> bool; // Indicate whether `cube` is fully in the support of the function represented by `self`. //fn fully_in_support(&self, cube : &Cube<F,N>) -> bool; @@ -39,13 +39,13 @@ /// The default implementation returns `[None; N]`. #[inline] #[allow(unused_variables)] - fn bisection_hint(&self, cube: &Cube<F, N>) -> [Option<F>; N] { + fn bisection_hint(&self, cube: &Cube<N, F>) -> [Option<F>; N] { [None; N] } /// Translate `self` by `x`. #[inline] - fn shift(self, x: Loc<F, N>) -> Shift<Self, F, N> { + fn shift(self, x: Loc<N, F>) -> Shift<Self, N, F> { Shift { shift: x, base_fn: self, @@ -55,46 +55,46 @@ /// Shift of [`Support`] and [`Mapping`]; output of [`Support::shift`]. #[derive(Copy, Clone, Debug, Serialize)] // Serialize! but not implemented by Loc. -pub struct Shift<T, F, const N: usize> { - shift: Loc<F, N>, +pub struct Shift<T, const N: usize, F = f64> { + shift: Loc<N, F>, base_fn: T, } -impl<'a, T, V: Space, F: Float, const N: usize> Mapping<Loc<F, N>> for Shift<T, F, N> +impl<'a, T, V: Space, F: Float, const N: usize> Mapping<Loc<N, F>> for Shift<T, N, F> where - T: Mapping<Loc<F, N>, Codomain = V>, + T: Mapping<Loc<N, F>, Codomain = V>, { type Codomain = V; #[inline] - fn apply<I: Instance<Loc<F, N>>>(&self, x: I) -> Self::Codomain { + fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { self.base_fn.apply(x.own() - &self.shift) } } -impl<'a, T, V: Space, F: Float, const N: usize> DifferentiableImpl<Loc<F, N>> for Shift<T, F, N> +impl<'a, T, V: Space, F: Float, const N: usize> DifferentiableImpl<Loc<N, F>> for Shift<T, N, F> where - T: DifferentiableMapping<Loc<F, N>, DerivativeDomain = V>, + T: DifferentiableMapping<Loc<N, F>, DerivativeDomain = V>, { type Derivative = V; #[inline] - fn differential_impl<I: Instance<Loc<F, N>>>(&self, x: I) -> Self::Derivative { + fn differential_impl<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Derivative { self.base_fn.differential(x.own() - &self.shift) } } -impl<'a, T, F: Float, const N: usize> Support<F, N> for Shift<T, F, N> +impl<'a, T, F: Float, const N: usize> Support<N, F> for Shift<T, N, F> where - T: Support<F, N>, + T: Support<N, F>, { #[inline] - fn support_hint(&self) -> Cube<F, N> { + fn support_hint(&self) -> Cube<N, F> { self.base_fn.support_hint().shift(&self.shift) } #[inline] - fn in_support(&self, x: &Loc<F, N>) -> bool { + fn in_support(&self, x: &Loc<N, F>) -> bool { self.base_fn.in_support(&(x - &self.shift)) } @@ -104,13 +104,13 @@ // } #[inline] - fn bisection_hint(&self, cube: &Cube<F, N>) -> [Option<F>; N] { + fn bisection_hint(&self, cube: &Cube<N, F>) -> [Option<F>; N] { let base_hint = self.base_fn.bisection_hint(cube); map2(base_hint, &self.shift, |h, s| h.map(|z| z + *s)) } } -impl<'a, T, F: Float, const N: usize> GlobalAnalysis<F, Bounds<F>> for Shift<T, F, N> +impl<'a, T, F: Float, const N: usize> GlobalAnalysis<F, Bounds<F>> for Shift<T, N, F> where T: LocalAnalysis<F, Bounds<F>, N>, { @@ -120,20 +120,20 @@ } } -impl<'a, T, F: Float, const N: usize> LocalAnalysis<F, Bounds<F>, N> for Shift<T, F, N> +impl<'a, T, F: Float, const N: usize> LocalAnalysis<F, Bounds<F>, N> for Shift<T, N, F> where T: LocalAnalysis<F, Bounds<F>, N>, { #[inline] - fn local_analysis(&self, cube: &Cube<F, N>) -> Bounds<F> { + fn local_analysis(&self, cube: &Cube<N, F>) -> Bounds<F> { self.base_fn.local_analysis(&cube.shift(&(-self.shift))) } } macro_rules! impl_shift_norm { ($($norm:ident)*) => { $( - impl<'a, T, F : Float, const N : usize> Norm<F, $norm> for Shift<T,F,N> - where T : Norm<F, $norm> { + impl<'a, T, F : Float, const N : usize> Norm<$norm, F> for Shift<T, N, F> + where T : Norm<$norm, F> { #[inline] fn norm(&self, n : $norm) -> F { self.base_fn.norm(n) @@ -144,18 +144,18 @@ impl_shift_norm!(L1 L2 Linfinity); -impl<'a, T, F: Float, C, const N: usize> Support<F, N> for Weighted<T, C> +impl<'a, T, F: Float, C, const N: usize> Support<N, F> for Weighted<T, C> where - T: Support<F, N>, + T: Support<N, F>, C: Constant<Type = F>, { #[inline] - fn support_hint(&self) -> Cube<F, N> { + fn support_hint(&self) -> Cube<N, F> { self.base_fn.support_hint() } #[inline] - fn in_support(&self, x: &Loc<F, N>) -> bool { + fn in_support(&self, x: &Loc<N, F>) -> bool { self.base_fn.in_support(x) } @@ -164,7 +164,7 @@ // } #[inline] - fn bisection_hint(&self, cube: &Cube<F, N>) -> [Option<F>; N] { + fn bisection_hint(&self, cube: &Cube<N, F>) -> [Option<F>; N] { self.base_fn.bisection_hint(cube) } } @@ -191,7 +191,7 @@ C: Constant<Type = F>, { #[inline] - fn local_analysis(&self, cube: &Cube<F, N>) -> Bounds<F> { + fn local_analysis(&self, cube: &Cube<N, F>) -> Bounds<F> { let Bounds(lower, upper) = self.base_fn.local_analysis(cube); debug_assert!(lower <= upper); match self.weight.value() { @@ -240,8 +240,8 @@ macro_rules! impl_weighted_norm { ($($norm:ident)*) => { $( - impl<'a, T, F : Float> Norm<F, $norm> for Weighted<T,F> - where T : Norm<F, $norm> { + impl<'a, T, F : Float> Norm<$norm, F> for Weighted<T,F> + where T : Norm<$norm, F> { #[inline] fn norm(&self, n : $norm) -> F { self.base_fn.norm(n) * self.weight.abs() @@ -261,14 +261,14 @@ pub T, ); -impl<'a, T, F: Float, const N: usize> Mapping<Loc<F, N>> for Normalised<T> +impl<'a, T, F: Float, const N: usize> Mapping<Loc<N, F>> for Normalised<T> where - T: Norm<F, L1> + Mapping<Loc<F, N>, Codomain = F>, + T: Norm<L1, F> + Mapping<Loc<N, F>, Codomain = F>, { type Codomain = F; #[inline] - fn apply<I: Instance<Loc<F, N>>>(&self, x: I) -> Self::Codomain { + fn apply<I: Instance<Loc<N, F>>>(&self, x: I) -> Self::Codomain { let w = self.0.norm(L1); if w == F::ZERO { F::ZERO @@ -278,17 +278,17 @@ } } -impl<'a, T, F: Float, const N: usize> Support<F, N> for Normalised<T> +impl<'a, T, F: Float, const N: usize> Support<N, F> for Normalised<T> where - T: Norm<F, L1> + Support<F, N>, + T: Norm<L1, F> + Support<N, F>, { #[inline] - fn support_hint(&self) -> Cube<F, N> { + fn support_hint(&self) -> Cube<N, F> { self.0.support_hint() } #[inline] - fn in_support(&self, x: &Loc<F, N>) -> bool { + fn in_support(&self, x: &Loc<N, F>) -> bool { self.0.in_support(x) } @@ -297,14 +297,14 @@ // } #[inline] - fn bisection_hint(&self, cube: &Cube<F, N>) -> [Option<F>; N] { + fn bisection_hint(&self, cube: &Cube<N, F>) -> [Option<F>; N] { self.0.bisection_hint(cube) } } impl<'a, T, F: Float> GlobalAnalysis<F, Bounds<F>> for Normalised<T> where - T: Norm<F, L1> + GlobalAnalysis<F, Bounds<F>>, + T: Norm<L1, F> + GlobalAnalysis<F, Bounds<F>>, { #[inline] fn global_analysis(&self) -> Bounds<F> { @@ -318,10 +318,10 @@ impl<'a, T, F: Float, const N: usize> LocalAnalysis<F, Bounds<F>, N> for Normalised<T> where - T: Norm<F, L1> + LocalAnalysis<F, Bounds<F>, N>, + T: Norm<L1, F> + LocalAnalysis<F, Bounds<F>, N>, { #[inline] - fn local_analysis(&self, cube: &Cube<F, N>) -> Bounds<F> { + fn local_analysis(&self, cube: &Cube<N, F>) -> Bounds<F> { let Bounds(lower, upper) = self.0.local_analysis(cube); debug_assert!(lower <= upper); let w = self.0.norm(L1); @@ -330,9 +330,9 @@ } } -impl<'a, T, F: Float> Norm<F, L1> for Normalised<T> +impl<'a, T, F: Float> Norm<L1, F> for Normalised<T> where - T: Norm<F, L1>, + T: Norm<L1, F>, { #[inline] fn norm(&self, _: L1) -> F { @@ -347,8 +347,8 @@ macro_rules! impl_normalised_norm { ($($norm:ident)*) => { $( - impl<'a, T, F : Float> Norm<F, $norm> for Normalised<T> - where T : Norm<F, $norm> + Norm<F, L1> { + impl<'a, T, F : Float> Norm<$norm, F> for Normalised<T> + where T : Norm<$norm, F> + Norm<L1, F> { #[inline] fn norm(&self, n : $norm) -> F { let w = self.0.norm(L1); @@ -361,26 +361,26 @@ impl_normalised_norm!(L2 Linfinity); /* -impl<F : Num, S : Support<F, N>, const N : usize> LocalAnalysis<F, NullAggregator, N> for S { - fn local_analysis(&self, _cube : &Cube<F, N>) -> NullAggregator { NullAggregator } +impl<F : Num, S : Support< N, F>, const N : usize> LocalAnalysis<F, NullAggregator, N> for S { + fn local_analysis(&self, _cube : &Cube<N, F>) -> NullAggregator { NullAggregator } } impl<F : Float, S : Bounded<F>, const N : usize> LocalAnalysis<F, Bounds<F>, N> for S { #[inline] - fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> { + fn local_analysis(&self, cube : &Cube<N, F>) -> Bounds<F> { self.bounds(cube) } }*/ /// Generator of [`Support`]-implementing component functions based on low storage requirement /// [ids][`Self::Id`]. -pub trait SupportGenerator<F: Float, const N: usize>: +pub trait SupportGenerator<const N: usize, F: Float = f64>: MulAssign<F> + DivAssign<F> + Neg<Output = Self> + Clone + Sync + Send + 'static { /// The identification type type Id: 'static + Copy; /// The type of the [`Support`] (often also a [`Mapping`]). - type SupportType: 'static + Support<F, N>; + type SupportType: 'static + Support<N, F>; /// An iterator over all the [`Support`]s of the generator. type AllDataIter<'a>: Iterator<Item = (Self::Id, Self::SupportType)> where