#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct VertexCache {
cache: Vec<Option<usize>>,
capacity: usize,
hits: usize,
misses: usize,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct CacheStats {
pub hits: usize,
pub misses: usize,
pub total: usize,
}
#[allow(dead_code)]
pub fn new_vertex_cache(capacity: usize) -> VertexCache {
VertexCache {
cache: vec![None; capacity],
capacity,
hits: 0,
misses: 0,
}
}
#[allow(dead_code)]
pub fn cache_vertex(cache: &mut VertexCache, vertex: usize) {
if cache.cache.iter().any(|v| *v == Some(vertex)) {
cache.hits += 1;
return;
}
cache.misses += 1;
cache.cache.rotate_right(1);
cache.cache[0] = Some(vertex);
}
#[allow(dead_code)]
pub fn cache_hit(cache: &VertexCache, vertex: usize) -> bool {
cache.cache.iter().any(|v| *v == Some(vertex))
}
#[allow(dead_code)]
pub fn cache_miss(cache: &VertexCache, vertex: usize) -> bool {
!cache_hit(cache, vertex)
}
#[allow(dead_code)]
pub fn cache_hit_rate(cache: &VertexCache) -> f32 {
let total = cache.hits + cache.misses;
if total == 0 {
return 0.0;
}
cache.hits as f32 / total as f32
}
#[allow(dead_code)]
pub fn cache_clear(cache: &mut VertexCache) {
for entry in cache.cache.iter_mut() {
*entry = None;
}
cache.hits = 0;
cache.misses = 0;
}
#[allow(dead_code)]
pub fn cache_capacity(cache: &VertexCache) -> usize {
cache.capacity
}
#[allow(dead_code)]
pub fn optimize_vertex_order(indices: &[usize], cache_size: usize) -> Vec<usize> {
let mut cache = new_vertex_cache(cache_size);
let mut result = Vec::with_capacity(indices.len());
for &idx in indices {
cache_vertex(&mut cache, idx);
result.push(idx);
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_cache() {
let c = new_vertex_cache(16);
assert_eq!(cache_capacity(&c), 16);
}
#[test]
fn test_cache_miss_then_hit() {
let mut c = new_vertex_cache(4);
assert!(cache_miss(&c, 0));
cache_vertex(&mut c, 0);
assert!(cache_hit(&c, 0));
}
#[test]
fn test_cache_hit_rate_empty() {
let c = new_vertex_cache(4);
assert!((cache_hit_rate(&c) - 0.0).abs() < 1e-6);
}
#[test]
fn test_cache_hit_rate_all_miss() {
let mut c = new_vertex_cache(2);
cache_vertex(&mut c, 0);
cache_vertex(&mut c, 1);
cache_vertex(&mut c, 2);
assert!((cache_hit_rate(&c) - 0.0).abs() < 1e-6);
}
#[test]
fn test_cache_hit_rate_repeated() {
let mut c = new_vertex_cache(4);
cache_vertex(&mut c, 0); cache_vertex(&mut c, 0); assert!((cache_hit_rate(&c) - 0.5).abs() < 1e-6);
}
#[test]
fn test_cache_clear() {
let mut c = new_vertex_cache(4);
cache_vertex(&mut c, 0);
cache_clear(&mut c);
assert!(cache_miss(&c, 0));
assert!((cache_hit_rate(&c) - 0.0).abs() < 1e-6);
}
#[test]
fn test_cache_eviction() {
let mut c = new_vertex_cache(2);
cache_vertex(&mut c, 0);
cache_vertex(&mut c, 1);
cache_vertex(&mut c, 2);
assert!(cache_miss(&c, 0));
assert!(cache_hit(&c, 1));
assert!(cache_hit(&c, 2));
}
#[test]
fn test_optimize_vertex_order() {
let indices = vec![0, 1, 2, 0, 1, 2];
let result = optimize_vertex_order(&indices, 4);
assert_eq!(result.len(), 6);
}
#[test]
fn test_cache_capacity() {
let c = new_vertex_cache(32);
assert_eq!(cache_capacity(&c), 32);
}
#[test]
fn test_cache_stats() {
let mut c = new_vertex_cache(4);
cache_vertex(&mut c, 0); cache_vertex(&mut c, 1); cache_vertex(&mut c, 0); assert_eq!(c.hits, 1);
assert_eq!(c.misses, 2);
}
}