--- a/src/bisection_tree/btfn.rs Sun Nov 10 09:02:57 2024 -0500 +++ b/src/bisection_tree/btfn.rs Tue Dec 31 09:12:43 2024 -0500 @@ -1,9 +1,8 @@ use numeric_literals::replace_float_literals; use std::iter::Sum; -use std::marker::PhantomData; use std::sync::Arc; -use crate::types::Float; +use crate::types::{Float, HasScalarField, HasRealField}; use crate::mapping::{Apply, Mapping, Differentiable}; //use crate::linops::{Apply, Linear}; use crate::sets::Set; @@ -29,21 +28,23 @@ /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`]. #[derive(Clone,Debug)] pub struct BTFN< - F : Float, - G : SupportGenerator<F, N>, + G : SupportGenerator<N>, BT /*: BTImpl<F, N>*/, const N : usize -> /*where G::SupportType : LocalAnalysis<F, A, N>*/ { +> { bt : BT, generator : Arc<G>, - _phantoms : PhantomData<F>, +} + +impl<G : SupportGenerator<N>, BT, const N : usize> HasScalarField for BTFN<G, BT, N> { + type Field = G::Field; } impl<F : Float, G, BT, const N : usize> -BTFN<F, G, BT, N> -where G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N>, - BT : BTImpl<F, N> { +BTFN<G, BT, N> +where G : SupportGenerator<N, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>, + BT : BTImpl<F, N, Data=G::Id> { /// Create a new BTFN from a support generator and a pre-initialised bisection tree. /// @@ -60,7 +61,6 @@ BTFN { bt : bt, generator : generator, - _phantoms : std::marker::PhantomData, } } @@ -85,11 +85,11 @@ /// The top node of the created [`BT`] will have the given `domain`. /// /// See the documentation for [`BTFN`] on the role of the `generator`. - pub fn construct(domain : Cube<F, N>, depth : BT::Depth, generator : G) -> Self { + pub fn construct(domain : Cube<G::Field, N>, depth : BT::Depth, generator : G) -> Self { Self::construct_arc(domain, depth, Arc::new(generator)) } - fn construct_arc(domain : Cube<F, N>, depth : BT::Depth, generator : Arc<G>) -> Self { + fn construct_arc(domain : Cube<G::Field, N>, depth : BT::Depth, generator : Arc<G>) -> Self { let mut bt = BT::new(domain, depth); for (d, support) in generator.all_data() { bt.insert(d, &support); @@ -101,10 +101,10 @@ /// /// This will construct a [`BTFN`] with the same components and generator as the (consumed) /// `self`, but a new `BT` with [`Aggregator`]s of type `ANew`. - pub fn convert_aggregator<ANew>(self) -> BTFN<F, G, BT::Converted<ANew>, N> + pub fn convert_aggregator<ANew>(self) -> BTFN<G, BT::Converted<ANew>, N> where ANew : Aggregator, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, ANew, N> { + G : SupportGenerator<N>, + G::SupportType : LocalAnalysis<ANew, Cube<G::RealField, N>> { BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator) } @@ -121,16 +121,16 @@ } impl<F : Float, G, BT, const N : usize> -BTFN<F, G, BT, N> -where G : SupportGenerator<F, N> { +BTFN<G, BT, N> +where G : SupportGenerator<N, RealField = F> { /// Change the [bisection tree][BTImpl] of the [`BTFN`] to a different one. /// /// This can be used to convert a [`PreBTFN`] to a full [`BTFN`], or the change /// the aggreagator; see also [`self.convert_aggregator`]. pub fn instantiate< BTNew : BTImpl<F, N, Data=G::Id>, - > (self, domain : Cube<F, N>, depth : BTNew::Depth) -> BTFN<F, G, BTNew, N> - where G::SupportType : LocalAnalysis<F, BTNew::Agg, N> { + > (self, domain : Cube<F, N>, depth : BTNew::Depth) -> BTFN<G, BTNew, N> + where G::SupportType : LocalAnalysis<BTNew::Agg, Cube<F, N>> { BTFN::construct_arc(domain, depth, self.generator) } } @@ -140,30 +140,29 @@ /// Most BTFN methods are not available, but if a BTFN is going to be summed with another /// before other use, it will be more efficient to not construct an unnecessary bisection tree /// that would be shortly dropped. -pub type PreBTFN<F, G, const N : usize> = BTFN<F, G, (), N>; +pub type PreBTFN<G, const N : usize> = BTFN<G, (), N>; -impl<F : Float, G, const N : usize> PreBTFN<F, G, N> where G : SupportGenerator<F, N> { +impl<G, const N : usize> PreBTFN<G, N> where G : SupportGenerator<N> { /// 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, } } } impl<F : Float, G, BT, const N : usize> -BTFN<F, G, BT, N> -where G : SupportGenerator<F, N, Id=usize>, - G::SupportType : LocalAnalysis<F, BT::Agg, N>, +BTFN<G, BT, N> +where G : SupportGenerator<N, Id=usize, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>, BT : BTImpl<F, N, Data=usize> { /// Helper function for implementing [`std::ops::Add`]. - fn add_another<G2>(&self, g2 : Arc<G2>) -> BTFN<F, BothGenerators<G, G2>, BT, N> - where G2 : SupportGenerator<F, N, Id=usize>, - G2::SupportType : LocalAnalysis<F, BT::Agg, N> { + fn add_another<G2>(&self, g2 : Arc<G2>) -> BTFN<BothGenerators<G, G2>, BT, N> + where G2 : SupportGenerator<N, Id=usize, RealField = F>, + G2::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { let mut bt = self.bt.clone(); let both = BothGenerators(Arc::clone(&self.generator), g2); @@ -175,7 +174,6 @@ BTFN { bt : bt, generator : Arc::new(both), - _phantoms : std::marker::PhantomData, } } } @@ -183,54 +181,54 @@ macro_rules! make_btfn_add { ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> - std::ops::Add<BTFN<F, G2, BT2, N>> for + std::ops::Add<BTFN<G2, BT2, N>> for $lhs where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize>, - G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, - G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { - type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; + G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, + G2 : SupportGenerator<N, Id=usize, RealField = F>, + G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, + G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> { + type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; #[inline] - fn add(self, other : BTFN<F, G2, BT2, N>) -> Self::Output { + fn add(self, other : BTFN<G2, BT2, N>) -> Self::Output { $preprocess(self).add_another(other.generator) } } impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> - std::ops::Add<&'b BTFN<F, G2, BT2, N>> for + std::ops::Add<&'b BTFN<G2, BT2, N>> for $lhs where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize>, - G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, - G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { + G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, + G2 : SupportGenerator<N, Id=usize, RealField = F>, + G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, + G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> { - type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; + type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; #[inline] - fn add(self, other : &'b BTFN<F, G2, BT2, N>) -> Self::Output { + fn add(self, other : &'b BTFN<G2, BT2, N>) -> Self::Output { $preprocess(self).add_another(other.generator.clone()) } } } } -make_btfn_add!(BTFN<F, G1, BT1, N>, std::convert::identity, ); -make_btfn_add!(&'a BTFN<F, G1, BT1, N>, Clone::clone, ); +make_btfn_add!(BTFN<G1, BT1, N>, std::convert::identity, ); +make_btfn_add!(&'a BTFN<G1, BT1, N>, Clone::clone, ); macro_rules! make_btfn_sub { ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> - std::ops::Sub<BTFN<F, G2, BT2, N>> for + std::ops::Sub<BTFN<G2, BT2, N>> for $lhs where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize>, - G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, - G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { - type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; + G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, + G2 : SupportGenerator<N, Id=usize, RealField = F>, + G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, + G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> { + type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; #[inline] - fn sub(self, other : BTFN<F, G2, BT2, N>) -> Self::Output { + fn sub(self, other : BTFN<G2, BT2, N>) -> Self::Output { $preprocess(self).add_another(Arc::new( Arc::try_unwrap(other.generator) .unwrap_or_else(|arc| (*arc).clone()) @@ -240,35 +238,35 @@ } impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> - std::ops::Sub<&'b BTFN<F, G2, BT2, N>> for + std::ops::Sub<&'b BTFN<G2, BT2, N>> for $lhs where BT1 : BTImpl<F, N, Data=usize>, - G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, - G2 : SupportGenerator<F, N, Id=usize> + Clone, - G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, - G2::SupportType : LocalAnalysis<F, BT1::Agg, N>, + G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, + G2 : SupportGenerator<N, Id=usize, RealField = F> + Clone, + G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, + G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, &'b G2 : std::ops::Neg<Output=G2> { - type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; + type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; #[inline] - fn sub(self, other : &'b BTFN<F, G2, BT2, N>) -> Self::Output { + fn sub(self, other : &'b BTFN<G2, BT2, N>) -> Self::Output { $preprocess(self).add_another(Arc::new((*other.generator).clone().neg())) } } } } -make_btfn_sub!(BTFN<F, G1, BT1, N>, std::convert::identity, ); -make_btfn_sub!(&'a BTFN<F, G1, BT1, N>, std::convert::identity, ); +make_btfn_sub!(BTFN<G1, BT1, N>, std::convert::identity, ); +make_btfn_sub!(&'a BTFN<G1, BT1, N>, std::convert::identity, ); macro_rules! make_btfn_scalarop_rhs { ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { impl<F : Float, G, BT, const N : usize> std::ops::$trait_assign<F> - for BTFN<F, G, BT, N> + for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> { + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { #[inline] fn $fn_assign(&mut self, t : F) { Arc::make_mut(&mut self.generator).$fn_assign(t); @@ -278,10 +276,10 @@ impl<F : Float, G, BT, const N : usize> std::ops::$trait<F> - for BTFN<F, G, BT, N> + for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> { + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { type Output = Self; #[inline] fn $fn(mut self, t : F) -> Self::Output { @@ -293,12 +291,12 @@ impl<'a, F : Float, G, BT, const N : usize> std::ops::$trait<F> - for &'a BTFN<F, G, BT, N> + for &'a BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N>, + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>, &'a G : std::ops::$trait<F,Output=G> { - type Output = BTFN<F, G, BT, N>; + type Output = BTFN<G, BT, N>; #[inline] fn $fn(self, t : F) -> Self::Output { self.new_generator(self.generator.$fn(t)) @@ -313,14 +311,14 @@ macro_rules! make_btfn_scalarop_lhs { ($trait:ident, $fn:ident, $fn_assign:ident, $($f:ident)+) => { $( impl<G, BT, const N : usize> - std::ops::$trait<BTFN<$f, G, BT, N>> + std::ops::$trait<BTFN<G, BT, N>> for $f where BT : BTImpl<$f, N>, - G : SupportGenerator<$f, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<$f, BT::Agg, N> { - type Output = BTFN<$f, G, BT, N>; + G : SupportGenerator<N, Id=BT::Data, RealField = $f>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<$f, N>> { + type Output = BTFN<G, BT, N>; #[inline] - fn $fn(self, mut a : BTFN<$f, G, BT, N>) -> Self::Output { + fn $fn(self, mut a : BTFN<G, BT, N>) -> Self::Output { Arc::make_mut(&mut a.generator).$fn_assign(self); a.refresh_aggregator(); a @@ -328,16 +326,16 @@ } impl<'a, G, BT, const N : usize> - std::ops::$trait<&'a BTFN<$f, G, BT, N>> + std::ops::$trait<&'a BTFN<G, BT, N>> for $f where BT : BTImpl<$f, N>, - G : SupportGenerator<$f, N, Id=BT::Data> + Clone, - G::SupportType : LocalAnalysis<$f, BT::Agg, N>, + G : SupportGenerator<N, Id=BT::Data, RealField = $f> + Clone, + G::SupportType : LocalAnalysis<BT::Agg, Cube<$f, N>>, // FIXME: This causes compiler overflow /*&'a G : std::ops::$trait<$f,Output=G>*/ { - type Output = BTFN<$f, G, BT, N>; + type Output = BTFN<G, BT, N>; #[inline] - fn $fn(self, a : &'a BTFN<$f, G, BT, N>) -> Self::Output { + fn $fn(self, a : &'a BTFN<G, BT, N>) -> Self::Output { let mut tmp = (*a.generator).clone(); tmp.$fn_assign(self); a.new_generator(tmp) @@ -355,10 +353,10 @@ ($trait:ident, $fn:ident) => { impl<F : Float, G, BT, const N : usize> std::ops::$trait - for BTFN<F, G, BT, N> + for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> { + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { type Output = Self; #[inline] fn $fn(mut self) -> Self::Output { @@ -391,10 +389,11 @@ // impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc<F, N>> -for BTFN<F, G, BT, N> +for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<&'a Loc<F, N>, Output = V>, + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> + + Apply<&'a Loc<F, N>, Output = V>, V : Sum { type Output = V; @@ -406,10 +405,11 @@ } impl<F : Float, G, BT, V, const N : usize> Apply<Loc<F, N>> -for BTFN<F, G, BT, N> +for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<Loc<F, N>, Output = V>, + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> + + Apply<Loc<F, N>, Output = V>, V : Sum { type Output = V; @@ -420,11 +420,13 @@ } } -impl<'a, F : Float, G, BT, V, const N : usize> Differentiable<&'a Loc<F, N>> -for BTFN<F, G, BT, N> +impl<'a, F : Float, G, BT, V : HasRealField<RealField=F>, const N : usize> +Differentiable<&'a Loc<F, N>> +for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<&'a Loc<F, N>, Derivative = V>, + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> + + Differentiable<&'a Loc<F, N>, Derivative = V>, V : Sum { type Derivative = V; @@ -437,11 +439,12 @@ } impl<F : Float, G, BT, V, const N : usize> Differentiable<Loc<F, N>> -for BTFN<F, G, BT, N> +for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<Loc<F, N>, Derivative = V>, - V : Sum { + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> + + Differentiable<Loc<F, N>, Derivative = V>, + V : Sum + HasRealField<RealField=F> { type Derivative = V; @@ -456,11 +459,11 @@ // GlobalAnalysis // -impl<F : Float, G, BT, const N : usize> GlobalAnalysis<F, BT::Agg> -for BTFN<F, G, BT, N> +impl<F : Float, G, BT, const N : usize> GlobalAnalysis<BT::Agg> +for BTFN<G, BT, N> where BT : BTImpl<F, N>, - G : SupportGenerator<F, N, Id=BT::Data>, - G::SupportType : LocalAnalysis<F, BT::Agg, N> { + G : SupportGenerator<N, Id=BT::Data, RealField = F>, + G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { #[inline] fn global_analysis(&self) -> BT::Agg { @@ -617,12 +620,12 @@ how : T, } -impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> +impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> for P2Refiner<F, RefineMax> where Cube<F, N> : P2Minimise<Loc<F, N>, F>, - G : SupportGenerator<F, N>, + G : SupportGenerator<N, RealField = F>, G::SupportType : Mapping<Loc<F, N>, Codomain=F> - + LocalAnalysis<F, Bounds<F>, N> { + + LocalAnalysis<Bounds<F>, Cube<F, N>> { type Result = Option<(Loc<F, N>, F)>; type Sorting = UpperBoundSorting<F>; @@ -674,12 +677,12 @@ } -impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> +impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> for P2Refiner<F, RefineMin> where Cube<F, N> : P2Minimise<Loc<F, N>, F>, - G : SupportGenerator<F, N>, + G : SupportGenerator<N, RealField = F>, G::SupportType : Mapping<Loc<F, N>, Codomain=F> - + LocalAnalysis<F, Bounds<F>, N> { + + LocalAnalysis<Bounds<F>, Cube<F, N>> { type Result = Option<(Loc<F, N>, F)>; type Sorting = LowerBoundSorting<F>; @@ -754,9 +757,9 @@ how : T, } -impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> +impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> for BoundRefiner<F, RefineMax> -where G : SupportGenerator<F, N> { +where G : SupportGenerator<N, RealField = F> { type Result = bool; type Sorting = UpperBoundSorting<F>; @@ -788,9 +791,9 @@ } } -impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> +impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> for BoundRefiner<F, RefineMin> -where G : SupportGenerator<F, N> { +where G : SupportGenerator<N, RealField = F> { type Result = bool; type Sorting = UpperBoundSorting<F>; @@ -837,11 +840,11 @@ // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, // the queue may run out, and we get “Refiner failure”. -impl<F : Float, G, BT, const N : usize> BTFN<F, G, BT, N> +impl<F : Float, G, BT, const N : usize> BTFN<G, BT, N> where BT : BTSearch<F, N, Agg=Bounds<F>>, - G : SupportGenerator<F, N, Id=BT::Data>, + G : SupportGenerator<N, Id=BT::Data, RealField = F>, G::SupportType : Mapping<Loc<F, N>,Codomain=F> - + LocalAnalysis<F, Bounds<F>, N>, + + LocalAnalysis<Bounds<F>, Cube<F, N>>, Cube<F, N> : P2Minimise<Loc<F, N>, F> { /// Maximise the `BTFN` within stated value `tolerance`.