| 49 /// |
49 /// |
| 50 /// For the type and const parameters, see the [module level documentation][super]. |
50 /// For the type and const parameters, see the [module level documentation][super]. |
| 51 #[derive(Clone, Debug)] |
51 #[derive(Clone, Debug)] |
| 52 pub(super) struct Branches<F: Num, D, A: Aggregator, const N: usize, const P: usize> { |
52 pub(super) struct Branches<F: Num, D, A: Aggregator, const N: usize, const P: usize> { |
| 53 /// Point for subdivision of the (unstored) [`Cube`] corresponding to the node. |
53 /// Point for subdivision of the (unstored) [`Cube`] corresponding to the node. |
| 54 pub(super) branch_at: Loc<F, N>, |
54 pub(super) branch_at: Loc<N, F>, |
| 55 /// Subnodes |
55 /// Subnodes |
| 56 pub(super) nodes: [Node<F, D, A, N, P>; P], |
56 pub(super) nodes: [Node<F, D, A, N, P>; P], |
| 57 } |
57 } |
| 58 |
58 |
| 59 /// Dirty workaround to broken Rust drop, see [https://github.com/rust-lang/rust/issues/58068](). |
59 /// Dirty workaround to broken Rust drop, see [https://github.com/rust-lang/rust/issues/58068](). |
| 182 { |
182 { |
| 183 /// Returns the index in {0, …, `P`-1} for the branch to which the point `x` corresponds. |
183 /// Returns the index in {0, …, `P`-1} for the branch to which the point `x` corresponds. |
| 184 /// |
184 /// |
| 185 /// This only takes the branch subdivision point $d$ into account, so is always succesfull. |
185 /// This only takes the branch subdivision point $d$ into account, so is always succesfull. |
| 186 /// Thus, for this point, each branch corresponds to a quadrant of $ℝ^N$ relative to $d$. |
186 /// Thus, for this point, each branch corresponds to a quadrant of $ℝ^N$ relative to $d$. |
| 187 fn get_node_index(&self, x: &Loc<F, N>) -> usize { |
187 fn get_node_index(&self, x: &Loc<N, F>) -> usize { |
| 188 izip!(0..P, x.iter(), self.branch_at.iter()) |
188 izip!(0..P, x.iter(), self.branch_at.iter()) |
| 189 .map(|(i, x_i, branch_i)| if x_i > branch_i { 1 << i } else { 0 }) |
189 .map(|(i, x_i, branch_i)| if x_i > branch_i { 1 << i } else { 0 }) |
| 190 .sum() |
190 .sum() |
| 191 } |
191 } |
| 192 |
192 |
| 193 /// Returns the node within `Self` containing the point `x`. |
193 /// Returns the node within `Self` containing the point `x`. |
| 194 /// |
194 /// |
| 195 /// This only takes the branch subdivision point $d$ into account, so is always succesfull. |
195 /// This only takes the branch subdivision point $d$ into account, so is always succesfull. |
| 196 /// Thus, for this point, each branch corresponds to a quadrant of $ℝ^N$ relative to $d$. |
196 /// Thus, for this point, each branch corresponds to a quadrant of $ℝ^N$ relative to $d$. |
| 197 #[inline] |
197 #[inline] |
| 198 fn get_node(&self, x: &Loc<F, N>) -> &Node<F, D, A, N, P> { |
198 fn get_node(&self, x: &Loc<N, F>) -> &Node<F, D, A, N, P> { |
| 199 &self.nodes[self.get_node_index(x)] |
199 &self.nodes[self.get_node_index(x)] |
| 200 } |
200 } |
| 201 } |
201 } |
| 202 |
202 |
| 203 /// An iterator over the $P=2^N$ subcubes of a [`Cube`] subdivided at a point `d`. |
203 /// An iterator over the $P=2^N$ subcubes of a [`Cube`] subdivided at a point `d`. |
| 204 pub(super) struct SubcubeIter<'b, F: Float, const N: usize, const P: usize> { |
204 pub(super) struct SubcubeIter<'b, F: Float, const N: usize, const P: usize> { |
| 205 domain: &'b Cube<F, N>, |
205 domain: &'b Cube<N, F>, |
| 206 branch_at: Loc<F, N>, |
206 branch_at: Loc<N, F>, |
| 207 index: usize, |
207 index: usize, |
| 208 } |
208 } |
| 209 |
209 |
| 210 /// Returns the `i`:th subcube of `domain` subdivided at `branch_at`. |
210 /// Returns the `i`:th subcube of `domain` subdivided at `branch_at`. |
| 211 #[inline] |
211 #[inline] |
| 212 fn get_subcube<F: Float, const N: usize>( |
212 fn get_subcube<F: Float, const N: usize>( |
| 213 branch_at: &Loc<F, N>, |
213 branch_at: &Loc<N, F>, |
| 214 domain: &Cube<F, N>, |
214 domain: &Cube<N, F>, |
| 215 i: usize, |
215 i: usize, |
| 216 ) -> Cube<F, N> { |
216 ) -> Cube<N, F> { |
| 217 map2_indexed(branch_at, domain, move |j, &branch, &[start, end]| { |
217 map2_indexed(branch_at, domain, move |j, &branch, &[start, end]| { |
| 218 if i & (1 << j) != 0 { |
218 if i & (1 << j) != 0 { |
| 219 [branch, end] |
219 [branch, end] |
| 220 } else { |
220 } else { |
| 221 [start, branch] |
221 [start, branch] |
| 244 A: Aggregator, |
244 A: Aggregator, |
| 245 D: 'static + Copy + Send + Sync, |
245 D: 'static + Copy + Send + Sync, |
| 246 { |
246 { |
| 247 /// Creates a new node branching structure, subdividing `domain` based on the |
247 /// Creates a new node branching structure, subdividing `domain` based on the |
| 248 /// [hint][Support::support_hint] of `support`. |
248 /// [hint][Support::support_hint] of `support`. |
| 249 pub(super) fn new_with<S: LocalAnalysis<F, A, N> + Support<F, N>>( |
249 pub(super) fn new_with<S: LocalAnalysis<F, A, N> + Support<N, F>>( |
| 250 domain: &Cube<F, N>, |
250 domain: &Cube<N, F>, |
| 251 support: &S, |
251 support: &S, |
| 252 ) -> Self { |
252 ) -> Self { |
| 253 let hint = support.bisection_hint(domain); |
253 let hint = support.bisection_hint(domain); |
| 254 let branch_at = map2(&hint, domain, |h, r| { |
254 let branch_at = map2(&hint, domain, |h, r| { |
| 255 h.unwrap_or_else(|| (r[0] + r[1]) / F::TWO) |
255 h.unwrap_or_else(|| (r[0] + r[1]) / F::TWO) |
| 270 } |
270 } |
| 271 |
271 |
| 272 /// Returns an iterator over the subcubes of `domain` subdivided at the branching point |
272 /// Returns an iterator over the subcubes of `domain` subdivided at the branching point |
| 273 /// of `self`. |
273 /// of `self`. |
| 274 #[inline] |
274 #[inline] |
| 275 pub(super) fn iter_subcubes<'b>(&self, domain: &'b Cube<F, N>) -> SubcubeIter<'b, F, N, P> { |
275 pub(super) fn iter_subcubes<'b>(&self, domain: &'b Cube<N, F>) -> SubcubeIter<'b, F, N, P> { |
| 276 SubcubeIter { |
276 SubcubeIter { |
| 277 domain: domain, |
277 domain: domain, |
| 278 branch_at: self.branch_at, |
278 branch_at: self.branch_at, |
| 279 index: 0, |
279 index: 0, |
| 280 } |
280 } |
| 281 } |
281 } |
| 282 |
282 |
| 283 /* |
283 /* |
| 284 /// Returns an iterator over all nodes and corresponding subcubes of `self`. |
284 /// Returns an iterator over all nodes and corresponding subcubes of `self`. |
| 285 #[inline] |
285 #[inline] |
| 286 pub(super) fn nodes_and_cubes<'a, 'b>(&'a self, domain : &'b Cube<F, N>) |
286 pub(super) fn nodes_and_cubes<'a, 'b>(&'a self, domain : &'b Cube<N, F>) |
| 287 -> std::iter::Zip<Iter<'a, Node<F,D,A,N,P>>, SubcubeIter<'b, F, N, P>> { |
287 -> std::iter::Zip<Iter<'a, Node<F,D,A,N,P>>, SubcubeIter<'b, F, N, P>> { |
| 288 self.nodes.iter().zip(self.iter_subcubes(domain)) |
288 self.nodes.iter().zip(self.iter_subcubes(domain)) |
| 289 } |
289 } |
| 290 */ |
290 */ |
| 291 |
291 |
| 292 /// Mutably iterate over all nodes and corresponding subcubes of `self`. |
292 /// Mutably iterate over all nodes and corresponding subcubes of `self`. |
| 293 #[inline] |
293 #[inline] |
| 294 pub(super) fn nodes_and_cubes_mut<'a, 'b>( |
294 pub(super) fn nodes_and_cubes_mut<'a, 'b>( |
| 295 &'a mut self, |
295 &'a mut self, |
| 296 domain: &'b Cube<F, N>, |
296 domain: &'b Cube<N, F>, |
| 297 ) -> std::iter::Zip<IterMut<'a, Node<F, D, A, N, P>>, SubcubeIter<'b, F, N, P>> { |
297 ) -> std::iter::Zip<IterMut<'a, Node<F, D, A, N, P>>, SubcubeIter<'b, F, N, P>> { |
| 298 let subcube_iter = self.iter_subcubes(domain); |
298 let subcube_iter = self.iter_subcubes(domain); |
| 299 self.nodes.iter_mut().zip(subcube_iter) |
299 self.nodes.iter_mut().zip(subcube_iter) |
| 300 } |
300 } |
| 301 |
301 |
| 302 /// Call `f` on all `(subnode, subcube)` pairs in multiple threads, if `guard` so deems. |
302 /// Call `f` on all `(subnode, subcube)` pairs in multiple threads, if `guard` so deems. |
| 303 #[inline] |
303 #[inline] |
| 304 fn recurse<'scope, 'smaller, 'refs>( |
304 fn recurse<'scope, 'smaller, 'refs>( |
| 305 &'smaller mut self, |
305 &'smaller mut self, |
| 306 domain: &'smaller Cube<F, N>, |
306 domain: &'smaller Cube<N, F>, |
| 307 task_budget: TaskBudget<'scope, 'refs>, |
307 task_budget: TaskBudget<'scope, 'refs>, |
| 308 guard: impl Fn(&Node<F, D, A, N, P>, &Cube<F, N>) -> bool + Send + 'smaller, |
308 guard: impl Fn(&Node<F, D, A, N, P>, &Cube<N, F>) -> bool + Send + 'smaller, |
| 309 mut f: impl for<'a> FnMut(&mut Node<F, D, A, N, P>, &Cube<F, N>, TaskBudget<'smaller, 'a>) |
309 mut f: impl for<'a> FnMut(&mut Node<F, D, A, N, P>, &Cube<N, F>, TaskBudget<'smaller, 'a>) |
| 310 + Send |
310 + Send |
| 311 + Copy |
311 + Copy |
| 312 + 'smaller, |
312 + 'smaller, |
| 313 ) where |
313 ) where |
| 314 'scope: 'smaller, |
314 'scope: 'smaller, |
| 330 /// * `d` is the data to be inserted |
330 /// * `d` is the data to be inserted |
| 331 /// * `new_leaf_depth` is the depth relative to `self` at which the data is to be inserted. |
331 /// * `new_leaf_depth` is the depth relative to `self` at which the data is to be inserted. |
| 332 /// * `support` is the [`Support`] that is used determine with which subcubes of `domain` |
332 /// * `support` is the [`Support`] that is used determine with which subcubes of `domain` |
| 333 /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with. |
333 /// (at subdivision depth `new_leaf_depth`) the data `d` is to be associated with. |
| 334 /// |
334 /// |
| 335 pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<F, N>>( |
335 pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<N, F>>( |
| 336 &mut self, |
336 &mut self, |
| 337 domain: &Cube<F, N>, |
337 domain: &Cube<N, F>, |
| 338 d: D, |
338 d: D, |
| 339 new_leaf_depth: M, |
339 new_leaf_depth: M, |
| 340 support: &S, |
340 support: &S, |
| 341 task_budget: TaskBudget<'scope, 'refs>, |
341 task_budget: TaskBudget<'scope, 'refs>, |
| 342 ) { |
342 ) { |
| 358 /// The type parameter `ANew´ is the new aggregator, and needs to be implemented for the |
358 /// The type parameter `ANew´ is the new aggregator, and needs to be implemented for the |
| 359 /// generator's `SupportType`. |
359 /// generator's `SupportType`. |
| 360 pub(super) fn convert_aggregator<ANew, G>( |
360 pub(super) fn convert_aggregator<ANew, G>( |
| 361 self, |
361 self, |
| 362 generator: &G, |
362 generator: &G, |
| 363 domain: &Cube<F, N>, |
363 domain: &Cube<N, F>, |
| 364 ) -> Branches<F, D, ANew, N, P> |
364 ) -> Branches<F, D, ANew, N, P> |
| 365 where |
365 where |
| 366 ANew: Aggregator, |
366 ANew: Aggregator, |
| 367 G: SupportGenerator<F, N, Id = D>, |
367 G: SupportGenerator<N, F, Id = D>, |
| 368 G::SupportType: LocalAnalysis<F, ANew, N>, |
368 G::SupportType: LocalAnalysis<F, ANew, N>, |
| 369 { |
369 { |
| 370 let branch_at = self.branch_at; |
370 let branch_at = self.branch_at; |
| 371 let subcube_iter = self.iter_subcubes(domain); |
371 let subcube_iter = self.iter_subcubes(domain); |
| 372 let new_nodes = self |
372 let new_nodes = self |
| 385 /// The `generator` is used to convert the data of type `D` of the branch into corresponding |
385 /// The `generator` is used to convert the data of type `D` of the branch into corresponding |
| 386 /// [`Support`]s. The `domain` is the cube corresponding to `self`. |
386 /// [`Support`]s. The `domain` is the cube corresponding to `self`. |
| 387 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
387 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
| 388 &mut self, |
388 &mut self, |
| 389 generator: &G, |
389 generator: &G, |
| 390 domain: &Cube<F, N>, |
390 domain: &Cube<N, F>, |
| 391 task_budget: TaskBudget<'scope, 'refs>, |
391 task_budget: TaskBudget<'scope, 'refs>, |
| 392 ) where |
392 ) where |
| 393 G: SupportGenerator<F, N, Id = D>, |
393 G: SupportGenerator<N, F, Id = D>, |
| 394 G::SupportType: LocalAnalysis<F, A, N>, |
394 G::SupportType: LocalAnalysis<F, A, N>, |
| 395 { |
395 { |
| 396 self.recurse( |
396 self.recurse( |
| 397 domain, |
397 domain, |
| 398 task_budget, |
398 task_budget, |
| 420 } |
420 } |
| 421 |
421 |
| 422 /* |
422 /* |
| 423 /// Get leaf data |
423 /// Get leaf data |
| 424 #[inline] |
424 #[inline] |
| 425 pub(super) fn get_leaf_data(&self, x : &Loc<F, N>) -> Option<&Vec<D>> { |
425 pub(super) fn get_leaf_data(&self, x : &Loc<N, F>) -> Option<&Vec<D>> { |
| 426 match self.data { |
426 match self.data { |
| 427 NodeOption::Uninitialised => None, |
427 NodeOption::Uninitialised => None, |
| 428 NodeOption::Leaf(ref data) => Some(data), |
428 NodeOption::Leaf(ref data) => Some(data), |
| 429 NodeOption::Branches(ref b) => b.get_node(x).get_leaf_data(x), |
429 NodeOption::Branches(ref b) => b.get_node(x).get_leaf_data(x), |
| 430 } |
430 } |
| 431 }*/ |
431 }*/ |
| 432 |
432 |
| 433 /// Get leaf data iterator |
433 /// Get leaf data iterator |
| 434 #[inline] |
434 #[inline] |
| 435 pub(super) fn get_leaf_data_iter(&self, x: &Loc<F, N>) -> Option<std::slice::Iter<'_, D>> { |
435 pub(super) fn get_leaf_data_iter(&self, x: &Loc<N, F>) -> Option<std::slice::Iter<'_, D>> { |
| 436 match self.data { |
436 match self.data { |
| 437 NodeOption::Uninitialised => None, |
437 NodeOption::Uninitialised => None, |
| 438 NodeOption::Leaf(ref data) => Some(data.iter()), |
438 NodeOption::Leaf(ref data) => Some(data.iter()), |
| 439 NodeOption::Branches(ref b) => b.get_node(x).get_leaf_data_iter(x), |
439 NodeOption::Branches(ref b) => b.get_node(x).get_leaf_data_iter(x), |
| 440 } |
440 } |
| 457 /// |
457 /// |
| 458 /// If `self` is already [`NodeOption::Leaf`], the data is inserted directly in this node. |
458 /// If `self` is already [`NodeOption::Leaf`], the data is inserted directly in this node. |
| 459 /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes |
459 /// If `self` is a [`NodeOption::Branches`], the data is passed to branches whose subcubes |
| 460 /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is |
460 /// `support` intersects. If an [`NodeOption::Uninitialised`] node is encountered, a new leaf is |
| 461 /// created at a minimum depth of `new_leaf_depth`. |
461 /// created at a minimum depth of `new_leaf_depth`. |
| 462 pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<F, N>>( |
462 pub(super) fn insert<'refs, 'scope, M: Depth, S: LocalAnalysis<F, A, N> + Support<N, F>>( |
| 463 &mut self, |
463 &mut self, |
| 464 domain: &Cube<F, N>, |
464 domain: &Cube<N, F>, |
| 465 d: D, |
465 d: D, |
| 466 new_leaf_depth: M, |
466 new_leaf_depth: M, |
| 467 support: &S, |
467 support: &S, |
| 468 task_budget: TaskBudget<'scope, 'refs>, |
468 task_budget: TaskBudget<'scope, 'refs>, |
| 469 ) { |
469 ) { |
| 513 /// The type parameter `ANew´ is the new aggregator, and needs to be implemented for the |
513 /// The type parameter `ANew´ is the new aggregator, and needs to be implemented for the |
| 514 /// generator's `SupportType`. |
514 /// generator's `SupportType`. |
| 515 pub(super) fn convert_aggregator<ANew, G>( |
515 pub(super) fn convert_aggregator<ANew, G>( |
| 516 mut self, |
516 mut self, |
| 517 generator: &G, |
517 generator: &G, |
| 518 domain: &Cube<F, N>, |
518 domain: &Cube<N, F>, |
| 519 ) -> Node<F, D, ANew, N, P> |
519 ) -> Node<F, D, ANew, N, P> |
| 520 where |
520 where |
| 521 ANew: Aggregator, |
521 ANew: Aggregator, |
| 522 G: SupportGenerator<F, N, Id = D>, |
522 G: SupportGenerator<N, F, Id = D>, |
| 523 G::SupportType: LocalAnalysis<F, ANew, N>, |
523 G::SupportType: LocalAnalysis<F, ANew, N>, |
| 524 { |
524 { |
| 525 // The mem::replace is needed due to the [`Drop`] implementation to extract self.data. |
525 // The mem::replace is needed due to the [`Drop`] implementation to extract self.data. |
| 526 match std::mem::replace(&mut self.data, NodeOption::Uninitialised) { |
526 match std::mem::replace(&mut self.data, NodeOption::Uninitialised) { |
| 527 NodeOption::Uninitialised => Node { |
527 NodeOption::Uninitialised => Node { |
| 559 /// The `generator` is used to convert the data of type `D` of the node into corresponding |
559 /// The `generator` is used to convert the data of type `D` of the node into corresponding |
| 560 /// [`Support`]s. The `domain` is the cube corresponding to `self`. |
560 /// [`Support`]s. The `domain` is the cube corresponding to `self`. |
| 561 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
561 pub(super) fn refresh_aggregator<'refs, 'scope, G>( |
| 562 &mut self, |
562 &mut self, |
| 563 generator: &G, |
563 generator: &G, |
| 564 domain: &Cube<F, N>, |
564 domain: &Cube<N, F>, |
| 565 task_budget: TaskBudget<'scope, 'refs>, |
565 task_budget: TaskBudget<'scope, 'refs>, |
| 566 ) where |
566 ) where |
| 567 G: SupportGenerator<F, N, Id = D>, |
567 G: SupportGenerator<N, F, Id = D>, |
| 568 G::SupportType: LocalAnalysis<F, A, N>, |
568 G::SupportType: LocalAnalysis<F, A, N>, |
| 569 { |
569 { |
| 570 match &mut self.data { |
570 match &mut self.data { |
| 571 NodeOption::Uninitialised => {} |
571 NodeOption::Uninitialised => {} |
| 572 NodeOption::Leaf(v) => { |
572 NodeOption::Leaf(v) => { |
| 608 pub struct BTNodeLookup; |
608 pub struct BTNodeLookup; |
| 609 |
609 |
| 610 /// Basic interface to a [`BT`] bisection tree. |
610 /// Basic interface to a [`BT`] bisection tree. |
| 611 /// |
611 /// |
| 612 /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait. |
612 /// Further routines are provided by the [`BTSearch`][super::refine::BTSearch] trait. |
| 613 pub trait BTImpl<F: Float, const N: usize>: |
613 pub trait BTImpl<const N: usize, F: Float = f64>: |
| 614 std::fmt::Debug + Clone + GlobalAnalysis<F, Self::Agg> |
614 std::fmt::Debug + Clone + GlobalAnalysis<F, Self::Agg> |
| 615 { |
615 { |
| 616 /// The data type stored in the tree |
616 /// The data type stored in the tree |
| 617 type Data: 'static + Copy + Send + Sync; |
617 type Data: 'static + Copy + Send + Sync; |
| 618 /// The depth type of the tree |
618 /// The depth type of the tree |
| 619 type Depth: Depth; |
619 type Depth: Depth; |
| 620 /// The type for the [aggregate information][Aggregator] about the `Data` stored in each node |
620 /// The type for the [aggregate information][Aggregator] about the `Data` stored in each node |
| 621 /// of the tree. |
621 /// of the tree. |
| 622 type Agg: Aggregator; |
622 type Agg: Aggregator; |
| 623 /// The type of the tree with the aggregator converted to `ANew`. |
623 /// The type of the tree with the aggregator converted to `ANew`. |
| 624 type Converted<ANew>: BTImpl<F, N, Data = Self::Data, Agg = ANew> |
624 type Converted<ANew>: BTImpl<N, F, Data = Self::Data, Agg = ANew> |
| 625 where |
625 where |
| 626 ANew: Aggregator; |
626 ANew: Aggregator; |
| 627 |
627 |
| 628 /// Insert the data `d` into the tree for `support`. |
628 /// Insert the data `d` into the tree for `support`. |
| 629 /// |
629 /// |
| 630 /// Every leaf node of the tree that intersects the `support` will contain a copy of |
630 /// Every leaf node of the tree that intersects the `support` will contain a copy of |
| 631 /// `d`. |
631 /// `d`. |
| 632 fn insert<S: LocalAnalysis<F, Self::Agg, N> + Support<F, N>>( |
632 fn insert<S: LocalAnalysis<F, Self::Agg, N> + Support<N, F>>( |
| 633 &mut self, |
633 &mut self, |
| 634 d: Self::Data, |
634 d: Self::Data, |
| 635 support: &S, |
635 support: &S, |
| 636 ); |
636 ); |
| 637 |
637 |
| 640 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
640 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
| 641 /// into corresponding [`Support`]s. |
641 /// into corresponding [`Support`]s. |
| 642 fn convert_aggregator<ANew, G>(self, generator: &G) -> Self::Converted<ANew> |
642 fn convert_aggregator<ANew, G>(self, generator: &G) -> Self::Converted<ANew> |
| 643 where |
643 where |
| 644 ANew: Aggregator, |
644 ANew: Aggregator, |
| 645 G: SupportGenerator<F, N, Id = Self::Data>, |
645 G: SupportGenerator<N, F, Id = Self::Data>, |
| 646 G::SupportType: LocalAnalysis<F, ANew, N>; |
646 G::SupportType: LocalAnalysis<F, ANew, N>; |
| 647 |
647 |
| 648 /// Refreshes the aggregator of the three after possible changes to the support generator. |
648 /// Refreshes the aggregator of the three after possible changes to the support generator. |
| 649 /// |
649 /// |
| 650 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
650 /// The `generator` is used to convert the data of type [`Self::Data`] contained in the tree |
| 651 /// into corresponding [`Support`]s. |
651 /// into corresponding [`Support`]s. |
| 652 fn refresh_aggregator<G>(&mut self, generator: &G) |
652 fn refresh_aggregator<G>(&mut self, generator: &G) |
| 653 where |
653 where |
| 654 G: SupportGenerator<F, N, Id = Self::Data>, |
654 G: SupportGenerator<N, F, Id = Self::Data>, |
| 655 G::SupportType: LocalAnalysis<F, Self::Agg, N>; |
655 G::SupportType: LocalAnalysis<F, Self::Agg, N>; |
| 656 |
656 |
| 657 /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain. |
657 /// Returns an iterator over all [`Self::Data`] items at the point `x` of the domain. |
| 658 fn iter_at(&self, x: &Loc<F, N>) -> std::slice::Iter<'_, Self::Data>; |
658 fn iter_at(&self, x: &Loc<N, F>) -> std::slice::Iter<'_, Self::Data>; |
| 659 |
659 |
| 660 /* |
660 /* |
| 661 /// Returns all [`Self::Data`] items at the point `x` of the domain. |
661 /// Returns all [`Self::Data`] items at the point `x` of the domain. |
| 662 fn data_at(&self, x : &Loc<F,N>) -> Arc<Vec<Self::Data>>; |
662 fn data_at(&self, x : &Loc<N, F>) -> Arc<Vec<Self::Data>>; |
| 663 */ |
663 */ |
| 664 |
664 |
| 665 /// Create a new tree on `domain` of indicated `depth`. |
665 /// Create a new tree on `domain` of indicated `depth`. |
| 666 fn new(domain: Cube<F, N>, depth: Self::Depth) -> Self; |
666 fn new(domain: Cube<N, F>, depth: Self::Depth) -> Self; |
| 667 } |
667 } |
| 668 |
668 |
| 669 /// The main bisection tree structure. |
669 /// The main bisection tree structure. |
| 670 /// |
670 /// |
| 671 /// It should be accessed via the [`BTImpl`] trait to hide the `const P : usize` parameter until |
671 /// It should be accessed via the [`BTImpl`] trait to hide the `const P : usize` parameter until |
| 677 BTNodeLookup: BTNode<F, D, A, N>, |
677 BTNodeLookup: BTNode<F, D, A, N>, |
| 678 { |
678 { |
| 679 /// The depth of the tree (initial, before refinement) |
679 /// The depth of the tree (initial, before refinement) |
| 680 pub(super) depth: M, |
680 pub(super) depth: M, |
| 681 /// The domain of the toplevel node |
681 /// The domain of the toplevel node |
| 682 pub(super) domain: Cube<F, N>, |
682 pub(super) domain: Cube<N, F>, |
| 683 /// The toplevel node of the tree |
683 /// The toplevel node of the tree |
| 684 pub(super) topnode: <BTNodeLookup as BTNode<F, D, A, N>>::Node, |
684 pub(super) topnode: <BTNodeLookup as BTNode<F, D, A, N>>::Node, |
| 685 } |
685 } |
| 686 |
686 |
| 687 macro_rules! impl_bt { |
687 macro_rules! impl_bt { |
| 691 D : 'static + Copy + Send + Sync + std::fmt::Debug, |
691 D : 'static + Copy + Send + Sync + std::fmt::Debug, |
| 692 A : Aggregator { |
692 A : Aggregator { |
| 693 type Node = Node<F,D,A,$n,{pow(2, $n)}>; |
693 type Node = Node<F,D,A,$n,{pow(2, $n)}>; |
| 694 } |
694 } |
| 695 |
695 |
| 696 impl<M,F,D,A> BTImpl<F,$n> for BT<M,F,D,A,$n> |
696 impl<M,F,D,A> BTImpl<$n, F> for BT<M,F,D,A,$n> |
| 697 where M : Depth, |
697 where M : Depth, |
| 698 F : Float, |
698 F : Float, |
| 699 D : 'static + Copy + Send + Sync + std::fmt::Debug, |
699 D : 'static + Copy + Send + Sync + std::fmt::Debug, |
| 700 A : Aggregator { |
700 A : Aggregator { |
| 701 type Data = D; |
701 type Data = D; |
| 702 type Depth = M; |
702 type Depth = M; |
| 703 type Agg = A; |
703 type Agg = A; |
| 704 type Converted<ANew> = BT<M,F,D,ANew,$n> where ANew : Aggregator; |
704 type Converted<ANew> = BT<M,F,D,ANew,$n> where ANew : Aggregator; |
| 705 |
705 |
| 706 fn insert<S: LocalAnalysis<F, A, $n> + Support<F, $n>>( |
706 fn insert<S: LocalAnalysis<F, A, $n> + Support< $n, F>>( |
| 707 &mut self, |
707 &mut self, |
| 708 d : D, |
708 d : D, |
| 709 support : &S |
709 support : &S |
| 710 ) { |
710 ) { |
| 711 with_task_budget(|task_budget| |
711 with_task_budget(|task_budget| |
| 719 ) |
719 ) |
| 720 } |
720 } |
| 721 |
721 |
| 722 fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew> |
722 fn convert_aggregator<ANew, G>(self, generator : &G) -> Self::Converted<ANew> |
| 723 where ANew : Aggregator, |
723 where ANew : Aggregator, |
| 724 G : SupportGenerator<F, $n, Id=D>, |
724 G : SupportGenerator< $n, F, Id=D>, |
| 725 G::SupportType : LocalAnalysis<F, ANew, $n> { |
725 G::SupportType : LocalAnalysis<F, ANew, $n> { |
| 726 let topnode = self.topnode.convert_aggregator(generator, &self.domain); |
726 let topnode = self.topnode.convert_aggregator(generator, &self.domain); |
| 727 |
727 |
| 728 BT { |
728 BT { |
| 729 depth : self.depth, |
729 depth : self.depth, |
| 731 topnode |
731 topnode |
| 732 } |
732 } |
| 733 } |
733 } |
| 734 |
734 |
| 735 fn refresh_aggregator<G>(&mut self, generator : &G) |
735 fn refresh_aggregator<G>(&mut self, generator : &G) |
| 736 where G : SupportGenerator<F, $n, Id=Self::Data>, |
736 where G : SupportGenerator< $n, F, Id=Self::Data>, |
| 737 G::SupportType : LocalAnalysis<F, Self::Agg, $n> { |
737 G::SupportType : LocalAnalysis<F, Self::Agg, $n> { |
| 738 with_task_budget(|task_budget| |
738 with_task_budget(|task_budget| |
| 739 self.topnode.refresh_aggregator(generator, &self.domain, task_budget) |
739 self.topnode.refresh_aggregator(generator, &self.domain, task_budget) |
| 740 ) |
740 ) |
| 741 } |
741 } |
| 742 |
742 |
| 743 /*fn data_at(&self, x : &Loc<F,$n>) -> Arc<Vec<D>> { |
743 /*fn data_at(&self, x : &Loc<$n, F>) -> Arc<Vec<D>> { |
| 744 self.topnode.get_leaf_data(x).unwrap_or_else(|| Arc::new(Vec::new())) |
744 self.topnode.get_leaf_data(x).unwrap_or_else(|| Arc::new(Vec::new())) |
| 745 }*/ |
745 }*/ |
| 746 |
746 |
| 747 fn iter_at(&self, x : &Loc<F,$n>) -> std::slice::Iter<'_, D> { |
747 fn iter_at(&self, x : &Loc<$n, F>) -> std::slice::Iter<'_, D> { |
| 748 self.topnode.get_leaf_data_iter(x).unwrap_or_else(|| [].iter()) |
748 self.topnode.get_leaf_data_iter(x).unwrap_or_else(|| [].iter()) |
| 749 } |
749 } |
| 750 |
750 |
| 751 fn new(domain : Cube<F, $n>, depth : M) -> Self { |
751 fn new(domain : Cube<$n, F>, depth : M) -> Self { |
| 752 BT { |
752 BT { |
| 753 depth : depth, |
753 depth : depth, |
| 754 domain : domain, |
754 domain : domain, |
| 755 topnode : Node::new(), |
755 topnode : Node::new(), |
| 756 } |
756 } |