aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_CoqProject1
-rw-r--r--src/Galois/BaseSystem.v2
-rw-r--r--src/Galois/ModularBaseSystem.v105
-rw-r--r--src/Util/CaseUtil.v12
-rw-r--r--src/Util/ListUtil.v141
5 files changed, 248 insertions, 13 deletions
diff --git a/_CoqProject b/_CoqProject
index 0e56c1ee2..d92e7e640 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -2,6 +2,7 @@
-R fiat/src Fiat
-R bedrock/Bedrock Bedrock
src/Tactics/VerdiTactics.v
+src/Util/CaseUtil.v
src/Util/ListUtil.v
src/Galois/Galois.v
src/Galois/GaloisTheory.v
diff --git a/src/Galois/BaseSystem.v b/src/Galois/BaseSystem.v
index e8c288de6..19fc90dba 100644
--- a/src/Galois/BaseSystem.v
+++ b/src/Galois/BaseSystem.v
@@ -1,5 +1,5 @@
Require Import List.
-Require Import Util.ListUtil.
+Require Import Util.ListUtil Util.CaseUtil.
Require Import ZArith.ZArith ZArith.Zdiv.
Require Import Omega NPeano Arith.
diff --git a/src/Galois/ModularBaseSystem.v b/src/Galois/ModularBaseSystem.v
index db9a8db2a..bd3f7dca0 100644
--- a/src/Galois/ModularBaseSystem.v
+++ b/src/Galois/ModularBaseSystem.v
@@ -2,6 +2,7 @@ Require Import Zpower ZArith.
Require Import List.
Require Import Crypto.Galois.BaseSystem Crypto.Galois.GaloisTheory.
Require Import Util.ListUtil.
+Require Import VerdiTactics.
Open Scope Z_scope.
Module Type PseudoMersenneBaseParams (Import B:BaseCoefs) (Import M:Modulus).
@@ -241,7 +242,7 @@ Module GFPseudoMersenneBase (BC:BaseCoefs) (M:Modulus) (P:PseudoMersenneBasePara
rewrite (combine_truncate_r us EC.base).
f_equal; f_equal.
unfold EC.base.
- rewrite (firstn_app _ _ (map (Z.mul (2 ^ P.k)) BC.base)); auto.
+ rewrite firstn_app_inleft; auto; omega.
Qed.
Lemma extended_base_length:
@@ -376,4 +377,106 @@ Module GFPseudoMersenneBase (BC:BaseCoefs) (M:Modulus) (P:PseudoMersenneBasePara
auto.
Qed.
+ Definition carry i us :=
+ let di := nth_default 0 us i in
+ let bi := nth_default 0 BC.base i in
+ let di' := di mod bi in
+ let cr := di / bi in
+ let us' := set_nth i di' us in
+ if eq_nat_dec i (pred (length BC.base))
+ then set_nth 0 (P.c * cr + nth_default 0 us 0 ) us' (* carry and reduce *)
+ else set_nth (S i) ( cr + nth_default 0 us (S i)) us'. (* simple carry *)
+
+ Lemma carry_length : forall i us,
+ (length us <= length BC.base)%nat ->
+ (length (carry i us) <= length BC.base)%nat.
+ Proof.
+ unfold carry; intros; break_if; subst; repeat (rewrite length_set_nth); auto.
+ Qed.
+
+ Lemma skipn_all : forall {T} n (xs:list T),
+ (n >= length xs)%nat ->
+ skipn n xs = nil.
+ Proof.
+ induction n, xs; boring; omega.
+ Qed.
+
+ Lemma fold_right_cons : forall {A B} (f:B->A->A) a b bs,
+ fold_right f a (b::bs) = f b (fold_right f a bs).
+ Proof.
+ reflexivity.
+ Qed.
+
+ Lemma length_cons : forall {T} (x:T) xs, length (x::xs) = S (length xs).
+ reflexivity.
+ Qed.
+
+ Lemma S_pred_nonzero : forall a, (a > 0 -> S (pred a) = a)%nat.
+ Proof.
+ destruct a; omega.
+ Qed.
+
+ Lemma firstn_combine : forall {A B} n (xs:list A) (ys:list B),
+ firstn n (combine xs ys) = combine (firstn n xs) (firstn n ys).
+ Proof.
+ induction n, xs, ys; boring.
+ Qed.
+
+ Lemma combine_nil_r : forall {A B} (xs:list A),
+ combine xs (@nil B) = nil.
+ Proof.
+ induction xs; boring.
+ Qed.
+
+ Lemma skipn_combine : forall {A B} n (xs:list A) (ys:list B),
+ skipn n (combine xs ys) = combine (skipn n xs) (skipn n ys).
+ Proof.
+ induction n, xs, ys; boring.
+ rewrite combine_nil_r; reflexivity.
+ Qed.
+
+ Lemma carry_rep_reduce : forall us u9 us' u0 x
+ (Heq: us = u0::us'++u9::nil)
+ (Hl : length us = length BC.base),
+ us ~= x ->
+ carry (pred (length BC.base)) us ~= x.
+ Proof.
+ autounfold; intuition; subst. rewrite carry_length; auto; omega.
+ unfold toGF, B.decode, B.decode', carry; break_if; intuition.
+ pose proof EC.base_length_nonzero.
+ repeat (rewrite combine_set_nth).
+ nth_inbounds.
+ nth_inbounds.
+ nth_inbounds; [|rewrite length_set_nth, combine_length, Min.min_l by auto; omega].
+ unfold nth_default.
+ nth_inbounds.
+ nth_inbounds.
+ nth_inbounds; [|rewrite combine_length, Min.min_l by auto; omega].
+ unfold splice_nth.
+
+ rewrite firstn0, app_nil_l.
+ assert (skipn (S (pred (length BC.base))) (combine (u0::us'++u9::nil) BC.base) = nil)
+ as Hnil; [|rewrite Hnil; clear Hnil]. {
+ rewrite skipn_all; auto.
+ rewrite combine_length, Min.min_l by auto; omega.
+ }
+ rewrite fold_right_cons.
+ rewrite B.base_eq_1cons at 1.
+ rewrite length_cons.
+ rewrite <- (pred_Sn (length (skipn 1 BC.base))).
+ rewrite skipn_length.
+ rewrite <- pred_of_minus.
+ rewrite firstn_combine.
+ rewrite skipn_app_inleft.
+ rewrite skipn_combine.
+ rewrite fold_right_app.
+ Abort.
+
+
+ Lemma carry_rep : forall i us x
+ (Hl : length us = length BC.base),
+ us ~= x ->
+ carry i us ~= x.
+ Proof.
+ Admitted.
End GFPseudoMersenneBase.
diff --git a/src/Util/CaseUtil.v b/src/Util/CaseUtil.v
new file mode 100644
index 000000000..35f207ffc
--- /dev/null
+++ b/src/Util/CaseUtil.v
@@ -0,0 +1,12 @@
+Require Import Arith.
+
+Ltac case_max :=
+ match goal with [ |- context[max ?x ?y] ] =>
+ destruct (le_dec x y);
+ match goal with
+ | [ H : (?x <= ?y)%nat |- context[max ?x ?y] ] => rewrite Max.max_r by
+ (exact H)
+ | [ H : ~ (?x <= ?y)%nat |- context[max ?x ?y] ] => rewrite Max.max_l by
+ (exact (le_Sn_le _ _ (not_le _ _ H)))
+ end
+ end.
diff --git a/src/Util/ListUtil.v b/src/Util/ListUtil.v
index 86e989731..c8ee7bd9d 100644
--- a/src/Util/ListUtil.v
+++ b/src/Util/ListUtil.v
@@ -126,17 +126,115 @@ Proof.
destruct (eq_nat_dec n m), (eq_nat_dec (S n) (S m)); nth_tac.
Qed.
-Lemma set_nth_equiv_splice: forall {T} n x (xs:list T),
+Lemma length_set_nth : forall {T} i (x:T) xs, length (set_nth i x xs) = length xs.
+ induction i, xs; boring.
+Qed.
+
+Lemma nth_error_length_exists_value : forall {A} (i : nat) (xs : list A),
+ (i < length xs)%nat -> exists x, nth_error xs i = Some x.
+Proof.
+ induction i, xs; boring; try omega.
+Qed.
+
+Lemma nth_error_length_not_error : forall {A} (i : nat) (xs : list A),
+ nth_error xs i = None -> (i < length xs)%nat -> False.
+Proof.
+ intros.
+ destruct (nth_error_length_exists_value i xs); intuition; congruence.
+Qed.
+
+Lemma nth_error_value_eq_nth_default : forall {T} i xs (x d:T),
+ nth_error xs i = Some x -> forall d, nth_default d xs i = x.
+Proof.
+ unfold nth_default; boring.
+Qed.
+
+Lemma skipn0 : forall {T} (xs:list T), skipn 0 xs = xs.
+Proof.
+ auto.
+Qed.
+
+Lemma firstn0 : forall {T} (xs:list T), firstn 0 xs = nil.
+Proof.
+ auto.
+Qed.
+
+Definition splice_nth {T} n (x:T) xs := firstn n xs ++ x :: skipn (S n) xs.
+Hint Unfold splice_nth.
+
+Lemma splice_nth_equiv_set_nth : forall {T} n x (xs:list T),
+ splice_nth n x xs =
+ if lt_dec n (length xs)
+ then set_nth n x xs
+ else xs ++ x::nil.
+Proof.
+ induction n, xs; boring.
+ break_if; break_if; auto; omega.
+Qed.
+
+Lemma splice_nth_equiv_set_nth_set : forall {T} n x (xs:list T),
+ n < length xs ->
+ splice_nth n x xs = set_nth n x xs.
+Proof.
+ intros.
+ rewrite splice_nth_equiv_set_nth.
+ break_if; auto; omega.
+Qed.
+
+Lemma splice_nth_equiv_set_nth_snoc : forall {T} n x (xs:list T),
+ n >= length xs ->
+ splice_nth n x xs = xs ++ x::nil.
+Proof.
+ intros.
+ rewrite splice_nth_equiv_set_nth.
+ break_if; auto; omega.
+Qed.
+
+Lemma set_nth_equiv_splice_nth: forall {T} n x (xs:list T),
set_nth n x xs =
if lt_dec n (length xs)
- then firstn n xs ++ x :: skipn (S n) xs
+ then splice_nth n x xs
else xs.
Proof.
induction n; destruct xs; intros; simpl in *;
try (rewrite IHn; clear IHn); auto.
- destruct (lt_dec n (length xs)), (lt_dec (S n) (S (length xs))); try omega; trivial.
+ break_if; break_if; auto; omega.
Qed.
+Ltac nth_error_inbounds :=
+ match goal with
+ | [ |- context[match nth_error ?xs ?i with Some _ => _ | None => _ end ] ] =>
+ case_eq (nth_error xs i);
+ match goal with
+ | [ |- forall _, nth_error xs i = Some _ -> _ ] =>
+ let x := fresh "x" in
+ let H := fresh "H" in
+ intros x H;
+ repeat progress erewrite H;
+ repeat progress erewrite (nth_error_value_eq_nth_default i xs x); auto
+ | [ |- nth_error xs i = None -> _ ] =>
+ let H := fresh "H" in
+ intros H;
+ destruct (nth_error_length_not_error _ _ H);
+ try omega
+ end;
+ idtac
+ end.
+
+Ltac set_nth_inbounds :=
+ match goal with
+ | [ |- context[set_nth ?i ?x ?xs] ] =>
+ rewrite (set_nth_equiv_splice_nth i x xs);
+ destruct (lt_dec i (length xs));
+ match goal with
+ | [ H : ~ (i < (length xs))%nat |- _ ] => destruct H
+ | [ H : (i < (length xs))%nat |- _ ] => try omega
+ end;
+ idtac
+ end.
+
+Ltac nth_inbounds := nth_error_inbounds || set_nth_inbounds.
+
Lemma combine_set_nth : forall {A B} n (x:A) xs (ys:list B),
combine (set_nth n x xs) ys =
match nth_error ys n with
@@ -207,21 +305,42 @@ Proof.
destruct n; auto.
Qed.
-Lemma firstn_app : forall {A} n (xs ys : list A), (n <= length xs)%nat ->
- firstn n xs = firstn n (xs ++ ys).
+Lemma firstn_app : forall {A} n (xs ys : list A),
+ firstn n (xs ++ ys) = firstn n xs ++ firstn (n - length xs) ys.
+Proof.
+ induction n, xs, ys; boring.
+Qed.
+
+Lemma skipn_app : forall {A} n (xs ys : list A),
+ skipn n (xs ++ ys) = skipn n xs ++ skipn (n - length xs) ys.
+Proof.
+ induction n, xs, ys; boring.
+Qed.
+
+Lemma firstn_app_inleft : forall {A} n (xs ys : list A), (n <= length xs)%nat ->
+ firstn n (xs ++ ys) = firstn n xs.
+Proof.
+ induction n, xs, ys; boring; try omega.
+Qed.
+
+Lemma skipn_app_inleft : forall {A} n (xs ys : list A), (n <= length xs)%nat ->
+ skipn n (xs ++ ys) = skipn n xs ++ ys.
Proof.
- induction n; destruct xs; destruct ys; simpl_list; boring; try omega.
- rewrite (IHn xs (a0 :: ys)) by omega; auto.
+ induction n, xs, ys; boring; try omega.
Qed.
-Lemma skipn_app : forall A (l l': list A), skipn (length l) (l ++ l') = l'.
+Lemma firstn_app_sharp : forall A (l l': list A), firstn (length l) (l ++ l') = l.
Proof.
- intros.
- induction l; simpl; auto.
+ induction l; boring.
+Qed.
+
+Lemma skipn_app_sharp : forall A (l l': list A), skipn (length l) (l ++ l') = l'.
+Proof.
+ induction l; boring.
Qed.
Lemma skipn_length : forall {A} n (xs : list A),
length (skipn n xs) = (length xs - n)%nat.
Proof.
-induction n; destruct xs; boring.
+ induction n, xs; boring.
Qed.