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 earlier: Vec<T>,
192 current: T,
194}
195#[allow(dead_code)]
196impl<T: Clone> VersionedRecord<T> {
197 pub fn new(initial: T) -> Self {
199 Self {
200 earlier: Vec::new(),
201 current: initial,
202 }
203 }
204 pub fn update(&mut self, val: T) {
206 let previous = std::mem::replace(&mut self.current, val);
207 self.earlier.push(previous);
208 }
209 pub fn current(&self) -> &T {
211 &self.current
212 }
213 pub fn at_version(&self, n: usize) -> Option<&T> {
215 match self.earlier.get(n) {
216 Some(value) => Some(value),
217 None if n == self.earlier.len() => Some(&self.current),
218 None => None,
219 }
220 }
221 pub fn version(&self) -> usize {
223 self.earlier.len()
224 }
225 pub fn has_history(&self) -> bool {
227 !self.earlier.is_empty()
228 }
229}
230#[allow(dead_code)]
232#[allow(missing_docs)]
233pub enum DecisionNode {
234 Leaf(String),
236 Branch {
238 key: String,
239 val: String,
240 yes_branch: Box<DecisionNode>,
241 no_branch: Box<DecisionNode>,
242 },
243}
244#[allow(dead_code)]
245impl DecisionNode {
246 pub fn evaluate(&self, ctx: &std::collections::HashMap<String, String>) -> &str {
248 match self {
249 DecisionNode::Leaf(action) => action.as_str(),
250 DecisionNode::Branch {
251 key,
252 val,
253 yes_branch,
254 no_branch,
255 } => {
256 let actual = ctx.get(key).map(|s| s.as_str()).unwrap_or("");
257 if actual == val.as_str() {
258 yes_branch.evaluate(ctx)
259 } else {
260 no_branch.evaluate(ctx)
261 }
262 }
263 }
264 }
265 pub fn depth(&self) -> usize {
267 match self {
268 DecisionNode::Leaf(_) => 0,
269 DecisionNode::Branch {
270 yes_branch,
271 no_branch,
272 ..
273 } => 1 + yes_branch.depth().max(no_branch.depth()),
274 }
275 }
276}
277#[allow(dead_code)]
279pub struct StackCalc {
280 stack: Vec<i64>,
281}
282#[allow(dead_code)]
283impl StackCalc {
284 pub fn new() -> Self {
286 Self { stack: Vec::new() }
287 }
288 pub fn push(&mut self, n: i64) {
290 self.stack.push(n);
291 }
292 fn apply_binary(&mut self, op: impl FnOnce(i64, i64) -> i64) -> Option<i64> {
296 let (rest_len, a, b) = match self.stack[..] {
297 [ref rest @ .., a, b] => (rest.len(), a, b),
298 _ => return None,
299 };
300 let value = op(a, b);
301 self.stack.truncate(rest_len);
302 self.stack.push(value);
303 Some(value)
304 }
305 pub fn add(&mut self) -> Option<i64> {
309 self.apply_binary(|a, b| a + b)
310 }
311 pub fn sub(&mut self) -> Option<i64> {
315 self.apply_binary(|a, b| a - b)
316 }
317 pub fn mul(&mut self) -> Option<i64> {
321 self.apply_binary(|a, b| a * b)
322 }
323 pub fn peek(&self) -> Option<i64> {
325 self.stack.last().copied()
326 }
327 pub fn depth(&self) -> usize {
329 self.stack.len()
330 }
331}
332#[allow(dead_code)]
334pub struct PrefixCounter {
335 children: std::collections::HashMap<char, PrefixCounter>,
336 count: usize,
337}
338#[allow(dead_code)]
339impl PrefixCounter {
340 pub fn new() -> Self {
342 Self {
343 children: std::collections::HashMap::new(),
344 count: 0,
345 }
346 }
347 pub fn record(&mut self, s: &str) {
349 self.count += 1;
350 let mut node = self;
351 for c in s.chars() {
352 node = node.children.entry(c).or_default();
353 node.count += 1;
354 }
355 }
356 pub fn count_with_prefix(&self, prefix: &str) -> usize {
358 let mut node = self;
359 for c in prefix.chars() {
360 match node.children.get(&c) {
361 Some(n) => node = n,
362 None => return 0,
363 }
364 }
365 node.count
366 }
367}
368#[allow(dead_code)]
370pub struct SmallMap<K: Ord + Clone, V: Clone> {
371 entries: Vec<(K, V)>,
372}
373#[allow(dead_code)]
374impl<K: Ord + Clone, V: Clone> SmallMap<K, V> {
375 pub fn new() -> Self {
377 Self {
378 entries: Vec::new(),
379 }
380 }
381 pub fn insert(&mut self, key: K, val: V) {
383 match self.entries.binary_search_by_key(&&key, |(k, _)| k) {
384 Ok(i) => self.entries[i].1 = val,
385 Err(i) => self.entries.insert(i, (key, val)),
386 }
387 }
388 pub fn get(&self, key: &K) -> Option<&V> {
390 self.entries
391 .binary_search_by_key(&key, |(k, _)| k)
392 .ok()
393 .map(|i| &self.entries[i].1)
394 }
395 pub fn len(&self) -> usize {
397 self.entries.len()
398 }
399 pub fn is_empty(&self) -> bool {
401 self.entries.is_empty()
402 }
403 pub fn keys(&self) -> Vec<&K> {
405 self.entries.iter().map(|(k, _)| k).collect()
406 }
407 pub fn values(&self) -> Vec<&V> {
409 self.entries.iter().map(|(_, v)| v).collect()
410 }
411}
412#[allow(dead_code)]
414pub struct WriteOnce<T> {
415 value: std::cell::Cell<Option<T>>,
416}
417#[allow(dead_code)]
418impl<T: Copy> WriteOnce<T> {
419 pub fn new() -> Self {
421 Self {
422 value: std::cell::Cell::new(None),
423 }
424 }
425 pub fn write(&self, val: T) -> bool {
427 if self.value.get().is_some() {
428 return false;
429 }
430 self.value.set(Some(val));
431 true
432 }
433 pub fn read(&self) -> Option<T> {
435 self.value.get()
436 }
437 pub fn is_written(&self) -> bool {
439 self.value.get().is_some()
440 }
441}
442#[allow(dead_code)]
444pub struct RawFnPtr {
445 ptr: usize,
447 arity: usize,
448 name: String,
449}
450#[allow(dead_code)]
451impl RawFnPtr {
452 pub fn new(ptr: usize, arity: usize, name: impl Into<String>) -> Self {
454 Self {
455 ptr,
456 arity,
457 name: name.into(),
458 }
459 }
460 pub fn arity(&self) -> usize {
462 self.arity
463 }
464 pub fn name(&self) -> &str {
466 &self.name
467 }
468 pub fn raw(&self) -> usize {
470 self.ptr
471 }
472}
473#[derive(Debug, Clone)]
475pub struct SimpResult {
476 pub expr: Expr,
478 pub applied: Vec<Name>,
480 pub changed: bool,
482}
483impl SimpResult {
484 pub fn unchanged(expr: Expr) -> Self {
486 Self {
487 expr,
488 applied: Vec::new(),
489 changed: false,
490 }
491 }
492 pub fn simplified(expr: Expr, applied: Vec<Name>) -> Self {
494 let changed = !applied.is_empty();
495 Self {
496 expr,
497 applied,
498 changed,
499 }
500 }
501}
502#[allow(dead_code)]
504pub struct NonEmptyVec<T> {
505 head: T,
506 tail: Vec<T>,
507}
508#[allow(dead_code)]
509impl<T> NonEmptyVec<T> {
510 pub fn singleton(val: T) -> Self {
512 Self {
513 head: val,
514 tail: Vec::new(),
515 }
516 }
517 pub fn push(&mut self, val: T) {
519 self.tail.push(val);
520 }
521 pub fn first(&self) -> &T {
523 &self.head
524 }
525 pub fn last(&self) -> &T {
527 self.tail.last().unwrap_or(&self.head)
528 }
529 pub fn len(&self) -> usize {
531 1 + self.tail.len()
532 }
533 pub fn is_empty(&self) -> bool {
535 self.len() == 0
536 }
537 pub fn to_vec(&self) -> Vec<&T> {
539 let mut v = vec![&self.head];
540 v.extend(self.tail.iter());
541 v
542 }
543}
544#[allow(dead_code)]
546pub struct Fixture {
547 data: std::collections::HashMap<String, String>,
548}
549#[allow(dead_code)]
550impl Fixture {
551 pub fn new() -> Self {
553 Self {
554 data: std::collections::HashMap::new(),
555 }
556 }
557 pub fn set(&mut self, key: impl Into<String>, val: impl Into<String>) {
559 self.data.insert(key.into(), val.into());
560 }
561 pub fn get(&self, key: &str) -> Option<&str> {
563 self.data.get(key).map(|s| s.as_str())
564 }
565 pub fn len(&self) -> usize {
567 self.data.len()
568 }
569 pub fn is_empty(&self) -> bool {
571 self.len() == 0
572 }
573}
574#[allow(dead_code)]
576pub struct PathBuf {
577 components: Vec<String>,
578}
579#[allow(dead_code)]
580impl PathBuf {
581 pub fn new() -> Self {
583 Self {
584 components: Vec::new(),
585 }
586 }
587 pub fn push(&mut self, comp: impl Into<String>) {
589 self.components.push(comp.into());
590 }
591 pub fn pop(&mut self) {
593 self.components.pop();
594 }
595 pub fn as_str(&self) -> String {
597 self.components.join("/")
598 }
599 pub fn depth(&self) -> usize {
601 self.components.len()
602 }
603 pub fn clear(&mut self) {
605 self.components.clear();
606 }
607}
608#[allow(dead_code)]
610pub struct TokenBucket {
611 capacity: u64,
612 tokens: u64,
613 refill_per_ms: u64,
614 last_refill: crate::wall_clock::Instant,
615}
616#[allow(dead_code)]
617impl TokenBucket {
618 pub fn new(capacity: u64, refill_per_ms: u64) -> Self {
620 Self {
621 capacity,
622 tokens: capacity,
623 refill_per_ms,
624 last_refill: crate::wall_clock::Instant::now(),
625 }
626 }
627 pub fn try_consume(&mut self, n: u64) -> bool {
629 self.refill();
630 if self.tokens >= n {
631 self.tokens -= n;
632 true
633 } else {
634 false
635 }
636 }
637 fn refill(&mut self) {
638 let now = crate::wall_clock::Instant::now();
639 let elapsed_ms = now.duration_since(self.last_refill).as_millis() as u64;
640 if elapsed_ms > 0 {
641 let new_tokens = elapsed_ms * self.refill_per_ms;
642 self.tokens = (self.tokens + new_tokens).min(self.capacity);
643 self.last_refill = now;
644 }
645 }
646 pub fn available(&self) -> u64 {
648 self.tokens
649 }
650 pub fn capacity(&self) -> u64 {
652 self.capacity
653 }
654}
655pub struct SimpLemmaSet {
657 lemmas: Vec<SimpLemma>,
658}
659impl SimpLemmaSet {
660 pub fn new() -> Self {
662 Self { lemmas: Vec::new() }
663 }
664 pub fn add(&mut self, lemma: SimpLemma) {
666 self.lemmas.push(lemma);
667 }
668 pub fn len(&self) -> usize {
670 self.lemmas.len()
671 }
672 pub fn is_empty(&self) -> bool {
674 self.lemmas.is_empty()
675 }
676 pub fn apply_once(&self, expr: &Expr) -> (Expr, bool) {
678 let mut current = expr.clone();
679 let mut changed = false;
680 for lemma in &self.lemmas {
681 let (new_expr, c) =
682 rewrite_once(¤t, lemma.effective_lhs(), lemma.effective_rhs());
683 if c {
684 current = new_expr;
685 changed = true;
686 }
687 }
688 (current, changed)
689 }
690 pub fn apply_all(&self, expr: &Expr) -> Expr {
692 let mut current = expr.clone();
693 loop {
694 let (new_expr, changed) = self.apply_once(¤t);
695 if !changed {
696 return current;
697 }
698 current = new_expr;
699 }
700 }
701 pub fn iter(&self) -> impl Iterator<Item = &SimpLemma> {
703 self.lemmas.iter()
704 }
705 pub fn find(&self, name: &Name) -> Option<&SimpLemma> {
707 self.lemmas.iter().find(|l| &l.name == name)
708 }
709}
710#[allow(dead_code)]
712pub struct WindowIterator<'a, T> {
713 pub(super) data: &'a [T],
714 pub(super) pos: usize,
715 pub(super) window: usize,
716}
717#[allow(dead_code)]
718impl<'a, T> WindowIterator<'a, T> {
719 pub fn new(data: &'a [T], window: usize) -> Self {
721 Self {
722 data,
723 pos: 0,
724 window,
725 }
726 }
727}
728#[allow(dead_code)]
730pub struct Stopwatch {
731 start: crate::wall_clock::Instant,
732 splits: Vec<f64>,
733}
734#[allow(dead_code)]
735impl Stopwatch {
736 pub fn start() -> Self {
738 Self {
739 start: crate::wall_clock::Instant::now(),
740 splits: Vec::new(),
741 }
742 }
743 pub fn split(&mut self) {
745 self.splits.push(self.elapsed_ms());
746 }
747 pub fn elapsed_ms(&self) -> f64 {
749 self.start.elapsed().as_secs_f64() * 1000.0
750 }
751 pub fn splits(&self) -> &[f64] {
753 &self.splits
754 }
755 pub fn num_splits(&self) -> usize {
757 self.splits.len()
758 }
759}
760#[allow(dead_code)]
762pub struct SimpleDag {
763 edges: Vec<Vec<usize>>,
765}
766#[allow(dead_code)]
767impl SimpleDag {
768 pub fn new(n: usize) -> Self {
770 Self {
771 edges: vec![Vec::new(); n],
772 }
773 }
774 pub fn add_edge(&mut self, from: usize, to: usize) {
776 if from < self.edges.len() {
777 self.edges[from].push(to);
778 }
779 }
780 pub fn successors(&self, node: usize) -> &[usize] {
782 self.edges.get(node).map(|v| v.as_slice()).unwrap_or(&[])
783 }
784 pub fn can_reach(&self, from: usize, to: usize) -> bool {
786 let mut visited = vec![false; self.edges.len()];
787 self.dfs(from, to, &mut visited)
788 }
789 fn dfs(&self, cur: usize, target: usize, visited: &mut Vec<bool>) -> bool {
790 if cur == target {
791 return true;
792 }
793 if cur >= visited.len() || visited[cur] {
794 return false;
795 }
796 visited[cur] = true;
797 for &next in self.successors(cur) {
798 if self.dfs(next, target, visited) {
799 return true;
800 }
801 }
802 false
803 }
804 pub fn topological_sort(&self) -> Option<Vec<usize>> {
806 let n = self.edges.len();
807 let mut in_degree = vec![0usize; n];
808 for succs in &self.edges {
809 for &s in succs {
810 if s < n {
811 in_degree[s] += 1;
812 }
813 }
814 }
815 let mut queue: std::collections::VecDeque<usize> =
816 (0..n).filter(|&i| in_degree[i] == 0).collect();
817 let mut order = Vec::new();
818 while let Some(node) = queue.pop_front() {
819 order.push(node);
820 for &s in self.successors(node) {
821 if s < n {
822 in_degree[s] -= 1;
823 if in_degree[s] == 0 {
824 queue.push_back(s);
825 }
826 }
827 }
828 }
829 if order.len() == n {
830 Some(order)
831 } else {
832 None
833 }
834 }
835 pub fn num_nodes(&self) -> usize {
837 self.edges.len()
838 }
839}
840#[allow(dead_code)]
842pub struct StringPool {
843 free: Vec<String>,
844}
845#[allow(dead_code)]
846impl StringPool {
847 pub fn new() -> Self {
849 Self { free: Vec::new() }
850 }
851 pub fn take(&mut self) -> String {
853 self.free.pop().unwrap_or_default()
854 }
855 pub fn give(&mut self, mut s: String) {
857 s.clear();
858 self.free.push(s);
859 }
860 pub fn free_count(&self) -> usize {
862 self.free.len()
863 }
864}
865#[allow(dead_code)]
867pub struct LabelSet {
868 labels: Vec<String>,
869}
870#[allow(dead_code)]
871impl LabelSet {
872 pub fn new() -> Self {
874 Self { labels: Vec::new() }
875 }
876 pub fn add(&mut self, label: impl Into<String>) {
878 let s = label.into();
879 if !self.labels.contains(&s) {
880 self.labels.push(s);
881 }
882 }
883 pub fn has(&self, label: &str) -> bool {
885 self.labels.iter().any(|l| l == label)
886 }
887 pub fn count(&self) -> usize {
889 self.labels.len()
890 }
891 pub fn all(&self) -> &[String] {
893 &self.labels
894 }
895}
896#[allow(dead_code)]
898pub struct FocusStack<T> {
899 items: Vec<T>,
900}
901#[allow(dead_code)]
902impl<T> FocusStack<T> {
903 pub fn new() -> Self {
905 Self { items: Vec::new() }
906 }
907 pub fn focus(&mut self, item: T) {
909 self.items.push(item);
910 }
911 pub fn blur(&mut self) -> Option<T> {
913 self.items.pop()
914 }
915 pub fn current(&self) -> Option<&T> {
917 self.items.last()
918 }
919 pub fn depth(&self) -> usize {
921 self.items.len()
922 }
923 pub fn is_empty(&self) -> bool {
925 self.items.is_empty()
926 }
927}
928#[allow(dead_code)]
930pub struct FlatSubstitution {
931 pairs: Vec<(String, String)>,
932}
933#[allow(dead_code)]
934impl FlatSubstitution {
935 pub fn new() -> Self {
937 Self { pairs: Vec::new() }
938 }
939 pub fn add(&mut self, from: impl Into<String>, to: impl Into<String>) {
941 self.pairs.push((from.into(), to.into()));
942 }
943 pub fn apply(&self, s: &str) -> String {
945 let mut result = s.to_string();
946 for (from, to) in &self.pairs {
947 result = result.replace(from.as_str(), to.as_str());
948 }
949 result
950 }
951 pub fn len(&self) -> usize {
953 self.pairs.len()
954 }
955 pub fn is_empty(&self) -> bool {
957 self.pairs.is_empty()
958 }
959}
960#[allow(dead_code)]
962pub struct ConfigNode {
963 key: String,
964 value: Option<String>,
965 children: Vec<ConfigNode>,
966}
967#[allow(dead_code)]
968impl ConfigNode {
969 pub fn leaf(key: impl Into<String>, value: impl Into<String>) -> Self {
971 Self {
972 key: key.into(),
973 value: Some(value.into()),
974 children: Vec::new(),
975 }
976 }
977 pub fn section(key: impl Into<String>) -> Self {
979 Self {
980 key: key.into(),
981 value: None,
982 children: Vec::new(),
983 }
984 }
985 pub fn add_child(&mut self, child: ConfigNode) {
987 self.children.push(child);
988 }
989 pub fn key(&self) -> &str {
991 &self.key
992 }
993 pub fn value(&self) -> Option<&str> {
995 self.value.as_deref()
996 }
997 pub fn num_children(&self) -> usize {
999 self.children.len()
1000 }
1001 pub fn lookup(&self, path: &str) -> Option<&str> {
1003 let mut parts = path.splitn(2, '.');
1004 let head = parts.next()?;
1005 let tail = parts.next();
1006 if head != self.key {
1007 return None;
1008 }
1009 match tail {
1010 None => self.value.as_deref(),
1011 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1012 }
1013 }
1014 fn lookup_relative(&self, path: &str) -> Option<&str> {
1015 let mut parts = path.splitn(2, '.');
1016 let head = parts.next()?;
1017 let tail = parts.next();
1018 if head != self.key {
1019 return None;
1020 }
1021 match tail {
1022 None => self.value.as_deref(),
1023 Some(rest) => self.children.iter().find_map(|c| c.lookup_relative(rest)),
1024 }
1025 }
1026}
1027#[derive(Clone, Debug)]
1029pub struct SimpLemma {
1030 pub name: Name,
1032 pub lhs: Expr,
1034 pub rhs: Expr,
1036 pub direction: SimpDirection,
1038 pub priority: i32,
1040}
1041impl SimpLemma {
1042 pub fn forward(name: Name, lhs: Expr, rhs: Expr) -> Self {
1044 Self {
1045 name,
1046 lhs,
1047 rhs,
1048 direction: SimpDirection::Forward,
1049 priority: 1000,
1050 }
1051 }
1052 pub fn backward(name: Name, lhs: Expr, rhs: Expr) -> Self {
1054 Self {
1055 name,
1056 lhs,
1057 rhs,
1058 direction: SimpDirection::Backward,
1059 priority: 1000,
1060 }
1061 }
1062 pub fn reversed(mut self) -> Self {
1064 self.direction = match self.direction {
1065 SimpDirection::Forward => SimpDirection::Backward,
1066 SimpDirection::Backward => SimpDirection::Forward,
1067 };
1068 std::mem::swap(&mut self.lhs, &mut self.rhs);
1069 self
1070 }
1071 pub fn effective_lhs(&self) -> &Expr {
1073 &self.lhs
1074 }
1075 pub fn effective_rhs(&self) -> &Expr {
1077 &self.rhs
1078 }
1079}
1080#[allow(dead_code)]
1082#[allow(missing_docs)]
1083pub struct RewriteRule {
1084 pub name: String,
1086 pub lhs: String,
1088 pub rhs: String,
1090 pub conditional: bool,
1092}
1093#[allow(dead_code)]
1094impl RewriteRule {
1095 pub fn unconditional(
1097 name: impl Into<String>,
1098 lhs: impl Into<String>,
1099 rhs: impl Into<String>,
1100 ) -> Self {
1101 Self {
1102 name: name.into(),
1103 lhs: lhs.into(),
1104 rhs: rhs.into(),
1105 conditional: false,
1106 }
1107 }
1108 pub fn conditional(
1110 name: impl Into<String>,
1111 lhs: impl Into<String>,
1112 rhs: impl Into<String>,
1113 ) -> Self {
1114 Self {
1115 name: name.into(),
1116 lhs: lhs.into(),
1117 rhs: rhs.into(),
1118 conditional: true,
1119 }
1120 }
1121 pub fn display(&self) -> String {
1123 format!("{}: {} → {}", self.name, self.lhs, self.rhs)
1124 }
1125}
1126#[allow(dead_code)]
1128pub struct SlidingSum {
1129 window: Vec<f64>,
1130 capacity: usize,
1131 pos: usize,
1132 sum: f64,
1133 count: usize,
1134}
1135#[allow(dead_code)]
1136impl SlidingSum {
1137 pub fn new(capacity: usize) -> Self {
1139 Self {
1140 window: vec![0.0; capacity],
1141 capacity,
1142 pos: 0,
1143 sum: 0.0,
1144 count: 0,
1145 }
1146 }
1147 pub fn push(&mut self, val: f64) {
1149 let oldest = self.window[self.pos];
1150 self.sum -= oldest;
1151 self.sum += val;
1152 self.window[self.pos] = val;
1153 self.pos = (self.pos + 1) % self.capacity;
1154 if self.count < self.capacity {
1155 self.count += 1;
1156 }
1157 }
1158 pub fn sum(&self) -> f64 {
1160 self.sum
1161 }
1162 pub fn mean(&self) -> Option<f64> {
1164 if self.count == 0 {
1165 None
1166 } else {
1167 Some(self.sum / self.count as f64)
1168 }
1169 }
1170 pub fn count(&self) -> usize {
1172 self.count
1173 }
1174}
1175#[allow(dead_code)]
1177pub struct MinHeap<T: Ord> {
1178 data: Vec<T>,
1179}
1180#[allow(dead_code)]
1181impl<T: Ord> MinHeap<T> {
1182 pub fn new() -> Self {
1184 Self { data: Vec::new() }
1185 }
1186 pub fn push(&mut self, val: T) {
1188 self.data.push(val);
1189 self.sift_up(self.data.len() - 1);
1190 }
1191 pub fn pop(&mut self) -> Option<T> {
1193 if self.data.is_empty() {
1194 return None;
1195 }
1196 let n = self.data.len();
1197 self.data.swap(0, n - 1);
1198 let min = self.data.pop();
1199 if !self.data.is_empty() {
1200 self.sift_down(0);
1201 }
1202 min
1203 }
1204 pub fn peek(&self) -> Option<&T> {
1206 self.data.first()
1207 }
1208 pub fn len(&self) -> usize {
1210 self.data.len()
1211 }
1212 pub fn is_empty(&self) -> bool {
1214 self.data.is_empty()
1215 }
1216 fn sift_up(&mut self, mut i: usize) {
1217 while i > 0 {
1218 let parent = (i - 1) / 2;
1219 if self.data[i] < self.data[parent] {
1220 self.data.swap(i, parent);
1221 i = parent;
1222 } else {
1223 break;
1224 }
1225 }
1226 }
1227 fn sift_down(&mut self, mut i: usize) {
1228 let n = self.data.len();
1229 loop {
1230 let left = 2 * i + 1;
1231 let right = 2 * i + 2;
1232 let mut smallest = i;
1233 if left < n && self.data[left] < self.data[smallest] {
1234 smallest = left;
1235 }
1236 if right < n && self.data[right] < self.data[smallest] {
1237 smallest = right;
1238 }
1239 if smallest == i {
1240 break;
1241 }
1242 self.data.swap(i, smallest);
1243 i = smallest;
1244 }
1245 }
1246}
1247#[allow(dead_code)]
1249pub enum Either2<A, B> {
1250 First(A),
1252 Second(B),
1254}
1255#[allow(dead_code)]
1256impl<A, B> Either2<A, B> {
1257 pub fn is_first(&self) -> bool {
1259 matches!(self, Either2::First(_))
1260 }
1261 pub fn is_second(&self) -> bool {
1263 matches!(self, Either2::Second(_))
1264 }
1265 pub fn first(self) -> Option<A> {
1267 match self {
1268 Either2::First(a) => Some(a),
1269 _ => None,
1270 }
1271 }
1272 pub fn second(self) -> Option<B> {
1274 match self {
1275 Either2::Second(b) => Some(b),
1276 _ => None,
1277 }
1278 }
1279 pub fn map_first<C, F: FnOnce(A) -> C>(self, f: F) -> Either2<C, B> {
1281 match self {
1282 Either2::First(a) => Either2::First(f(a)),
1283 Either2::Second(b) => Either2::Second(b),
1284 }
1285 }
1286}
1287#[allow(dead_code)]
1289pub struct SparseVec<T: Default + Clone + PartialEq> {
1290 entries: std::collections::HashMap<usize, T>,
1291 default_: T,
1292 logical_len: usize,
1293}
1294#[allow(dead_code)]
1295impl<T: Default + Clone + PartialEq> SparseVec<T> {
1296 pub fn new(len: usize) -> Self {
1298 Self {
1299 entries: std::collections::HashMap::new(),
1300 default_: T::default(),
1301 logical_len: len,
1302 }
1303 }
1304 pub fn set(&mut self, idx: usize, val: T) {
1306 if val == self.default_ {
1307 self.entries.remove(&idx);
1308 } else {
1309 self.entries.insert(idx, val);
1310 }
1311 }
1312 pub fn get(&self, idx: usize) -> &T {
1314 self.entries.get(&idx).unwrap_or(&self.default_)
1315 }
1316 pub fn len(&self) -> usize {
1318 self.logical_len
1319 }
1320 pub fn is_empty(&self) -> bool {
1322 self.len() == 0
1323 }
1324 pub fn nnz(&self) -> usize {
1326 self.entries.len()
1327 }
1328}