torsh-backend 0.1.2

Backend abstraction layer for ToRSh
Documentation
//! SciRS2 Parallel Operations Integration
//!
//! This module provides parallel operations using scirs2-core's parallel processing
//! capabilities, fully compliant with SciRS2 POLICY.
//!
//! ## SciRS2 POLICY Compliance
//! ✅ This module uses scirs2-core::parallel_ops for ALL parallel operations

// ✅ SciRS2 POLICY: Use scirs2_core::parallel_ops (migration complete!)
pub use scirs2_core::parallel_ops::*;

/// Get the number of threads available for parallel operations
///
/// # SciRS2 POLICY
/// ✅ Uses scirs2_core::parallel_ops::current_num_threads() (fully migrated)
#[inline]
pub fn get_parallel_threads() -> usize {
    current_num_threads()
}

/// Execute a parallel for loop over a range
///
/// # SciRS2 POLICY
/// ✅ Uses scirs2_core::parallel_ops primitives (fully migrated)
#[inline]
pub fn parallel_for_range<F>(start: usize, end: usize, op: F)
where
    F: Fn(usize) + Send + Sync,
{
    (start..end).into_par_iter().for_each(op);
}

/// Execute a parallel map over a range
///
/// # SciRS2 POLICY
/// ✅ Uses scirs2_core::parallel_ops primitives (fully migrated)
#[inline]
pub fn parallel_map_range<F, R>(start: usize, end: usize, op: F) -> Vec<R>
where
    F: Fn(usize) -> R + Send + Sync,
    R: Send,
{
    (start..end).into_par_iter().map(op).collect()
}

/// Module for convenience imports
pub mod prelude {
    pub use super::{get_parallel_threads, parallel_for_range, parallel_map_range};
    // ✅ SciRS2 POLICY: Re-export scirs2_core::parallel_ops (fully migrated)
    pub use scirs2_core::parallel_ops::*;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parallel_threads() {
        let num = get_parallel_threads();
        assert!(num > 0, "Should have at least 1 thread");
    }

    #[test]
    fn test_parallel_for_range() {
        use std::sync::{Arc, Mutex};
        let sum = Arc::new(Mutex::new(0));
        let sum_clone = Arc::clone(&sum);

        parallel_for_range(0, 100, move |i| {
            let mut s = sum_clone.lock().expect("lock should not be poisoned");
            *s += i;
        });

        let result = *sum.lock().expect("lock should not be poisoned");
        assert_eq!(result, (0..100).sum::<usize>());
    }

    #[test]
    fn test_parallel_map_range() {
        let results = parallel_map_range(0, 10, |i| i * i);
        assert_eq!(results, vec![0, 1, 4, 9, 16, 25, 36, 49, 64, 81]);
    }
}