fountain_utility 2.0.0

Data operators and testing utilities for fountain code libraries
Documentation
// Copyright (c) 2025 Shenghao Yang. All rights reserved.
// Licensed under the MIT License. See LICENSE-MIT for details.

//! Operation counting and analysis for fountain code performance evaluation

use fountain_engine::types::Operation;
use serde::{Deserialize, Serialize};

/// Operation counters for tracking different types of operations in DataManager
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct PerformanceMetrics {
    /// Number of multiply-by-alpha operations
    pub multiply_alpha: usize,
    /// Number of scalar multiplication operations
    pub multiply_scalar: usize,
    /// Number of vector addition operations
    pub vector_add: usize,
    /// Number of multiply-add (axpy) operations
    pub mul_add: usize,
    /// Peak number of vectors stored simultaneously
    pub max_storage: usize,
    /// Number of coded vectors produced or consumed
    pub num_coded_vectors: usize,
}

impl PerformanceMetrics {
    /// Count operations
    pub fn from_operations(operations: &[Operation], coded_vector_inserted: usize) -> Self {
        let mut metrics = Self::default();
        let mut current_storage = coded_vector_inserted;
        for operation in operations {
            match operation {
                Operation::EnsureZero { list_id } => {
                    current_storage += list_id.len();
                    if current_storage > metrics.max_storage {
                        metrics.max_storage = current_storage;
                    }
                }
                Operation::EnsureZeroOne { .. } => {
                    current_storage += 1;
                    if current_storage > metrics.max_storage {
                        metrics.max_storage = current_storage;
                    }
                }
                Operation::MultiplyAlpha { .. } => metrics.multiply_alpha += 1,
                Operation::MultiplyScalar { .. } => metrics.multiply_scalar += 1,
                Operation::AddOneToVector { .. } => metrics.vector_add += 1,
                Operation::AddTwoToVector { .. } => metrics.vector_add += 2,
                Operation::AddThreeToVector { .. } => metrics.vector_add += 3,
                Operation::AddToVector { list_id, .. } => metrics.vector_add += list_id.len(),
                Operation::BroadcastAdd { target_ids, .. } => {
                    metrics.vector_add += target_ids.len()
                }
                Operation::MulAdd { .. } => metrics.mul_add += 1,
                Operation::MoveTo { .. } => {}
                Operation::CopyTo { .. } => {
                    current_storage += 1;
                    if current_storage > metrics.max_storage {
                        metrics.max_storage = current_storage;
                    }
                }
                Operation::Remove { .. } => {
                    if let Some(new_value) = current_storage.checked_sub(1) {
                        current_storage = new_value;
                    } else {
                        //current_storage = 0;
                        panic!("Current storage is 0, cannot remove a vector");
                    }
                }
                Operation::InfoCodedVector { .. } => metrics.num_coded_vectors += 1,
            }
        }
        metrics
    }
}