241 A : Aggregator, |
241 A : Aggregator, |
242 D : 'static + Copy + Send + Sync { |
242 D : 'static + Copy + Send + Sync { |
243 |
243 |
244 /// Creates a new node branching structure, subdividing `domain` based on the |
244 /// Creates a new node branching structure, subdividing `domain` based on the |
245 /// [hint][Support::support_hint] of `support`. |
245 /// [hint][Support::support_hint] of `support`. |
246 pub(super) fn new_with<S : LocalAnalysis <F, A, N>>( |
246 pub(super) fn new_with<S>( |
247 domain : &Cube<F,N>, |
247 domain : &Cube<F,N>, |
248 support : &S |
248 support : &S |
249 ) -> Self { |
249 ) -> Self |
|
250 where S : Support<N, RealField=F> + LocalAnalysis<A, Cube<F, N>> { |
250 let hint = support.bisection_hint(domain); |
251 let hint = support.bisection_hint(domain); |
251 let branch_at = map2(&hint, domain, |h, r| { |
252 let branch_at = map2(&hint, domain, |h, r| { |
252 h.unwrap_or_else(|| (r[0]+r[1])/F::TWO).max(r[0]).min(r[1]) |
253 h.unwrap_or_else(|| (r[0]+r[1])/F::TWO).max(r[0]).min(r[1]) |
253 }).into(); |
254 }).into(); |
254 Branches{ |
255 Branches{ |
319 /// * `d` is the data to be inserted |
320 /// * `d` is the data to be inserted |
320 /// * `new_leaf_depth` is the depth relative to `self` at which the data is to be inserted. |
321 /// * `new_leaf_depth` is the depth relative to `self` at which the data is to be inserted. |
321 /// * `support` is the [`Support`] that is used determine with which subcubes of `domain` |
322 /// * `support` is the [`Support`] that is used determine with which subcubes of `domain` |
322 /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with. |
323 /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with. |
323 /// |
324 /// |
324 pub(super) fn insert<'refs, 'scope, M : Depth, S : LocalAnalysis<F, A, N>>( |
325 pub(super) fn insert<'refs, 'scope, M : Depth, S>( |
325 &mut self, |
326 &mut self, |
326 domain : &Cube<F,N>, |
327 domain : &Cube<F,N>, |
327 d : D, |
328 d : D, |
328 new_leaf_depth : M, |
329 new_leaf_depth : M, |
329 support : &S, |
330 support : &S, |
330 task_budget : TaskBudget<'scope, 'refs>, |
331 task_budget : TaskBudget<'scope, 'refs>, |
331 ) { |
332 ) |
|
333 where S : Support<N, RealField=F> + LocalAnalysis<A, Cube<F, N>> { |
332 let support_hint = support.support_hint(); |
334 let support_hint = support.support_hint(); |
333 self.recurse(domain, task_budget, |
335 self.recurse(domain, task_budget, |
334 |_, subcube| support_hint.intersects(&subcube), |
336 |_, subcube| support_hint.intersects(&subcube), |
335 move |node, subcube, new_budget| node.insert(subcube, d, new_leaf_depth, support, |
337 move |node, subcube, new_budget| node.insert(subcube, d, new_leaf_depth, support, |
336 new_budget)); |
338 new_budget)); |
346 self, |
348 self, |
347 generator : &G, |
349 generator : &G, |
348 domain : &Cube<F, N> |
350 domain : &Cube<F, N> |
349 ) -> Branches<F,D,ANew,N,P> |
351 ) -> Branches<F,D,ANew,N,P> |
350 where ANew : Aggregator, |
352 where ANew : Aggregator, |
351 G : SupportGenerator<F, N, Id=D>, |
353 G : SupportGenerator<N, Id=D, RealField = F>, |
352 G::SupportType : LocalAnalysis<F, ANew, N> { |
354 G::SupportType : LocalAnalysis<ANew, Cube<F, N>> { |
353 let branch_at = self.branch_at; |
355 let branch_at = self.branch_at; |
354 let subcube_iter = self.iter_subcubes(domain); |
356 let subcube_iter = self.iter_subcubes(domain); |
355 let new_nodes = self.nodes.into_iter().zip(subcube_iter).map(|(node, subcube)| { |
357 let new_nodes = self.nodes.into_iter().zip(subcube_iter).map(|(node, subcube)| { |
356 Node::convert_aggregator(node, generator, &subcube) |
358 Node::convert_aggregator(node, generator, &subcube) |
357 }); |
359 }); |
368 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
370 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
369 &mut self, |
371 &mut self, |
370 generator : &G, |
372 generator : &G, |
371 domain : &Cube<F, N>, |
373 domain : &Cube<F, N>, |
372 task_budget : TaskBudget<'scope, 'refs>, |
374 task_budget : TaskBudget<'scope, 'refs>, |
373 ) where G : SupportGenerator<F, N, Id=D>, |
375 ) where G : SupportGenerator<N, Id=D, RealField = F>, |
374 G::SupportType : LocalAnalysis<F, A, N> { |
376 G::SupportType : LocalAnalysis<A, Cube<F, N>> { |
375 self.recurse(domain, task_budget, |
377 self.recurse(domain, task_budget, |
376 |_, _| true, |
378 |_, _| true, |
377 move |node, subcube, new_budget| node.refresh_aggregator(generator, subcube, |
379 move |node, subcube, new_budget| node.refresh_aggregator(generator, subcube, |
378 new_budget)); |
380 new_budget)); |
379 } |
381 } |
432 /// |
434 /// |
433 /// If `self` is already [`NodeOption::Leaf`], the data is inserted directly in this node. |
435 /// If `self` is already [`NodeOption::Leaf`], the data is inserted directly in this node. |
434 /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes |
436 /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes |
435 /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is |
437 /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is |
436 /// created at a minimum depth of `new_leaf_depth`. |
438 /// created at a minimum depth of `new_leaf_depth`. |
437 pub(super) fn insert<'refs, 'scope, M : Depth, S : LocalAnalysis <F, A, N>>( |
439 pub(super) fn insert<'refs, 'scope, M : Depth, S>( |
438 &mut self, |
440 &mut self, |
439 domain : &Cube<F,N>, |
441 domain : &Cube<F,N>, |
440 d : D, |
442 d : D, |
441 new_leaf_depth : M, |
443 new_leaf_depth : M, |
442 support : &S, |
444 support : &S, |
443 task_budget : TaskBudget<'scope, 'refs>, |
445 task_budget : TaskBudget<'scope, 'refs>, |
444 ) { |
446 ) |
|
447 where S : Support<N, RealField = F> + LocalAnalysis<A, Cube<F, N>> { |
445 match &mut self.data { |
448 match &mut self.data { |
446 NodeOption::Uninitialised => { |
449 NodeOption::Uninitialised => { |
447 // Replace uninitialised node with a leaf or a branch |
450 // Replace uninitialised node with a leaf or a branch |
448 self.data = match new_leaf_depth.lower() { |
451 self.data = match new_leaf_depth.lower() { |
449 None => { |
452 None => { |
491 mut self, |
494 mut self, |
492 generator : &G, |
495 generator : &G, |
493 domain : &Cube<F, N> |
496 domain : &Cube<F, N> |
494 ) -> Node<F,D,ANew,N,P> |
497 ) -> Node<F,D,ANew,N,P> |
495 where ANew : Aggregator, |
498 where ANew : Aggregator, |
496 G : SupportGenerator<F, N, Id=D>, |
499 G : SupportGenerator<N, Id=D, RealField = F>, |
497 G::SupportType : LocalAnalysis<F, ANew, N> { |
500 G::SupportType : LocalAnalysis<ANew, Cube<F, N>> { |
498 |
501 |
499 // The mem::replace is needed due to the [`Drop`] implementation to extract self.data. |
502 // The mem::replace is needed due to the [`Drop`] implementation to extract self.data. |
500 match std::mem::replace(&mut self.data, NodeOption::Uninitialised) { |
503 match std::mem::replace(&mut self.data, NodeOption::Uninitialised) { |
501 NodeOption::Uninitialised => Node { |
504 NodeOption::Uninitialised => Node { |
502 data : NodeOption::Uninitialised, |
505 data : NodeOption::Uninitialised, |
535 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
538 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
536 &mut self, |
539 &mut self, |
537 generator : &G, |
540 generator : &G, |
538 domain : &Cube<F, N>, |
541 domain : &Cube<F, N>, |
539 task_budget : TaskBudget<'scope, 'refs>, |
542 task_budget : TaskBudget<'scope, 'refs>, |
540 ) where G : SupportGenerator<F, N, Id=D>, |
543 ) where G : SupportGenerator<N, Id=D, RealField = F>, |
541 G::SupportType : LocalAnalysis<F, A, N> { |
544 G::SupportType : LocalAnalysis<A, Cube<F, N>> { |
542 match &mut self.data { |
545 match &mut self.data { |
543 NodeOption::Uninitialised => { }, |
546 NodeOption::Uninitialised => { }, |
544 NodeOption::Leaf(v) => { |
547 NodeOption::Leaf(v) => { |
545 self.aggregator = A::new(); |
548 self.aggregator = A::new(); |
546 self.aggregator.aggregate(v.iter().map(|d| { |
549 self.aggregator.aggregate(v.iter().map(|d| { |
578 pub struct BTNodeLookup; |
581 pub struct BTNodeLookup; |
579 |
582 |
580 /// Basic interface to a [`BT`] bisection tree. |
583 /// Basic interface to a [`BT`] bisection tree. |
581 /// |
584 /// |
582 /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait. |
585 /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait. |
583 pub trait BTImpl<F : Float, const N : usize> : std::fmt::Debug + Clone + GlobalAnalysis<F, Self::Agg> { |
586 pub trait BTImpl<F : Float, const N : usize> : std::fmt::Debug + Clone + GlobalAnalysis<Self::Agg> { |
584 /// The data type stored in the tree |
587 /// The data type stored in the tree |
585 type Data : 'static + Copy + Send + Sync; |
588 type Data : 'static + Copy + Send + Sync; |
586 /// The depth type of the tree |
589 /// The depth type of the tree |
587 type Depth : Depth; |
590 type Depth : Depth; |
588 /// The type for the [aggregate information][Aggregator] about the `Data` stored in each node |
591 /// The type for the [aggregate information][Aggregator] about the `Data` stored in each node |
593 |
596 |
594 /// Insert the data `d` into the tree for `support`. |
597 /// Insert the data `d` into the tree for `support`. |
595 /// |
598 /// |
596 /// Every leaf node of the tree that intersects the `support` will contain a copy of |
599 /// Every leaf node of the tree that intersects the `support` will contain a copy of |
597 /// `d`. |
600 /// `d`. |
598 fn insert<S : LocalAnalysis<F, Self::Agg, N>>( |
601 fn insert<S>( |
599 &mut self, |
602 &mut self, |
600 d : Self::Data, |
603 d : Self::Data, |
601 support : &S |
604 support : &S |
602 ); |
605 ) |
|
606 where S: Support<N, RealField=F> + LocalAnalysis<Self::Agg, Cube<F, N>>; |
603 |
607 |
604 /// Construct a new instance of the tree for a different aggregator |
608 /// Construct a new instance of the tree for a different aggregator |
605 /// |
609 /// |
606 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
610 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
607 /// into corresponding [`Support`]s. |
611 /// into corresponding [`Support`]s. |
608 fn convert_aggregator<ANew, G>(self, generator : &G) |
612 fn convert_aggregator<ANew, G>(self, generator : &G) |
609 -> Self::Converted<ANew> |
613 -> Self::Converted<ANew> |
610 where ANew : Aggregator, |
614 where ANew : Aggregator, |
611 G : SupportGenerator<F, N, Id=Self::Data>, |
615 G : SupportGenerator< N, Id=Self::Data, RealField = F>, |
612 G::SupportType : LocalAnalysis<F, ANew, N>; |
616 G::SupportType : LocalAnalysis<ANew, Cube<F, N>>; |
613 |
617 |
614 |
618 |
615 /// Refreshes the aggregator of the three after possible changes to the support generator. |
619 /// Refreshes the aggregator of the three after possible changes to the support generator. |
616 /// |
620 /// |
617 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
621 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
618 /// into corresponding [`Support`]s. |
622 /// into corresponding [`Support`]s. |
619 fn refresh_aggregator<G>(&mut self, generator : &G) |
623 fn refresh_aggregator<G>(&mut self, generator : &G) |
620 where G : SupportGenerator<F, N, Id=Self::Data>, |
624 where G : SupportGenerator<N, Id=Self::Data, RealField = F>, |
621 G::SupportType : LocalAnalysis<F, Self::Agg, N>; |
625 G::SupportType : LocalAnalysis<Self::Agg, Cube<F, N>>; |
622 |
626 |
623 /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain. |
627 /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain. |
624 fn iter_at(&self, x : &Loc<F,N>) -> std::slice::Iter<'_, Self::Data>; |
628 fn iter_at(&self, x : &Loc<F,N>) -> std::slice::Iter<'_, Self::Data>; |
625 |
629 |
626 /* |
630 /* |
688 ) |
693 ) |
689 } |
694 } |
690 |
695 |
691 fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew> |
696 fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew> |
692 where ANew : Aggregator, |
697 where ANew : Aggregator, |
693 G : SupportGenerator<F, $n, Id=D>, |
698 G : SupportGenerator<$n, Id=D, RealField = F>, |
694 G::SupportType : LocalAnalysis<F, ANew, $n> { |
699 G::SupportType : LocalAnalysis<ANew, Cube<F, $n>> { |
695 let topnode = self.topnode.convert_aggregator(generator, &self.domain); |
700 let topnode = self.topnode.convert_aggregator(generator, &self.domain); |
696 |
701 |
697 BT { |
702 BT { |
698 depth : self.depth, |
703 depth : self.depth, |
699 domain : self.domain, |
704 domain : self.domain, |
700 topnode |
705 topnode |
701 } |
706 } |
702 } |
707 } |
703 |
708 |
704 fn refresh_aggregator<G>(&mut self, generator : &G) |
709 fn refresh_aggregator<G>(&mut self, generator : &G) |
705 where G : SupportGenerator<F, $n, Id=Self::Data>, |
710 where G : SupportGenerator<$n, Id=Self::Data, RealField = F>, |
706 G::SupportType : LocalAnalysis<F, Self::Agg, $n> { |
711 G::SupportType : LocalAnalysis<Self::Agg, Cube<F, $n>> { |
707 with_task_budget(|task_budget| |
712 with_task_budget(|task_budget| |
708 self.topnode.refresh_aggregator(generator, &self.domain, task_budget) |
713 self.topnode.refresh_aggregator(generator, &self.domain, task_budget) |
709 ) |
714 ) |
710 } |
715 } |
711 |
716 |
724 topnode : Node::new(), |
729 topnode : Node::new(), |
725 } |
730 } |
726 } |
731 } |
727 } |
732 } |
728 |
733 |
729 impl<M,F,D,A> GlobalAnalysis<F,A> for BT<M,F,D,A,$n> |
734 impl<M,F,D,A> GlobalAnalysis<A> for BT<M,F,D,A,$n> |
730 where M : Depth, |
735 where M : Depth, |
731 F : Float, |
736 F : Float, |
732 D : 'static + Copy + Send + Sync + std::fmt::Debug, |
737 D : 'static + Copy + Send + Sync + std::fmt::Debug, |
733 A : Aggregator { |
738 A : Aggregator { |
734 fn global_analysis(&self) -> A { |
739 fn global_analysis(&self) -> A { |