Skip to main content

oxilean_std/array/
functions_2.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
6
7use super::functions::*;
8
9/// `Array.prefix_sum_correct : ∀ {n}, Array Nat n → Prop`
10///
11/// Correctness of prefix sums: for all valid ranges [l, r],
12/// the range sum equals prefix[r] - prefix[l-1].
13#[allow(dead_code)]
14pub fn arr_ext_prefix_sum_correct_ty() -> Expr {
15    implicit_pi(
16        "n",
17        nat_ty(),
18        default_pi("arr", array_of(nat_ty(), Expr::BVar(0)), prop()),
19    )
20}
21/// `Array.diff_array : {α : Type} → {n : Nat} → Array α n → Array α n`
22///
23/// Difference array: for an array a, define d where d[0] = a[0],
24/// d[i] = a[i] - a[i-1]. Supports O(1) range update, O(n) reconstruction.
25#[allow(dead_code)]
26pub fn arr_ext_diff_array_ty() -> Expr {
27    implicit_pi(
28        "α",
29        type1(),
30        implicit_pi(
31            "n",
32            nat_ty(),
33            default_pi(
34                "arr",
35                array_of(Expr::BVar(1), Expr::BVar(0)),
36                array_of(Expr::BVar(2), Expr::BVar(1)),
37            ),
38        ),
39    )
40}
41/// `Array.sparse_table : {α : Type} → {n : Nat} → [Ord α] → Array α n → Type`
42///
43/// Sparse table for range-minimum queries (RMQ): precomputes answers for all
44/// power-of-2 length intervals in O(n log n) time, enabling O(1) RMQ.
45#[allow(dead_code)]
46pub fn arr_ext_sparse_table_ty() -> Expr {
47    implicit_pi(
48        "α",
49        type1(),
50        implicit_pi(
51            "n",
52            nat_ty(),
53            inst_pi(
54                "inst",
55                ord_of(Expr::BVar(1)),
56                default_pi("arr", array_of(Expr::BVar(2), Expr::BVar(1)), type1()),
57            ),
58        ),
59    )
60}
61/// `Array.rmq_correct : ∀ {α n}, [Ord α] → Array α n → Prop`
62///
63/// Range minimum query correctness: the sparse table answers RMQ queries
64/// correctly, returning the minimum element in the queried range.
65#[allow(dead_code)]
66pub fn arr_ext_rmq_correct_ty() -> Expr {
67    implicit_pi(
68        "α",
69        type1(),
70        implicit_pi(
71            "n",
72            nat_ty(),
73            inst_pi(
74                "inst",
75                ord_of(Expr::BVar(1)),
76                default_pi("arr", array_of(Expr::BVar(2), Expr::BVar(1)), prop()),
77            ),
78        ),
79    )
80}
81/// `Array2D : Type → Nat → Nat → Type`
82///
83/// A two-dimensional array of `rows × cols` elements of type `α`.
84#[allow(dead_code)]
85pub fn arr_ext_array2d_ty() -> Expr {
86    default_pi(
87        "α",
88        type1(),
89        default_pi("rows", nat_ty(), default_pi("cols", nat_ty(), type1())),
90    )
91}
92/// `Array2D.transpose : {α : Type} → {r c : Nat} → Array2D α r c → Array2D α c r`
93///
94/// Matrix transposition: swaps rows and columns. `transpose (transpose M) = M`.
95#[allow(dead_code)]
96pub fn arr_ext_transpose_ty() -> Expr {
97    implicit_pi(
98        "α",
99        type1(),
100        implicit_pi(
101            "r",
102            nat_ty(),
103            implicit_pi(
104                "c",
105                nat_ty(),
106                default_pi(
107                    "m",
108                    app3(
109                        Expr::Const(Name::str("Array2D"), vec![]),
110                        Expr::BVar(2),
111                        Expr::BVar(1),
112                        Expr::BVar(0),
113                    ),
114                    type1(),
115                ),
116            ),
117        ),
118    )
119}
120/// `Array.rotate_left : {α : Type} → {n : Nat} → Nat → Array α n → Array α n`
121///
122/// Left rotation by k positions: moves the first k elements to the end.
123/// `rotate_left 0 a = a`, `rotate_left n a = a`.
124#[allow(dead_code)]
125pub fn arr_ext_rotate_left_ty() -> Expr {
126    implicit_pi(
127        "α",
128        type1(),
129        implicit_pi(
130            "n",
131            nat_ty(),
132            default_pi(
133                "k",
134                nat_ty(),
135                default_pi(
136                    "arr",
137                    array_of(Expr::BVar(2), Expr::BVar(1)),
138                    array_of(Expr::BVar(3), Expr::BVar(2)),
139                ),
140            ),
141        ),
142    )
143}
144/// `Array.rotate_right : {α : Type} → {n : Nat} → Nat → Array α n → Array α n`
145///
146/// Right rotation by k positions: moves the last k elements to the front.
147/// Right and left rotations are inverses.
148#[allow(dead_code)]
149pub fn arr_ext_rotate_right_ty() -> Expr {
150    implicit_pi(
151        "α",
152        type1(),
153        implicit_pi(
154            "n",
155            nat_ty(),
156            default_pi(
157                "k",
158                nat_ty(),
159                default_pi(
160                    "arr",
161                    array_of(Expr::BVar(2), Expr::BVar(1)),
162                    array_of(Expr::BVar(3), Expr::BVar(2)),
163                ),
164            ),
165        ),
166    )
167}
168/// `Array.rotate_inverse : ∀ {α n k}, Array α n → Prop`
169///
170/// Rotation inverse law: `rotate_right k (rotate_left k a) = a` and
171/// `rotate_left k (rotate_right k a) = a`.
172#[allow(dead_code)]
173pub fn arr_ext_rotate_inverse_ty() -> Expr {
174    implicit_pi(
175        "α",
176        type1(),
177        implicit_pi(
178            "n",
179            nat_ty(),
180            implicit_pi(
181                "k",
182                nat_ty(),
183                default_pi("arr", array_of(Expr::BVar(2), Expr::BVar(1)), prop()),
184            ),
185        ),
186    )
187}
188/// `Array.suffix_array : {n : Nat} → Array Nat n → Array Nat n`
189///
190/// Suffix array construction: given a string (represented as an array of
191/// character codes), compute the lexicographically sorted array of suffix start
192/// indices. Used in O(n log n) string matching algorithms.
193#[allow(dead_code)]
194pub fn arr_ext_suffix_array_ty() -> Expr {
195    implicit_pi(
196        "n",
197        nat_ty(),
198        default_pi(
199            "str",
200            array_of(nat_ty(), Expr::BVar(0)),
201            array_of(nat_ty(), Expr::BVar(1)),
202        ),
203    )
204}
205/// `Array.suffix_array_correct : ∀ {n}, Array Nat n → Prop`
206///
207/// Suffix array correctness: the suffix array SA is a permutation of [0..n)
208/// such that the suffixes str[SA[i]..] are in strictly increasing lexicographic order.
209#[allow(dead_code)]
210pub fn arr_ext_suffix_array_correct_ty() -> Expr {
211    implicit_pi(
212        "n",
213        nat_ty(),
214        default_pi("str", array_of(nat_ty(), Expr::BVar(0)), prop()),
215    )
216}
217/// `Array.convolution : {n : Nat} → Array Nat n → Array Nat n → Array Nat n`
218///
219/// Discrete convolution of two length-n sequences. The FFT-based algorithm
220/// computes this in O(n log n) time versus the naive O(n²).
221#[allow(dead_code)]
222pub fn arr_ext_convolution_ty() -> Expr {
223    implicit_pi(
224        "n",
225        nat_ty(),
226        default_pi(
227            "a",
228            array_of(nat_ty(), Expr::BVar(0)),
229            default_pi(
230                "b",
231                array_of(nat_ty(), Expr::BVar(1)),
232                array_of(nat_ty(), Expr::BVar(2)),
233            ),
234        ),
235    )
236}
237/// `Array.fft_conv_correct : ∀ {n}, Array Nat n → Array Nat n → Prop`
238///
239/// FFT convolution correctness: the fast convolution result equals the
240/// naive pointwise convolution result.
241#[allow(dead_code)]
242pub fn arr_ext_fft_conv_correct_ty() -> Expr {
243    implicit_pi(
244        "n",
245        nat_ty(),
246        default_pi(
247            "a",
248            array_of(nat_ty(), Expr::BVar(0)),
249            default_pi("b", array_of(nat_ty(), Expr::BVar(1)), prop()),
250        ),
251    )
252}
253/// `PersistentArray : Type → Nat → Type`
254///
255/// A persistent (purely functional) array: all versions of the array are
256/// accessible after updates. Implemented via balanced binary trees or path
257/// copying, supporting O(log n) access and update.
258#[allow(dead_code)]
259pub fn arr_ext_persistent_array_ty() -> Expr {
260    default_pi("α", type1(), default_pi("n", nat_ty(), type1()))
261}
262/// `PersistentArray.get : {α : Type} → {n : Nat} → PersistentArray α n → Fin n → α`
263///
264/// Persistent array lookup: O(log n) access without mutation.
265#[allow(dead_code)]
266pub fn arr_ext_persistent_get_ty() -> Expr {
267    implicit_pi(
268        "α",
269        type1(),
270        implicit_pi(
271            "n",
272            nat_ty(),
273            default_pi(
274                "pa",
275                app2(
276                    Expr::Const(Name::str("PersistentArray"), vec![]),
277                    Expr::BVar(1),
278                    Expr::BVar(0),
279                ),
280                default_pi("i", fin_of(Expr::BVar(1)), Expr::BVar(3)),
281            ),
282        ),
283    )
284}
285/// `PersistentArray.set : {α : Type} → {n : Nat} → PersistentArray α n → Fin n → α → PersistentArray α n`
286///
287/// Persistent array update: returns a new version with updated element at
288/// index i; original version is unaffected (path copying).
289#[allow(dead_code)]
290pub fn arr_ext_persistent_set_ty() -> Expr {
291    implicit_pi(
292        "α",
293        type1(),
294        implicit_pi(
295            "n",
296            nat_ty(),
297            default_pi(
298                "pa",
299                app2(
300                    Expr::Const(Name::str("PersistentArray"), vec![]),
301                    Expr::BVar(1),
302                    Expr::BVar(0),
303                ),
304                default_pi(
305                    "i",
306                    fin_of(Expr::BVar(1)),
307                    default_pi(
308                        "v",
309                        Expr::BVar(3),
310                        app2(
311                            Expr::Const(Name::str("PersistentArray"), vec![]),
312                            Expr::BVar(4),
313                            Expr::BVar(3),
314                        ),
315                    ),
316                ),
317            ),
318        ),
319    )
320}
321/// `Array.chunksOf : {α : Type} → {n : Nat} → Nat → Array α n → List (List α)`
322///
323/// Split an array into consecutive chunks of size k. The last chunk may be
324/// smaller if n is not divisible by k. Used in SIMD/vectorization.
325#[allow(dead_code)]
326pub fn arr_ext_chunks_of_ty() -> Expr {
327    implicit_pi(
328        "α",
329        type1(),
330        implicit_pi(
331            "n",
332            nat_ty(),
333            default_pi(
334                "k",
335                nat_ty(),
336                default_pi(
337                    "arr",
338                    array_of(Expr::BVar(2), Expr::BVar(1)),
339                    list_of(list_of(Expr::BVar(3))),
340                ),
341            ),
342        ),
343    )
344}
345/// `Array.chunks_cover : ∀ {α n k}, Array α n → Prop`
346///
347/// Coverage property of chunking: concatenating all chunks yields the original
348/// array. `concat (chunksOf k a) = toList a`.
349#[allow(dead_code)]
350pub fn arr_ext_chunks_cover_ty() -> Expr {
351    implicit_pi(
352        "α",
353        type1(),
354        implicit_pi(
355            "n",
356            nat_ty(),
357            implicit_pi(
358                "k",
359                nat_ty(),
360                default_pi("arr", array_of(Expr::BVar(2), Expr::BVar(1)), prop()),
361            ),
362        ),
363    )
364}
365/// `Array.par_map : {α β : Type} → {n : Nat} → (α → β) → Array α n → Array β n`
366///
367/// Parallel array map: conceptually applies f to each element concurrently.
368/// The result is identical to sequential map; only execution is parallel.
369#[allow(dead_code)]
370pub fn arr_ext_par_map_ty() -> Expr {
371    implicit_pi(
372        "α",
373        type1(),
374        implicit_pi(
375            "β",
376            type1(),
377            implicit_pi(
378                "n",
379                nat_ty(),
380                default_pi(
381                    "f",
382                    arrow(Expr::BVar(2), Expr::BVar(1)),
383                    default_pi(
384                        "arr",
385                        array_of(Expr::BVar(3), Expr::BVar(1)),
386                        array_of(Expr::BVar(3), Expr::BVar(2)),
387                    ),
388                ),
389            ),
390        ),
391    )
392}
393/// `Array.par_map_correct : ∀ {α β n}, (α → β) → Array α n → Prop`
394///
395/// Correctness of parallel map: `par_map f a = map f a`.
396/// The parallel execution produces identical results to sequential mapping.
397#[allow(dead_code)]
398pub fn arr_ext_par_map_correct_ty() -> Expr {
399    implicit_pi(
400        "α",
401        type1(),
402        implicit_pi(
403            "β",
404            type1(),
405            implicit_pi(
406                "n",
407                nat_ty(),
408                default_pi(
409                    "f",
410                    arrow(Expr::BVar(2), Expr::BVar(1)),
411                    default_pi("arr", array_of(Expr::BVar(3), Expr::BVar(1)), prop()),
412                ),
413            ),
414        ),
415    )
416}
417/// `Array.par_reduce : {α : Type} → {n : Nat} → (α → α → α) → α → Array α n → α`
418///
419/// Parallel reduction: applies an associative binary operator to reduce an
420/// array to a single value in O(log n) parallel time.
421#[allow(dead_code)]
422pub fn arr_ext_par_reduce_ty() -> Expr {
423    implicit_pi(
424        "α",
425        type1(),
426        implicit_pi(
427            "n",
428            nat_ty(),
429            default_pi(
430                "op",
431                arrow(Expr::BVar(1), arrow(Expr::BVar(2), Expr::BVar(2))),
432                default_pi(
433                    "init",
434                    Expr::BVar(2),
435                    default_pi("arr", array_of(Expr::BVar(3), Expr::BVar(2)), Expr::BVar(4)),
436                ),
437            ),
438        ),
439    )
440}
441/// `Array.scan_left : {α β : Type} → {n : Nat} → (β → α → β) → β → Array α n → Array β (n+1)`
442///
443/// Left scan (prefix scan): produces an array of prefix reductions.
444/// `scan_left f z [a0, a1, ..., an-1] = [z, f z a0, f (f z a0) a1, ...]`.
445#[allow(dead_code)]
446pub fn arr_ext_scan_left_ty() -> Expr {
447    implicit_pi(
448        "α",
449        type1(),
450        implicit_pi(
451            "β",
452            type1(),
453            implicit_pi(
454                "n",
455                nat_ty(),
456                default_pi(
457                    "f",
458                    arrow(Expr::BVar(1), arrow(Expr::BVar(3), Expr::BVar(2))),
459                    default_pi(
460                        "init",
461                        Expr::BVar(2),
462                        default_pi(
463                            "arr",
464                            array_of(Expr::BVar(4), Expr::BVar(2)),
465                            array_of(Expr::BVar(4), nat_succ(Expr::BVar(3))),
466                        ),
467                    ),
468                ),
469            ),
470        ),
471    )
472}
473/// `Array.map_fuse : ∀ {α β γ n}, (β → γ) → (α → β) → Array α n → Prop`
474///
475/// Map fusion law: two consecutive maps can be fused into one pass.
476/// `map g (map f a) = map (g ∘ f) a`. This enables loop fusion optimization.
477#[allow(dead_code)]
478pub fn arr_ext_map_fuse_ty() -> Expr {
479    implicit_pi(
480        "α",
481        type1(),
482        implicit_pi(
483            "β",
484            type1(),
485            implicit_pi(
486                "γ",
487                type1(),
488                implicit_pi(
489                    "n",
490                    nat_ty(),
491                    default_pi(
492                        "g",
493                        arrow(Expr::BVar(2), Expr::BVar(1)),
494                        default_pi(
495                            "f",
496                            arrow(Expr::BVar(4), Expr::BVar(3)),
497                            default_pi("arr", array_of(Expr::BVar(5), Expr::BVar(2)), prop()),
498                        ),
499                    ),
500                ),
501            ),
502        ),
503    )
504}
505/// `Array.filter_map_fuse : ∀ {α β n}, (α → Option β) → Array α n → Prop`
506///
507/// filterMap fusion: applying filterMap (a combined filter and map) is equivalent
508/// to first mapping then filtering, but in a single pass.
509#[allow(dead_code)]
510pub fn arr_ext_filter_map_fuse_ty() -> Expr {
511    implicit_pi(
512        "α",
513        type1(),
514        implicit_pi(
515            "β",
516            type1(),
517            implicit_pi(
518                "n",
519                nat_ty(),
520                default_pi(
521                    "f",
522                    arrow(Expr::BVar(2), option_of(Expr::BVar(1))),
523                    default_pi("arr", array_of(Expr::BVar(3), Expr::BVar(1)), prop()),
524                ),
525            ),
526        ),
527    )
528}
529/// `Array.fold_map_fuse : ∀ {α β γ n}, (β → γ → γ) → γ → (α → β) → Array α n → Prop`
530///
531/// Fold-map fusion: `foldl g z (map f a) = foldl (λacc x, g acc (f x)) z a`.
532/// Avoids constructing the intermediate mapped array.
533#[allow(dead_code)]
534pub fn arr_ext_fold_map_fuse_ty() -> Expr {
535    implicit_pi(
536        "α",
537        type1(),
538        implicit_pi(
539            "β",
540            type1(),
541            implicit_pi(
542                "γ",
543                type1(),
544                implicit_pi(
545                    "n",
546                    nat_ty(),
547                    default_pi(
548                        "g",
549                        arrow(Expr::BVar(2), arrow(Expr::BVar(2), Expr::BVar(2))),
550                        default_pi(
551                            "z",
552                            Expr::BVar(3),
553                            default_pi(
554                                "f",
555                                arrow(Expr::BVar(5), Expr::BVar(4)),
556                                default_pi("arr", array_of(Expr::BVar(6), Expr::BVar(3)), prop()),
557                            ),
558                        ),
559                    ),
560                ),
561            ),
562        ),
563    )
564}
565/// Register all extended array axioms into the kernel environment.
566///
567/// This adds axioms for: functor/monad laws, sort stability, reverse involution,
568/// append laws, slices, prefix sums, 2D arrays, rotation, suffix arrays,
569/// convolution, persistent arrays, chunking, parallel map, and fusion laws.
570pub fn register_array_extended(env: &mut Environment) -> Result<(), String> {
571    let axioms: &[(&str, Expr)] = &[
572        ("Array.map_id", arr_ext_map_id_ty()),
573        ("Array.map_comp", arr_ext_map_comp_ty()),
574        ("Array.pure_map_size", arr_ext_pure_map_size_ty()),
575        ("Array.bind_assoc", arr_ext_bind_assoc_ty()),
576        ("Array.mergesort", arr_ext_mergesort_ty()),
577        ("Array.sort_stable", arr_ext_sort_stable_ty()),
578        ("Array.sort_perm", arr_ext_sort_perm_ty()),
579        ("Array.sort_sorted", arr_ext_sort_sorted_ty()),
580        ("Array.qsort_average_case", arr_ext_qsort_avg_ty()),
581        ("Array.reverse_involution", arr_ext_reverse_involution_ty()),
582        ("Array.reverse_size", arr_ext_reverse_size_ty()),
583        ("Array.append_assoc", arr_ext_append_assoc_ty()),
584        ("Array.append_empty_left", arr_ext_append_empty_left_ty()),
585        ("Array.append_empty_right", arr_ext_append_empty_right_ty()),
586        ("Array.append_size", arr_ext_append_size_ty()),
587        ("Array.slice", arr_ext_slice_ty()),
588        ("Array.prefix_sum", arr_ext_prefix_sum_ty()),
589        ("Array.prefix_sum_correct", arr_ext_prefix_sum_correct_ty()),
590        ("Array.diff_array", arr_ext_diff_array_ty()),
591        ("Array.sparse_table", arr_ext_sparse_table_ty()),
592        ("Array.rmq_correct", arr_ext_rmq_correct_ty()),
593        ("Array2D", arr_ext_array2d_ty()),
594        ("Array2D.transpose", arr_ext_transpose_ty()),
595        ("Array.rotate_left", arr_ext_rotate_left_ty()),
596        ("Array.rotate_right", arr_ext_rotate_right_ty()),
597        ("Array.rotate_inverse", arr_ext_rotate_inverse_ty()),
598        ("Array.suffix_array", arr_ext_suffix_array_ty()),
599        (
600            "Array.suffix_array_correct",
601            arr_ext_suffix_array_correct_ty(),
602        ),
603        ("Array.convolution", arr_ext_convolution_ty()),
604        ("Array.fft_conv_correct", arr_ext_fft_conv_correct_ty()),
605        ("PersistentArray", arr_ext_persistent_array_ty()),
606        ("PersistentArray.get", arr_ext_persistent_get_ty()),
607        ("PersistentArray.set", arr_ext_persistent_set_ty()),
608        ("Array.chunksOf", arr_ext_chunks_of_ty()),
609        ("Array.chunks_cover", arr_ext_chunks_cover_ty()),
610        ("Array.par_map", arr_ext_par_map_ty()),
611        ("Array.par_map_correct", arr_ext_par_map_correct_ty()),
612        ("Array.par_reduce", arr_ext_par_reduce_ty()),
613        ("Array.scan_left", arr_ext_scan_left_ty()),
614        ("Array.map_fuse", arr_ext_map_fuse_ty()),
615        ("Array.filter_map_fuse", arr_ext_filter_map_fuse_ty()),
616        ("Array.fold_map_fuse", arr_ext_fold_map_fuse_ty()),
617    ];
618    for (name, ty) in axioms {
619        env.add(Declaration::Axiom {
620            name: Name::str(*name),
621            univ_params: vec![],
622            ty: ty.clone(),
623        })
624        .ok();
625    }
626    Ok(())
627}
628/// Merge sort implementation on a mutable slice.
629///
630/// Returns a sorted copy of the input using stable merge sort.
631///
632/// # Example
633/// ```
634/// # use oxilean_std::array::merge_sort;
635/// let sorted = merge_sort(&[3, 1, 4, 1, 5, 9, 2, 6]);
636/// assert_eq!(sorted, vec![1, 1, 2, 3, 4, 5, 6, 9]);
637/// ```
638#[allow(dead_code)]
639pub fn merge_sort(data: &[i64]) -> Vec<i64> {
640    if data.len() <= 1 {
641        return data.to_vec();
642    }
643    let mid = data.len() / 2;
644    let left = merge_sort(&data[..mid]);
645    let right = merge_sort(&data[mid..]);
646    let mut result = Vec::with_capacity(data.len());
647    let (mut i, mut j) = (0, 0);
648    while i < left.len() && j < right.len() {
649        if left[i] <= right[j] {
650            result.push(left[i]);
651            i += 1;
652        } else {
653            result.push(right[j]);
654            j += 1;
655        }
656    }
657    result.extend_from_slice(&left[i..]);
658    result.extend_from_slice(&right[j..]);
659    result
660}