honeycomb_core/cmap/dim3/
basic_ops.rs1use std::cell::RefCell;
11use std::collections::{HashSet, VecDeque};
12
13use rayon::prelude::*;
14
15use crate::cmap::{
16 CMap3, DartIdType, EdgeIdType, FaceIdType, NULL_DART_ID, VertexIdType, VolumeIdType,
17};
18use crate::geometry::CoordsFloat;
19use crate::stm::{StmClosureResult, StmError, Transaction, atomically};
20
21thread_local! {
25 static AUXILIARIES: RefCell<(VecDeque<DartIdType>, HashSet<DartIdType>)> = RefCell::new(
26 (
27 VecDeque::with_capacity(10),
28 HashSet::with_capacity(10),
29 )
30 );
31}
32
33impl<T: CoordsFloat> CMap3<T> {
35 pub fn beta_tx<const I: u8>(
49 &self,
50 t: &mut Transaction,
51 dart_id: DartIdType,
52 ) -> StmClosureResult<DartIdType> {
53 assert!(I < 4);
54 self.betas[(I, dart_id)].read(t)
55 }
56
57 pub fn beta_rt_tx(
69 &self,
70 t: &mut Transaction,
71 i: u8,
72 dart_id: DartIdType,
73 ) -> StmClosureResult<DartIdType> {
74 assert!(i < 4);
75 match i {
76 0 => self.beta_tx::<0>(t, dart_id),
77 1 => self.beta_tx::<1>(t, dart_id),
78 2 => self.beta_tx::<2>(t, dart_id),
79 3 => self.beta_tx::<3>(t, dart_id),
80 _ => unreachable!(),
81 }
82 }
83
84 #[must_use = "unused return value"]
90 pub fn beta<const I: u8>(&self, dart_id: DartIdType) -> DartIdType {
91 assert!(I < 4);
92 self.betas[(I, dart_id)].read_atomic()
93 }
94
95 #[must_use = "unused return value"]
101 pub fn beta_rt(&self, i: u8, dart_id: DartIdType) -> DartIdType {
102 assert!(i < 4);
103 match i {
104 0 => self.beta::<0>(dart_id),
105 1 => self.beta::<1>(dart_id),
106 2 => self.beta::<2>(dart_id),
107 3 => self.beta::<3>(dart_id),
108 _ => unreachable!(),
109 }
110 }
111
112 #[must_use = "unused return value"]
124 pub fn is_i_free<const I: u8>(&self, dart_id: DartIdType) -> bool {
125 self.beta::<I>(dart_id) == NULL_DART_ID
126 }
127
128 #[must_use = "unused return value"]
134 pub fn is_free(&self, dart_id: DartIdType) -> bool {
135 self.beta::<0>(dart_id) == NULL_DART_ID
136 && self.beta::<1>(dart_id) == NULL_DART_ID
137 && self.beta::<2>(dart_id) == NULL_DART_ID
138 && self.beta::<3>(dart_id) == NULL_DART_ID
139 }
140
141 #[must_use = "unused return value"]
153 pub fn is_free_tx(&self, t: &mut Transaction, dart_id: DartIdType) -> StmClosureResult<bool> {
154 Ok(self.beta_tx::<0>(t, dart_id)? == NULL_DART_ID
155 && self.beta_tx::<1>(t, dart_id)? == NULL_DART_ID
156 && self.beta_tx::<2>(t, dart_id)? == NULL_DART_ID)
157 }
158}
159
160impl<T: CoordsFloat> CMap3<T> {
162 #[must_use = "unused return value"]
166 pub fn vertex_id(&self, dart_id: DartIdType) -> VertexIdType {
167 atomically(|t| self.vertex_id_tx(t, dart_id))
168 }
169
170 pub fn vertex_id_tx(
180 &self,
181 t: &mut Transaction,
182 dart_id: DartIdType,
183 ) -> Result<VertexIdType, StmError> {
184 AUXILIARIES.with(|cell| {
185 let (pending, marked) = &mut *cell.borrow_mut();
186 pending.clear();
188 marked.clear();
189 pending.push_front(dart_id);
191 marked.insert(NULL_DART_ID); let mut min = dart_id;
194
195 while let Some(d) = pending.pop_front() {
196 if marked.insert(d) {
197 min = min.min(d);
198 let (b0, b2, b3) = (
199 self.beta_tx::<0>(t, d)?, self.beta_tx::<2>(t, d)?,
201 self.beta_tx::<3>(t, d)?,
202 );
203 pending.push_back(self.beta_tx::<1>(t, b3)?);
204 pending.push_back(self.beta_tx::<3>(t, b2)?);
205 pending.push_back(self.beta_tx::<1>(t, b2)?);
206 pending.push_back(self.beta_tx::<3>(t, b0)?); pending.push_back(self.beta_tx::<2>(t, b0)?); }
209 }
210
211 Ok(min)
212 })
213 }
214
215 #[must_use = "unused return value"]
219 pub fn edge_id(&self, dart_id: DartIdType) -> EdgeIdType {
220 atomically(|t| self.edge_id_tx(t, dart_id))
221 }
222
223 pub fn edge_id_tx(
233 &self,
234 t: &mut Transaction,
235 dart_id: DartIdType,
236 ) -> Result<EdgeIdType, StmError> {
237 AUXILIARIES.with(|cell| {
238 let (pending, marked) = &mut *cell.borrow_mut();
239 pending.clear();
241 marked.clear();
242 pending.push_back(dart_id);
244 marked.insert(NULL_DART_ID);
245
246 let mut min = dart_id;
247
248 while let Some(d) = pending.pop_front() {
249 if marked.insert(d) {
250 min = min.min(d);
251 for im in [self.beta_tx::<2>(t, d)?, self.beta_tx::<3>(t, d)?] {
252 pending.push_back(im);
253 }
254 }
255 }
256
257 Ok(min)
258 })
259 }
260
261 #[must_use = "unused return value"]
265 pub fn face_id(&self, dart_id: DartIdType) -> FaceIdType {
266 atomically(|t| self.face_id_tx(t, dart_id))
267 }
268
269 pub fn face_id_tx(
279 &self,
280 t: &mut Transaction,
281 dart_id: DartIdType,
282 ) -> Result<FaceIdType, StmError> {
283 AUXILIARIES.with(|cell| {
284 let (_pending, marked) = &mut *cell.borrow_mut();
285 marked.clear();
287 marked.insert(NULL_DART_ID); let b3_dart_id = self.beta_tx::<3>(t, dart_id)?;
291 let (mut lb, mut rb) = (dart_id, b3_dart_id);
292 let mut min = if rb == NULL_DART_ID { lb } else { lb.min(rb) };
293
294 while marked.insert(lb) || marked.insert(rb) {
295 (lb, rb) = (self.beta_tx::<1>(t, lb)?, self.beta_tx::<0>(t, rb)?);
296 if lb != NULL_DART_ID {
297 min = min.min(lb);
298 }
299 if rb != NULL_DART_ID {
300 min = min.min(rb);
301 }
302 }
303 if lb == NULL_DART_ID || rb == NULL_DART_ID {
305 (lb, rb) = (
306 self.beta_tx::<0>(t, dart_id)?,
307 self.beta_tx::<1>(t, b3_dart_id)?,
308 );
309 while marked.insert(lb) || marked.insert(rb) {
310 (lb, rb) = (self.beta_tx::<0>(t, lb)?, self.beta_tx::<1>(t, rb)?);
311 if lb != NULL_DART_ID {
312 min = min.min(lb);
313 }
314 if rb != NULL_DART_ID {
315 min = min.min(rb);
316 }
317 }
318 }
319
320 Ok(min)
321 })
322 }
323
324 #[must_use = "unused return value"]
328 pub fn volume_id(&self, dart_id: DartIdType) -> VolumeIdType {
329 atomically(|t| self.volume_id_tx(t, dart_id))
330 }
331
332 pub fn volume_id_tx(
342 &self,
343 t: &mut Transaction,
344 dart_id: DartIdType,
345 ) -> Result<VolumeIdType, StmError> {
346 AUXILIARIES.with(|cell| {
347 let (pending, marked) = &mut *cell.borrow_mut();
348 pending.clear();
350 marked.clear();
351 pending.push_front(dart_id);
353 marked.insert(NULL_DART_ID); let mut min = dart_id;
356
357 while let Some(d) = pending.pop_front() {
358 if marked.insert(d) {
359 min = min.min(d);
360 pending.push_back(self.beta_tx::<1>(t, d)?);
361 pending.push_back(self.beta_tx::<0>(t, d)?); pending.push_back(self.beta_tx::<2>(t, d)?);
363 }
364 }
365
366 Ok(min)
367 })
368 }
369
370 pub fn iter_vertices(&self) -> impl Iterator<Item = VertexIdType> + '_ {
372 (1..self.n_darts() as DartIdType)
373 .zip(self.unused_darts.iter().skip(1))
374 .filter_map(
375 |(d, unused)| {
376 if unused.read_atomic() { None } else { Some(d) }
377 },
378 )
379 .filter_map(|d| {
380 let vid = self.vertex_id(d);
381 if d == vid { Some(vid) } else { None }
382 })
383 }
384
385 pub fn iter_edges(&self) -> impl Iterator<Item = EdgeIdType> + '_ {
387 (1..self.n_darts() as DartIdType)
388 .zip(self.unused_darts.iter().skip(1))
389 .filter_map(
390 |(d, unused)| {
391 if unused.read_atomic() { None } else { Some(d) }
392 },
393 )
394 .filter_map(|d| {
395 let eid = self.edge_id(d);
396 if d == eid { Some(eid) } else { None }
397 })
398 }
399
400 pub fn iter_faces(&self) -> impl Iterator<Item = FaceIdType> + '_ {
402 (1..self.n_darts() as DartIdType)
403 .zip(self.unused_darts.iter().skip(1))
404 .filter_map(
405 |(d, unused)| {
406 if unused.read_atomic() { None } else { Some(d) }
407 },
408 )
409 .filter_map(|d| {
410 let fid = self.face_id(d);
411 if d == fid { Some(fid) } else { None }
412 })
413 }
414
415 pub fn iter_volumes(&self) -> impl Iterator<Item = VolumeIdType> + '_ {
417 (1..self.n_darts() as DartIdType)
418 .zip(self.unused_darts.iter().skip(1))
419 .filter_map(
420 |(d, unused)| {
421 if unused.read_atomic() { None } else { Some(d) }
422 },
423 )
424 .filter_map(|d| {
425 let vid = self.volume_id(d);
426 if d == vid { Some(vid) } else { None }
427 })
428 }
429
430 #[must_use = "iterators are lazy and do nothing unless consumed"]
432 pub fn par_iter_vertices(&self) -> impl ParallelIterator<Item = VertexIdType> + '_ {
433 (1..self.n_darts() as DartIdType)
434 .into_par_iter()
435 .filter_map(|d| {
436 if atomically(|t| self.is_unused_tx(t, d)) {
437 None
438 } else {
439 Some(d)
440 }
441 })
442 .filter_map(|d| {
443 let vid = self.vertex_id(d);
444 if d == vid { Some(vid) } else { None }
445 })
446 }
447
448 #[must_use = "iterators are lazy and do nothing unless consumed"]
450 pub fn par_iter_edges(&self) -> impl ParallelIterator<Item = EdgeIdType> + '_ {
451 (1..self.n_darts() as DartIdType)
452 .into_par_iter()
453 .filter_map(|d| {
454 if atomically(|t| self.is_unused_tx(t, d)) {
455 None
456 } else {
457 Some(d)
458 }
459 })
460 .filter_map(|d| {
461 let eid = self.edge_id(d);
462 if d == eid { Some(eid) } else { None }
463 })
464 }
465
466 #[must_use = "iterators are lazy and do nothing unless consumed"]
468 pub fn par_iter_faces(&self) -> impl ParallelIterator<Item = FaceIdType> + '_ {
469 (1..self.n_darts() as DartIdType)
470 .into_par_iter()
471 .filter_map(|d| {
472 if atomically(|t| self.is_unused_tx(t, d)) {
473 None
474 } else {
475 Some(d)
476 }
477 })
478 .filter_map(|d| {
479 let fid = self.face_id(d);
480 if d == fid { Some(fid) } else { None }
481 })
482 }
483
484 #[must_use = "iterators are lazy and do nothing unless consumed"]
486 pub fn par_iter_volumes(&self) -> impl ParallelIterator<Item = VolumeIdType> + '_ {
487 (1..self.n_darts() as DartIdType)
488 .into_par_iter()
489 .filter_map(|d| {
490 if atomically(|t| self.is_unused_tx(t, d)) {
491 None
492 } else {
493 Some(d)
494 }
495 })
496 .filter_map(|d| {
497 let vid = self.volume_id(d);
498 if d == vid { Some(vid) } else { None }
499 })
500 }
501}