--- a/src/bisection_tree/bt.rs Thu May 01 08:40:33 2025 -0500 +++ b/src/bisection_tree/bt.rs Thu May 01 13:06:58 2025 -0500 @@ -51,7 +51,7 @@ #[derive(Clone, Debug)] pub(super) struct Branches<F: Num, D, A: Aggregator, const N: usize, const P: usize> { /// Point for subdivision of the (unstored) [`Cube`] corresponding to the node. - pub(super) branch_at: Loc<F, N>, + pub(super) branch_at: Loc<N, F>, /// Subnodes pub(super) nodes: [Node<F, D, A, N, P>; P], } @@ -184,7 +184,7 @@ /// /// This only takes the branch subdivision point $d$ into account, so is always succesfull. /// Thus, for this point, each branch corresponds to a quadrant of $ℝ^N$ relative to $d$. - fn get_node_index(&self, x: &Loc<F, N>) -> usize { + fn get_node_index(&self, x: &Loc<N, F>) -> usize { izip!(0..P, x.iter(), self.branch_at.iter()) .map(|(i, x_i, branch_i)| if x_i > branch_i { 1 << i } else { 0 }) .sum() @@ -195,25 +195,25 @@ /// This only takes the branch subdivision point $d$ into account, so is always succesfull. /// Thus, for this point, each branch corresponds to a quadrant of $ℝ^N$ relative to $d$. #[inline] - fn get_node(&self, x: &Loc<F, N>) -> &Node<F, D, A, N, P> { + fn get_node(&self, x: &Loc<N, F>) -> &Node<F, D, A, N, P> { &self.nodes[self.get_node_index(x)] } } /// An iterator over the $P=2^N$ subcubes of a [`Cube`] subdivided at a point `d`. pub(super) struct SubcubeIter<'b, F: Float, const N: usize, const P: usize> { - domain: &'b Cube<F, N>, - branch_at: Loc<F, N>, + domain: &'b Cube<N, F>, + branch_at: Loc<N, F>, index: usize, } /// Returns the `i`:th subcube of `domain` subdivided at `branch_at`. #[inline] fn get_subcube<F: Float, const N: usize>( - branch_at: &Loc<F, N>, - domain: &Cube<F, N>, + branch_at: &Loc<N, F>, + domain: &Cube<N, F>, i: usize, -) -> Cube<F, N> { +) -> Cube<N, F> { map2_indexed(branch_at, domain, move |j, &branch, &[start, end]| { if i & (1 << j) != 0 { [branch, end] @@ -225,7 +225,7 @@ } impl<'a, 'b, F: Float, const N: usize, const P: usize> Iterator for SubcubeIter<'b, F, N, P> { - type Item = Cube<F, N>; + type Item = Cube<N, F>; #[inline] fn next(&mut self) -> Option<Self::Item> { if self.index < P { @@ -246,8 +246,8 @@ { /// Creates a new node branching structure, subdividing `domain` based on the /// [hint][Support::support_hint] of `support`. - pub(super) fn new_with<S: LocalAnalysis<F, A, N> + Support<F, N>>( - domain: &Cube<F, N>, + pub(super) fn new_with<S: LocalAnalysis<F, A, N> + Support<N, F>>( + domain: &Cube<N, F>, support: &S, ) -> Self { let hint = support.bisection_hint(domain); @@ -272,7 +272,7 @@ /// Returns an iterator over the subcubes of `domain` subdivided at the branching point /// of `self`. #[inline] - pub(super) fn iter_subcubes<'b>(&self, domain: &'b Cube<F, N>) -> SubcubeIter<'b, F, N, P> { + pub(super) fn iter_subcubes<'b>(&self, domain: &'b Cube<N, F>) -> SubcubeIter<'b, F, N, P> { SubcubeIter { domain: domain, branch_at: self.branch_at, @@ -283,7 +283,7 @@ /* /// Returns an iterator over all nodes and corresponding subcubes of `self`. #[inline] - pub(super) fn nodes_and_cubes<'a, 'b>(&'a self, domain : &'b Cube<F, N>) + pub(super) fn nodes_and_cubes<'a, 'b>(&'a self, domain : &'b Cube<N, F>) -> std::iter::Zip<Iter<'a, Node<F,D,A,N,P>>, SubcubeIter<'b, F, N, P>> { self.nodes.iter().zip(self.iter_subcubes(domain)) } @@ -293,7 +293,7 @@ #[inline] pub(super) fn nodes_and_cubes_mut<'a, 'b>( &'a mut self, - domain: &'b Cube<F, N>, + domain: &'b Cube<N, F>, ) -> std::iter::Zip<IterMut<'a, Node<F, D, A, N, P>>, SubcubeIter<'b, F, N, P>> { let subcube_iter = self.iter_subcubes(domain); self.nodes.iter_mut().zip(subcube_iter) @@ -303,10 +303,10 @@ #[inline] fn recurse<'scope, 'smaller, 'refs>( &'smaller mut self, - domain: &'smaller Cube<F, N>, + domain: &'smaller Cube<N, F>, task_budget: TaskBudget<'scope, 'refs>, - guard: impl Fn(&Node<F, D, A, N, P>, &Cube<F, N>) -> bool + Send + 'smaller, - mut f: impl for<'a> FnMut(&mut Node<F, D, A, N, P>, &Cube<F, N>, TaskBudget<'smaller, 'a>) + guard: impl Fn(&Node<F, D, A, N, P>, &Cube<N, F>) -> bool + Send + 'smaller, + mut f: impl for<'a> FnMut(&mut Node<F, D, A, N, P>, &Cube<N, F>, TaskBudget<'smaller, 'a>) + Send + Copy + 'smaller, @@ -332,9 +332,9 @@ /// * `support` is the [`Support`] that is used determine with which subcubes of `domain` /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with. /// - pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<F, N>>( + pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<N, F>>( &mut self, - domain: &Cube<F, N>, + domain: &Cube<N, F>, d: D, new_leaf_depth: M, support: &S, @@ -360,11 +360,11 @@ pub(super) fn convert_aggregator<ANew, G>( self, generator: &G, - domain: &Cube<F, N>, + domain: &Cube<N, F>, ) -> Branches<F, D, ANew, N, P> where ANew: Aggregator, - G: SupportGenerator<F, N, Id = D>, + G: SupportGenerator<N, F, Id = D>, G::SupportType: LocalAnalysis<F, ANew, N>, { let branch_at = self.branch_at; @@ -387,10 +387,10 @@ pub(super) fn refresh_aggregator<'refs, 'scope, G>( &mut self, generator: &G, - domain: &Cube<F, N>, + domain: &Cube<N, F>, task_budget: TaskBudget<'scope, 'refs>, ) where - G: SupportGenerator<F, N, Id = D>, + G: SupportGenerator<N, F, Id = D>, G::SupportType: LocalAnalysis<F, A, N>, { self.recurse( @@ -422,7 +422,7 @@ /* /// Get leaf data #[inline] - pub(super) fn get_leaf_data(&self, x : &Loc<F, N>) -> Option<&Vec<D>> { + pub(super) fn get_leaf_data(&self, x : &Loc<N, F>) -> Option<&Vec<D>> { match self.data { NodeOption::Uninitialised => None, NodeOption::Leaf(ref data) => Some(data), @@ -432,7 +432,7 @@ /// Get leaf data iterator #[inline] - pub(super) fn get_leaf_data_iter(&self, x: &Loc<F, N>) -> Option<std::slice::Iter<'_, D>> { + pub(super) fn get_leaf_data_iter(&self, x: &Loc<N, F>) -> Option<std::slice::Iter<'_, D>> { match self.data { NodeOption::Uninitialised => None, NodeOption::Leaf(ref data) => Some(data.iter()), @@ -459,9 +459,9 @@ /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is /// created at a minimum depth of `new_leaf_depth`. - pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<F, N>>( + pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<N, F>>( &mut self, - domain: &Cube<F, N>, + domain: &Cube<N, F>, d: D, new_leaf_depth: M, support: &S, @@ -515,11 +515,11 @@ pub(super) fn convert_aggregator<ANew, G>( mut self, generator: &G, - domain: &Cube<F, N>, + domain: &Cube<N, F>, ) -> Node<F, D, ANew, N, P> where ANew: Aggregator, - G: SupportGenerator<F, N, Id = D>, + G: SupportGenerator<N, F, Id = D>, G::SupportType: LocalAnalysis<F, ANew, N>, { // The mem::replace is needed due to the [`Drop`] implementation to extract self.data. @@ -561,10 +561,10 @@ pub(super) fn refresh_aggregator<'refs, 'scope, G>( &mut self, generator: &G, - domain: &Cube<F, N>, + domain: &Cube<N, F>, task_budget: TaskBudget<'scope, 'refs>, ) where - G: SupportGenerator<F, N, Id = D>, + G: SupportGenerator<N, F, Id = D>, G::SupportType: LocalAnalysis<F, A, N>, { match &mut self.data { @@ -610,7 +610,7 @@ /// Basic interface to a [`BT`] bisection tree. /// /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait. -pub trait BTImpl<F: Float, const N: usize>: +pub trait BTImpl<const N: usize, F: Float = f64>: std::fmt::Debug + Clone + GlobalAnalysis<F, Self::Agg> { /// The data type stored in the tree @@ -621,7 +621,7 @@ /// of the tree. type Agg: Aggregator; /// The type of the tree with the aggregator converted to `ANew`. - type Converted<ANew>: BTImpl<F, N, Data = Self::Data, Agg = ANew> + type Converted<ANew>: BTImpl<N, F, Data = Self::Data, Agg = ANew> where ANew: Aggregator; @@ -629,7 +629,7 @@ /// /// Every leaf node of the tree that intersects the `support` will contain a copy of /// `d`. - fn insert<S: LocalAnalysis<F, Self::Agg, N> + Support<F, N>>( + fn insert<S: LocalAnalysis<F, Self::Agg, N> + Support<N, F>>( &mut self, d: Self::Data, support: &S, @@ -642,7 +642,7 @@ fn convert_aggregator<ANew, G>(self, generator: &G) -> Self::Converted<ANew> where ANew: Aggregator, - G: SupportGenerator<F, N, Id = Self::Data>, + G: SupportGenerator<N, F, Id = Self::Data>, G::SupportType: LocalAnalysis<F, ANew, N>; /// Refreshes the aggregator of the three after possible changes to the support generator. @@ -651,19 +651,19 @@ /// into corresponding [`Support`]s. fn refresh_aggregator<G>(&mut self, generator: &G) where - G: SupportGenerator<F, N, Id = Self::Data>, + G: SupportGenerator<N, F, Id = Self::Data>, G::SupportType: LocalAnalysis<F, Self::Agg, N>; /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain. - fn iter_at(&self, x: &Loc<F, N>) -> std::slice::Iter<'_, Self::Data>; + fn iter_at(&self, x: &Loc<N, F>) -> std::slice::Iter<'_, Self::Data>; /* /// Returns all [`Self::Data`] items at the point `x` of the domain. - fn data_at(&self, x : &Loc<F,N>) -> Arc<Vec<Self::Data>>; + fn data_at(&self, x : &Loc<N, F>) -> Arc<Vec<Self::Data>>; */ /// Create a new tree on `domain` of indicated `depth`. - fn new(domain: Cube<F, N>, depth: Self::Depth) -> Self; + fn new(domain: Cube<N, F>, depth: Self::Depth) -> Self; } /// The main bisection tree structure. @@ -679,7 +679,7 @@ /// The depth of the tree (initial, before refinement) pub(super) depth: M, /// The domain of the toplevel node - pub(super) domain: Cube<F, N>, + pub(super) domain: Cube<N, F>, /// The toplevel node of the tree pub(super) topnode: <BTNodeLookup as BTNode<F, D, A, N>>::Node, } @@ -693,7 +693,7 @@ type Node = Node<F,D,A,$n,{pow(2, $n)}>; } - impl<M,F,D,A> BTImpl<F,$n> for BT<M,F,D,A,$n> + impl<M,F,D,A> BTImpl<$n, F> for BT<M,F,D,A,$n> where M : Depth, F : Float, D : 'static + Copy + Send + Sync + std::fmt::Debug, @@ -703,7 +703,7 @@ type Agg = A; type Converted<ANew> = BT<M,F,D,ANew,$n> where ANew : Aggregator; - fn insert<S: LocalAnalysis<F, A, $n> + Support<F, $n>>( + fn insert<S: LocalAnalysis<F, A, $n> + Support< $n, F>>( &mut self, d : D, support : &S @@ -721,7 +721,7 @@ fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew> where ANew : Aggregator, - G : SupportGenerator<F, $n, Id=D>, + G : SupportGenerator< $n, F, Id=D>, G::SupportType : LocalAnalysis<F, ANew, $n> { let topnode = self.topnode.convert_aggregator(generator, &self.domain); @@ -733,22 +733,22 @@ } fn refresh_aggregator<G>(&mut self, generator : &G) - where G : SupportGenerator<F, $n, Id=Self::Data>, + where G : SupportGenerator< $n, F, Id=Self::Data>, G::SupportType : LocalAnalysis<F, Self::Agg, $n> { with_task_budget(|task_budget| self.topnode.refresh_aggregator(generator, &self.domain, task_budget) ) } - /*fn data_at(&self, x : &Loc<F,$n>) -> Arc<Vec<D>> { + /*fn data_at(&self, x : &Loc<$n, F>) -> Arc<Vec<D>> { self.topnode.get_leaf_data(x).unwrap_or_else(|| Arc::new(Vec::new())) }*/ - fn iter_at(&self, x : &Loc<F,$n>) -> std::slice::Iter<'_, D> { + fn iter_at(&self, x : &Loc<$n, F>) -> std::slice::Iter<'_, D> { self.topnode.get_leaf_data_iter(x).unwrap_or_else(|| [].iter()) } - fn new(domain : Cube<F, $n>, depth : M) -> Self { + fn new(domain : Cube<$n, F>, depth : M) -> Self { BT { depth : depth, domain : domain,