use super::functions::*;
use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
#[allow(dead_code)]
pub struct MealyMachineRs<S, I, O> {
transition: Box<dyn Fn(S, I) -> (S, O)>,
state: S,
}
#[allow(dead_code)]
impl<S: Clone + 'static, I: 'static, O: 'static> MealyMachineRs<S, I, O> {
pub fn new(state: S, transition: impl Fn(S, I) -> (S, O) + 'static) -> Self {
Self {
transition: Box::new(transition),
state,
}
}
pub fn step(&mut self, input: I) -> O {
let old_state = self.state.clone();
let (new_state, output) = (self.transition)(old_state, input);
self.state = new_state;
output
}
pub fn run_vec(&mut self, inputs: Vec<I>) -> Vec<O> {
inputs.into_iter().map(|i| self.step(i)).collect()
}
pub fn current_state(&self) -> &S {
&self.state
}
pub fn reset(&mut self, state: S) {
self.state = state;
}
}
#[allow(dead_code)]
pub struct MooreMachineRs<S, I, O> {
transition: Box<dyn Fn(&S, I) -> S>,
output: Box<dyn Fn(&S) -> O>,
state: S,
}
#[allow(dead_code)]
impl<S: 'static, I: 'static, O: 'static> MooreMachineRs<S, I, O> {
pub fn new(
state: S,
transition: impl Fn(&S, I) -> S + 'static,
output: impl Fn(&S) -> O + 'static,
) -> Self {
Self {
transition: Box::new(transition),
output: Box::new(output),
state,
}
}
pub fn read_output(&self) -> O {
(self.output)(&self.state)
}
pub fn step(&mut self, input: I) {
self.state = (self.transition)(&self.state, input);
}
pub fn run_vec(&mut self, inputs: Vec<I>) -> Vec<O> {
let mut results = Vec::with_capacity(inputs.len());
for inp in inputs {
results.push(self.read_output());
self.step(inp);
}
results
}
pub fn state(&self) -> &S {
&self.state
}
}
#[allow(dead_code)]
pub struct StreamWindow<T> {
buf: Vec<Option<T>>,
size: usize,
pos: usize,
count: usize,
}
#[allow(dead_code)]
impl<T: Clone> StreamWindow<T> {
pub fn new(size: usize) -> Self {
Self {
buf: vec![None; size],
size,
pos: 0,
count: 0,
}
}
pub fn push(&mut self, val: T) {
self.buf[self.pos] = Some(val);
self.pos = (self.pos + 1) % self.size;
self.count += 1;
}
pub fn window(&self) -> Vec<T> {
let len = self.count.min(self.size);
let mut result = Vec::with_capacity(len);
let start = if self.count >= self.size { self.pos } else { 0 };
for i in 0..len {
let idx = (start + i) % self.size;
if let Some(ref v) = self.buf[idx] {
result.push(v.clone());
}
}
result
}
pub fn len(&self) -> usize {
self.count.min(self.size)
}
pub fn is_empty(&self) -> bool {
self.count == 0
}
pub fn window_size(&self) -> usize {
self.size
}
}
#[derive(Debug, Clone, Default)]
pub struct StreamDeclStats {
pub core: usize,
pub combinators: usize,
pub monad: usize,
pub theorems: usize,
}
impl StreamDeclStats {
pub fn compute(env: &Environment) -> Self {
let core_names = ["Stream", "Stream.cons", "Stream.head", "Stream.tail"];
let combinator_names = [
"Stream.map",
"Stream.take",
"Stream.zip",
"Stream.iterate",
"Stream.drop",
"Stream.nth",
"Stream.const",
"Stream.filter",
];
let monad_names = ["Stream.pure", "Stream.scan", "Stream.interleave"];
let theorem_names = ["Stream.head_cons", "Stream.tail_cons"];
let count = |names: &[&str]| {
names
.iter()
.filter(|&&n| env.get(&Name::str(n)).is_some())
.count()
};
Self {
core: count(&core_names),
combinators: count(&combinator_names),
monad: count(&monad_names),
theorems: count(&theorem_names),
}
}
pub fn total(&self) -> usize {
self.core + self.combinators + self.monad + self.theorems
}
}
#[allow(dead_code)]
pub struct PriorityMerge<T> {
left: LazyStream<T>,
right: LazyStream<T>,
}
#[allow(dead_code)]
impl<T: 'static> PriorityMerge<T> {
pub fn new(left: LazyStream<T>, right: LazyStream<T>) -> Self {
Self { left, right }
}
pub fn next(&mut self) -> Option<T> {
self.left.next().or_else(|| self.right.next())
}
pub fn take_n(&mut self, n: usize) -> Vec<T> {
(0..n).filter_map(|_| self.next()).collect()
}
}
#[allow(dead_code)]
pub struct CountMinSketchRs {
table: Vec<Vec<u64>>,
d: usize,
w: usize,
}
#[allow(dead_code)]
impl CountMinSketchRs {
pub fn new(d: usize, w: usize) -> Self {
Self {
table: vec![vec![0u64; w]; d],
d,
w,
}
}
pub fn update(&mut self, item: u64) {
for row in 0..self.d {
let col = self.strm_ext_hash(item, row as u64) % self.w;
self.table[row][col] += 1;
}
}
pub fn estimate(&self, item: u64) -> u64 {
(0..self.d)
.map(|row| {
let col = self.strm_ext_hash(item, row as u64) % self.w;
self.table[row][col]
})
.min()
.unwrap_or(0)
}
fn strm_ext_hash(&self, item: u64, seed: u64) -> usize {
let h = item
.wrapping_mul(2654435761)
.wrapping_add(seed.wrapping_mul(40503));
h as usize
}
pub fn total_updates(&self) -> u64 {
if self.d > 0 {
self.table[0].iter().sum()
} else {
0
}
}
}
pub struct LazyStream<T> {
gen: Box<dyn FnMut() -> Option<T>>,
}
impl<T> LazyStream<T> {
pub fn from_fn(gen: impl FnMut() -> Option<T> + 'static) -> Self {
Self { gen: Box::new(gen) }
}
pub fn constant(val: T) -> Self
where
T: Clone + 'static,
{
Self::from_fn(move || Some(val.clone()))
}
pub fn iterate(mut init: T, mut f: impl FnMut(T) -> T + 'static) -> Self
where
T: Clone + 'static,
{
Self::from_fn(move || {
let curr = init.clone();
init = f(init.clone());
Some(curr)
})
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Option<T> {
(self.gen)()
}
pub fn take(mut self, n: usize) -> Vec<T> {
(0..n).filter_map(|_| self.next()).collect()
}
}
#[allow(dead_code)]
pub struct BloomFilterRs {
bits: Vec<bool>,
k: usize,
m: usize,
}
#[allow(dead_code)]
impl BloomFilterRs {
pub fn new(m: usize, k: usize) -> Self {
Self {
bits: vec![false; m],
k,
m,
}
}
pub fn insert(&mut self, item: u64) {
for i in 0..self.k {
let idx = self.strm_ext_hash(item, i as u64) % self.m;
self.bits[idx] = true;
}
}
pub fn query(&self, item: u64) -> bool {
(0..self.k).all(|i| {
let idx = self.strm_ext_hash(item, i as u64) % self.m;
self.bits[idx]
})
}
fn strm_ext_hash(&self, item: u64, seed: u64) -> usize {
let h = item
.wrapping_mul(6364136223846793005)
.wrapping_add(seed.wrapping_mul(1442695040888963407));
h as usize
}
pub fn count_set(&self) -> usize {
self.bits.iter().filter(|&&b| b).count()
}
pub fn capacity(&self) -> usize {
self.m
}
}