1use super::functions::*;
6use crate::{Expr, Literal, Name};
7use std::collections::HashMap;
8
9#[allow(dead_code)]
11pub struct StatSummary {
12 count: u64,
13 sum: f64,
14 min: f64,
15 max: f64,
16}
17#[allow(dead_code)]
18impl StatSummary {
19 pub fn new() -> Self {
21 Self {
22 count: 0,
23 sum: 0.0,
24 min: f64::INFINITY,
25 max: f64::NEG_INFINITY,
26 }
27 }
28 pub fn record(&mut self, val: f64) {
30 self.count += 1;
31 self.sum += val;
32 if val < self.min {
33 self.min = val;
34 }
35 if val > self.max {
36 self.max = val;
37 }
38 }
39 pub fn mean(&self) -> Option<f64> {
41 if self.count == 0 {
42 None
43 } else {
44 Some(self.sum / self.count as f64)
45 }
46 }
47 pub fn min(&self) -> Option<f64> {
49 if self.count == 0 {
50 None
51 } else {
52 Some(self.min)
53 }
54 }
55 pub fn max(&self) -> Option<f64> {
57 if self.count == 0 {
58 None
59 } else {
60 Some(self.max)
61 }
62 }
63 pub fn count(&self) -> u64 {
65 self.count
66 }
67}
68#[allow(dead_code)]
70pub struct RewriteRuleSet {
71 rules: Vec<RewriteRule>,
72}
73#[allow(dead_code)]
74impl RewriteRuleSet {
75 pub fn new() -> Self {
77 Self { rules: Vec::new() }
78 }
79 pub fn add(&mut self, rule: RewriteRule) {
81 self.rules.push(rule);
82 }
83 pub fn len(&self) -> usize {
85 self.rules.len()
86 }
87 pub fn is_empty(&self) -> bool {
89 self.rules.is_empty()
90 }
91 pub fn conditional_rules(&self) -> Vec<&RewriteRule> {
93 self.rules.iter().filter(|r| r.conditional).collect()
94 }
95 pub fn unconditional_rules(&self) -> Vec<&RewriteRule> {
97 self.rules.iter().filter(|r| !r.conditional).collect()
98 }
99 pub fn get(&self, name: &str) -> Option<&RewriteRule> {
101 self.rules.iter().find(|r| r.name == name)
102 }
103}
104#[derive(Clone, Copy, Debug, PartialEq, Eq)]
106pub enum SimpDirection {
107 Forward,
109 Backward,
111}
112#[allow(dead_code)]
114pub struct TransitiveClosure {
115 adj: Vec<Vec<usize>>,
116 n: usize,
117}
118#[allow(dead_code)]
119impl TransitiveClosure {
120 pub fn new(n: usize) -> Self {
122 Self {
123 adj: vec![Vec::new(); n],
124 n,
125 }
126 }
127 pub fn add_edge(&mut self, from: usize, to: usize) {
129 if from < self.n {
130 self.adj[from].push(to);
131 }
132 }
133 pub fn reachable_from(&self, start: usize) -> Vec<usize> {
135 let mut visited = vec![false; self.n];
136 let mut queue = std::collections::VecDeque::new();
137 queue.push_back(start);
138 while let Some(node) = queue.pop_front() {
139 if node >= self.n || visited[node] {
140 continue;
141 }
142 visited[node] = true;
143 for &next in &self.adj[node] {
144 queue.push_back(next);
145 }
146 }
147 (0..self.n).filter(|&i| visited[i]).collect()
148 }
149 pub fn can_reach(&self, from: usize, to: usize) -> bool {
151 self.reachable_from(from).contains(&to)
152 }
153}
154#[allow(dead_code)]
156pub struct TransformStat {
157 before: StatSummary,
158 after: StatSummary,
159}
160#[allow(dead_code)]
161impl TransformStat {
162 pub fn new() -> Self {
164 Self {
165 before: StatSummary::new(),
166 after: StatSummary::new(),
167 }
168 }
169 pub fn record_before(&mut self, v: f64) {
171 self.before.record(v);
172 }
173 pub fn record_after(&mut self, v: f64) {
175 self.after.record(v);
176 }
177 pub fn mean_ratio(&self) -> Option<f64> {
179 let b = self.before.mean()?;
180 let a = self.after.mean()?;
181 if b.abs() < f64::EPSILON {
182 return None;
183 }
184 Some(a / b)
185 }
186}
187#[allow(dead_code)]
189pub struct VersionedRecord<T: Clone> {
190 history: Vec<T>,
191}
192#[allow(dead_code)]
193impl<T: Clone> VersionedRecord<T> {
194 pub fn new(initial: T) -> Self {
196 Self {
197 history: vec![initial],
198 }
199 }
200 pub fn update(&mut self, val: T) {
202 self.history.push(val);
203 }
204 pub fn current(&self) -> &T {
206 self.history
207 .last()
208 .expect("VersionedRecord history is always non-empty after construction")
209 }
210 pub fn at_version(&self, n: usize) -> Option<&T> {
212 self.history.get(n)
213 }
214 pub fn version(&self) -> usize {
216 self.history.len() - 1
217 }
218 pub fn has_history(&self) -> bool {
220 self.history.len() > 1
221 }
222}
223#[allow(dead_code)]
225#[allow(missing_docs)]
226pub enum DecisionNode {
227 Leaf(String),
229 Branch {
231 key: String,
232 val: String,
233 yes_branch: Box<DecisionNode>,
234 no_branch: Box<DecisionNode>,
235 },
236}
237#[allow(dead_code)]
238impl DecisionNode {
239 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
241 match self {
242 DecisionNode::Leaf(action) => action.as_str(),
243 DecisionNode::Branch {
244 key,
245 val,
246 yes_branch,
247 no_branch,
248 } => {
249 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
250 if actual == val.as_str() {
251 yes_branch.evaluate(ctx)
252 } else {
253 no_branch.evaluate(ctx)
254 }
255 }
256 }
257 }
258 pub fn depth(&self) -> usize {
260 match self {
261 DecisionNode::Leaf(_) => 0,
262 DecisionNode::Branch {
263 yes_branch,
264 no_branch,
265 ..
266 } => 1 + yes_branch.depth().max(no_branch.depth()),
267 }
268 }
269}
270#[allow(dead_code)]
272pub struct StackCalc {
273 stack: Vec<i64>,
274}
275#[allow(dead_code)]
276impl StackCalc {
277 pub fn new() -> Self {
279 Self { stack: Vec::new() }
280 }
281 pub fn push(&mut self, n: i64) {
283 self.stack.push(n);
284 }
285 pub fn add(&mut self) {
287 let b = self
288 .stack
289 .pop()
290 .expect("stack must have at least two values for add");
291 let a = self
292 .stack
293 .pop()
294 .expect("stack must have at least two values for add");
295 self.stack.push(a + b);
296 }
297 pub fn sub(&mut self) {
299 let b = self
300 .stack
301 .pop()
302 .expect("stack must have at least two values for sub");
303 let a = self
304 .stack
305 .pop()
306 .expect("stack must have at least two values for sub");
307 self.stack.push(a - b);
308 }
309 pub fn mul(&mut self) {
311 let b = self
312 .stack
313 .pop()
314 .expect("stack must have at least two values for mul");
315 let a = self
316 .stack
317 .pop()
318 .expect("stack must have at least two values for mul");
319 self.stack.push(a * b);
320 }
321 pub fn peek(&self) -> Option<i64> {
323 self.stack.last().copied()
324 }
325 pub fn depth(&self) -> usize {
327 self.stack.len()
328 }
329}
330#[allow(dead_code)]
332pub struct PrefixCounter {
333 children: std::collections::HashMap<char, PrefixCounter>,
334 count: usize,
335}
336#[allow(dead_code)]
337impl PrefixCounter {
338 pub fn new() -> Self {
340 Self {
341 children: std::collections::HashMap::new(),
342 count: 0,
343 }
344 }
345 pub fn record(&mut self, s: &str) {
347 self.count += 1;
348 let mut node = self;
349 for c in s.chars() {
350 node = node.children.entry(c).or_default();
351 node.count += 1;
352 }
353 }
354 pub fn count_with_prefix(&self, prefix: &str) -> usize {
356 let mut node = self;
357 for c in prefix.chars() {
358 match node.children.get(&c) {
359 Some(n) => node = n,
360 None => return 0,
361 }
362 }
363 node.count
364 }
365}
366#[allow(dead_code)]
368pub struct SmallMap<K: Ord + Clone, V: Clone> {
369 entries: Vec<(K, V)>,
370}
371#[allow(dead_code)]
372impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
373 pub fn new() -> Self {
375 Self {
376 entries: Vec::new(),
377 }
378 }
379 pub fn insert(&mut self, key: K, val: V) {
381 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
382 Ok(i) => self.entries[i].1 = val,
383 Err(i) => self.entries.insert(i, (key, val)),
384 }
385 }
386 pub fn get(&self, key: &K) -> Option<&V> {
388 self.entries
389 .binary_search_by_key(&key, |(k, _)| k)
390 .ok()
391 .map(|i| &self.entries[i].1)
392 }
393 pub fn len(&self) -> usize {
395 self.entries.len()
396 }
397 pub fn is_empty(&self) -> bool {
399 self.entries.is_empty()
400 }
401 pub fn keys(&self) -> Vec<&K> {
403 self.entries.iter().map(|(k, _)| k).collect()
404 }
405 pub fn values(&self) -> Vec<&V> {
407 self.entries.iter().map(|(_, v)| v).collect()
408 }
409}
410#[allow(dead_code)]
412pub struct WriteOnce<T> {
413 value: std::cell::Cell<Option<T>>,
414}
415#[allow(dead_code)]
416impl<T: Copy> WriteOnce<T> {
417 pub fn new() -> Self {
419 Self {
420 value: std::cell::Cell::new(None),
421 }
422 }
423 pub fn write(&self, val: T) -> bool {
425 if self.value.get().is_some() {
426 return false;
427 }
428 self.value.set(Some(val));
429 true
430 }
431 pub fn read(&self) -> Option<T> {
433 self.value.get()
434 }
435 pub fn is_written(&self) -> bool {
437 self.value.get().is_some()
438 }
439}
440#[allow(dead_code)]
442pub struct RawFnPtr {
443 ptr: usize,
445 arity: usize,
446 name: String,
447}
448#[allow(dead_code)]
449impl RawFnPtr {
450 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
452 Self {
453 ptr,
454 arity,
455 name: name.into(),
456 }
457 }
458 pub fn arity(&self) -> usize {
460 self.arity
461 }
462 pub fn name(&self) -> &str {
464 &self.name
465 }
466 pub fn raw(&self) -> usize {
468 self.ptr
469 }
470}
471#[derive(Debug, Clone)]
473pub struct SimpResult {
474 pub expr: Expr,
476 pub applied: Vec<Name>,
478 pub changed: bool,
480}
481impl SimpResult {
482 pub fn unchanged(expr: Expr) -> Self {
484 Self {
485 expr,
486 applied: Vec::new(),
487 changed: false,
488 }
489 }
490 pub fn simplified(expr: Expr, applied: Vec<Name>) -> Self {
492 let changed = !applied.is_empty();
493 Self {
494 expr,
495 applied,
496 changed,
497 }
498 }
499}
500#[allow(dead_code)]
502pub struct NonEmptyVec<T> {
503 head: T,
504 tail: Vec<T>,
505}
506#[allow(dead_code)]
507impl<T> NonEmptyVec<T> {
508 pub fn singleton(val: T) -> Self {
510 Self {
511 head: val,
512 tail: Vec::new(),
513 }
514 }
515 pub fn push(&mut self, val: T) {
517 self.tail.push(val);
518 }
519 pub fn first(&self) -> &T {
521 &self.head
522 }
523 pub fn last(&self) -> &T {
525 self.tail.last().unwrap_or(&self.head)
526 }
527 pub fn len(&self) -> usize {
529 1 + self.tail.len()
530 }
531 pub fn is_empty(&self) -> bool {
533 self.len() == 0
534 }
535 pub fn to_vec(&self) -> Vec<&T> {
537 let mut v = vec![&self.head];
538 v.extend(self.tail.iter());
539 v
540 }
541}
542#[allow(dead_code)]
544pub struct Fixture {
545 data: std::collections::HashMap<String, String>,
546}
547#[allow(dead_code)]
548impl Fixture {
549 pub fn new() -> Self {
551 Self {
552 data: std::collections::HashMap::new(),
553 }
554 }
555 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
557 self.data.insert(key.into(), val.into());
558 }
559 pub fn get(&self, key: &str) -> Option<&str> {
561 self.data.get(key).map(|s| s.as_str())
562 }
563 pub fn len(&self) -> usize {
565 self.data.len()
566 }
567 pub fn is_empty(&self) -> bool {
569 self.len() == 0
570 }
571}
572#[allow(dead_code)]
574pub struct PathBuf {
575 components: Vec<String>,
576}
577#[allow(dead_code)]
578impl PathBuf {
579 pub fn new() -> Self {
581 Self {
582 components: Vec::new(),
583 }
584 }
585 pub fn push(&mut self, comp: impl Into<String>) {
587 self.components.push(comp.into());
588 }
589 pub fn pop(&mut self) {
591 self.components.pop();
592 }
593 pub fn as_str(&self) -> String {
595 self.components.join("/")
596 }
597 pub fn depth(&self) -> usize {
599 self.components.len()
600 }
601 pub fn clear(&mut self) {
603 self.components.clear();
604 }
605}
606#[allow(dead_code)]
608pub struct TokenBucket {
609 capacity: u64,
610 tokens: u64,
611 refill_per_ms: u64,
612 last_refill: std::time::Instant,
613}
614#[allow(dead_code)]
615impl TokenBucket {
616 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
618 Self {
619 capacity,
620 tokens: capacity,
621 refill_per_ms,
622 last_refill: std::time::Instant::now(),
623 }
624 }
625 pub fn try_consume(&mut self, n: u64) -> bool {
627 self.refill();
628 if self.tokens >= n {
629 self.tokens -= n;
630 true
631 } else {
632 false
633 }
634 }
635 fn refill(&mut self) {
636 let now = std::time::Instant::now();
637 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
638 if elapsed_ms > 0 {
639 let new_tokens = elapsed_ms * self.refill_per_ms;
640 self.tokens = (self.tokens + new_tokens).min(self.capacity);
641 self.last_refill = now;
642 }
643 }
644 pub fn available(&self) -> u64 {
646 self.tokens
647 }
648 pub fn capacity(&self) -> u64 {
650 self.capacity
651 }
652}
653pub struct SimpLemmaSet {
655 lemmas: Vec<SimpLemma>,
656}
657impl SimpLemmaSet {
658 pub fn new() -> Self {
660 Self { lemmas: Vec::new() }
661 }
662 pub fn add(&mut self, lemma: SimpLemma) {
664 self.lemmas.push(lemma);
665 }
666 pub fn len(&self) -> usize {
668 self.lemmas.len()
669 }
670 pub fn is_empty(&self) -> bool {
672 self.lemmas.is_empty()
673 }
674 pub fn apply_once(&self, expr: &Expr) -> (Expr, bool) {
676 let mut current = expr.clone();
677 let mut changed = false;
678 for lemma in &self.lemmas {
679 let (new_expr, c) =
680 rewrite_once(¤t, lemma.effective_lhs(), lemma.effective_rhs());
681 if c {
682 current = new_expr;
683 changed = true;
684 }
685 }
686 (current, changed)
687 }
688 pub fn apply_all(&self, expr: &Expr) -> Expr {
690 let mut current = expr.clone();
691 loop {
692 let (new_expr, changed) = self.apply_once(¤t);
693 if !changed {
694 return current;
695 }
696 current = new_expr;
697 }
698 }
699 pub fn iter(&self) -> impl Iterator<Item = &SimpLemma> {
701 self.lemmas.iter()
702 }
703 pub fn find(&self, name: &Name) -> Option<&SimpLemma> {
705 self.lemmas.iter().find(|l| &l.name == name)
706 }
707}
708#[allow(dead_code)]
710pub struct WindowIterator<'a, T> {
711 pub(super) data: &'a [T],
712 pub(super) pos: usize,
713 pub(super) window: usize,
714}
715#[allow(dead_code)]
716impl<'a, T> WindowIterator<'a, T> {
717 pub fn new(data: &'a [T], window: usize) -> Self {
719 Self {
720 data,
721 pos: 0,
722 window,
723 }
724 }
725}
726#[allow(dead_code)]
728pub struct Stopwatch {
729 start: std::time::Instant,
730 splits: Vec<f64>,
731}
732#[allow(dead_code)]
733impl Stopwatch {
734 pub fn start() -> Self {
736 Self {
737 start: std::time::Instant::now(),
738 splits: Vec::new(),
739 }
740 }
741 pub fn split(&mut self) {
743 self.splits.push(self.elapsed_ms());
744 }
745 pub fn elapsed_ms(&self) -> f64 {
747 self.start.elapsed().as_secs_f64() * 1000.0
748 }
749 pub fn splits(&self) -> &[f64] {
751 &self.splits
752 }
753 pub fn num_splits(&self) -> usize {
755 self.splits.len()
756 }
757}
758#[allow(dead_code)]
760pub struct SimpleDag {
761 edges: Vec<Vec<usize>>,
763}
764#[allow(dead_code)]
765impl SimpleDag {
766 pub fn new(n: usize) -> Self {
768 Self {
769 edges: vec![Vec::new(); n],
770 }
771 }
772 pub fn add_edge(&mut self, from: usize, to: usize) {
774 if from < self.edges.len() {
775 self.edges[from].push(to);
776 }
777 }
778 pub fn successors(&self, node: usize) -> &[usize] {
780 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
781 }
782 pub fn can_reach(&self, from: usize, to: usize) -> bool {
784 let mut visited = vec![false; self.edges.len()];
785 self.dfs(from, to, &mut visited)
786 }
787 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
788 if cur == target {
789 return true;
790 }
791 if cur >= visited.len() || visited[cur] {
792 return false;
793 }
794 visited[cur] = true;
795 for &next in self.successors(cur) {
796 if self.dfs(next, target, visited) {
797 return true;
798 }
799 }
800 false
801 }
802 pub fn topological_sort(&self) -> Option<Vec<usize>> {
804 let n = self.edges.len();
805 let mut in_degree = vec![0usize; n];
806 for succs in &self.edges {
807 for &s in succs {
808 if s < n {
809 in_degree[s] += 1;
810 }
811 }
812 }
813 let mut queue: std::collections::VecDeque<usize> =
814 (0..n).filter(|&i| in_degree[i] == 0).collect();
815 let mut order = Vec::new();
816 while let Some(node) = queue.pop_front() {
817 order.push(node);
818 for &s in self.successors(node) {
819 if s < n {
820 in_degree[s] -= 1;
821 if in_degree[s] == 0 {
822 queue.push_back(s);
823 }
824 }
825 }
826 }
827 if order.len() == n {
828 Some(order)
829 } else {
830 None
831 }
832 }
833 pub fn num_nodes(&self) -> usize {
835 self.edges.len()
836 }
837}
838#[allow(dead_code)]
840pub struct StringPool {
841 free: Vec<String>,
842}
843#[allow(dead_code)]
844impl StringPool {
845 pub fn new() -> Self {
847 Self { free: Vec::new() }
848 }
849 pub fn take(&mut self) -> String {
851 self.free.pop().unwrap_or_default()
852 }
853 pub fn give(&mut self, mut s: String) {
855 s.clear();
856 self.free.push(s);
857 }
858 pub fn free_count(&self) -> usize {
860 self.free.len()
861 }
862}
863#[allow(dead_code)]
865pub struct LabelSet {
866 labels: Vec<String>,
867}
868#[allow(dead_code)]
869impl LabelSet {
870 pub fn new() -> Self {
872 Self { labels: Vec::new() }
873 }
874 pub fn add(&mut self, label: impl Into<String>) {
876 let s = label.into();
877 if !self.labels.contains(&s) {
878 self.labels.push(s);
879 }
880 }
881 pub fn has(&self, label: &str) -> bool {
883 self.labels.iter().any(|l| l == label)
884 }
885 pub fn count(&self) -> usize {
887 self.labels.len()
888 }
889 pub fn all(&self) -> &[String] {
891 &self.labels
892 }
893}
894#[allow(dead_code)]
896pub struct FocusStack<T> {
897 items: Vec<T>,
898}
899#[allow(dead_code)]
900impl<T> FocusStack<T> {
901 pub fn new() -> Self {
903 Self { items: Vec::new() }
904 }
905 pub fn focus(&mut self, item: T) {
907 self.items.push(item);
908 }
909 pub fn blur(&mut self) -> Option<T> {
911 self.items.pop()
912 }
913 pub fn current(&self) -> Option<&T> {
915 self.items.last()
916 }
917 pub fn depth(&self) -> usize {
919 self.items.len()
920 }
921 pub fn is_empty(&self) -> bool {
923 self.items.is_empty()
924 }
925}
926#[allow(dead_code)]
928pub struct FlatSubstitution {
929 pairs: Vec<(String, String)>,
930}
931#[allow(dead_code)]
932impl FlatSubstitution {
933 pub fn new() -> Self {
935 Self { pairs: Vec::new() }
936 }
937 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
939 self.pairs.push((from.into(), to.into()));
940 }
941 pub fn apply(&self, s: &str) -> String {
943 let mut result = s.to_string();
944 for (from, to) in &self.pairs {
945 result = result.replace(from.as_str(), to.as_str());
946 }
947 result
948 }
949 pub fn len(&self) -> usize {
951 self.pairs.len()
952 }
953 pub fn is_empty(&self) -> bool {
955 self.pairs.is_empty()
956 }
957}
958#[allow(dead_code)]
960pub struct ConfigNode {
961 key: String,
962 value: Option<String>,
963 children: Vec<ConfigNode>,
964}
965#[allow(dead_code)]
966impl ConfigNode {
967 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
969 Self {
970 key: key.into(),
971 value: Some(value.into()),
972 children: Vec::new(),
973 }
974 }
975 pub fn section(key: impl Into<String>) -> Self {
977 Self {
978 key: key.into(),
979 value: None,
980 children: Vec::new(),
981 }
982 }
983 pub fn add_child(&mut self, child: ConfigNode) {
985 self.children.push(child);
986 }
987 pub fn key(&self) -> &str {
989 &self.key
990 }
991 pub fn value(&self) -> Option<&str> {
993 self.value.as_deref()
994 }
995 pub fn num_children(&self) -> usize {
997 self.children.len()
998 }
999 pub fn lookup(&self, path: &str) -> Option<&str> {
1001 let mut parts = path.splitn(2, '.');
1002 let head = parts.next()?;
1003 let tail = parts.next();
1004 if head != self.key {
1005 return None;
1006 }
1007 match tail {
1008 None => self.value.as_deref(),
1009 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1010 }
1011 }
1012 fn lookup_relative(&self, path: &str) -> Option<&str> {
1013 let mut parts = path.splitn(2, '.');
1014 let head = parts.next()?;
1015 let tail = parts.next();
1016 if head != self.key {
1017 return None;
1018 }
1019 match tail {
1020 None => self.value.as_deref(),
1021 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1022 }
1023 }
1024}
1025#[derive(Clone, Debug)]
1027pub struct SimpLemma {
1028 pub name: Name,
1030 pub lhs: Expr,
1032 pub rhs: Expr,
1034 pub direction: SimpDirection,
1036 pub priority: i32,
1038}
1039impl SimpLemma {
1040 pub fn forward(name: Name, lhs: Expr, rhs: Expr) -> Self {
1042 Self {
1043 name,
1044 lhs,
1045 rhs,
1046 direction: SimpDirection::Forward,
1047 priority: 1000,
1048 }
1049 }
1050 pub fn backward(name: Name, lhs: Expr, rhs: Expr) -> Self {
1052 Self {
1053 name,
1054 lhs,
1055 rhs,
1056 direction: SimpDirection::Backward,
1057 priority: 1000,
1058 }
1059 }
1060 pub fn reversed(mut self) -> Self {
1062 self.direction = match self.direction {
1063 SimpDirection::Forward => SimpDirection::Backward,
1064 SimpDirection::Backward => SimpDirection::Forward,
1065 };
1066 std::mem::swap(&mut self.lhs, &mut self.rhs);
1067 self
1068 }
1069 pub fn effective_lhs(&self) -> &Expr {
1071 &self.lhs
1072 }
1073 pub fn effective_rhs(&self) -> &Expr {
1075 &self.rhs
1076 }
1077}
1078#[allow(dead_code)]
1080#[allow(missing_docs)]
1081pub struct RewriteRule {
1082 pub name: String,
1084 pub lhs: String,
1086 pub rhs: String,
1088 pub conditional: bool,
1090}
1091#[allow(dead_code)]
1092impl RewriteRule {
1093 pub fn unconditional(
1095 name: impl Into<String>,
1096 lhs: impl Into<String>,
1097 rhs: impl Into<String>,
1098 ) -> Self {
1099 Self {
1100 name: name.into(),
1101 lhs: lhs.into(),
1102 rhs: rhs.into(),
1103 conditional: false,
1104 }
1105 }
1106 pub fn conditional(
1108 name: impl Into<String>,
1109 lhs: impl Into<String>,
1110 rhs: impl Into<String>,
1111 ) -> Self {
1112 Self {
1113 name: name.into(),
1114 lhs: lhs.into(),
1115 rhs: rhs.into(),
1116 conditional: true,
1117 }
1118 }
1119 pub fn display(&self) -> String {
1121 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
1122 }
1123}
1124#[allow(dead_code)]
1126pub struct SlidingSum {
1127 window: Vec<f64>,
1128 capacity: usize,
1129 pos: usize,
1130 sum: f64,
1131 count: usize,
1132}
1133#[allow(dead_code)]
1134impl SlidingSum {
1135 pub fn new(capacity: usize) -> Self {
1137 Self {
1138 window: vec![0.0; capacity],
1139 capacity,
1140 pos: 0,
1141 sum: 0.0,
1142 count: 0,
1143 }
1144 }
1145 pub fn push(&mut self, val: f64) {
1147 let oldest = self.window[self.pos];
1148 self.sum -= oldest;
1149 self.sum += val;
1150 self.window[self.pos] = val;
1151 self.pos = (self.pos + 1) % self.capacity;
1152 if self.count < self.capacity {
1153 self.count += 1;
1154 }
1155 }
1156 pub fn sum(&self) -> f64 {
1158 self.sum
1159 }
1160 pub fn mean(&self) -> Option<f64> {
1162 if self.count == 0 {
1163 None
1164 } else {
1165 Some(self.sum / self.count as f64)
1166 }
1167 }
1168 pub fn count(&self) -> usize {
1170 self.count
1171 }
1172}
1173#[allow(dead_code)]
1175pub struct MinHeap<T: Ord> {
1176 data: Vec<T>,
1177}
1178#[allow(dead_code)]
1179impl<T: Ord> MinHeap<T> {
1180 pub fn new() -> Self {
1182 Self { data: Vec::new() }
1183 }
1184 pub fn push(&mut self, val: T) {
1186 self.data.push(val);
1187 self.sift_up(self.data.len() - 1);
1188 }
1189 pub fn pop(&mut self) -> Option<T> {
1191 if self.data.is_empty() {
1192 return None;
1193 }
1194 let n = self.data.len();
1195 self.data.swap(0, n - 1);
1196 let min = self.data.pop();
1197 if !self.data.is_empty() {
1198 self.sift_down(0);
1199 }
1200 min
1201 }
1202 pub fn peek(&self) -> Option<&T> {
1204 self.data.first()
1205 }
1206 pub fn len(&self) -> usize {
1208 self.data.len()
1209 }
1210 pub fn is_empty(&self) -> bool {
1212 self.data.is_empty()
1213 }
1214 fn sift_up(&mut self, mut i: usize) {
1215 while i > 0 {
1216 let parent = (i - 1) / 2;
1217 if self.data[i] < self.data[parent] {
1218 self.data.swap(i, parent);
1219 i = parent;
1220 } else {
1221 break;
1222 }
1223 }
1224 }
1225 fn sift_down(&mut self, mut i: usize) {
1226 let n = self.data.len();
1227 loop {
1228 let left = 2 * i + 1;
1229 let right = 2 * i + 2;
1230 let mut smallest = i;
1231 if left < n && self.data[left] < self.data[smallest] {
1232 smallest = left;
1233 }
1234 if right < n && self.data[right] < self.data[smallest] {
1235 smallest = right;
1236 }
1237 if smallest == i {
1238 break;
1239 }
1240 self.data.swap(i, smallest);
1241 i = smallest;
1242 }
1243 }
1244}
1245#[allow(dead_code)]
1247pub enum Either2<A, B> {
1248 First(A),
1250 Second(B),
1252}
1253#[allow(dead_code)]
1254impl<A, B> Either2<A, B> {
1255 pub fn is_first(&self) -> bool {
1257 matches!(self, Either2::First(_))
1258 }
1259 pub fn is_second(&self) -> bool {
1261 matches!(self, Either2::Second(_))
1262 }
1263 pub fn first(self) -> Option<A> {
1265 match self {
1266 Either2::First(a) => Some(a),
1267 _ => None,
1268 }
1269 }
1270 pub fn second(self) -> Option<B> {
1272 match self {
1273 Either2::Second(b) => Some(b),
1274 _ => None,
1275 }
1276 }
1277 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
1279 match self {
1280 Either2::First(a) => Either2::First(f(a)),
1281 Either2::Second(b) => Either2::Second(b),
1282 }
1283 }
1284}
1285#[allow(dead_code)]
1287pub struct SparseVec<T: Default + Clone + PartialEq> {
1288 entries: std::collections::HashMap<usize, T>,
1289 default_: T,
1290 logical_len: usize,
1291}
1292#[allow(dead_code)]
1293impl<T: Default + Clone + PartialEq> SparseVec<T> {
1294 pub fn new(len: usize) -> Self {
1296 Self {
1297 entries: std::collections::HashMap::new(),
1298 default_: T::default(),
1299 logical_len: len,
1300 }
1301 }
1302 pub fn set(&mut self, idx: usize, val: T) {
1304 if val == self.default_ {
1305 self.entries.remove(&idx);
1306 } else {
1307 self.entries.insert(idx, val);
1308 }
1309 }
1310 pub fn get(&self, idx: usize) -> &T {
1312 self.entries.get(&idx).unwrap_or(&self.default_)
1313 }
1314 pub fn len(&self) -> usize {
1316 self.logical_len
1317 }
1318 pub fn is_empty(&self) -> bool {
1320 self.len() == 0
1321 }
1322 pub fn nnz(&self) -> usize {
1324 self.entries.len()
1325 }
1326}