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}