Skip to content

Commit 65ac0be

Browse files
committed
More results on lists (take/drop) and bit-encoding (bs2int/chunk)
1 parent 5775739 commit 65ac0be

File tree

2 files changed

+179
-3
lines changed

2 files changed

+179
-3
lines changed

theories/datatypes/BitEncoding.ec

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,6 @@ proof.
235235
by rewrite addrAC.
236236
qed.
237237

238-
(*-----------------------------------------------------------------------------*)
239238
lemma bs2int_cat s1 s2 :
240239
bs2int (s1 ++ s2) = bs2int s1 + (2 ^ (size s1)) * bs2int s2.
241240
proof.
@@ -244,6 +243,47 @@ proof.
244243
by rewrite exprD_nneg ?size_ge0.
245244
qed.
246245

246+
lemma bs2intD (s1 s2 : bool list) (i : int) :
247+
i = size s1 => bs2int s1 + (2 ^ i) * bs2int s2 = bs2int (s1 ++ s2).
248+
proof. by move=> ->; apply/eq_sym/bs2int_cat. qed.
249+
250+
lemma bs2int_take_drop (i : int) (s : bool list) :
251+
0 <= i => bs2int s = bs2int (take i s) + 2 ^ i * bs2int (drop i s).
252+
proof.
253+
move=> ge0_i; case: (i < size s); last first.
254+
- move=> /lezNgt lei; rewrite drop_oversize //.
255+
by rewrite bs2int_nil /= take_oversize.
256+
move=> ltis; rewrite -{1}[s](@cat_take_drop i) bs2int_cat.
257+
by rewrite size_take 1?ltis.
258+
qed.
259+
260+
lemma bs2int_div (i : int) (s : bool list) :
261+
0 <= i => bs2int s %/ 2^i = bs2int (drop i s).
262+
proof.
263+
move=> ge0_i; rewrite (@bs2int_take_drop i) //.
264+
rewrite mulrC divzMDr 1:expf_eq0 // pdiv_small //.
265+
rewrite bs2int_ge0 /= &(ltr_le_trans (2 ^ (size (take i s)))).
266+
- by apply/bs2int_le2Xs.
267+
- by rewrite &(ler_weexpn2l) //= size_ge0 /= &(size_take_le).
268+
qed.
269+
270+
lemma bs2int_mod (s : bool list) (i : int) :
271+
0 <= i => bs2int s %% 2^i = bs2int (take i s).
272+
proof.
273+
move=> ge0_i; rewrite (@bs2int_take_drop i) //.
274+
rewrite mulrC modzMDr pmod_small // bs2int_ge0 /=.
275+
apply/(ltr_le_trans (2 ^ (size (take i s)))).
276+
- by apply/bs2int_le2Xs.
277+
- by rewrite &(ler_weexpn2l) //= size_ge0 /= &(size_take_le).
278+
qed.
279+
280+
lemma inj_bs2int_eqsize (s1 s2 : bool list) :
281+
size s1 = size s2 => bs2int s1 = bs2int s2 => s1 = s2.
282+
proof.
283+
elim: s1 s2 => [|x1 s1 ih] [|x2 s2] //=; ~-1:smt(size_ge0).
284+
by move/addzI => eq_sz /=; rewrite !bs2int_cons /#.
285+
qed.
286+
247287
lemma bs2int_range s :
248288
bs2int s \in range 0 (2 ^ size s).
249289
proof. by apply/mem_range; split; [apply bs2int_ge0|move => _; apply bs2int_le2Xs]. qed.
@@ -276,7 +316,6 @@ proof. by rewrite bs2int_cat bs2int_nseq_false size_nseq. qed.
276316
lemma bs2int_pow2 K N :
277317
bs2int (nseq K false ++ true :: nseq N false) = 2 ^ max 0 K.
278318
proof. by rewrite bs2int_mulr_pow2 bs2int1. qed.
279-
280319
end BS2Int.
281320

282321

@@ -611,6 +650,14 @@ rewrite ler_maxr 1:subr_ge0 1:-subr_ge0 1:(ler_trans r) ?ge0_r //.
611650
by move/ler_eqVlt: ler=> [<-|->].
612651
qed.
613652
653+
lemma size_nth_chunk ['a] (x0 : 'a list) (s : 'a list) (i n : int) :
654+
0 <= n => 0 <= i < (size s) %/ n => size (nth x0 (chunk n s) i) = n.
655+
proof.
656+
move/lez_eqVlt => [<<- //|]; first by rewrite divz0 /#.
657+
move=> gt0_n rgi; apply: (@in_chunk_size n s) => //.
658+
by rewrite mem_nth size_chunk.
659+
qed.
660+
614661
lemma size_flatten_chunk r (bs : 'a list) : 0 < r =>
615662
size (flatten (chunk r bs)) = (size bs) %/ r * r.
616663
proof.
@@ -669,4 +716,30 @@ rewrite size_drop ?mulr_ge0 // 1:ltrW // szxs -mulrBl.
669716
rewrite ler_maxr ?mulr_ge0 1,2:ltrW ?subr_gt0 ?ler_pmull //.
670717
by rewrite ler_subr_addl -ltzE.
671718
qed.
719+
720+
lemma inj_chunk ['a] (n : int) (s1 s2 : 'a list) :
721+
0 < n => n %| size s1 => n %| size s2 => chunk n s1 = chunk n s2 => s1 = s2.
722+
proof.
723+
move=> gt0_n dvd1 dvd2 ^ /(congr1 List.size).
724+
rewrite !size_chunk //; move: dvd1 dvd2.
725+
move=> /dvdzP[q] ^sz1E -> /dvdzP[q'] ^sz2E ->.
726+
rewrite !mulzK ~-1:gtr_eqF // => <<- @/chunk.
727+
rewrite sz1E sz2E mulzK 1:gtr_eqF //.
728+
elim/natind: q s1 s2 sz1E sz2E => [q ge0_q|q ge0_q ih] /=.
729+
- smt(size_ge0 size_eq0).
730+
move=> s1 s2; rewrite mulzDl /= [_ + n]addrC => szE1 szE2.
731+
have := size_eqD _ _ _ _ _ szE1; ~-1: move=> //#.
732+
have := size_eqD _ _ _ _ _ szE2; ~-1: move=> //#.
733+
case=> [s1a s1b] [# sz1a sz1b ->] [s2a s2b] [# sz2a sz2b ->].
734+
rewrite !mkseqSr /(\o) //= !drop0 !take_catl ?(sz1a, sz2a) //.
735+
rewrite !take_oversize ?(sz1a, sz2a) // => -[<-].
736+
move=> eq_tl; congr; apply: ih => //.
737+
apply: (eq_trans _ _ (eq_trans _ eq_tl _)).
738+
- apply: eq_in_mkseq => i rgi /=; rewrite mulzDr /=.
739+
rewrite [n+_]addrC -drop_drop ~-1://#.
740+
by rewrite drop_catr ?sz2a //= drop0.
741+
- apply: eq_in_mkseq => i rgi /=; rewrite mulzDr /=.
742+
rewrite [n+_]addrC -drop_drop ~-1://#.
743+
by rewrite drop_catr ?sz2a //= drop0.
744+
qed.
672745
end BitChunking.

theories/datatypes/List.ec

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,14 @@ rewrite drop_cat lez_eqVlt; case: (n = size s1) => [->|] //=.
827827
by rewrite drop0 drop_size.
828828
qed.
829829
830+
lemma drop_catl ['a] (s1 s2 : 'a list) (i : int) :
831+
i <= size s1 => drop i (s1 ++ s2) = drop i s1 ++ s2.
832+
proof. by move=> ?; rewrite drop_cat_le iftrue. qed.
833+
834+
lemma drop_catr ['a] (s1 s2 : 'a list) (i : int) :
835+
size s1 <= i => drop i (s1 ++ s2) = drop (i - size s1) s2.
836+
proof. by move=> ?; rewrite drop_cat iffalse // ltzNge. qed.
837+
830838
lemma drop_size_cat n (s1 s2 : 'a list):
831839
size s1 = n => drop n (s1 ++ s2) = s2.
832840
proof. by move=> <-; rewrite drop_cat subzz ltzz drop0. qed.
@@ -902,6 +910,14 @@ rewrite take_cat lez_eqVlt; case: (n = size s1) => [->|] //=.
902910
by rewrite take0 take_size cats0.
903911
qed.
904912
913+
lemma take_catl ['a] (s1 s2 : 'a list) (i : int) :
914+
i <= size s1 => take i (s1 ++ s2) = take i s1.
915+
proof. by move=> ?; rewrite take_cat_le iftrue. qed.
916+
917+
lemma take_catr ['a] (s1 s2 : 'a list) (i : int) :
918+
size s1 <= i => take i (s1 ++ s2) = s1 ++ take (i - size s1) s2.
919+
proof. by move=> ?; rewrite take_cat iffalse // ltzNge. qed.
920+
905921
lemma take_size_cat n (s1 s2 : 'a list):
906922
size s1 = n => take n (s1 ++ s2) = s1.
907923
proof. by move=> <-; rewrite take_cat subzz ltzz take0 cats0. qed.
@@ -916,6 +932,37 @@ qed.
916932
lemma cat_take_drop n (s : 'a list): take n s ++ drop n s = s.
917933
proof. by elim: s n=> /#. qed.
918934

935+
lemma takeD ['a] (s : 'a list) (i j : int) :
936+
0 <= i => 0 <= j => take (i + j) s = take i s ++ take j (drop i s).
937+
proof.
938+
move=> ge0_i ge0_j; case: (size s <= i) => [sz_le|/ltzNge sz_lt].
939+
- by rewrite drop_oversize //= cats0 !take_oversize //#.
940+
rewrite -{1}[s](cat_take_drop i) take_cat.
941+
by rewrite size_take // sz_lt /= iffalse 1:/# addrAC.
942+
qed.
943+
944+
lemma size_eqD ['a] (m n : int) (s : 'a list) :
945+
0 <= m => 0 <= n => size s = m + n =>
946+
exists s1 s2, (size s1 = m /\ size s2 = n) /\ s = s1 ++ s2.
947+
proof.
948+
move=> ge0_m ge0_n szs; exists (take m s) (drop m s).
949+
by rewrite cat_take_drop /= !(size_take, size_drop) //#.
950+
qed.
951+
952+
lemma drop_take ['a] (s : 'a list) (i j : int) :
953+
0 <= i => 0 <= j => drop i (take j s) = take (j-i) (drop i s).
954+
proof.
955+
move=> ge0_i ge0_j; case: (j < i) => [lt_ji|/lezNgt le_ij].
956+
- rewrite (take_le0 (j-i)) 1:/# drop_oversize //.
957+
by apply/(lez_trans j)/ltzW => //; apply/size_take_le.
958+
case: (i < size s) => [lti|]; last first.
959+
- move=> /lezNgt lei; rewrite !drop_oversize //=.
960+
by rewrite &(lez_trans _ _ _ _ lei) size_take //#.
961+
rewrite {1}(_ : j = i + (j - i)) 1:addzCA //.
962+
rewrite takeD ~-1://# drop_catr // 1:&(size_take_le) //.
963+
by rewrite drop_le0 // size_take // lti.
964+
qed.
965+
919966
lemma mem_drop n (s:'a list) x: mem (drop n s) x => mem s x.
920967
proof. by rewrite -{2}[s](cat_take_drop n) mem_cat=>->. qed.
921968
@@ -951,6 +998,14 @@ move=> i [ge0_i lti]; rewrite nth_cat size_take //= lt_n_s /=.
951998
smt(nth_take nth_drop).
952999
qed.
9531000

1001+
lemma drop_take1_nth ['a] (x0 : 'a) (s : 'a list) (i : int) :
1002+
0 <= i < size s => take 1 (drop i s) = [nth x0 s i].
1003+
proof.
1004+
move=> [ge0_i lti]; rewrite -{1}[s](cat_take_insert_drop x0 i) //.
1005+
rewrite drop_cat_le size_take // lti /=.
1006+
by rewrite drop_oversize 1:size_take // 1:lti //= take0.
1007+
qed.
1008+
9541009
lemma splitPr (xs : 'a list) (x : 'a): mem xs x =>
9551010
exists s1, exists s2, xs = s1 ++ x :: s2.
9561011
proof.
@@ -2548,9 +2603,14 @@ lemma mkseqS f n : 0 <= n =>
25482603
mkseq<:'a> f (n + 1) = rcons (mkseq f n) (f n).
25492604
proof. by move=> ge0_n; rewrite /mkseq iotaSr //= map_rcons. qed.
25502605
2551-
lemma mkseqSr ['a] (f : int -> 'a) n : 0 <= n => mkseq f (n + 1) = f 0 :: mkseq (f \o ((+)%Int 1)) n.
2606+
lemma mkseqSr ['a] (f : int -> 'a) n : 0 <= n =>
2607+
mkseq f (n + 1) = f 0 :: mkseq (f \o ((+)%Int 1)) n.
25522608
proof. by move => le0n; rewrite /mkseq iotaS //= map_comp -iota_addl. qed.
25532609
2610+
lemma mkseqSr_minus ['a] (f : int -> 'a) (n : int) :
2611+
0 < n => mkseq f n = f 0 :: mkseq (f \o (+) 1) (n - 1).
2612+
proof. by move=> gt0_n; rewrite (mkseqSr _ (n-1)) //#. qed.
2613+
25542614
lemma mkseq_add (f : int -> 'a) n m : 0 <= n => 0 <= m =>
25552615
mkseq f (n+m) = mkseq f n ++ mkseq (fun i => f (n+i)) m.
25562616
proof.
@@ -2801,6 +2861,9 @@ proof.
28012861
by rewrite !flatten_cons ih catA.
28022862
qed.
28032863
2864+
lemma flatten1 ['a] (x : 'a list) : flatten [x] = x.
2865+
proof. by rewrite flatten_cons flatten_nil cats0. qed.
2866+
28042867
lemma flatten_rcons (s : 'a list list) (x : 'a list) :
28052868
flatten (rcons s x) = flatten s ++ x.
28062869
proof. by rewrite -cats1 flatten_cat flatten_seq1. qed.
@@ -2929,6 +2992,46 @@ rewrite (_ : max 0 k = k) 1:/# //; elim: k ge0_k => [|k ge0_k ih].
29292992
by rewrite nseqS // flatten_cons count_cat /#.
29302993
qed.
29312994
2995+
lemma size_flatten_ctt ['a] (n : int) (s : 'a list list) :
2996+
(forall x, x \in s => size x = n)
2997+
=> size (flatten s) = n * (size s).
2998+
proof.
2999+
move=> sz_s; rewrite size_flatten (iffLR _ _ (eq_in_map _ (fun _ => n) _)) //.
3000+
by elim: {sz_s} s => //= s @/sumz /= ->; rewrite mulzDr.
3001+
qed.
3002+
3003+
lemma drop_flatten_ctt ['a] (m n : int) (s : 'a list list) :
3004+
(forall x, x \in s => size x = m)
3005+
=> drop (m * n) (flatten s) = flatten (drop n s).
3006+
proof.
3007+
move=> hsz; case: (m < 0) => [lt0_m|/lezNgt ge0_m].
3008+
- have ->>//: s = []; apply: contraLR lt0_m.
3009+
case: s hsz => // x s /(_ x _) // <- _.
3010+
by rewrite ltzNge /= size_ge0.
3011+
elim/natind: n s hsz => [n le0_n|n ge0_n ih] s hsz.
3012+
- by rewrite !drop_le0 //#.
3013+
rewrite mulzDr /=; case: s hsz => // x s hsz.
3014+
rewrite flatten_cons drop_cat hsz // iffalse 1:/#.
3015+
rewrite -addrA /= iffalse 1:/# &(ih) => ??.
3016+
by apply: hsz => /=; right.
3017+
qed.
3018+
3019+
lemma take_flatten_ctt ['a] (m n : int) (s : 'a list list) :
3020+
(forall x, x \in s => size x = m)
3021+
=> take (m * n) (flatten s) = flatten (take n s).
3022+
proof.
3023+
move=> hsz; case: (m < 0) => [lt0_m|/lezNgt ge0_m].
3024+
- have ->>//: s = []; apply: contraLR lt0_m.
3025+
case: s hsz => // x s /(_ x _) // <- _.
3026+
by rewrite ltzNge /= size_ge0.
3027+
elim/natind: n s hsz => [n le0_n|n ge0_n ih] s hsz.
3028+
- by rewrite !take_le0 //#.
3029+
rewrite mulzDr /=; case: s hsz => // x s hsz.
3030+
rewrite flatten_cons take_cat hsz // iffalse 1:/#.
3031+
rewrite -addrA /= iffalse 1:/# ih // => ??.
3032+
by apply: hsz => /=; right.
3033+
qed.
3034+
29323035
lemma perm_eq_pair ['a 'b] (s : ('a * 'b) list) : uniq s => perm_eq s
29333036
(flatten
29343037
(map (fun a => filter (fun xy : _ * _ => xy.`1 = a) s)

0 commit comments

Comments
 (0)