Skip to main content

oxilean_std/stream/
types.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use super::functions::*;
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
7
8/// A Mealy machine over Rust values: given state S, reads input I, emits output O.
9///
10/// Each step function takes the current state and an input and returns
11/// the next state plus an output.
12#[allow(dead_code)]
13pub struct MealyMachineRs<S, I, O> {
14    /// The transition function: (state, input) → (next_state, output).
15    transition: Box<dyn Fn(S, I) -> (S, O)>,
16    /// The current state of the machine.
17    state: S,
18}
19#[allow(dead_code)]
20impl<S: Clone + 'static, I: 'static, O: 'static> MealyMachineRs<S, I, O> {
21    /// Create a new Mealy machine with an initial state and transition function.
22    pub fn new(state: S, transition: impl Fn(S, I) -> (S, O) + 'static) -> Self {
23        Self {
24            transition: Box::new(transition),
25            state,
26        }
27    }
28    /// Step the machine with one input, returning the output and advancing state.
29    pub fn step(&mut self, input: I) -> O {
30        let old_state = self.state.clone();
31        let (new_state, output) = (self.transition)(old_state, input);
32        self.state = new_state;
33        output
34    }
35    /// Run the machine over a vector of inputs, collecting outputs.
36    pub fn run_vec(&mut self, inputs: Vec<I>) -> Vec<O> {
37        inputs.into_iter().map(|i| self.step(i)).collect()
38    }
39    /// Get the current state.
40    pub fn current_state(&self) -> &S {
41        &self.state
42    }
43    /// Reset the machine to a new state.
44    pub fn reset(&mut self, state: S) {
45        self.state = state;
46    }
47}
48/// A Moore machine over Rust values: output depends only on state.
49///
50/// Each transition takes a state and input and returns the next state.
51/// The output function maps states to outputs.
52#[allow(dead_code)]
53pub struct MooreMachineRs<S, I, O> {
54    /// Transition function: (state, input) → next_state.
55    transition: Box<dyn Fn(&S, I) -> S>,
56    /// Output function: state → output.
57    output: Box<dyn Fn(&S) -> O>,
58    /// The current state.
59    state: S,
60}
61#[allow(dead_code)]
62impl<S: 'static, I: 'static, O: 'static> MooreMachineRs<S, I, O> {
63    /// Create a new Moore machine.
64    pub fn new(
65        state: S,
66        transition: impl Fn(&S, I) -> S + 'static,
67        output: impl Fn(&S) -> O + 'static,
68    ) -> Self {
69        Self {
70            transition: Box::new(transition),
71            output: Box::new(output),
72            state,
73        }
74    }
75    /// Read the current output (depends only on state).
76    pub fn read_output(&self) -> O {
77        (self.output)(&self.state)
78    }
79    /// Advance the machine with one input.
80    pub fn step(&mut self, input: I) {
81        self.state = (self.transition)(&self.state, input);
82    }
83    /// Run the machine over a vector of inputs, collecting one output per step.
84    pub fn run_vec(&mut self, inputs: Vec<I>) -> Vec<O> {
85        let mut results = Vec::with_capacity(inputs.len());
86        for inp in inputs {
87            results.push(self.read_output());
88            self.step(inp);
89        }
90        results
91    }
92    /// Get the current state.
93    pub fn state(&self) -> &S {
94        &self.state
95    }
96}
97/// A stream window that maintains a sliding window over a stream.
98///
99/// Useful for streaming algorithms that need fixed-size recent history.
100#[allow(dead_code)]
101pub struct StreamWindow<T> {
102    /// The circular buffer.
103    buf: Vec<Option<T>>,
104    /// Window size.
105    size: usize,
106    /// Write position.
107    pos: usize,
108    /// Number of elements inserted.
109    count: usize,
110}
111#[allow(dead_code)]
112impl<T: Clone> StreamWindow<T> {
113    /// Create a new stream window of the given size.
114    pub fn new(size: usize) -> Self {
115        Self {
116            buf: vec![None; size],
117            size,
118            pos: 0,
119            count: 0,
120        }
121    }
122    /// Push a new element into the window.
123    pub fn push(&mut self, val: T) {
124        self.buf[self.pos] = Some(val);
125        self.pos = (self.pos + 1) % self.size;
126        self.count += 1;
127    }
128    /// Return the current window contents in order (oldest to newest).
129    pub fn window(&self) -> Vec<T> {
130        let len = self.count.min(self.size);
131        let mut result = Vec::with_capacity(len);
132        let start = if self.count >= self.size { self.pos } else { 0 };
133        for i in 0..len {
134            let idx = (start + i) % self.size;
135            if let Some(ref v) = self.buf[idx] {
136                result.push(v.clone());
137            }
138        }
139        result
140    }
141    /// Return the number of elements currently in the window.
142    pub fn len(&self) -> usize {
143        self.count.min(self.size)
144    }
145    /// Return true if the window is empty.
146    pub fn is_empty(&self) -> bool {
147        self.count == 0
148    }
149    /// Return the window size.
150    pub fn window_size(&self) -> usize {
151        self.size
152    }
153}
154/// Count stream-related declarations by category.
155#[derive(Debug, Clone, Default)]
156pub struct StreamDeclStats {
157    /// Number of core type/constructor declarations.
158    pub core: usize,
159    /// Number of combinator declarations.
160    pub combinators: usize,
161    /// Number of monad/applicative declarations.
162    pub monad: usize,
163    /// Number of theorem declarations.
164    pub theorems: usize,
165}
166impl StreamDeclStats {
167    /// Compute stats for the given environment.
168    pub fn compute(env: &Environment) -> Self {
169        let core_names = ["Stream", "Stream.cons", "Stream.head", "Stream.tail"];
170        let combinator_names = [
171            "Stream.map",
172            "Stream.take",
173            "Stream.zip",
174            "Stream.iterate",
175            "Stream.drop",
176            "Stream.nth",
177            "Stream.const",
178            "Stream.filter",
179        ];
180        let monad_names = ["Stream.pure", "Stream.scan", "Stream.interleave"];
181        let theorem_names = ["Stream.head_cons", "Stream.tail_cons"];
182        let count = |names: &[&str]| {
183            names
184                .iter()
185                .filter(|&&n| env.get(&Name::str(n)).is_some())
186                .count()
187        };
188        Self {
189            core: count(&core_names),
190            combinators: count(&combinator_names),
191            monad: count(&monad_names),
192            theorems: count(&theorem_names),
193        }
194    }
195    /// Total number of stream declarations.
196    pub fn total(&self) -> usize {
197        self.core + self.combinators + self.monad + self.theorems
198    }
199}
200/// A reactive stream combinator that merges two streams by priority.
201///
202/// When both streams have elements, the left stream takes priority.
203#[allow(dead_code)]
204pub struct PriorityMerge<T> {
205    left: LazyStream<T>,
206    right: LazyStream<T>,
207}
208#[allow(dead_code)]
209impl<T: 'static> PriorityMerge<T> {
210    /// Create a new priority merge of two streams.
211    pub fn new(left: LazyStream<T>, right: LazyStream<T>) -> Self {
212        Self { left, right }
213    }
214    /// Get the next element, preferring the left stream.
215    pub fn next(&mut self) -> Option<T> {
216        self.left.next().or_else(|| self.right.next())
217    }
218    /// Collect `n` elements from the merged stream.
219    pub fn take_n(&mut self, n: usize) -> Vec<T> {
220        (0..n).filter_map(|_| self.next()).collect()
221    }
222}
223/// A count-min sketch for streaming frequency estimation.
224///
225/// Provides approximate frequency counts for stream elements.
226#[allow(dead_code)]
227pub struct CountMinSketchRs {
228    /// 2D table of counts.
229    table: Vec<Vec<u64>>,
230    /// Number of rows (hash functions).
231    d: usize,
232    /// Number of columns (width).
233    w: usize,
234}
235#[allow(dead_code)]
236impl CountMinSketchRs {
237    /// Create a new count-min sketch with `d` rows and `w` columns.
238    pub fn new(d: usize, w: usize) -> Self {
239        Self {
240            table: vec![vec![0u64; w]; d],
241            d,
242            w,
243        }
244    }
245    /// Update the sketch with one occurrence of an item.
246    pub fn update(&mut self, item: u64) {
247        for row in 0..self.d {
248            let col = self.strm_ext_hash(item, row as u64) % self.w;
249            self.table[row][col] += 1;
250        }
251    }
252    /// Estimate the frequency of an item.
253    pub fn estimate(&self, item: u64) -> u64 {
254        (0..self.d)
255            .map(|row| {
256                let col = self.strm_ext_hash(item, row as u64) % self.w;
257                self.table[row][col]
258            })
259            .min()
260            .unwrap_or(0)
261    }
262    fn strm_ext_hash(&self, item: u64, seed: u64) -> usize {
263        let h = item
264            .wrapping_mul(2654435761)
265            .wrapping_add(seed.wrapping_mul(40503));
266        h as usize
267    }
268    /// Return total number of updates recorded (sum of row 0).
269    pub fn total_updates(&self) -> u64 {
270        if self.d > 0 {
271            self.table[0].iter().sum()
272        } else {
273            0
274        }
275    }
276}
277/// A purely Rust-level lazy stream (for algorithm testing).
278///
279/// Unlike the OxiLean expression-level Stream, this is a Rust iterator wrapper.
280pub struct LazyStream<T> {
281    /// Underlying item source (boxed closure for laziness).
282    gen: Box<dyn FnMut() -> Option<T>>,
283}
284impl<T> LazyStream<T> {
285    /// Create a stream from a generator function.
286    pub fn from_fn(gen: impl FnMut() -> Option<T> + 'static) -> Self {
287        Self { gen: Box::new(gen) }
288    }
289    /// Create an infinite stream that always yields the same value.
290    pub fn constant(val: T) -> Self
291    where
292        T: Clone + 'static,
293    {
294        Self::from_fn(move || Some(val.clone()))
295    }
296    /// Create a stream that iterates `init, f(init), f(f(init)), ...`.
297    pub fn iterate(mut init: T, mut f: impl FnMut(T) -> T + 'static) -> Self
298    where
299        T: Clone + 'static,
300    {
301        Self::from_fn(move || {
302            let curr = init.clone();
303            init = f(init.clone());
304            Some(curr)
305        })
306    }
307    /// Advance the stream and get the next element.
308    #[allow(clippy::should_implement_trait)]
309    pub fn next(&mut self) -> Option<T> {
310        (self.gen)()
311    }
312    /// Take the first `n` elements.
313    pub fn take(mut self, n: usize) -> Vec<T> {
314        (0..n).filter_map(|_| self.next()).collect()
315    }
316}
317/// A simple Bloom filter over stream elements.
318///
319/// Uses k independent hash functions to track set membership approximately.
320#[allow(dead_code)]
321pub struct BloomFilterRs {
322    /// Bit array.
323    bits: Vec<bool>,
324    /// Number of hash functions.
325    k: usize,
326    /// Size of the bit array.
327    m: usize,
328}
329#[allow(dead_code)]
330impl BloomFilterRs {
331    /// Create a new Bloom filter with `m` bits and `k` hash functions.
332    pub fn new(m: usize, k: usize) -> Self {
333        Self {
334            bits: vec![false; m],
335            k,
336            m,
337        }
338    }
339    /// Insert an element into the filter.
340    pub fn insert(&mut self, item: u64) {
341        for i in 0..self.k {
342            let idx = self.strm_ext_hash(item, i as u64) % self.m;
343            self.bits[idx] = true;
344        }
345    }
346    /// Query whether an element might be in the set.
347    pub fn query(&self, item: u64) -> bool {
348        (0..self.k).all(|i| {
349            let idx = self.strm_ext_hash(item, i as u64) % self.m;
350            self.bits[idx]
351        })
352    }
353    /// Simple internal hash combining item and seed.
354    fn strm_ext_hash(&self, item: u64, seed: u64) -> usize {
355        let h = item
356            .wrapping_mul(6364136223846793005)
357            .wrapping_add(seed.wrapping_mul(1442695040888963407));
358        h as usize
359    }
360    /// Return the number of set bits.
361    pub fn count_set(&self) -> usize {
362        self.bits.iter().filter(|&&b| b).count()
363    }
364    /// Return the capacity (m).
365    pub fn capacity(&self) -> usize {
366        self.m
367    }
368}