#![allow(dead_code)]
use std::collections::HashMap;
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct MemoEntry<V> {
pub value: V,
pub access_count: u32,
}
#[derive(Debug)]
#[allow(dead_code)]
pub struct MemoTable<V> {
entries: HashMap<u64, MemoEntry<V>>,
hit_count: u64,
miss_count: u64,
}
#[allow(dead_code)]
pub fn new_memo_table<V>() -> MemoTable<V> {
MemoTable {
entries: HashMap::new(),
hit_count: 0,
miss_count: 0,
}
}
#[allow(dead_code)]
pub fn memo_get<V>(table: &mut MemoTable<V>, key: u64) -> Option<&V> {
if let Some(entry) = table.entries.get_mut(&key) {
entry.access_count += 1;
table.hit_count += 1;
Some(&entry.value)
} else {
table.miss_count += 1;
None
}
}
#[allow(dead_code)]
pub fn memo_set<V>(table: &mut MemoTable<V>, key: u64, value: V) {
table.entries.insert(
key,
MemoEntry {
value,
access_count: 0,
},
);
}
#[allow(dead_code)]
pub fn memo_contains<V>(table: &MemoTable<V>, key: u64) -> bool {
table.entries.contains_key(&key)
}
#[allow(dead_code)]
pub fn memo_invalidate<V>(table: &mut MemoTable<V>, key: u64) -> bool {
table.entries.remove(&key).is_some()
}
#[allow(dead_code)]
pub fn memo_clear<V>(table: &mut MemoTable<V>) {
table.entries.clear();
}
#[allow(dead_code)]
pub fn memo_len<V>(table: &MemoTable<V>) -> usize {
table.entries.len()
}
#[allow(dead_code)]
pub fn memo_hit_rate<V>(table: &MemoTable<V>) -> f32 {
let total = table.hit_count + table.miss_count;
if total == 0 {
return 0.0;
}
table.hit_count as f32 / total as f32
}
#[allow(dead_code)]
pub fn memo_hits<V>(table: &MemoTable<V>) -> u64 {
table.hit_count
}
#[allow(dead_code)]
pub fn memo_misses<V>(table: &MemoTable<V>) -> u64 {
table.miss_count
}
#[allow(dead_code)]
pub fn memo_access_count<V>(table: &MemoTable<V>, key: u64) -> u32 {
table.entries.get(&key).map(|e| e.access_count).unwrap_or(0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_set_and_get() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 1, 100);
assert_eq!(memo_get(&mut t, 1), Some(&100));
}
#[test]
fn test_miss() {
let mut t: MemoTable<u32> = new_memo_table();
assert_eq!(memo_get(&mut t, 99), None);
assert_eq!(memo_misses(&t), 1);
}
#[test]
fn test_hit_count() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 5, 50);
memo_get(&mut t, 5);
memo_get(&mut t, 5);
assert_eq!(memo_hits(&t), 2);
}
#[test]
fn test_hit_rate() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 1, 1);
memo_get(&mut t, 1); memo_get(&mut t, 2); let hr = memo_hit_rate(&t);
assert!((hr - 0.5_f32).abs() < 1e-5);
}
#[test]
fn test_invalidate() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 7, 77);
assert!(memo_invalidate(&mut t, 7));
assert!(!memo_contains(&t, 7));
}
#[test]
fn test_contains() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 3, 30);
assert!(memo_contains(&t, 3));
assert!(!memo_contains(&t, 4));
}
#[test]
fn test_clear() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 1, 1);
memo_clear(&mut t);
assert_eq!(memo_len(&t), 0);
}
#[test]
fn test_access_count() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 10, 100);
memo_get(&mut t, 10);
memo_get(&mut t, 10);
memo_get(&mut t, 10);
assert_eq!(memo_access_count(&t, 10), 3);
}
#[test]
fn test_len() {
let mut t: MemoTable<u32> = new_memo_table();
memo_set(&mut t, 1, 1);
memo_set(&mut t, 2, 2);
assert_eq!(memo_len(&t), 2);
}
}