| 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 { |