eryon-mem 0.0.4

this crate implements the memory-related aspects of the eryon framework
/*
    Appellation: features <module>
    Contrib: @FL03
*/
use num_traits::{Float, FromPrimitive, ToPrimitive};

/// A topological feature that persists across transformations.
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(
    feature = "serde",
    derive(serde::Deserialize, serde::Serialize),
    serde(rename_all = "camelCase")
)]
pub struct PersistentFeature<T = f32> {
    pub(crate) id: usize,
    pub(crate) birth: usize,
    pub(crate) content: Vec<usize>,
    pub(crate) death: Option<usize>,
    pub(crate) dimension: usize,
    pub(crate) importance: T,
    pub(crate) occurrences: usize,
}

impl<T> PersistentFeature<T> {
    pub fn from_parts(
        id: usize,
        birth: usize,
        content: Vec<usize>,
        dimension: usize,
        importance: T,
    ) -> Self {
        Self {
            id,
            birth,
            content,
            death: None,
            dimension,
            importance,
            occurrences: 1,
        }
    }
    /// returns the birth of a feature
    pub const fn birth(&self) -> usize {
        self.birth
    }
    /// returns a mutable reference to the birth of a feature
    pub const fn birth_mut(&mut self) -> &mut usize {
        &mut self.birth
    }
    /// returns the dimension of the feature
    pub const fn dimension(&self) -> usize {
        self.dimension
    }
    /// returns a mutable reference to the dimension of the feature
    pub const fn dimension_mut(&mut self) -> &mut usize {
        &mut self.dimension
    }
    /// returns the id of the feature
    pub const fn id(&self) -> usize {
        self.id
    }
    /// returns a mutable reference to the id of the feature
    pub const fn id_mut(&mut self) -> &mut usize {
        &mut self.id
    }

    /// returns the occurrences of the feature
    pub const fn occurrences(&self) -> usize {
        self.occurrences
    }
    /// returns a mutable reference to the occurrences of the feature
    pub const fn occurrences_mut(&mut self) -> &mut usize {
        &mut self.occurrences
    }
    /// returns an immutable reference to the importance of the feature
    pub const fn importance(&self) -> &T {
        &self.importance
    }
    /// returns a mutable reference to the importance of the feature
    pub const fn importance_mut(&mut self) -> &mut T {
        &mut self.importance
    }
    /// returns an immutable reference to the features content
    pub const fn content(&self) -> &Vec<usize> {
        &self.content
    }
    /// returns a mutable reference to the feature's content
    pub const fn content_mut(&mut self) -> &mut Vec<usize> {
        &mut self.content
    }
    /// get the death time of this feature; None if still active
    pub const fn death(&self) -> Option<usize> {
        self.death
    }
    pub const fn death_mut(&mut self) -> Option<&mut usize> {
        self.death.as_mut()
    }
    /// scale the importance of the feature
    pub fn importance_to_usize_by(&self, scale: T) -> usize
    where
        T: Copy + core::ops::Mul<T, Output = T> + ToPrimitive,
    {
        (self.importance * scale).to_usize().unwrap()
    }
    /// scale the importance of the feature
    pub fn importance_to_usize_by_10(&self) -> usize
    where
        T: Copy + core::ops::Mul<Output = T> + FromPrimitive + ToPrimitive,
    {
        Self::importance_to_usize_by(self, T::from_usize(10).unwrap())
    }

    pub fn update_importance_by_occurrences(&mut self)
    where
        T: Float + FromPrimitive,
    {
        let ten = T::from_usize(10).unwrap();
        let occurrences = T::from_usize(self.occurrences).unwrap();
        self.set_importance(occurrences.min(ten) / ten);
    }
    /// update the birth of a feature
    pub fn set_birth(&mut self, birth: usize) {
        self.birth = birth;
    }

    /// set the content of the feature
    pub fn set_content<I>(&mut self, content: I)
    where
        I: IntoIterator<Item = usize>,
    {
        self.content = Vec::from_iter(content);
    }
    /// set the death of the feature
    pub fn set_death(&mut self, death: usize) {
        self.death = Some(death);
    }
    /// update the dimension of a feature
    pub fn set_dimension(&mut self, dimension: usize) {
        self.dimension = dimension;
    }
    /// update the id of a feature pattern
    pub fn set_id(&mut self, id: usize) {
        self.id = id;
    }
    /// update the importance of a feature
    pub fn set_importance(&mut self, importance: T) {
        self.importance = importance;
    }
    /// update the occurrences of a feature
    pub fn set_occurrences(&mut self, occurrences: usize) {
        self.occurrences = occurrences;
    }
    /// consumes the current instance to create another with the specified birth
    pub fn with_birth(self, birth: usize) -> Self {
        Self { birth, ..self }
    }
    /// consumes the current instance to create another with the given content
    pub fn with_content<I>(self, iter: I) -> Self
    where
        I: IntoIterator<Item = usize>,
    {
        Self {
            content: Vec::from_iter(iter),
            ..self
        }
    }
    /// consumes the current instance to create another with the given death time
    pub fn with_death(self, death: Option<usize>) -> Self {
        Self { death, ..self }
    }
    /// consumes the current instance to create another with the specified dimension
    pub fn with_dimension(self, dimension: usize) -> Self {
        Self { dimension, ..self }
    }
    /// consumes the current instance to create another with the specified id
    pub fn with_id(self, id: usize) -> Self {
        Self { id, ..self }
    }
    /// consumes the current instance to create another with the specified importance
    pub fn with_importance(self, importance: T) -> Self {
        Self { importance, ..self }
    }
    /// consumes the current instance to create another with the specified occurrences
    pub fn with_occurrences(self, occurrences: usize) -> Self {
        Self {
            occurrences,
            ..self
        }
    }
    /// check if the feature contains a given content
    pub fn contains(&self, content: &usize) -> bool {
        self.content.contains(content)
    }
    /// check if the feature does not have a death time
    pub fn is_alive(&self) -> bool {
        self.death.is_none()
    }
    /// check if a feature has died
    pub fn is_dead(&self) -> bool {
        self.death.is_some()
    }
    /// returns the number of elements in the content
    pub fn content_len(&self) -> usize {
        self.content.len()
    }
    /// decrement the number of occurrences
    pub fn decrement_occurrences(&mut self) {
        self.occurrences -= 1;
    }
    /// Increment the occurrence count
    pub fn increment_occurrences(&mut self) {
        self.occurrences += 1;
    }
}

impl<T> core::ops::Index<usize> for PersistentFeature<T> {
    type Output = usize;

    fn index(&self, index: usize) -> &Self::Output {
        &self.content[index]
    }
}

impl<T> core::ops::IndexMut<usize> for PersistentFeature<T> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.content[index]
    }
}