fountain_engine 1.1.0

Core algorithms for fountain code encoding and decoding
Documentation
// Copyright (c) 2025 Shenghao Yang. All rights reserved.
// Licensed under AGPL-3.0 or commercial license. See LICENSE for details.

/// Maximum number of inactive vectors allowed in the system.
pub const MAX_INACTIVE_NUM: usize = 100; // Adjust this value as needed

/// Type alias for degree set generator function (symbol index -> active and inactive indices).
pub type DegreeSetFn = Box<dyn FnMut(usize) -> Vec<usize>>;

/// A struct for decoding configuration.
#[derive(Clone, Debug)]
pub struct DecodingConfig {
    pub max_inactive_num: usize,
    pub num_padding: usize,
    pub pre_inactivation: PreInactivation,
    pub inac_strategy: InactivationStrategy,
    pub subs_method: SubstitutionMethod,
}

impl Default for DecodingConfig {
    fn default() -> Self {
        Self {
            max_inactive_num: 0,
            num_padding: 0,
            pre_inactivation: PreInactivation::NoPre,
            inac_strategy: InactivationStrategy::ByIndex,
            subs_method: SubstitutionMethod::Direct,
        }
    }
}

impl DecodingConfig {
    /// Set the pre-inactivation flag to true.
    pub fn with_pre_inact(mut self) -> Self {
        self.pre_inactivation = PreInactivation::YesPre;
        self
    }
    pub fn with_max_inact_num(mut self, max_inactive_num: usize) -> Self {
        self.max_inactive_num = max_inactive_num;
        self
    }
}

/// Parameters defining the structure of a fountain code.
///
/// Specifies the number of source, active, inactive, LDPC, and HDPC vectors
/// that together determine the code's parity-check matrix layout.
#[derive(Clone, Debug)]
pub struct CodeParams {
    /// Total number of source (message) vectors.
    pub k: usize,
    /// Number of active source vectors (decoded via BP).
    pub a: usize,
    /// Number of inactive source vectors (decoded via GE), equal to `k - a`.
    pub b: usize,
    /// Number of LDPC (Low-Density Parity-Check) constraint vectors.
    pub l: usize,
    /// Number of HDPC (High-Density Parity-Check) constraint vectors.
    pub h: usize,
    // Number of pre-inactive source vectors.
    //pub i: usize,
    // Number of padding source vectors.
    //pub p: usize,
}

impl CodeParams {
    /// Creates new code parameters with pre-inactivation.
    /// - `b` is computed as `k - a`.
    /// - `i` is computed as `b + h`.
    pub fn new(k: usize, a: usize, l: usize, h: usize) -> Self {
        let b = k - a;
        Self { k, a, b, l, h }
    }

    /// Returns the number of active variable vectors (`a + l`).
    pub fn num_active(&self) -> usize {
        self.a + self.l
    }

    /// Returns the number of pre-inactive variable vectors (`i`).
    pub fn num_pre_inactive(&self) -> usize {
        self.b + self.h
    }

    /// Same as [`num_pre_inactive`](Self::num_pre_inactive); kept for call sites that use this name.
    #[inline]
    pub fn num_inactive(&self) -> usize {
        self.num_pre_inactive()
    }

    /// Returns the combined count of message and LDPC vectors (`k + l`).
    pub fn num_message_ldpc(&self) -> usize {
        self.k + self.l
    }

    /// Returns the total number of variable vectors (`k + l + h`).
    pub fn num_total(&self) -> usize {
        self.k + self.l + self.h
    }
}

/// Distinguishes between systematic and ordinary fountain codes.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CodeType {
    /// Ordinary (non-systematic) encoding and decoding.
    Ordinary,
    /// Systematic encoding and decoding, where source symbols appear unmodified in the output.
    Systematic,
}

/// Identifies which solver configuration to use based on code type and direction.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum SolverType {
    /// Ordinary encoding solver.
    OrdEnc,
    /// Ordinary decoding solver.
    OrdDec,
    /// Systematic encoding solver.
    SysEnc,
    /// Systematic decoding solver.
    SysDec,
}

/// Strategy for selecting which variable to inactivate during BP decoding.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum InactivationStrategy {
    /// Inactivate by original variable index order.
    ByIndex,
    /// Inactivate the first remaining active variable.
    FirstActive,
    /// Inactivate the last remaining active variable.
    LastActive,
    /// Inactivate the variable with minimum remaining degree.
    MinDegree,
    /// Use a trial-run heuristic to choose the best inactivation.
    TrailRun,
}

/// Method used for back-substitution after Gaussian elimination.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum SubstitutionMethod {
    /// Solve directly using the GE-reduced matrix.
    Direct,
    /// Solve using the original constraint matrix.
    Original,
}

/// Type of pre-inactivation for decoding.
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum PreInactivation {
    /// No pre-inactivation.
    NoPre,
    /// Pre-inactivate HDPC variable vectors.
    YesPre,
}

/// Result of the decoding process.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum DecodeStatus {
    /// All source vectors have been successfully recovered.
    Decoded,
    /// Decoding is not yet complete.
    NotDecoded,
}


/// Data vector operations that can be recorded for delayed execution.
///
/// Each variant represents a single atomic operation on data vectors
/// identified by their unique IDs. The [`DataManager`](crate::DataManager)
/// records these operations and optionally forwards them to a
/// [`DataOperator`](crate::traits::DataOperator) for immediate execution.
#[derive(Debug, Clone)]
pub enum Operation {
    /// Zero out the vectors with the given IDs.
    EnsureZero {
        /// IDs of vectors to zero.
        list_id: Vec<usize>,
    },
    /// Multiply a vector element-wise by the primitive element alpha in GF(256).
    MultiplyAlpha {
        /// ID of the vector to multiply.
        id: usize,
    },
    /// Multiply a vector element-wise by a GF(256) scalar.
    MultiplyScalar {
        /// GF(256) scalar multiplier.
        scalar: u8,
        /// ID of the vector to multiply.
        id: usize,
    },
    /// XOR (add in GF(2)/GF(256)) multiple source vectors into a target vector.
    AddToVector {
        /// IDs of source vectors to XOR into the target.
        list_id: Vec<usize>,
        /// ID of the destination vector.
        target_id: usize,
    },
    /// XOR a single source vector into each of several target vectors.
    BroadcastAdd {
        /// ID of the source vector.
        src_id: usize,
        /// IDs of destination vectors.
        target_ids: Vec<usize>,
    },
    /// Multiply source vector by a scalar and XOR the result into the target: `target += scalar * src`.
    MulAdd {
        /// ID of the source vector.
        src_id: usize,
        /// GF(256) scalar multiplier.
        scalar: u8,
        /// ID of the destination vector.
        target_id: usize,
    },
    /// Move a vector from `src_id` to `target_id`, invalidating the source.
    MoveTo {
        /// ID of the source vector.
        src_id: usize,
        /// ID of the destination vector.
        target_id: usize,
    },
    /// Copy a vector from `src_id` to `target_id`, keeping the source intact.
    CopyTo {
        /// ID of the source vector.
        src_id: usize,
        /// ID of the destination vector.
        target_id: usize,
    },
    /// Remove (deallocate) a vector.
    Remove {
        /// ID of the vector to remove.
        id: usize,
    },
    /// Informational marker associating a coded vector ID with its data vector ID.
    InfoCodedVector {
        /// External coded vector identifier.
        coded_id: usize,
        /// Internal data vector identifier.
        data_id: usize,
    },
}