native_neural_network_std 0.2.1

Ergonomic std wrapper for the `native_neural_network` crate (no_std) — std-friendly re-exports and utilities.
Documentation
use native_neural_network_std as nn;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};

fn scale_from_env() -> usize {
    std::env::var("STRESS_SCALE")
        .ok()
        .and_then(|s| s.parse().ok())
        .unwrap_or(1)
}

#[test]
fn cpu_backend_abstraction_real() {
    let previous = native_neural_network_std::std::engine_std::get_compute_backend();
    native_neural_network_std::std::engine_std::set_compute_backend(
        native_neural_network_std::std::engine_std::ComputeBackend::Cpu,
    );
    assert_eq!(
        native_neural_network_std::std::engine_std::get_compute_backend(),
        native_neural_network_std::std::engine_std::ComputeBackend::Cpu
    );
    native_neural_network_std::std::engine_std::set_compute_backend(previous);
}

#[test]
fn stress_massive_allocations() {
    for cycle in 0..10 {
        let mut holders = Vec::with_capacity(8);
        for _ in 0..8 {
            let n = 100_000_000usize;
            let mut v = vec![0f32; n];
            for i in (0..n).step_by(10_000_000) {
                v[i] = (i as f32).sin();
            }
            holders.push(v);
        }
        thread::sleep(Duration::from_millis(500));
        drop(holders);
        println!("cycle {} completed", cycle);
    }
}

#[test]
fn stress_threads_shared_access() {
    let cpus = thread::available_parallelism()
        .map(|n| n.get())
        .unwrap_or(4);
    let shared = Arc::new(Mutex::new(vec![0u8; 10_000_000]));
    let mut handles = Vec::new();
    for _ in 0..(cpus * 4) {
        let s = Arc::clone(&shared);
        handles.push(thread::spawn(move || {
            for _ in 0..100 {
                let mut guard = s.lock().unwrap();
                guard[0] = guard[0].wrapping_add(1);
                drop(guard);
                thread::sleep(Duration::from_millis(5));
            }
        }));
    }
    for h in handles {
        h.join().unwrap();
    }
}

#[test]
fn stress_numerical_limits() {
    let extremes = [
        f32::INFINITY,
        f32::NEG_INFINITY,
        f32::NAN,
        0.0f32,
        1e-38f32,
        1e38f32,
    ];
    for &x in &extremes {
        let add = x + 1.0f32;
        let mul = x * 2.0f32;
        let sq = x.sqrt();
        if x.is_finite() {
            assert!(
                add.is_finite() && mul.is_finite() && sq.is_finite(),
                "finite inputs must produce finite results"
            );
        } else {
            assert!(
                !add.is_finite() || !mul.is_finite() || !sq.is_finite(),
                "non-finite should propagate non-finites"
            );
        }
        println!("checked {} -> {}, {}, {}", x, add, mul, sq);
    }
}

#[test]
fn stress_cpu_oscillation() {
    let cpus = thread::available_parallelism()
        .map(|n| n.get())
        .unwrap_or(4);
    let duration = Duration::from_secs(10);
    let start = Instant::now();
    let mut handles = Vec::new();
    for _ in 0..cpus {
        handles.push(thread::spawn(move || {
            while Instant::now() - start < duration {
                let mut acc = 0u64;
                for i in 0..5_000_000u64 {
                    acc = acc.wrapping_add(i);
                }
                thread::sleep(Duration::from_millis(10));
            }
        }));
    }
    for h in handles {
        h.join().unwrap();
    }
}

#[test]
fn stress_combined_max() {
    let cpus = thread::available_parallelism()
        .map(|n| n.get())
        .unwrap_or(4);
    let shared = Arc::new(Mutex::new(Vec::<u8>::new()));
    let mut handles = Vec::new();
    for _ in 0..cpus {
        let s = Arc::clone(&shared);
        handles.push(thread::spawn(move || {
            for _ in 0..50 {
                let v = vec![0u8; 10_000_000];
                {
                    let mut g = s.lock().unwrap();
                    g.extend_from_slice(&v[0..100]);
                }
                let mut acc = 0u64;
                for i in 0..1_000_000u64 {
                    acc = acc.wrapping_add(i);
                }
                drop(v);
                thread::sleep(Duration::from_millis(20));
            }
        }));
    }
    for h in handles {
        h.join().unwrap();
    }
}

#[test]
fn stress_alloc_massive_network() {
    let scale = scale_from_env();
    let base = 512usize.saturating_mul(scale);
    let layers = vec![base, base * 2, base * 2, base];
    let wcount =
        nn::std::network_std::NeuralNetworkStd::expected_weights_count(&layers).unwrap_or(0);
    let bcount =
        nn::std::network_std::NeuralNetworkStd::expected_biases_count(&layers).unwrap_or(0);
    let weights = vec![1f32; wcount];
    let biases = vec![0f32; bcount];
    let _net = nn::std::network_std::NeuralNetworkStd::from_parts(layers.clone(), weights, biases)
        .expect("construct");
}

#[test]
fn stress_alloc_free_cycles() {
    let scale = scale_from_env();
    let base = 256usize.saturating_mul(scale);
    let layers = vec![base, base * 2, base];
    let wcount =
        nn::std::network_std::NeuralNetworkStd::expected_weights_count(&layers).unwrap_or(0);
    let bcount =
        nn::std::network_std::NeuralNetworkStd::expected_biases_count(&layers).unwrap_or(0);
    for _ in 0..100 {
        let weights = vec![0.5f32; wcount];
        let biases = vec![0.0f32; bcount];
        let net =
            nn::std::network_std::NeuralNetworkStd::from_parts(layers.clone(), weights, biases)
                .expect("construct");
        nn::std::network_std::validate_network_parts(&net.layers, &net.weights, &net.biases);
        nn::std::network_std::network_stats(&net.layers, &net.weights, &net.biases);
        drop(net);
    }
}

#[test]
fn stress_kv_cache_saturation() {
    let max_tokens = 50_000usize;
    let head_dim = 64usize;
    let num_heads = 8usize;
    let mut kv = nn::std::kv_cache_std::KvCacheStd::new(max_tokens, head_dim, num_heads);
    let stride = head_dim * num_heads;
    let token = vec![1f32; stride];
    for i in 0..(max_tokens + 5) {
        let res = kv.append_token(&token, &token);
        if i < max_tokens {
            assert!(res.is_ok());
        } else {
            assert!(res.is_err());
        }
    }
}

#[test]
fn stress_multithread_forward() {
    let scale = scale_from_env();
    let base = 128usize.saturating_mul(scale);
    let layers = vec![base, base * 2, base];
    let wcount =
        nn::std::network_std::NeuralNetworkStd::expected_weights_count(&layers).unwrap_or(0);
    let bcount =
        nn::std::network_std::NeuralNetworkStd::expected_biases_count(&layers).unwrap_or(0);
    let weights = vec![0.1f32; wcount];
    let biases = vec![0f32; bcount];
    let net = Arc::new(
        nn::std::network_std::NeuralNetworkStd::from_parts(layers.clone(), weights, biases)
            .expect("construct"),
    );
    let threads = thread::available_parallelism()
        .map(|n| n.get())
        .unwrap_or(4)
        .saturating_mul(2);
    let mut handles = Vec::new();
    for _ in 0..threads {
        let net = Arc::clone(&net);
        let layers = layers.clone();
        handles.push(thread::spawn(move || {
            for _ in 0..100 {
                nn::std::network_std::validate_network_parts(&layers, &net.weights, &net.biases);
            }
        }));
    }
    for h in handles {
        h.join().unwrap();
    }
}

#[test]
fn stress_numeric_extremes() {
    let scale = scale_from_env();
    let base = 64usize.saturating_mul(scale);
    let layers = vec![base, base * 2, base];
    let wcount =
        nn::std::network_std::NeuralNetworkStd::expected_weights_count(&layers).unwrap_or(0);
    let bcount =
        nn::std::network_std::NeuralNetworkStd::expected_biases_count(&layers).unwrap_or(0);
    let mut weights = vec![1f32; wcount];
    let mut biases = vec![0f32; bcount];
    if !weights.is_empty() {
        weights[0] = f32::INFINITY;
    }
    if biases.len() > 1 {
        biases[1] = f32::NAN;
    }
    let net = nn::std::network_std::NeuralNetworkStd::from_parts(layers.clone(), weights, biases)
        .expect("construct");
    nn::std::network_std::validate_network_parts(&net.layers, &net.weights, &net.biases);
    nn::std::network_std::network_stats(&net.layers, &net.weights, &net.biases);
}