Skip to main content

oxilean_std/vec/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{
6    BinderInfo, Declaration, Environment, Expr, InductiveEnv, InductiveType, IntroRule, Level, Name,
7};
8
9use super::types::{CircularBuffer, DList, FenwickTree, FixedVec, PrefixScan, SparseVec};
10
11/// Build Vec type in the environment.
12///
13/// Vec : (α : Type) → Nat → Type
14pub fn build_vec_env(env: &mut Environment, ind_env: &mut InductiveEnv) -> Result<(), String> {
15    let type1 = Expr::Sort(Level::succ(Level::zero()));
16    let vec_ty = Expr::Pi(
17        BinderInfo::Default,
18        Name::str("α"),
19        Box::new(type1.clone()),
20        Box::new(Expr::Pi(
21            BinderInfo::Default,
22            Name::str("n"),
23            Box::new(Expr::Const(Name::str("Nat"), vec![])),
24            Box::new(type1.clone()),
25        )),
26    );
27    let nil_ty = Expr::Pi(
28        BinderInfo::Implicit,
29        Name::str("α"),
30        Box::new(type1.clone()),
31        Box::new(Expr::App(
32            Box::new(Expr::App(
33                Box::new(Expr::Const(Name::str("Vec"), vec![])),
34                Box::new(Expr::BVar(0)),
35            )),
36            Box::new(Expr::Const(Name::str("Nat.zero"), vec![])),
37        )),
38    );
39    let cons_ty = Expr::Pi(
40        BinderInfo::Implicit,
41        Name::str("α"),
42        Box::new(type1.clone()),
43        Box::new(Expr::Pi(
44            BinderInfo::Implicit,
45            Name::str("n"),
46            Box::new(Expr::Const(Name::str("Nat"), vec![])),
47            Box::new(Expr::Pi(
48                BinderInfo::Default,
49                Name::str("head"),
50                Box::new(Expr::BVar(1)),
51                Box::new(Expr::Pi(
52                    BinderInfo::Default,
53                    Name::str("tail"),
54                    Box::new(Expr::App(
55                        Box::new(Expr::App(
56                            Box::new(Expr::Const(Name::str("Vec"), vec![])),
57                            Box::new(Expr::BVar(2)),
58                        )),
59                        Box::new(Expr::BVar(1)),
60                    )),
61                    Box::new(Expr::App(
62                        Box::new(Expr::App(
63                            Box::new(Expr::Const(Name::str("Vec"), vec![])),
64                            Box::new(Expr::BVar(3)),
65                        )),
66                        Box::new(Expr::App(
67                            Box::new(Expr::Const(Name::str("Nat.succ"), vec![])),
68                            Box::new(Expr::BVar(2)),
69                        )),
70                    )),
71                )),
72            )),
73        )),
74    );
75    let vec_ind = InductiveType::new(
76        Name::str("Vec"),
77        vec![],
78        1,
79        1,
80        vec_ty.clone(),
81        vec![
82            IntroRule {
83                name: Name::str("Vec.nil"),
84                ty: nil_ty.clone(),
85            },
86            IntroRule {
87                name: Name::str("Vec.cons"),
88                ty: cons_ty.clone(),
89            },
90        ],
91    );
92    ind_env.add(vec_ind).map_err(|e| format!("{}", e))?;
93    env.add(Declaration::Axiom {
94        name: Name::str("Vec"),
95        univ_params: vec![],
96        ty: vec_ty,
97    })
98    .map_err(|e| e.to_string())?;
99    env.add(Declaration::Axiom {
100        name: Name::str("Vec.nil"),
101        univ_params: vec![],
102        ty: nil_ty,
103    })
104    .map_err(|e| e.to_string())?;
105    env.add(Declaration::Axiom {
106        name: Name::str("Vec.cons"),
107        univ_params: vec![],
108        ty: cons_ty,
109    })
110    .map_err(|e| e.to_string())?;
111    Ok(())
112}
113#[cfg(test)]
114mod tests {
115    use super::*;
116    #[test]
117    fn test_build_vec_env() {
118        let mut env = Environment::new();
119        let mut ind_env = InductiveEnv::new();
120        let type1 = Expr::Sort(Level::succ(Level::zero()));
121        env.add(Declaration::Axiom {
122            name: Name::str("Nat"),
123            univ_params: vec![],
124            ty: type1.clone(),
125        })
126        .expect("operation should succeed");
127        env.add(Declaration::Axiom {
128            name: Name::str("Nat.zero"),
129            univ_params: vec![],
130            ty: Expr::Const(Name::str("Nat"), vec![]),
131        })
132        .expect("operation should succeed");
133        env.add(Declaration::Axiom {
134            name: Name::str("Nat.succ"),
135            univ_params: vec![],
136            ty: Expr::Pi(
137                BinderInfo::Default,
138                Name::str("n"),
139                Box::new(Expr::Const(Name::str("Nat"), vec![])),
140                Box::new(Expr::Const(Name::str("Nat"), vec![])),
141            ),
142        })
143        .expect("operation should succeed");
144        assert!(build_vec_env(&mut env, &mut ind_env).is_ok());
145        assert!(env.get(&Name::str("Vec")).is_some());
146        assert!(env.get(&Name::str("Vec.nil")).is_some());
147        assert!(env.get(&Name::str("Vec.cons")).is_some());
148    }
149}
150/// Concatenate two vectors into a new one.
151#[allow(dead_code)]
152pub fn vec_append<T: Clone>(a: &[T], b: &[T]) -> Vec<T> {
153    let mut result = a.to_vec();
154    result.extend_from_slice(b);
155    result
156}
157/// Return `true` if `v` contains `elem`.
158#[allow(dead_code)]
159pub fn vec_contains<T: PartialEq>(v: &[T], elem: &T) -> bool {
160    v.contains(elem)
161}
162/// Return the index of the first occurrence of `elem`, or `None`.
163#[allow(dead_code)]
164pub fn vec_index_of<T: PartialEq>(v: &[T], elem: &T) -> Option<usize> {
165    v.iter().position(|x| x == elem)
166}
167/// Remove all occurrences of `elem` from `v`.
168#[allow(dead_code)]
169pub fn vec_remove_all<T: PartialEq>(v: Vec<T>, elem: &T) -> Vec<T> {
170    v.into_iter().filter(|x| x != elem).collect()
171}
172/// Deduplicate a vector (keeping first occurrence), preserving order.
173#[allow(dead_code)]
174pub fn vec_dedup_stable<T: PartialEq + Clone>(v: &[T]) -> Vec<T> {
175    let mut seen = Vec::new();
176    for item in v {
177        if !seen.contains(item) {
178            seen.push(item.clone());
179        }
180    }
181    seen
182}
183/// Flatten a `Vec<Vec<T>>` into a `Vec<T>`.
184#[allow(dead_code)]
185pub fn vec_flatten<T>(v: Vec<Vec<T>>) -> Vec<T> {
186    v.into_iter().flatten().collect()
187}
188/// Return the last element of a slice, or `None`.
189#[allow(dead_code)]
190pub fn vec_last<T>(v: &[T]) -> Option<&T> {
191    v.last()
192}
193/// Return the first element of a slice, or `None`.
194#[allow(dead_code)]
195pub fn vec_head<T>(v: &[T]) -> Option<&T> {
196    v.first()
197}
198/// Return all but the last element (i.e. `init` of the vector).
199#[allow(dead_code)]
200pub fn vec_init<T: Clone>(v: &[T]) -> Vec<T> {
201    if v.is_empty() {
202        vec![]
203    } else {
204        v[..v.len() - 1].to_vec()
205    }
206}
207/// Return all but the first element (i.e. `tail` of the vector).
208#[allow(dead_code)]
209pub fn vec_tail<T: Clone>(v: &[T]) -> Vec<T> {
210    if v.is_empty() {
211        vec![]
212    } else {
213        v[1..].to_vec()
214    }
215}
216/// Split a vector at `index`, returning `(left, right)`.
217#[allow(dead_code)]
218pub fn vec_split_at<T: Clone>(v: &[T], index: usize) -> (Vec<T>, Vec<T>) {
219    let idx = index.min(v.len());
220    (v[..idx].to_vec(), v[idx..].to_vec())
221}
222/// Zip two vectors into a vector of pairs (up to the shorter length).
223#[allow(dead_code)]
224pub fn vec_zip<A: Clone, B: Clone>(a: &[A], b: &[B]) -> Vec<(A, B)> {
225    a.iter()
226        .zip(b.iter())
227        .map(|(x, y)| (x.clone(), y.clone()))
228        .collect()
229}
230/// Unzip a vector of pairs into two vectors.
231#[allow(dead_code)]
232pub fn vec_unzip<A, B>(v: Vec<(A, B)>) -> (Vec<A>, Vec<B>) {
233    v.into_iter().unzip()
234}
235/// Return the vector with element at `index` removed.
236#[allow(dead_code)]
237pub fn vec_remove_at<T: Clone>(v: &[T], index: usize) -> Vec<T> {
238    let mut result = v.to_vec();
239    if index < result.len() {
240        result.remove(index);
241    }
242    result
243}
244/// Insert `elem` at `index`, shifting subsequent elements right.
245#[allow(dead_code)]
246pub fn vec_insert_at<T: Clone>(v: &[T], index: usize, elem: T) -> Vec<T> {
247    let mut result = v.to_vec();
248    let idx = index.min(result.len());
249    result.insert(idx, elem);
250    result
251}
252/// Replace the element at `index` with `new_val`.
253#[allow(dead_code)]
254pub fn vec_set<T: Clone>(v: &[T], index: usize, new_val: T) -> Vec<T> {
255    let mut result = v.to_vec();
256    if index < result.len() {
257        result[index] = new_val;
258    }
259    result
260}
261/// Reverse a vector.
262#[allow(dead_code)]
263pub fn vec_reverse<T: Clone>(v: &[T]) -> Vec<T> {
264    let mut result = v.to_vec();
265    result.reverse();
266    result
267}
268/// Rotate a vector left by `n` positions.
269#[allow(dead_code)]
270pub fn vec_rotate_left<T: Clone>(v: &[T], n: usize) -> Vec<T> {
271    if v.is_empty() {
272        return vec![];
273    }
274    let n = n % v.len();
275    let mut result = v[n..].to_vec();
276    result.extend_from_slice(&v[..n]);
277    result
278}
279/// Rotate a vector right by `n` positions.
280#[allow(dead_code)]
281pub fn vec_rotate_right<T: Clone>(v: &[T], n: usize) -> Vec<T> {
282    if v.is_empty() {
283        return vec![];
284    }
285    let n = n % v.len();
286    vec_rotate_left(v, v.len() - n)
287}
288/// Return every `n`-th element starting from `start`.
289#[allow(dead_code)]
290pub fn vec_step_by<T: Clone>(v: &[T], start: usize, step: usize) -> Vec<T> {
291    if step == 0 {
292        return vec![];
293    }
294    v.iter()
295        .enumerate()
296        .filter(|(i, _)| i >= &start && (i - start) % step == 0)
297        .map(|(_, x)| x.clone())
298        .collect()
299}
300/// Count elements matching a predicate.
301#[allow(dead_code)]
302pub fn vec_count_where<T, F: Fn(&T) -> bool>(v: &[T], pred: F) -> usize {
303    v.iter().filter(|x| pred(x)).count()
304}
305/// Partition into matching and non-matching elements.
306#[allow(dead_code)]
307pub fn vec_partition<T, F: Fn(&T) -> bool>(v: Vec<T>, pred: F) -> (Vec<T>, Vec<T>) {
308    v.into_iter().partition(|x| pred(x))
309}
310/// Map a fallible function over a vector, returning early on error.
311#[allow(dead_code)]
312pub fn vec_try_map<T, U, E, F: Fn(T) -> Result<U, E>>(v: Vec<T>, f: F) -> Result<Vec<U>, E> {
313    v.into_iter().map(f).collect()
314}
315/// Interleave `sep` between elements of `v`.
316#[allow(dead_code)]
317pub fn vec_intersperse<T: Clone>(v: &[T], sep: T) -> Vec<T> {
318    if v.is_empty() {
319        return vec![];
320    }
321    let mut result = Vec::with_capacity(v.len() * 2 - 1);
322    for (i, x) in v.iter().enumerate() {
323        if i > 0 {
324            result.push(sep.clone());
325        }
326        result.push(x.clone());
327    }
328    result
329}
330/// Transpose a `Vec<Vec<T>>` (rows ↔ columns).
331///
332/// The input must be rectangular (all inner vecs same length).
333#[allow(dead_code)]
334pub fn vec_transpose<T: Clone>(matrix: &[Vec<T>]) -> Vec<Vec<T>> {
335    if matrix.is_empty() || matrix[0].is_empty() {
336        return vec![];
337    }
338    let rows = matrix.len();
339    let cols = matrix[0].len();
340    (0..cols)
341        .map(|c| (0..rows).map(|r| matrix[r][c].clone()).collect())
342        .collect()
343}
344/// Produce all combinations of one element from each inner slice.
345///
346/// E.g. `[[1,2],[3,4]]` → `[[1,3],[1,4],[2,3],[2,4]]`.
347#[allow(dead_code)]
348pub fn vec_cartesian_product<T: Clone>(vecs: &[Vec<T>]) -> Vec<Vec<T>> {
349    if vecs.is_empty() {
350        return vec![vec![]];
351    }
352    let mut result = vec![vec![]];
353    for row in vecs {
354        let mut new_result = Vec::new();
355        for prefix in &result {
356            for item in row {
357                let mut new_prefix = prefix.clone();
358                new_prefix.push(item.clone());
359                new_result.push(new_prefix);
360            }
361        }
362        result = new_result;
363    }
364    result
365}
366/// Return the maximum element of a non-empty slice, or `None`.
367#[allow(dead_code)]
368pub fn vec_max<T: Ord + Clone>(v: &[T]) -> Option<T> {
369    v.iter().max().cloned()
370}
371/// Return the minimum element of a non-empty slice, or `None`.
372#[allow(dead_code)]
373pub fn vec_min<T: Ord + Clone>(v: &[T]) -> Option<T> {
374    v.iter().min().cloned()
375}
376/// Sum all `u64` values in a slice.
377#[allow(dead_code)]
378pub fn vec_sum_u64(v: &[u64]) -> u64 {
379    v.iter().sum()
380}
381/// Product of all `u64` values in a slice.
382#[allow(dead_code)]
383pub fn vec_product_u64(v: &[u64]) -> u64 {
384    v.iter().product()
385}
386#[cfg(test)]
387mod vec_extra_tests {
388    use super::*;
389    #[test]
390    fn test_vec_append() {
391        let a = vec![1, 2];
392        let b = vec![3, 4];
393        assert_eq!(vec_append(&a, &b), vec![1, 2, 3, 4]);
394    }
395    #[test]
396    fn test_vec_dedup_stable() {
397        let v = vec![1, 2, 1, 3, 2, 4];
398        assert_eq!(vec_dedup_stable(&v), vec![1, 2, 3, 4]);
399    }
400    #[test]
401    fn test_vec_flatten() {
402        let v = vec![vec![1, 2], vec![3], vec![4, 5]];
403        assert_eq!(vec_flatten(v), vec![1, 2, 3, 4, 5]);
404    }
405    #[test]
406    fn test_vec_head_tail() {
407        let v = vec![10, 20, 30];
408        assert_eq!(vec_head(&v), Some(&10));
409        assert_eq!(vec_tail(&v), vec![20, 30]);
410        assert_eq!(vec_init(&v), vec![10, 20]);
411    }
412    #[test]
413    fn test_vec_zip_unzip() {
414        let a = vec![1, 2, 3];
415        let b = vec!["a", "b", "c"];
416        let zipped = vec_zip(&a, &b);
417        assert_eq!(zipped, vec![(1, "a"), (2, "b"), (3, "c")]);
418        let (a2, b2): (Vec<_>, Vec<_>) = vec_unzip(zipped);
419        assert_eq!(a2, a);
420        assert_eq!(b2, b);
421    }
422    #[test]
423    fn test_vec_rotate() {
424        let v = vec![1, 2, 3, 4, 5];
425        assert_eq!(vec_rotate_left(&v, 2), vec![3, 4, 5, 1, 2]);
426        assert_eq!(vec_rotate_right(&v, 2), vec![4, 5, 1, 2, 3]);
427    }
428    #[test]
429    fn test_vec_intersperse() {
430        let v = vec![1, 2, 3];
431        assert_eq!(vec_intersperse(&v, 0), vec![1, 0, 2, 0, 3]);
432    }
433    #[test]
434    fn test_vec_transpose() {
435        let m = vec![vec![1, 2, 3], vec![4, 5, 6]];
436        let t = vec_transpose(&m);
437        assert_eq!(t, vec![vec![1, 4], vec![2, 5], vec![3, 6]]);
438    }
439    #[test]
440    fn test_vec_cartesian_product() {
441        let vecs = vec![vec![1, 2], vec![3, 4]];
442        let product = vec_cartesian_product(&vecs);
443        assert_eq!(product.len(), 4);
444        assert!(product.contains(&vec![1, 3]));
445        assert!(product.contains(&vec![2, 4]));
446    }
447    #[test]
448    fn test_vec_partition() {
449        let v = vec![1, 2, 3, 4, 5, 6];
450        let (even, odd) = vec_partition(v, |x| x % 2 == 0);
451        assert_eq!(even, vec![2, 4, 6]);
452        assert_eq!(odd, vec![1, 3, 5]);
453    }
454    #[test]
455    fn test_fixed_vec() {
456        let fv = FixedVec::from_vec(vec![10, 20, 30]);
457        assert_eq!(fv.len(), 3);
458        assert_eq!(fv.get(1), Some(&20));
459        assert_eq!(fv.get(5), None);
460    }
461    #[test]
462    fn test_vec_step_by() {
463        let v = vec![0, 1, 2, 3, 4, 5, 6];
464        assert_eq!(vec_step_by(&v, 0, 2), vec![0, 2, 4, 6]);
465    }
466    #[test]
467    fn test_vec_count_where() {
468        let v = vec![1, 2, 3, 4, 5];
469        assert_eq!(vec_count_where(&v, |x| *x > 3), 2);
470    }
471    #[test]
472    fn test_vec_min_max() {
473        let v = vec![3, 1, 4, 1, 5, 9];
474        assert_eq!(vec_min(&v), Some(1));
475        assert_eq!(vec_max(&v), Some(9));
476    }
477    #[test]
478    fn test_vec_remove_at_insert_at() {
479        let v = vec![1, 2, 3, 4];
480        let removed = vec_remove_at(&v, 1);
481        assert_eq!(removed, vec![1, 3, 4]);
482        let inserted = vec_insert_at(&v, 2, 99);
483        assert_eq!(inserted, vec![1, 2, 99, 3, 4]);
484    }
485    #[test]
486    fn test_vec_try_map() {
487        let v = vec!["1", "2", "3"];
488        let result: Result<Vec<u32>, _> = vec_try_map(v, |s| s.parse::<u32>());
489        assert_eq!(result.expect("result should be valid"), vec![1, 2, 3]);
490    }
491}
492/// Assert that two slices have the same length and return an error otherwise.
493#[allow(dead_code)]
494pub fn same_length_check<A, B>(a: &[A], b: &[B]) -> Result<(), String> {
495    if a.len() == b.len() {
496        Ok(())
497    } else {
498        Err(format!("length mismatch: {} vs {}", a.len(), b.len()))
499    }
500}
501/// Zip two slices, failing if they have different lengths.
502#[allow(dead_code)]
503pub fn zip_exact<A: Clone, B: Clone>(a: &[A], b: &[B]) -> Result<Vec<(A, B)>, String> {
504    same_length_check(a, b)?;
505    Ok(vec_zip(a, b))
506}
507/// Map over a slice and collect the results, also returning the original indices.
508#[allow(dead_code)]
509pub fn indexed_map<T, U, F: Fn(usize, &T) -> U>(v: &[T], f: F) -> Vec<(usize, U)> {
510    v.iter().enumerate().map(|(i, x)| (i, f(i, x))).collect()
511}
512/// Find the index of the maximum element.
513#[allow(dead_code)]
514pub fn argmax<T: PartialOrd>(v: &[T]) -> Option<usize> {
515    if v.is_empty() {
516        return None;
517    }
518    let mut best = 0;
519    for (i, x) in v.iter().enumerate() {
520        if *x > v[best] {
521            best = i;
522        }
523    }
524    Some(best)
525}
526/// Find the index of the minimum element.
527#[allow(dead_code)]
528pub fn argmin<T: PartialOrd>(v: &[T]) -> Option<usize> {
529    if v.is_empty() {
530        return None;
531    }
532    let mut best = 0;
533    for (i, x) in v.iter().enumerate() {
534        if *x < v[best] {
535            best = i;
536        }
537    }
538    Some(best)
539}
540/// Run-length encode a slice: consecutive equal elements become `(value, count)`.
541#[allow(dead_code)]
542pub fn run_length_encode<T: PartialEq + Clone>(v: &[T]) -> Vec<(T, usize)> {
543    if v.is_empty() {
544        return vec![];
545    }
546    let mut result = Vec::new();
547    let mut current = v[0].clone();
548    let mut count = 1;
549    for item in &v[1..] {
550        if *item == current {
551            count += 1;
552        } else {
553            result.push((current.clone(), count));
554            current = item.clone();
555            count = 1;
556        }
557    }
558    result.push((current, count));
559    result
560}
561/// Decode a run-length encoded sequence back to a flat vector.
562#[allow(dead_code)]
563pub fn run_length_decode<T: Clone>(encoded: &[(T, usize)]) -> Vec<T> {
564    let mut result = Vec::new();
565    for (item, count) in encoded {
566        for _ in 0..*count {
567            result.push(item.clone());
568        }
569    }
570    result
571}
572/// Sliding window iterator: produce all sub-slices of length `window`.
573#[allow(dead_code)]
574pub fn windows_collect<T: Clone>(v: &[T], window: usize) -> Vec<Vec<T>> {
575    if window == 0 || window > v.len() {
576        return vec![];
577    }
578    v.windows(window).map(|w| w.to_vec()).collect()
579}
580/// Return `true` if `v` is a palindrome.
581#[allow(dead_code)]
582pub fn is_palindrome<T: PartialEq>(v: &[T]) -> bool {
583    let n = v.len();
584    for i in 0..n / 2 {
585        if v[i] != v[n - 1 - i] {
586            return false;
587        }
588    }
589    true
590}
591/// Flatten one level of nesting.
592#[allow(dead_code)]
593pub fn flatten_once<T: Clone>(v: &[Vec<T>]) -> Vec<T> {
594    v.iter().flat_map(|inner| inner.iter().cloned()).collect()
595}
596/// Group consecutive elements by a key function.
597#[allow(dead_code)]
598pub fn group_by<T: Clone, K: PartialEq, F: Fn(&T) -> K>(v: &[T], key: F) -> Vec<Vec<T>> {
599    if v.is_empty() {
600        return vec![];
601    }
602    let mut groups: Vec<Vec<T>> = Vec::new();
603    let mut current_group = vec![v[0].clone()];
604    let mut current_key = key(&v[0]);
605    for item in &v[1..] {
606        let k = key(item);
607        if k == current_key {
608            current_group.push(item.clone());
609        } else {
610            groups.push(current_group.clone());
611            current_group = vec![item.clone()];
612            current_key = k;
613        }
614    }
615    groups.push(current_group);
616    groups
617}
618#[cfg(test)]
619mod vec_extra_tests2 {
620    use super::*;
621    #[test]
622    fn test_same_length_check() {
623        assert!(same_length_check(&[1, 2], &[3, 4]).is_ok());
624        assert!(same_length_check(&[1], &[3, 4]).is_err());
625    }
626    #[test]
627    fn test_zip_exact() {
628        let a = vec![1, 2, 3];
629        let b = vec!["a", "b", "c"];
630        let z = zip_exact(&a, &b).expect("operation should succeed");
631        assert_eq!(z.len(), 3);
632        assert!(zip_exact(&[1], &[2, 3]).is_err());
633    }
634    #[test]
635    fn test_argmax_argmin() {
636        let v = vec![3.0f64, 1.0, 4.0, 1.0, 5.0, 9.0, 2.0, 6.0];
637        assert_eq!(argmax(&v), Some(5));
638        assert_eq!(argmin(&v), Some(1));
639        let empty: Vec<f64> = vec![];
640        assert!(argmax(&empty).is_none());
641    }
642    #[test]
643    fn test_run_length_encode_decode() {
644        let v = vec![1, 1, 2, 3, 3, 3, 1];
645        let enc = run_length_encode(&v);
646        assert_eq!(enc, vec![(1, 2), (2, 1), (3, 3), (1, 1)]);
647        let dec = run_length_decode(&enc);
648        assert_eq!(dec, v);
649    }
650    #[test]
651    fn test_windows_collect() {
652        let v = vec![1, 2, 3, 4];
653        let wins = windows_collect(&v, 2);
654        assert_eq!(wins, vec![vec![1, 2], vec![2, 3], vec![3, 4]]);
655    }
656    #[test]
657    fn test_is_palindrome() {
658        assert!(is_palindrome(&[1, 2, 1]));
659        assert!(is_palindrome(&[1, 2, 2, 1]));
660        assert!(!is_palindrome(&[1, 2, 3]));
661        assert!(is_palindrome::<i32>(&[]));
662    }
663    #[test]
664    fn test_flatten_once() {
665        let v = vec![vec![1, 2], vec![3], vec![4, 5]];
666        assert_eq!(flatten_once(&v), vec![1, 2, 3, 4, 5]);
667    }
668    #[test]
669    fn test_group_by() {
670        let v = vec![1, 1, 2, 3, 3, 1];
671        let groups = group_by(&v, |x| *x);
672        assert_eq!(groups.len(), 4);
673        assert_eq!(groups[0], vec![1, 1]);
674        assert_eq!(groups[2], vec![3, 3]);
675    }
676    #[test]
677    fn test_indexed_map() {
678        let v = vec![10, 20, 30];
679        let result = indexed_map(&v, |i, x| i + x);
680        assert_eq!(result, vec![(0, 10), (1, 21), (2, 32)]);
681    }
682}
683/// Return elements in `a` not in `b` (order-preserving, `O(n*m)`).
684#[allow(dead_code)]
685pub fn vec_difference<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
686    a.iter().filter(|x| !b.contains(x)).cloned().collect()
687}
688/// Return elements in both `a` and `b` (order-preserving, keeps first occurrence).
689#[allow(dead_code)]
690pub fn vec_intersection<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
691    a.iter().filter(|x| b.contains(x)).cloned().collect()
692}
693/// Return elements in either `a` or `b` but not both (symmetric difference).
694#[allow(dead_code)]
695pub fn vec_symmetric_difference<T: PartialEq + Clone>(a: &[T], b: &[T]) -> Vec<T> {
696    let mut result = vec_difference(a, b);
697    result.extend(vec_difference(b, a));
698    result
699}
700/// Return `true` if `a` and `b` are set-equal (same elements, any order).
701#[allow(dead_code)]
702pub fn vec_set_eq<T: PartialEq>(a: &[T], b: &[T]) -> bool {
703    if a.len() != b.len() {
704        return false;
705    }
706    a.iter().all(|x| b.contains(x))
707}
708/// Return `true` if `a` is a subset of `b` (all elements of `a` appear in `b`).
709#[allow(dead_code)]
710pub fn vec_is_subset<T: PartialEq>(a: &[T], b: &[T]) -> bool {
711    a.iter().all(|x| b.contains(x))
712}
713/// Compute the arithmetic mean of a `f64` slice.
714///
715/// Returns `f64::NAN` for an empty slice.
716#[allow(dead_code)]
717pub fn vec_mean_f64(v: &[f64]) -> f64 {
718    if v.is_empty() {
719        return f64::NAN;
720    }
721    v.iter().sum::<f64>() / v.len() as f64
722}
723/// Compute the variance (population) of a `f64` slice.
724#[allow(dead_code)]
725pub fn vec_variance_f64(v: &[f64]) -> f64 {
726    if v.is_empty() {
727        return f64::NAN;
728    }
729    let mean = vec_mean_f64(v);
730    v.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / v.len() as f64
731}
732/// Compute the standard deviation (population) of a `f64` slice.
733#[allow(dead_code)]
734pub fn vec_std_dev_f64(v: &[f64]) -> f64 {
735    vec_variance_f64(v).sqrt()
736}
737/// Compute the median of a `f64` slice.
738///
739/// Returns `f64::NAN` for empty slices; averages the two middle elements for
740/// even-length slices.
741#[allow(dead_code)]
742pub fn vec_median_f64(v: &[f64]) -> f64 {
743    if v.is_empty() {
744        return f64::NAN;
745    }
746    let mut sorted = v.to_vec();
747    sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
748    let n = sorted.len();
749    if n % 2 == 1 {
750        sorted[n / 2]
751    } else {
752        (sorted[n / 2 - 1] + sorted[n / 2]) / 2.0
753    }
754}
755/// Normalise a `f64` vector so that its values sum to 1.0.
756///
757/// Returns the vector unchanged if the sum is zero.
758#[allow(dead_code)]
759pub fn vec_normalize_f64(v: &[f64]) -> Vec<f64> {
760    let total: f64 = v.iter().sum();
761    if total == 0.0 {
762        return v.to_vec();
763    }
764    v.iter().map(|x| x / total).collect()
765}
766/// Split a slice into chunks of `size`.
767///
768/// The last chunk may be shorter than `size`.
769#[allow(dead_code)]
770pub fn vec_chunks<T: Clone>(v: &[T], size: usize) -> Vec<Vec<T>> {
771    if size == 0 {
772        return vec![];
773    }
774    v.chunks(size).map(|c| c.to_vec()).collect()
775}
776/// Take up to `n` elements from the front of a slice.
777#[allow(dead_code)]
778pub fn vec_take<T: Clone>(v: &[T], n: usize) -> Vec<T> {
779    v.iter().take(n).cloned().collect()
780}
781/// Drop the first `n` elements.
782#[allow(dead_code)]
783pub fn vec_drop<T: Clone>(v: &[T], n: usize) -> Vec<T> {
784    v.iter().skip(n).cloned().collect()
785}
786/// Take elements while a predicate is true.
787#[allow(dead_code)]
788pub fn vec_take_while<T: Clone, F: Fn(&T) -> bool>(v: &[T], pred: F) -> Vec<T> {
789    v.iter().take_while(|x| pred(x)).cloned().collect()
790}
791/// Drop elements while a predicate is true.
792#[allow(dead_code)]
793pub fn vec_drop_while<T: Clone, F: Fn(&T) -> bool>(v: &[T], pred: F) -> Vec<T> {
794    v.iter().skip_while(|x| pred(x)).cloned().collect()
795}
796#[cfg(test)]
797mod vec_set_op_tests {
798    use super::*;
799    #[test]
800    fn test_vec_difference() {
801        assert_eq!(vec_difference(&[1, 2, 3], &[2, 4]), vec![1, 3]);
802    }
803    #[test]
804    fn test_vec_intersection() {
805        assert_eq!(vec_intersection(&[1, 2, 3, 4], &[2, 4, 6]), vec![2, 4]);
806    }
807    #[test]
808    fn test_vec_symmetric_difference() {
809        let r = vec_symmetric_difference(&[1, 2, 3], &[2, 3, 4]);
810        assert!(r.contains(&1) && r.contains(&4));
811        assert!(!r.contains(&2));
812    }
813    #[test]
814    fn test_vec_set_eq() {
815        assert!(vec_set_eq(&[1, 2, 3], &[3, 1, 2]));
816        assert!(!vec_set_eq(&[1, 2], &[1, 2, 3]));
817    }
818    #[test]
819    fn test_vec_is_subset() {
820        assert!(vec_is_subset(&[1, 2], &[1, 2, 3]));
821        assert!(!vec_is_subset(&[1, 4], &[1, 2, 3]));
822    }
823    #[test]
824    fn test_vec_mean_f64() {
825        assert!((vec_mean_f64(&[1.0, 2.0, 3.0]) - 2.0).abs() < 1e-9);
826        assert!(vec_mean_f64(&[]).is_nan());
827    }
828    #[test]
829    fn test_vec_variance_f64() {
830        let v = vec![2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
831        let var = vec_variance_f64(&v);
832        assert!((var - 4.0).abs() < 1e-9);
833    }
834    #[test]
835    fn test_vec_std_dev_f64() {
836        let v = vec![2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
837        let std = vec_std_dev_f64(&v);
838        assert!((std - 2.0).abs() < 1e-9);
839    }
840    #[test]
841    fn test_vec_median_f64_odd() {
842        assert!((vec_median_f64(&[3.0, 1.0, 2.0]) - 2.0).abs() < 1e-9);
843    }
844    #[test]
845    fn test_vec_median_f64_even() {
846        assert!((vec_median_f64(&[1.0, 3.0, 5.0, 7.0]) - 4.0).abs() < 1e-9);
847    }
848    #[test]
849    fn test_vec_normalize_f64() {
850        let v = vec![1.0, 2.0, 3.0, 4.0];
851        let n = vec_normalize_f64(&v);
852        let sum: f64 = n.iter().sum();
853        assert!((sum - 1.0).abs() < 1e-9);
854    }
855    #[test]
856    fn test_vec_chunks() {
857        let v = vec![1, 2, 3, 4, 5];
858        let chunks = vec_chunks(&v, 2);
859        assert_eq!(chunks.len(), 3);
860        assert_eq!(chunks[2], vec![5]);
861    }
862    #[test]
863    fn test_vec_take_drop() {
864        let v = vec![1, 2, 3, 4, 5];
865        assert_eq!(vec_take(&v, 3), vec![1, 2, 3]);
866        assert_eq!(vec_drop(&v, 3), vec![4, 5]);
867    }
868    #[test]
869    fn test_vec_take_while_drop_while() {
870        let v = vec![1, 2, 3, 4, 5];
871        let tw = vec_take_while(&v, |x| *x < 4);
872        assert_eq!(tw, vec![1, 2, 3]);
873        let dw = vec_drop_while(&v, |x| *x < 4);
874        assert_eq!(dw, vec![4, 5]);
875    }
876    #[test]
877    fn test_vec_normalize_zero_sum() {
878        let v = vec![0.0, 0.0, 0.0];
879        let n = vec_normalize_f64(&v);
880        assert_eq!(n, v);
881    }
882    #[test]
883    fn test_vec_chunks_zero_size() {
884        let v = vec![1, 2, 3];
885        let chunks = vec_chunks(&v, 0);
886        assert!(chunks.is_empty());
887    }
888}
889pub fn vec_ext_prop_axiom(name: &str, env: &mut Environment) -> std::result::Result<(), String> {
890    let prop = Expr::Sort(Level::zero());
891    env.add(Declaration::Axiom {
892        name: Name::str(name),
893        univ_params: vec![],
894        ty: prop,
895    })
896    .map_err(|e| e.to_string())
897}
898/// Build `∀ (α : Type), Prop`.
899pub fn vec_ext_forall1_axiom(name: &str, env: &mut Environment) -> std::result::Result<(), String> {
900    let prop = Expr::Sort(Level::zero());
901    let type1 = Expr::Sort(Level::succ(Level::zero()));
902    let ty = Expr::Pi(
903        BinderInfo::Implicit,
904        Name::str("α"),
905        Box::new(type1),
906        Box::new(prop),
907    );
908    env.add(Declaration::Axiom {
909        name: Name::str(name),
910        univ_params: vec![],
911        ty,
912    })
913    .map_err(|e| e.to_string())
914}
915/// Build `∀ (α β : Type), Prop`.
916pub fn vec_ext_forall2_axiom(name: &str, env: &mut Environment) -> std::result::Result<(), String> {
917    let prop = Expr::Sort(Level::zero());
918    let type1 = Expr::Sort(Level::succ(Level::zero()));
919    let ty = Expr::Pi(
920        BinderInfo::Implicit,
921        Name::str("α"),
922        Box::new(type1.clone()),
923        Box::new(Expr::Pi(
924            BinderInfo::Implicit,
925            Name::str("β"),
926            Box::new(type1),
927            Box::new(prop),
928        )),
929    );
930    env.add(Declaration::Axiom {
931        name: Name::str(name),
932        univ_params: vec![],
933        ty,
934    })
935    .map_err(|e| e.to_string())
936}
937/// Build `∀ (α β γ : Type), Prop`.
938pub fn vec_ext_forall3_axiom(name: &str, env: &mut Environment) -> std::result::Result<(), String> {
939    let prop = Expr::Sort(Level::zero());
940    let type1 = Expr::Sort(Level::succ(Level::zero()));
941    let ty = Expr::Pi(
942        BinderInfo::Implicit,
943        Name::str("α"),
944        Box::new(type1.clone()),
945        Box::new(Expr::Pi(
946            BinderInfo::Implicit,
947            Name::str("β"),
948            Box::new(type1.clone()),
949            Box::new(Expr::Pi(
950                BinderInfo::Implicit,
951                Name::str("γ"),
952                Box::new(type1),
953                Box::new(prop),
954            )),
955        )),
956    );
957    env.add(Declaration::Axiom {
958        name: Name::str(name),
959        univ_params: vec![],
960        ty,
961    })
962    .map_err(|e| e.to_string())
963}
964/// `Vec.functor_map_id : ∀ α, map id xs = xs`
965pub fn vec_ext_build_functor_map_id(env: &mut Environment) -> std::result::Result<(), String> {
966    vec_ext_forall1_axiom("Vec.functor_map_id", env)
967}
968/// `Vec.functor_map_comp : ∀ α β γ (f : α → β) (g : β → γ), map (g ∘ f) = map g ∘ map f`
969pub fn vec_ext_build_functor_map_comp(env: &mut Environment) -> std::result::Result<(), String> {
970    vec_ext_forall3_axiom("Vec.functor_map_comp", env)
971}
972/// `Vec.monad_left_id : ∀ α β (a : α) (f : α → Vec β), andThen [a] f = f a`
973pub fn vec_ext_build_monad_left_id(env: &mut Environment) -> std::result::Result<(), String> {
974    vec_ext_forall2_axiom("Vec.monad_left_id", env)
975}
976/// `Vec.monad_right_id : ∀ α (xs : Vec α), andThen xs pure = xs`
977pub fn vec_ext_build_monad_right_id(env: &mut Environment) -> std::result::Result<(), String> {
978    vec_ext_forall1_axiom("Vec.monad_right_id", env)
979}
980/// `Vec.monad_assoc : ∀ α β γ, andThen (andThen xs f) g = andThen xs (fun x => andThen (f x) g)`
981pub fn vec_ext_build_monad_assoc(env: &mut Environment) -> std::result::Result<(), String> {
982    vec_ext_forall3_axiom("Vec.monad_assoc", env)
983}
984/// `Vec.ap_identity : ap [id] xs = xs`
985pub fn vec_ext_build_ap_identity(env: &mut Environment) -> std::result::Result<(), String> {
986    vec_ext_forall1_axiom("Vec.ap_identity", env)
987}
988/// `Vec.ap_homomorphism : ap [f] [v] = [f v]`
989pub fn vec_ext_build_ap_homomorphism(env: &mut Environment) -> std::result::Result<(), String> {
990    vec_ext_forall2_axiom("Vec.ap_homomorphism", env)
991}
992/// `Vec.ap_interchange : ap fs [v] = ap [fun f => f v] fs`
993pub fn vec_ext_build_ap_interchange(env: &mut Environment) -> std::result::Result<(), String> {
994    vec_ext_forall2_axiom("Vec.ap_interchange", env)
995}
996/// `Vec.ap_composition : ap (ap (ap [∘] fs) gs) xs = ap fs (ap gs xs)`
997pub fn vec_ext_build_ap_composition(env: &mut Environment) -> std::result::Result<(), String> {
998    vec_ext_forall3_axiom("Vec.ap_composition", env)
999}
1000/// `Vec.foldr_nil : foldr f z [] = z`
1001pub fn vec_ext_build_foldr_nil(env: &mut Environment) -> std::result::Result<(), String> {
1002    vec_ext_forall2_axiom("Vec.foldr_nil", env)
1003}
1004/// `Vec.foldr_cons : foldr f z (x::xs) = f x (foldr f z xs)`
1005pub fn vec_ext_build_foldr_cons(env: &mut Environment) -> std::result::Result<(), String> {
1006    vec_ext_forall2_axiom("Vec.foldr_cons", env)
1007}
1008/// `Vec.foldl_nil : foldl f z [] = z`
1009pub fn vec_ext_build_foldl_nil(env: &mut Environment) -> std::result::Result<(), String> {
1010    vec_ext_forall2_axiom("Vec.foldl_nil", env)
1011}
1012/// `Vec.foldl_cons : foldl f z (x::xs) = foldl f (f z x) xs`
1013pub fn vec_ext_build_foldl_cons(env: &mut Environment) -> std::result::Result<(), String> {
1014    vec_ext_forall2_axiom("Vec.foldl_cons", env)
1015}
1016/// `Vec.foldl_foldr_duality : foldl f z xs = foldr (flip f) z (reverse xs)`
1017pub fn vec_ext_build_foldl_foldr_duality(env: &mut Environment) -> std::result::Result<(), String> {
1018    vec_ext_forall2_axiom("Vec.foldl_foldr_duality", env)
1019}
1020/// `Vec.scanl_nil : scanl f z [] = [z]`
1021pub fn vec_ext_build_scanl_nil(env: &mut Environment) -> std::result::Result<(), String> {
1022    vec_ext_forall2_axiom("Vec.scanl_nil", env)
1023}
1024/// `Vec.scanl_cons : scanl f z (x::xs) = z :: scanl f (f z x) xs`
1025pub fn vec_ext_build_scanl_cons(env: &mut Environment) -> std::result::Result<(), String> {
1026    vec_ext_forall2_axiom("Vec.scanl_cons", env)
1027}
1028/// `Vec.scanr_nil : scanr f z [] = [z]`
1029pub fn vec_ext_build_scanr_nil(env: &mut Environment) -> std::result::Result<(), String> {
1030    vec_ext_forall2_axiom("Vec.scanr_nil", env)
1031}
1032/// `Vec.scanr_cons : head (scanr f z (x::xs)) = f x (head (scanr f z xs))`
1033pub fn vec_ext_build_scanr_cons(env: &mut Environment) -> std::result::Result<(), String> {
1034    vec_ext_forall2_axiom("Vec.scanr_cons", env)
1035}
1036/// `Vec.scanl_last : last (scanl f z xs) = foldl f z xs`
1037pub fn vec_ext_build_scanl_last(env: &mut Environment) -> std::result::Result<(), String> {
1038    vec_ext_forall2_axiom("Vec.scanl_last", env)
1039}
1040/// `Vec.sort_is_permutation : sort xs is a permutation of xs`
1041pub fn vec_ext_build_sort_is_permutation(env: &mut Environment) -> std::result::Result<(), String> {
1042    vec_ext_forall1_axiom("Vec.sort_is_permutation", env)
1043}
1044/// `Vec.sort_is_sorted : ∀ α [Ord α] xs, isSorted (sort xs)`
1045pub fn vec_ext_build_sort_is_sorted(env: &mut Environment) -> std::result::Result<(), String> {
1046    vec_ext_forall1_axiom("Vec.sort_is_sorted", env)
1047}
1048/// `Vec.stable_sort_preserves_order : stable sort preserves relative order of equal elements`
1049pub fn vec_ext_build_stable_sort(env: &mut Environment) -> std::result::Result<(), String> {
1050    vec_ext_forall1_axiom("Vec.stable_sort_preserves_order", env)
1051}
1052/// `Vec.sort_idempotent : sort (sort xs) = sort xs`
1053pub fn vec_ext_build_sort_idempotent(env: &mut Environment) -> std::result::Result<(), String> {
1054    vec_ext_forall1_axiom("Vec.sort_idempotent", env)
1055}
1056/// `Vec.map_fusion : map f (map g xs) = map (f ∘ g) xs`
1057pub fn vec_ext_build_map_fusion(env: &mut Environment) -> std::result::Result<(), String> {
1058    vec_ext_forall3_axiom("Vec.map_fusion", env)
1059}
1060/// `Vec.filter_fusion : filter p (filter q xs) = filter (fun x => p x && q x) xs`
1061pub fn vec_ext_build_filter_fusion(env: &mut Environment) -> std::result::Result<(), String> {
1062    vec_ext_forall1_axiom("Vec.filter_fusion", env)
1063}
1064/// `Vec.map_filter_fusion : map f (filter p xs) = filterMap (fun x => if p x then Some (f x) else None) xs`
1065pub fn vec_ext_build_map_filter_fusion(env: &mut Environment) -> std::result::Result<(), String> {
1066    vec_ext_forall2_axiom("Vec.map_filter_fusion", env)
1067}
1068/// `Vec.fold_build_duality : foldr f z (build g) = g f z` (deforestation)
1069pub fn vec_ext_build_fold_build_duality(env: &mut Environment) -> std::result::Result<(), String> {
1070    vec_ext_forall2_axiom("Vec.fold_build_duality", env)
1071}
1072/// `Vec.fin_index_get : ∀ {α n} (xs : Vec α n) (i : Fin n), xs[i] is within bounds`
1073pub fn vec_ext_build_fin_index_get(env: &mut Environment) -> std::result::Result<(), String> {
1074    vec_ext_forall2_axiom("Vec.fin_index_get", env)
1075}
1076/// `Vec.fin_index_set : ∀ {α n} (xs : Vec α n) (i : Fin n) v, set xs i v has same length`
1077pub fn vec_ext_build_fin_index_set(env: &mut Environment) -> std::result::Result<(), String> {
1078    vec_ext_forall2_axiom("Vec.fin_index_set", env)
1079}
1080/// `Vec.fin_map_preserves_length : length (map f xs) = length xs`
1081pub fn vec_ext_build_fin_map_length(env: &mut Environment) -> std::result::Result<(), String> {
1082    vec_ext_forall2_axiom("Vec.fin_map_preserves_length", env)
1083}
1084/// `Vec.reverse_involutive : reverse (reverse xs) = xs`
1085pub fn vec_ext_build_reverse_involutive(env: &mut Environment) -> std::result::Result<(), String> {
1086    vec_ext_forall1_axiom("Vec.reverse_involutive", env)
1087}
1088/// `Vec.reverse_append : reverse (xs ++ ys) = reverse ys ++ reverse xs`
1089pub fn vec_ext_build_reverse_append(env: &mut Environment) -> std::result::Result<(), String> {
1090    vec_ext_forall1_axiom("Vec.reverse_append", env)
1091}
1092/// `Vec.reverse_map : reverse (map f xs) = map f (reverse xs)`
1093pub fn vec_ext_build_reverse_map(env: &mut Environment) -> std::result::Result<(), String> {
1094    vec_ext_forall2_axiom("Vec.reverse_map", env)
1095}
1096/// `Vec.take_drop_reconstruct : take n xs ++ drop n xs = xs`
1097pub fn vec_ext_build_take_drop_reconstruct(
1098    env: &mut Environment,
1099) -> std::result::Result<(), String> {
1100    vec_ext_forall1_axiom("Vec.take_drop_reconstruct", env)
1101}
1102/// `Vec.take_length : length (take n xs) = min n (length xs)`
1103pub fn vec_ext_build_take_length(env: &mut Environment) -> std::result::Result<(), String> {
1104    vec_ext_forall1_axiom("Vec.take_length", env)
1105}
1106/// `Vec.drop_length : length (drop n xs) = max 0 (length xs - n)`
1107pub fn vec_ext_build_drop_length(env: &mut Environment) -> std::result::Result<(), String> {
1108    vec_ext_forall1_axiom("Vec.drop_length", env)
1109}
1110/// `Vec.zip_length : length (zip xs ys) = min (length xs) (length ys)`
1111pub fn vec_ext_build_zip_length(env: &mut Environment) -> std::result::Result<(), String> {
1112    vec_ext_forall2_axiom("Vec.zip_length", env)
1113}
1114/// `Vec.unzip_zip : unzip (zip xs ys) = (take (min n m) xs, take (min n m) ys)`
1115pub fn vec_ext_build_unzip_zip(env: &mut Environment) -> std::result::Result<(), String> {
1116    vec_ext_forall2_axiom("Vec.unzip_zip", env)
1117}
1118/// `Vec.zip_map : zip (map f xs) (map g ys) = map (bimap f g) (zip xs ys)`
1119pub fn vec_ext_build_zip_map(env: &mut Environment) -> std::result::Result<(), String> {
1120    vec_ext_forall3_axiom("Vec.zip_map", env)
1121}
1122/// `Vec.chunks_flatten : flatten (chunks n xs) = xs`  (when n > 0)
1123pub fn vec_ext_build_chunks_flatten(env: &mut Environment) -> std::result::Result<(), String> {
1124    vec_ext_forall1_axiom("Vec.chunks_flatten", env)
1125}
1126/// `Vec.chunks_all_size : ∀ chunk ∈ init (chunks n xs), length chunk = n`
1127pub fn vec_ext_build_chunks_all_size(env: &mut Environment) -> std::result::Result<(), String> {
1128    vec_ext_forall1_axiom("Vec.chunks_all_size", env)
1129}
1130/// `Vec.chunks_count : length (chunks n xs) = ceil (length xs / n)`
1131pub fn vec_ext_build_chunks_count(env: &mut Environment) -> std::result::Result<(), String> {
1132    vec_ext_forall1_axiom("Vec.chunks_count", env)
1133}
1134/// `Vec.append_nil_left : [] ++ xs = xs`
1135pub fn vec_ext_build_append_nil_left(env: &mut Environment) -> std::result::Result<(), String> {
1136    vec_ext_forall1_axiom("Vec.append_nil_left", env)
1137}
1138/// `Vec.append_nil_right : xs ++ [] = xs`
1139pub fn vec_ext_build_append_nil_right(env: &mut Environment) -> std::result::Result<(), String> {
1140    vec_ext_forall1_axiom("Vec.append_nil_right", env)
1141}
1142/// `Vec.append_assoc : (xs ++ ys) ++ zs = xs ++ (ys ++ zs)`
1143pub fn vec_ext_build_append_assoc(env: &mut Environment) -> std::result::Result<(), String> {
1144    vec_ext_forall1_axiom("Vec.append_assoc", env)
1145}
1146/// `Vec.length_append : length (xs ++ ys) = length xs + length ys`
1147pub fn vec_ext_build_length_append(env: &mut Environment) -> std::result::Result<(), String> {
1148    vec_ext_forall1_axiom("Vec.length_append", env)
1149}
1150/// `Vec.rotate_left_right_inverse : rotateLeft n (rotateRight n xs) = xs`
1151pub fn vec_ext_build_rotate_left_right_inv(
1152    env: &mut Environment,
1153) -> std::result::Result<(), String> {
1154    vec_ext_forall1_axiom("Vec.rotate_left_right_inverse", env)
1155}
1156/// `Vec.rotate_length : length (rotateLeft n xs) = length xs`
1157pub fn vec_ext_build_rotate_length(env: &mut Environment) -> std::result::Result<(), String> {
1158    vec_ext_forall1_axiom("Vec.rotate_length", env)
1159}
1160/// `Vec.rotate_zero : rotateLeft 0 xs = xs`
1161pub fn vec_ext_build_rotate_zero(env: &mut Environment) -> std::result::Result<(), String> {
1162    vec_ext_forall1_axiom("Vec.rotate_zero", env)
1163}
1164/// `Vec.dlist_append_assoc : dlist append is associative`
1165pub fn vec_ext_build_dlist_append_assoc(env: &mut Environment) -> std::result::Result<(), String> {
1166    vec_ext_forall1_axiom("Vec.dlist_append_assoc", env)
1167}
1168/// `Vec.dlist_to_list_preserves : toList (dlist d) = d []`
1169pub fn vec_ext_build_dlist_to_list(env: &mut Environment) -> std::result::Result<(), String> {
1170    vec_ext_forall1_axiom("Vec.dlist_to_list_preserves", env)
1171}
1172/// `Vec.concat_map_id : concatMap pure xs = xs`
1173pub fn vec_ext_build_concat_map_id(env: &mut Environment) -> std::result::Result<(), String> {
1174    vec_ext_forall1_axiom("Vec.concat_map_id", env)
1175}
1176/// `Vec.concat_map_assoc : concatMap (concatMap f ∘ g) = concatMap f ∘ concatMap g`
1177pub fn vec_ext_build_concat_map_assoc(env: &mut Environment) -> std::result::Result<(), String> {
1178    vec_ext_forall3_axiom("Vec.concat_map_assoc", env)
1179}
1180/// `Vec.flatten_singleton : flatten [[x1], [x2], ...] = [x1, x2, ...]`
1181pub fn vec_ext_build_flatten_singleton(env: &mut Environment) -> std::result::Result<(), String> {
1182    vec_ext_forall1_axiom("Vec.flatten_singleton", env)
1183}
1184/// `Vec.flatten_map : flatten (map (map f) xss) = map f (flatten xss)`
1185pub fn vec_ext_build_flatten_map(env: &mut Environment) -> std::result::Result<(), String> {
1186    vec_ext_forall2_axiom("Vec.flatten_map", env)
1187}
1188/// `Vec.span_reconstruct : fst (span p xs) ++ snd (span p xs) = xs`
1189pub fn vec_ext_build_span_reconstruct(env: &mut Environment) -> std::result::Result<(), String> {
1190    vec_ext_forall1_axiom("Vec.span_reconstruct", env)
1191}
1192/// `Vec.partition_reconstruct : fst (partition p xs) ++ snd (partition p xs)` is permutation
1193pub fn vec_ext_build_partition_reconstruct(
1194    env: &mut Environment,
1195) -> std::result::Result<(), String> {
1196    vec_ext_forall1_axiom("Vec.partition_reconstruct", env)
1197}
1198/// `Vec.groupBy_flatten : flatten (groupBy eq xs) = xs`
1199pub fn vec_ext_build_groupby_flatten(env: &mut Environment) -> std::result::Result<(), String> {
1200    vec_ext_forall1_axiom("Vec.groupBy_flatten", env)
1201}
1202/// `Vec.prefix_sum_correct : prefixSum xs[i] = sum (take (i+1) xs)`
1203pub fn vec_ext_build_prefix_sum_correct(env: &mut Environment) -> std::result::Result<(), String> {
1204    vec_ext_prop_axiom("Vec.prefix_sum_correct", env)
1205}
1206/// `Vec.parallel_prefix_sequential_equiv : parallelPrefix f z xs = scanl f z xs`
1207pub fn vec_ext_build_parallel_prefix_equiv(
1208    env: &mut Environment,
1209) -> std::result::Result<(), String> {
1210    vec_ext_forall2_axiom("Vec.parallel_prefix_sequential_equiv", env)
1211}
1212/// `Vec.fenwick_prefix_sum_correct : query fenwick i = sum (take (i+1) original)`
1213pub fn vec_ext_build_fenwick_correct(env: &mut Environment) -> std::result::Result<(), String> {
1214    vec_ext_prop_axiom("Vec.fenwick_prefix_sum_correct", env)
1215}
1216/// `Vec.rle_decode_encode : decode (encode xs) = xs`
1217pub fn vec_ext_build_rle_roundtrip(env: &mut Environment) -> std::result::Result<(), String> {
1218    vec_ext_forall1_axiom("Vec.rle_decode_encode", env)
1219}
1220/// `Vec.rle_length : sum (map snd (rle xs)) = length xs`
1221pub fn vec_ext_build_rle_length(env: &mut Environment) -> std::result::Result<(), String> {
1222    vec_ext_forall1_axiom("Vec.rle_length", env)
1223}
1224/// `Vec.matrix_transpose_involutive : transpose (transpose m) = m`
1225pub fn vec_ext_build_matrix_transpose_invol(
1226    env: &mut Environment,
1227) -> std::result::Result<(), String> {
1228    vec_ext_forall1_axiom("Vec.matrix_transpose_involutive", env)
1229}
1230/// `Vec.matrix_row_count : length (transpose m) = length (head m)`
1231pub fn vec_ext_build_matrix_row_count(env: &mut Environment) -> std::result::Result<(), String> {
1232    vec_ext_forall1_axiom("Vec.matrix_row_count", env)
1233}
1234/// `Vec.matrix_col_count : length (head (transpose m)) = length m`
1235pub fn vec_ext_build_matrix_col_count(env: &mut Environment) -> std::result::Result<(), String> {
1236    vec_ext_forall1_axiom("Vec.matrix_col_count", env)
1237}
1238/// Register all extended Vec axioms into `env`.
1239///
1240/// Adds 35+ axioms covering:
1241/// - Vector functor/monad/applicative laws
1242/// - Fold laws (foldr, foldl)
1243/// - Scan operations (scanl, scanr)
1244/// - Sorting laws (stability, permutation)
1245/// - Fusion/deforestation
1246/// - Fin-indexed vectors
1247/// - Reverse, take/drop, zip/unzip laws
1248/// - Chunking operations
1249/// - Free monoid structure
1250/// - Rotations and circular buffers
1251/// - DList representation
1252/// - ConcatMap/flatten laws
1253/// - Span/partition/groupBy
1254/// - Parallel prefix operations
1255/// - Run-length encoding
1256/// - Matrix as nested vector
1257pub fn register_vec_extended_axioms(env: &mut Environment) {
1258    let builders: &[fn(&mut Environment) -> std::result::Result<(), String>] = &[
1259        vec_ext_build_functor_map_id,
1260        vec_ext_build_functor_map_comp,
1261        vec_ext_build_monad_left_id,
1262        vec_ext_build_monad_right_id,
1263        vec_ext_build_monad_assoc,
1264        vec_ext_build_ap_identity,
1265        vec_ext_build_ap_homomorphism,
1266        vec_ext_build_ap_interchange,
1267        vec_ext_build_ap_composition,
1268        vec_ext_build_foldr_nil,
1269        vec_ext_build_foldr_cons,
1270        vec_ext_build_foldl_nil,
1271        vec_ext_build_foldl_cons,
1272        vec_ext_build_foldl_foldr_duality,
1273        vec_ext_build_scanl_nil,
1274        vec_ext_build_scanl_cons,
1275        vec_ext_build_scanr_nil,
1276        vec_ext_build_scanr_cons,
1277        vec_ext_build_scanl_last,
1278        vec_ext_build_sort_is_permutation,
1279        vec_ext_build_sort_is_sorted,
1280        vec_ext_build_stable_sort,
1281        vec_ext_build_sort_idempotent,
1282        vec_ext_build_map_fusion,
1283        vec_ext_build_filter_fusion,
1284        vec_ext_build_map_filter_fusion,
1285        vec_ext_build_fold_build_duality,
1286        vec_ext_build_fin_index_get,
1287        vec_ext_build_fin_index_set,
1288        vec_ext_build_fin_map_length,
1289        vec_ext_build_reverse_involutive,
1290        vec_ext_build_reverse_append,
1291        vec_ext_build_reverse_map,
1292        vec_ext_build_take_drop_reconstruct,
1293        vec_ext_build_take_length,
1294        vec_ext_build_drop_length,
1295        vec_ext_build_zip_length,
1296        vec_ext_build_unzip_zip,
1297        vec_ext_build_zip_map,
1298        vec_ext_build_chunks_flatten,
1299        vec_ext_build_chunks_all_size,
1300        vec_ext_build_chunks_count,
1301        vec_ext_build_append_nil_left,
1302        vec_ext_build_append_nil_right,
1303        vec_ext_build_append_assoc,
1304        vec_ext_build_length_append,
1305        vec_ext_build_rotate_left_right_inv,
1306        vec_ext_build_rotate_length,
1307        vec_ext_build_rotate_zero,
1308        vec_ext_build_dlist_append_assoc,
1309        vec_ext_build_dlist_to_list,
1310        vec_ext_build_concat_map_id,
1311        vec_ext_build_concat_map_assoc,
1312        vec_ext_build_flatten_singleton,
1313        vec_ext_build_flatten_map,
1314        vec_ext_build_span_reconstruct,
1315        vec_ext_build_partition_reconstruct,
1316        vec_ext_build_groupby_flatten,
1317        vec_ext_build_prefix_sum_correct,
1318        vec_ext_build_parallel_prefix_equiv,
1319        vec_ext_build_fenwick_correct,
1320        vec_ext_build_rle_roundtrip,
1321        vec_ext_build_rle_length,
1322        vec_ext_build_matrix_transpose_invol,
1323        vec_ext_build_matrix_row_count,
1324        vec_ext_build_matrix_col_count,
1325    ];
1326    for builder in builders {
1327        let _ = builder(env);
1328    }
1329}
1330#[cfg(test)]
1331mod vec_extended_axiom_tests {
1332    use super::*;
1333    fn make_env() -> Environment {
1334        let mut env = Environment::new();
1335        let type1 = Expr::Sort(Level::succ(Level::zero()));
1336        env.add(Declaration::Axiom {
1337            name: Name::str("Nat"),
1338            univ_params: vec![],
1339            ty: type1.clone(),
1340        })
1341        .expect("operation should succeed");
1342        env.add(Declaration::Axiom {
1343            name: Name::str("Nat.zero"),
1344            univ_params: vec![],
1345            ty: Expr::Const(Name::str("Nat"), vec![]),
1346        })
1347        .expect("operation should succeed");
1348        env.add(Declaration::Axiom {
1349            name: Name::str("Nat.succ"),
1350            univ_params: vec![],
1351            ty: Expr::Pi(
1352                BinderInfo::Default,
1353                Name::str("n"),
1354                Box::new(Expr::Const(Name::str("Nat"), vec![])),
1355                Box::new(Expr::Const(Name::str("Nat"), vec![])),
1356            ),
1357        })
1358        .expect("operation should succeed");
1359        env
1360    }
1361    #[test]
1362    fn test_register_vec_extended_axioms_runs() {
1363        let mut env = make_env();
1364        register_vec_extended_axioms(&mut env);
1365        assert!(env.get(&Name::str("Vec.functor_map_id")).is_some());
1366        assert!(env.get(&Name::str("Vec.monad_left_id")).is_some());
1367        assert!(env.get(&Name::str("Vec.append_assoc")).is_some());
1368    }
1369    #[test]
1370    fn test_functor_laws_present() {
1371        let mut env = make_env();
1372        register_vec_extended_axioms(&mut env);
1373        assert!(env.get(&Name::str("Vec.functor_map_id")).is_some());
1374        assert!(env.get(&Name::str("Vec.functor_map_comp")).is_some());
1375    }
1376    #[test]
1377    fn test_monad_laws_present() {
1378        let mut env = make_env();
1379        register_vec_extended_axioms(&mut env);
1380        assert!(env.get(&Name::str("Vec.monad_left_id")).is_some());
1381        assert!(env.get(&Name::str("Vec.monad_right_id")).is_some());
1382        assert!(env.get(&Name::str("Vec.monad_assoc")).is_some());
1383    }
1384    #[test]
1385    fn test_applicative_laws_present() {
1386        let mut env = make_env();
1387        register_vec_extended_axioms(&mut env);
1388        assert!(env.get(&Name::str("Vec.ap_identity")).is_some());
1389        assert!(env.get(&Name::str("Vec.ap_homomorphism")).is_some());
1390        assert!(env.get(&Name::str("Vec.ap_interchange")).is_some());
1391        assert!(env.get(&Name::str("Vec.ap_composition")).is_some());
1392    }
1393    #[test]
1394    fn test_fold_laws_present() {
1395        let mut env = make_env();
1396        register_vec_extended_axioms(&mut env);
1397        assert!(env.get(&Name::str("Vec.foldr_nil")).is_some());
1398        assert!(env.get(&Name::str("Vec.foldr_cons")).is_some());
1399        assert!(env.get(&Name::str("Vec.foldl_nil")).is_some());
1400        assert!(env.get(&Name::str("Vec.foldl_cons")).is_some());
1401        assert!(env.get(&Name::str("Vec.foldl_foldr_duality")).is_some());
1402    }
1403    #[test]
1404    fn test_scan_laws_present() {
1405        let mut env = make_env();
1406        register_vec_extended_axioms(&mut env);
1407        assert!(env.get(&Name::str("Vec.scanl_nil")).is_some());
1408        assert!(env.get(&Name::str("Vec.scanl_cons")).is_some());
1409        assert!(env.get(&Name::str("Vec.scanr_nil")).is_some());
1410        assert!(env.get(&Name::str("Vec.scanr_cons")).is_some());
1411        assert!(env.get(&Name::str("Vec.scanl_last")).is_some());
1412    }
1413    #[test]
1414    fn test_sort_laws_present() {
1415        let mut env = make_env();
1416        register_vec_extended_axioms(&mut env);
1417        assert!(env.get(&Name::str("Vec.sort_is_permutation")).is_some());
1418        assert!(env.get(&Name::str("Vec.sort_is_sorted")).is_some());
1419        assert!(env
1420            .get(&Name::str("Vec.stable_sort_preserves_order"))
1421            .is_some());
1422        assert!(env.get(&Name::str("Vec.sort_idempotent")).is_some());
1423    }
1424    #[test]
1425    fn test_fusion_laws_present() {
1426        let mut env = make_env();
1427        register_vec_extended_axioms(&mut env);
1428        assert!(env.get(&Name::str("Vec.map_fusion")).is_some());
1429        assert!(env.get(&Name::str("Vec.filter_fusion")).is_some());
1430        assert!(env.get(&Name::str("Vec.map_filter_fusion")).is_some());
1431        assert!(env.get(&Name::str("Vec.fold_build_duality")).is_some());
1432    }
1433    #[test]
1434    fn test_fin_indexed_laws_present() {
1435        let mut env = make_env();
1436        register_vec_extended_axioms(&mut env);
1437        assert!(env.get(&Name::str("Vec.fin_index_get")).is_some());
1438        assert!(env.get(&Name::str("Vec.fin_index_set")).is_some());
1439        assert!(env
1440            .get(&Name::str("Vec.fin_map_preserves_length"))
1441            .is_some());
1442    }
1443    #[test]
1444    fn test_reverse_laws_present() {
1445        let mut env = make_env();
1446        register_vec_extended_axioms(&mut env);
1447        assert!(env.get(&Name::str("Vec.reverse_involutive")).is_some());
1448        assert!(env.get(&Name::str("Vec.reverse_append")).is_some());
1449        assert!(env.get(&Name::str("Vec.reverse_map")).is_some());
1450    }
1451    #[test]
1452    fn test_take_drop_laws_present() {
1453        let mut env = make_env();
1454        register_vec_extended_axioms(&mut env);
1455        assert!(env.get(&Name::str("Vec.take_drop_reconstruct")).is_some());
1456        assert!(env.get(&Name::str("Vec.take_length")).is_some());
1457        assert!(env.get(&Name::str("Vec.drop_length")).is_some());
1458    }
1459    #[test]
1460    fn test_zip_laws_present() {
1461        let mut env = make_env();
1462        register_vec_extended_axioms(&mut env);
1463        assert!(env.get(&Name::str("Vec.zip_length")).is_some());
1464        assert!(env.get(&Name::str("Vec.unzip_zip")).is_some());
1465        assert!(env.get(&Name::str("Vec.zip_map")).is_some());
1466    }
1467    #[test]
1468    fn test_chunking_laws_present() {
1469        let mut env = make_env();
1470        register_vec_extended_axioms(&mut env);
1471        assert!(env.get(&Name::str("Vec.chunks_flatten")).is_some());
1472        assert!(env.get(&Name::str("Vec.chunks_all_size")).is_some());
1473        assert!(env.get(&Name::str("Vec.chunks_count")).is_some());
1474    }
1475    #[test]
1476    fn test_free_monoid_laws_present() {
1477        let mut env = make_env();
1478        register_vec_extended_axioms(&mut env);
1479        assert!(env.get(&Name::str("Vec.append_nil_left")).is_some());
1480        assert!(env.get(&Name::str("Vec.append_nil_right")).is_some());
1481        assert!(env.get(&Name::str("Vec.append_assoc")).is_some());
1482        assert!(env.get(&Name::str("Vec.length_append")).is_some());
1483    }
1484    #[test]
1485    fn test_rotation_laws_present() {
1486        let mut env = make_env();
1487        register_vec_extended_axioms(&mut env);
1488        assert!(env
1489            .get(&Name::str("Vec.rotate_left_right_inverse"))
1490            .is_some());
1491        assert!(env.get(&Name::str("Vec.rotate_length")).is_some());
1492        assert!(env.get(&Name::str("Vec.rotate_zero")).is_some());
1493    }
1494    #[test]
1495    fn test_dlist_laws_present() {
1496        let mut env = make_env();
1497        register_vec_extended_axioms(&mut env);
1498        assert!(env.get(&Name::str("Vec.dlist_append_assoc")).is_some());
1499        assert!(env.get(&Name::str("Vec.dlist_to_list_preserves")).is_some());
1500    }
1501    #[test]
1502    fn test_concat_map_laws_present() {
1503        let mut env = make_env();
1504        register_vec_extended_axioms(&mut env);
1505        assert!(env.get(&Name::str("Vec.concat_map_id")).is_some());
1506        assert!(env.get(&Name::str("Vec.concat_map_assoc")).is_some());
1507        assert!(env.get(&Name::str("Vec.flatten_singleton")).is_some());
1508        assert!(env.get(&Name::str("Vec.flatten_map")).is_some());
1509    }
1510    #[test]
1511    fn test_span_partition_laws_present() {
1512        let mut env = make_env();
1513        register_vec_extended_axioms(&mut env);
1514        assert!(env.get(&Name::str("Vec.span_reconstruct")).is_some());
1515        assert!(env.get(&Name::str("Vec.partition_reconstruct")).is_some());
1516        assert!(env.get(&Name::str("Vec.groupBy_flatten")).is_some());
1517    }
1518    #[test]
1519    fn test_parallel_prefix_laws_present() {
1520        let mut env = make_env();
1521        register_vec_extended_axioms(&mut env);
1522        assert!(env.get(&Name::str("Vec.prefix_sum_correct")).is_some());
1523        assert!(env
1524            .get(&Name::str("Vec.parallel_prefix_sequential_equiv"))
1525            .is_some());
1526        assert!(env
1527            .get(&Name::str("Vec.fenwick_prefix_sum_correct"))
1528            .is_some());
1529    }
1530    #[test]
1531    fn test_rle_laws_present() {
1532        let mut env = make_env();
1533        register_vec_extended_axioms(&mut env);
1534        assert!(env.get(&Name::str("Vec.rle_decode_encode")).is_some());
1535        assert!(env.get(&Name::str("Vec.rle_length")).is_some());
1536    }
1537    #[test]
1538    fn test_matrix_laws_present() {
1539        let mut env = make_env();
1540        register_vec_extended_axioms(&mut env);
1541        assert!(env
1542            .get(&Name::str("Vec.matrix_transpose_involutive"))
1543            .is_some());
1544        assert!(env.get(&Name::str("Vec.matrix_row_count")).is_some());
1545        assert!(env.get(&Name::str("Vec.matrix_col_count")).is_some());
1546    }
1547    #[test]
1548    fn test_circular_buffer_basic() {
1549        let buf: CircularBuffer<i32> = CircularBuffer::new(8);
1550        assert_eq!(buf.capacity(), 8);
1551        assert!(buf.is_empty());
1552        assert!(!buf.is_full());
1553    }
1554    #[test]
1555    fn test_dlist_singleton_to_vec() {
1556        let d = DList::singleton(42i32);
1557        assert_eq!(d.to_vec(), vec![42]);
1558    }
1559    #[test]
1560    fn test_prefix_scan_inclusive() {
1561        let ps = PrefixScan::inclusive(vec![1, 3, 6, 10]);
1562        assert_eq!(ps.values(), &[1, 3, 6, 10]);
1563        assert!(ps.inclusive);
1564        assert_eq!(ps.len(), 4);
1565    }
1566    #[test]
1567    fn test_fenwick_tree_basic() {
1568        let mut ft = FenwickTree::new(5);
1569        ft.update(1, 3);
1570        ft.update(2, 2);
1571        ft.update(3, 7);
1572        assert_eq!(ft.query(1), 3);
1573        assert_eq!(ft.query(2), 5);
1574        assert_eq!(ft.query(3), 12);
1575    }
1576    #[test]
1577    fn test_sparse_vec_get_set() {
1578        let mut sv: SparseVec<i32> = SparseVec::new(10, 0);
1579        assert_eq!(*sv.get(5), 0);
1580        sv.set(5, 42);
1581        assert_eq!(*sv.get(5), 42);
1582        assert_eq!(*sv.get(3), 0);
1583        assert_eq!(sv.nnz(), 1);
1584    }
1585    #[test]
1586    fn test_all_35_plus_vec_axioms_registered() {
1587        let mut env = make_env();
1588        register_vec_extended_axioms(&mut env);
1589        let axiom_names = [
1590            "Vec.functor_map_id",
1591            "Vec.functor_map_comp",
1592            "Vec.monad_left_id",
1593            "Vec.monad_right_id",
1594            "Vec.monad_assoc",
1595            "Vec.ap_identity",
1596            "Vec.ap_homomorphism",
1597            "Vec.ap_interchange",
1598            "Vec.ap_composition",
1599            "Vec.foldr_nil",
1600            "Vec.foldr_cons",
1601            "Vec.foldl_nil",
1602            "Vec.foldl_cons",
1603            "Vec.foldl_foldr_duality",
1604            "Vec.scanl_nil",
1605            "Vec.scanl_cons",
1606            "Vec.scanr_nil",
1607            "Vec.scanr_cons",
1608            "Vec.scanl_last",
1609            "Vec.sort_is_permutation",
1610            "Vec.sort_is_sorted",
1611            "Vec.stable_sort_preserves_order",
1612            "Vec.sort_idempotent",
1613            "Vec.map_fusion",
1614            "Vec.filter_fusion",
1615            "Vec.map_filter_fusion",
1616            "Vec.fold_build_duality",
1617            "Vec.fin_index_get",
1618            "Vec.fin_index_set",
1619            "Vec.fin_map_preserves_length",
1620            "Vec.reverse_involutive",
1621            "Vec.reverse_append",
1622            "Vec.reverse_map",
1623            "Vec.take_drop_reconstruct",
1624            "Vec.take_length",
1625        ];
1626        let mut found = 0usize;
1627        for name in &axiom_names {
1628            if env.get(&Name::str(*name)).is_some() {
1629                found += 1;
1630            }
1631        }
1632        assert!(found >= 35, "Expected at least 35 axioms, found {}", found);
1633    }
1634}