core_models/abstractions/
funarr.rs1#[hax_lib::fstar::replace(
11 r#"
12open FStar.FunctionalExtensionality
13noeq type t_FunArray (n: u64) (t: Type0) = | FunArray : (i:u64 {v i < v n} ^-> t) -> t_FunArray n t
14
15let ${FunArray::<0, ()>::get} (v_N: u64) (#v_T: Type0) (self: t_FunArray v_N v_T) (i: u64 {v i < v v_N}) : v_T =
16 self._0 i
17
18let ${FunArray::<0, ()>::from_fn::<fn(u64)->()>}
19 (v_N: u64)
20 (#v_T: Type0)
21 (f: (i: u64 {v i < v v_N}) -> v_T)
22 : t_FunArray v_N v_T = FunArray (on (i: u64 {v i < v v_N}) f)
23
24let ${FunArray::<0, ()>::as_vec} n #t (self: t_FunArray n t) = FStar.Seq.init (v n) (fun i -> self._0 (mk_u64 i))
25
26let rec ${FunArray::<0, ()>::fold::<()>} n #t #a (arr: t_FunArray n t) (init: a) (f: a -> t -> a): Tot a (decreases (v n)) =
27 match n with
28 | MkInt 0 -> init
29 | MkInt n ->
30 let acc: a = f init (arr._0 (mk_u64 0)) in
31 let n = MkInt (n - 1) in
32 ${FunArray::<0, ()>::fold::<()>} n #t #a
33 (${FunArray::<0, ()>::from_fn::<fn(u64)->()>} n (fun i -> arr._0 (i +. mk_u64 1)))
34 acc f
35"#
36)]
37#[derive(Copy, Clone, Eq, PartialEq)]
38pub struct FunArray<const N: u64, T>([Option<T>; 512]);
39
40#[hax_lib::exclude]
41impl<const N: u64, T> FunArray<N, T> {
42 pub fn get(&self, i: u64) -> &T {
44 self.0[i as usize].as_ref().unwrap()
45 }
46 pub fn from_fn<F: Fn(u64) -> T>(f: F) -> Self {
48 let arr = core::array::from_fn(|i| {
50 if (i as u64) < N {
51 Some(f(i as u64))
52 } else {
53 None
54 }
55 });
56 Self(arr)
57 }
58
59 pub fn as_vec(&self) -> Vec<T>
61 where
62 T: Clone,
63 {
64 self.0[0..(N as usize)]
65 .iter()
66 .cloned()
67 .map(|x| x.unwrap())
68 .collect()
69 }
70
71 pub fn fold<A>(&self, mut init: A, f: fn(A, T) -> A) -> A
77 where
78 T: Clone,
79 {
80 for i in 0..N {
81 init = f(init, self[i].clone());
82 }
83 init
84 }
85}
86
87macro_rules! impl_pointwise {
88 ($n:literal, $($i:literal)*) => {
89 impl<T: Copy> FunArray<$n, T> {
90 pub fn pointwise(self) -> Self {
91 Self::from_fn(|i| match i {
92 $($i => self[$i],)*
93 _ => unreachable!(),
94 })
95 }
96 }
97 };
98}
99
100impl_pointwise!(4, 0 1 2 3);
101impl_pointwise!(8, 0 1 2 3 4 5 6 7);
102impl_pointwise!(16, 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15);
103
104#[hax_lib::exclude]
105impl<const N: u64, T: Clone> TryFrom<Vec<T>> for FunArray<N, T> {
106 type Error = ();
107 fn try_from(v: Vec<T>) -> Result<Self, ()> {
108 if (v.len() as u64) < N {
109 Err(())
110 } else {
111 Ok(Self::from_fn(|i| v[i as usize].clone()))
112 }
113 }
114}
115
116#[hax_lib::exclude]
117impl<const N: u64, T: core::fmt::Debug + Clone> core::fmt::Debug for FunArray<N, T> {
118 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119 write!(f, "{:?}", self.as_vec())
120 }
121}
122
123#[hax_lib::attributes]
124impl<const N: u64, T> core::ops::Index<u64> for FunArray<N, T> {
125 type Output = T;
126 #[requires(index < N)]
127 fn index(&self, index: u64) -> &Self::Output {
128 self.get(index)
129 }
130}