honeycomb-core 0.11.0

Core structure implementation for combinatorial maps
Documentation
mod one;
mod three;
mod two;

use fast_stm::atomically_with_err;

use crate::cmap::{CMap3, DartIdType, LinkError};
use crate::geometry::CoordsFloat;
use crate::stm::{Transaction, TransactionClosureResult};

/// # **Link operations**
impl<T: CoordsFloat> CMap3<T> {
    /// `I`-link operator.
    ///
    /// # Description
    ///
    /// This operation corresponds to coherently linking two darts via their *β* images. Unlike
    /// sewing, this does not alter associated attributes. For a thorough explanation of this
    /// operation, its hypothesis & consequences, refer to the [user guide][UG].
    ///
    /// [UG]: https://lihpc-computational-geometry.github.io/honeycomb/user-guide/definitions/sew.html
    ///
    /// # Arguments
    ///
    /// - `const I: u8` -- Link dimension.
    /// - `t: &mut Transaction` -- Transaction associated to the operation.
    /// - `lhs_dart_id: DartIdType` -- First dart ID.
    /// - `rhs_dart_id: DartIdType` -- Second dart ID.
    ///
    /// # Errors
    ///
    /// This method should be called in a transactional context. The `Result` is then used to
    /// validate the transaction; Errors should not be processed manually, only processed via the
    /// `?` operator. The policy in case of failure can be defined when creating the transaction,
    /// using `Transaction::with_control`.
    ///
    /// It may return an error if the transaction fails or if the link fails; See [`LinkError`] for
    /// more detail about the latter.
    ///
    /// # Panics
    ///
    /// The method may panic if:
    /// - `I >= 4` or `I == 0`,
    /// - the two darts are not `I`-linkable.
    pub fn link_tx<const I: u8>(
        &self,
        t: &mut Transaction,
        lhs_dart_id: DartIdType,
        rhs_dart_id: DartIdType,
    ) -> TransactionClosureResult<(), LinkError> {
        // these assertions + match on a const are optimized away
        assert!(I < 4);
        assert_ne!(I, 0);
        match I {
            1 => self.one_link_tx(t, lhs_dart_id, rhs_dart_id),
            2 => self.two_link_tx(t, lhs_dart_id, rhs_dart_id),
            3 => self.three_link_tx(t, lhs_dart_id, rhs_dart_id),
            _ => unreachable!(),
        }
    }

    /// `I`-unlink operator.
    ///
    /// # Description
    ///
    /// This operation corresponds to unlinking two darts by resetting their *β* images. Unlike
    /// unsewing, this does not alter associated attributes. For a thorough explanation of this
    /// operation, its hypothesis & consequences, refer to the [user guide][UG].
    ///
    /// [UG]: https://lihpc-computational-geometry.github.io/honeycomb/user-guide/definitions/sew.html
    ///
    /// # Arguments
    ///
    /// - `const I: u8` -- Unlink dimension.
    /// - `t: &mut Transaction` -- Transaction associated to the operation.
    /// - `lhs_dart_id: DartIdType` -- First dart ID.
    ///
    /// The second dart ID is fetched using `I` and `lhs_dart_id`.
    ///
    /// # Errors
    ///
    /// This method should be called in a transactional context. The `Result` is then used to
    /// validate the transaction; Errors should not be processed manually, only processed via the
    /// `?` operator. The policy in case of failure can be defined when creating the transaction,
    /// using `Transaction::with_control`.
    ///
    /// # Panics
    ///
    /// The method may panic if:
    /// - `I >= 4` or `I == 0`,
    /// - `lhs_dart_id` is already `I`-free.
    pub fn unlink_tx<const I: u8>(
        &self,
        t: &mut Transaction,
        lhs_dart_id: DartIdType,
    ) -> TransactionClosureResult<(), LinkError> {
        // these assertions + match on a const are optimized away
        assert!(I < 4);
        assert_ne!(I, 0);
        match I {
            1 => self.one_unlink_tx(t, lhs_dart_id),
            2 => self.two_unlink_tx(t, lhs_dart_id),
            3 => self.three_unlink_tx(t, lhs_dart_id),
            _ => unreachable!(),
        }
    }

    /// `I`-link operator.
    ///
    /// This variant is equivalent to [`link`][Self::link], but internally uses a transaction that
    /// will be retried until validated.
    ///
    /// # Errors
    ///
    /// It may return an error if the transaction fails or if the link fails; See [`LinkError`] for
    /// more detail about the latter.
    ///
    /// # Panics
    ///
    /// The method may panic if:
    /// - `I >= 4` or `I == 0`,
    /// - `lhs_dart_id` is already `I`-free.
    pub fn link<const I: u8>(
        &self,
        lhs_dart_id: DartIdType,
        rhs_dart_id: DartIdType,
    ) -> Result<(), LinkError> {
        // these assertions + match on a const are optimized away
        assert!(I < 4);
        assert_ne!(I, 0);
        match I {
            1 => atomically_with_err(|t| self.one_link_tx(t, lhs_dart_id, rhs_dart_id)),
            2 => atomically_with_err(|t| self.two_link_tx(t, lhs_dart_id, rhs_dart_id)),
            3 => atomically_with_err(|t| self.three_link_tx(t, lhs_dart_id, rhs_dart_id)),
            _ => unreachable!(),
        }
    }

    /// `I`-unlink operator.
    ///
    /// This variant is equivalent to [`unlink`][Self::unlink], but internally uses a transaction
    /// that will be retried until validated.
    ///
    /// # Errors
    ///
    /// It may return an error if the transaction fails or if the link fails; See [`LinkError`] for
    /// more detail about the latter.
    ///
    /// # Panics
    ///
    /// The method may panic if:
    /// - `I >= 4` or `I == 0`,
    /// - `lhs_dart_id` is already `I`-free.
    pub fn unlink<const I: u8>(&self, lhs_dart_id: DartIdType) -> Result<(), LinkError> {
        // these assertions + match on a const are optimized away
        assert!(I < 4);
        assert_ne!(I, 0);
        match I {
            1 => atomically_with_err(|t| self.one_unlink_tx(t, lhs_dart_id)),
            2 => atomically_with_err(|t| self.two_unlink_tx(t, lhs_dart_id)),
            3 => atomically_with_err(|t| self.three_unlink_tx(t, lhs_dart_id)),
            _ => unreachable!(),
        }
    }
}