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((VecDeque::with_capacity(10), HashSet::with_capacity(10)));
26}
27
28impl<T: CoordsFloat> CMap3<T> {
30 pub fn beta_tx<const I: u8>(
44 &self,
45 t: &mut Transaction,
46 dart_id: DartIdType,
47 ) -> StmClosureResult<DartIdType> {
48 assert!(I < 4);
49 self.betas[(I, dart_id)].read(t)
50 }
51
52 pub fn beta_rt_tx(
64 &self,
65 t: &mut Transaction,
66 i: u8,
67 dart_id: DartIdType,
68 ) -> StmClosureResult<DartIdType> {
69 assert!(i < 4);
70 match i {
71 0 => self.beta_tx::<0>(t, dart_id),
72 1 => self.beta_tx::<1>(t, dart_id),
73 2 => self.beta_tx::<2>(t, dart_id),
74 3 => self.beta_tx::<3>(t, dart_id),
75 _ => unreachable!(),
76 }
77 }
78
79 #[must_use = "unused return value"]
85 pub fn beta<const I: u8>(&self, dart_id: DartIdType) -> DartIdType {
86 assert!(I < 4);
87 self.betas[(I, dart_id)].read_atomic()
88 }
89
90 #[must_use = "unused return value"]
96 pub fn beta_rt(&self, i: u8, dart_id: DartIdType) -> DartIdType {
97 assert!(i < 4);
98 match i {
99 0 => self.beta::<0>(dart_id),
100 1 => self.beta::<1>(dart_id),
101 2 => self.beta::<2>(dart_id),
102 3 => self.beta::<3>(dart_id),
103 _ => unreachable!(),
104 }
105 }
106
107 #[must_use = "unused return value"]
119 pub fn is_i_free<const I: u8>(&self, dart_id: DartIdType) -> bool {
120 self.beta::<I>(dart_id) == NULL_DART_ID
121 }
122
123 #[must_use = "unused return value"]
129 pub fn is_free(&self, dart_id: DartIdType) -> bool {
130 self.beta::<0>(dart_id) == NULL_DART_ID
131 && self.beta::<1>(dart_id) == NULL_DART_ID
132 && self.beta::<2>(dart_id) == NULL_DART_ID
133 && self.beta::<3>(dart_id) == NULL_DART_ID
134 }
135
136 #[must_use = "unused return value"]
142 pub fn is_free_tx(&self, t: &mut Transaction, dart_id: DartIdType) -> StmClosureResult<bool> {
143 Ok(self.beta_tx::<0>(t, dart_id)? == NULL_DART_ID
144 && self.beta_tx::<1>(t, dart_id)? == NULL_DART_ID
145 && self.beta_tx::<2>(t, dart_id)? == NULL_DART_ID)
146 }
147}
148
149impl<T: CoordsFloat> CMap3<T> {
151 #[must_use = "unused return value"]
155 pub fn vertex_id(&self, dart_id: DartIdType) -> VertexIdType {
156 atomically(|t| self.vertex_id_tx(t, dart_id))
157 }
158
159 pub fn vertex_id_tx(
169 &self,
170 t: &mut Transaction,
171 dart_id: DartIdType,
172 ) -> Result<VertexIdType, StmError> {
173 AUXILIARIES.with(|cell| {
174 let (pending, marked) = &mut *cell.borrow_mut();
175 pending.clear();
177 marked.clear();
178 pending.push_front(dart_id);
180 marked.insert(NULL_DART_ID); let mut min = dart_id;
183
184 while let Some(d) = pending.pop_front() {
185 if marked.insert(d) {
186 min = min.min(d);
187 let (b0, b2, b3) = (
188 self.beta_tx::<0>(t, d)?, self.beta_tx::<2>(t, d)?,
190 self.beta_tx::<3>(t, d)?,
191 );
192 pending.push_back(self.beta_tx::<1>(t, b3)?);
193 pending.push_back(self.beta_tx::<3>(t, b2)?);
194 pending.push_back(self.beta_tx::<1>(t, b2)?);
195 pending.push_back(self.beta_tx::<3>(t, b0)?); pending.push_back(self.beta_tx::<2>(t, b0)?); }
198 }
199
200 Ok(min)
201 })
202 }
203
204 #[must_use = "unused return value"]
208 pub fn edge_id(&self, dart_id: DartIdType) -> EdgeIdType {
209 atomically(|t| self.edge_id_tx(t, dart_id))
210 }
211
212 pub fn edge_id_tx(
222 &self,
223 t: &mut Transaction,
224 dart_id: DartIdType,
225 ) -> Result<EdgeIdType, StmError> {
226 AUXILIARIES.with(|cell| {
227 let (pending, marked) = &mut *cell.borrow_mut();
228 pending.clear();
230 marked.clear();
231 pending.push_back(dart_id);
233 marked.insert(NULL_DART_ID);
234
235 let mut min = dart_id;
236
237 while let Some(d) = pending.pop_front() {
238 if marked.insert(d) {
239 min = min.min(d);
240 for im in [self.beta_tx::<2>(t, d)?, self.beta_tx::<3>(t, d)?] {
241 pending.push_back(im);
242 }
243 }
244 }
245
246 Ok(min)
247 })
248 }
249
250 #[must_use = "unused return value"]
254 pub fn face_id(&self, dart_id: DartIdType) -> FaceIdType {
255 atomically(|t| self.face_id_tx(t, dart_id))
256 }
257
258 pub fn face_id_tx(
268 &self,
269 t: &mut Transaction,
270 dart_id: DartIdType,
271 ) -> Result<FaceIdType, StmError> {
272 AUXILIARIES.with(|cell| {
273 let (_pending, marked) = &mut *cell.borrow_mut();
274 marked.clear();
276 marked.insert(NULL_DART_ID); let b3_dart_id = self.beta_tx::<3>(t, dart_id)?;
280 let (mut lb, mut rb) = (dart_id, b3_dart_id);
281 let mut min = if rb == NULL_DART_ID { lb } else { lb.min(rb) };
282
283 while marked.insert(lb) || marked.insert(rb) {
284 (lb, rb) = (self.beta_tx::<1>(t, lb)?, self.beta_tx::<0>(t, rb)?);
285 if lb != NULL_DART_ID {
286 min = min.min(lb);
287 }
288 if rb != NULL_DART_ID {
289 min = min.min(rb);
290 }
291 }
292 if lb == NULL_DART_ID || rb == NULL_DART_ID {
294 (lb, rb) = (
295 self.beta_tx::<0>(t, dart_id)?,
296 self.beta_tx::<1>(t, b3_dart_id)?,
297 );
298 while marked.insert(lb) || marked.insert(rb) {
299 (lb, rb) = (self.beta_tx::<0>(t, lb)?, self.beta_tx::<1>(t, rb)?);
300 if lb != NULL_DART_ID {
301 min = min.min(lb);
302 }
303 if rb != NULL_DART_ID {
304 min = min.min(rb);
305 }
306 }
307 }
308
309 Ok(min)
310 })
311 }
312
313 #[must_use = "unused return value"]
317 pub fn volume_id(&self, dart_id: DartIdType) -> VolumeIdType {
318 atomically(|t| self.volume_id_tx(t, dart_id))
319 }
320
321 pub fn volume_id_tx(
331 &self,
332 t: &mut Transaction,
333 dart_id: DartIdType,
334 ) -> Result<VolumeIdType, StmError> {
335 AUXILIARIES.with(|cell| {
336 let (pending, marked) = &mut *cell.borrow_mut();
337 pending.clear();
339 marked.clear();
340 pending.push_front(dart_id);
342 marked.insert(NULL_DART_ID); let mut min = dart_id;
345
346 while let Some(d) = pending.pop_front() {
347 if marked.insert(d) {
348 min = min.min(d);
349 pending.push_back(self.beta_tx::<1>(t, d)?);
350 pending.push_back(self.beta_tx::<0>(t, d)?); pending.push_back(self.beta_tx::<2>(t, d)?);
352 }
353 }
354
355 Ok(min)
356 })
357 }
358
359 pub fn iter_vertices(&self) -> impl Iterator<Item = VertexIdType> + '_ {
361 (1..self.n_darts() as DartIdType)
362 .zip(self.unused_darts.iter().skip(1))
363 .filter_map(
364 |(d, unused)| {
365 if unused.read_atomic() { None } else { Some(d) }
366 },
367 )
368 .filter_map(|d| {
369 let vid = self.vertex_id(d);
370 if d == vid { Some(vid) } else { None }
371 })
372 }
373
374 pub fn iter_edges(&self) -> impl Iterator<Item = EdgeIdType> + '_ {
376 (1..self.n_darts() as DartIdType)
377 .zip(self.unused_darts.iter().skip(1))
378 .filter_map(
379 |(d, unused)| {
380 if unused.read_atomic() { None } else { Some(d) }
381 },
382 )
383 .filter_map(|d| {
384 let eid = self.edge_id(d);
385 if d == eid { Some(eid) } else { None }
386 })
387 }
388
389 pub fn iter_faces(&self) -> impl Iterator<Item = FaceIdType> + '_ {
391 (1..self.n_darts() as DartIdType)
392 .zip(self.unused_darts.iter().skip(1))
393 .filter_map(
394 |(d, unused)| {
395 if unused.read_atomic() { None } else { Some(d) }
396 },
397 )
398 .filter_map(|d| {
399 let fid = self.face_id(d);
400 if d == fid { Some(fid) } else { None }
401 })
402 }
403
404 pub fn iter_volumes(&self) -> impl Iterator<Item = VolumeIdType> + '_ {
406 (1..self.n_darts() as DartIdType)
407 .zip(self.unused_darts.iter().skip(1))
408 .filter_map(
409 |(d, unused)| {
410 if unused.read_atomic() { None } else { Some(d) }
411 },
412 )
413 .filter_map(|d| {
414 let vid = self.volume_id(d);
415 if d == vid { Some(vid) } else { None }
416 })
417 }
418
419 pub fn par_iter_vertices(&self) -> impl ParallelIterator<Item = VertexIdType> + '_ {
421 (1..self.n_darts() as DartIdType)
422 .into_par_iter()
423 .filter_map(|d| {
424 if atomically(|t| self.is_unused_tx(t, d)) {
425 None
426 } else {
427 Some(d)
428 }
429 })
430 .filter_map(|d| {
431 let vid = self.vertex_id(d);
432 if d == vid { Some(vid) } else { None }
433 })
434 }
435
436 pub fn par_iter_edges(&self) -> impl ParallelIterator<Item = EdgeIdType> + '_ {
438 (1..self.n_darts() as DartIdType)
439 .into_par_iter()
440 .filter_map(|d| {
441 if atomically(|t| self.is_unused_tx(t, d)) {
442 None
443 } else {
444 Some(d)
445 }
446 })
447 .filter_map(|d| {
448 let eid = self.edge_id(d);
449 if d == eid { Some(eid) } else { None }
450 })
451 }
452
453 pub fn par_iter_faces(&self) -> impl ParallelIterator<Item = FaceIdType> + '_ {
455 (1..self.n_darts() as DartIdType)
456 .into_par_iter()
457 .filter_map(|d| {
458 if atomically(|t| self.is_unused_tx(t, d)) {
459 None
460 } else {
461 Some(d)
462 }
463 })
464 .filter_map(|d| {
465 let fid = self.face_id(d);
466 if d == fid { Some(fid) } else { None }
467 })
468 }
469
470 pub fn par_iter_volumes(&self) -> impl ParallelIterator<Item = VolumeIdType> + '_ {
472 (1..self.n_darts() as DartIdType)
473 .into_par_iter()
474 .filter_map(|d| {
475 if atomically(|t| self.is_unused_tx(t, d)) {
476 None
477 } else {
478 Some(d)
479 }
480 })
481 .filter_map(|d| {
482 let vid = self.volume_id(d);
483 if d == vid { Some(vid) } else { None }
484 })
485 }
486}