aboutsummaryrefslogtreecommitdiff
path: root/src/Arithmetic/Saturated.v
diff options
context:
space:
mode:
authorGravatar jadep <jade.philipoom@gmail.com>2017-06-18 14:56:15 -0400
committerGravatar jadep <jade.philipoom@gmail.com>2017-06-18 14:56:15 -0400
commit30d96c047e7afe6bd1b3b84ab6532ebf1d7c5aa1 (patch)
tree16144ae37032ca890b68b6501869c06d83afc5a1 /src/Arithmetic/Saturated.v
parent0079e9a94925a781cc96df59b7b45ec551c94c29 (diff)
define strong small and re-prove small_add and small_compact with that definition
Diffstat (limited to 'src/Arithmetic/Saturated.v')
-rw-r--r--src/Arithmetic/Saturated.v142
1 files changed, 106 insertions, 36 deletions
diff --git a/src/Arithmetic/Saturated.v b/src/Arithmetic/Saturated.v
index 0904e6332..7b42c31e7 100644
--- a/src/Arithmetic/Saturated.v
+++ b/src/Arithmetic/Saturated.v
@@ -387,30 +387,6 @@ Module Columns.
rewrite (subst_append t), to_list_append, hd_append. reflexivity.
Qed.
- Lemma small_compact {n} x :
- hd (n:=n) (snd (Columns.compact x)) < weight 1 / weight 0.
- Proof.
- match goal with
- |- ?G => assert (G /\ fst (compact x) = fst (compact x)); [|tauto]
- end. (* assert a dummy second statement so that fst (compact x) is in context *)
- cbv [compact compact_cps compact_step compact_step_cps];
- autorewrite with uncps push_id.
- change (fun i s a => compact_digit_cps i (s :: a) id)
- with (fun i s a => compact_digit i (s :: a)).
- remember (fun i s a => compact_digit i (s :: a)) as f.
-
- rewrite <-hd_to_list with (a:=0).
-
- apply @mapi_with'_linvariant with (n:=S n) (start:=0) (f:=f) (inp:=x); intros; try tauto; (split; [|reflexivity]).
- { let P := fresh "H" in
- match goal with H : _ /\ _ |- _ => destruct H end.
- destruct n0; simpl. subst f.
- { rewrite compact_digit_mod.
- apply Z.mod_pos_bound, Z.gt_lt, weight_divides. }
- { rewrite hd_to_list in H1. assumption. } }
- { simpl. apply Z.gt_lt, weight_divides. }
- Qed.
-
Definition cons_to_nth_cps {n} i (x:Z) (t:(list Z)^n)
{T} (f:(list Z)^n->T) :=
@on_tuple_cps _ _ nil (update_nth_cps i (cons x)) n n t _ f.
@@ -706,7 +682,7 @@ Section UniformWeight.
cbv [uweight]. rewrite <-Z.pow_sub_r by (rewrite ?Nat2Z.inj_succ; omega).
apply Z.lt_gt, Z.pow_pos_nonneg; rewrite ?Nat2Z.inj_succ; omega.
Qed.
-
+
End UniformWeight.
Section API.
@@ -716,7 +692,8 @@ Section API.
(* lowest limb is less than its bound; this is required for [divmod]
to simply separate the lowest limb from the rest and be equivalent
to normal div/mod with [bound]. *)
- Definition small {n} (p : T n) : Prop := List.hd 0 (to_list _ p) < bound.
+ Definition small {n} (p : T n) : Prop :=
+ forall x, In x (to_list _ p) -> 0 <= x < bound.
Definition zero {n:nat} : T n := B.Positional.zeros n.
@@ -776,12 +753,51 @@ Section API.
End CPSProofs.
Hint Rewrite join0_id divmod_id drop_high_id scmul_id add_id : uncps.
-
+
Section Proofs.
Definition eval {n} (p : T n) : Z :=
B.Positional.eval (uweight bound) p.
+ Lemma In_to_list_left_tl n (p : Z^S n) x:
+ In x (to_list n (left_tl p)) -> In x (to_list (S n) p).
+ Admitted.
+
+ Lemma In_left_hd n (p : Z^S n):
+ In (left_hd p) (to_list _ p).
+ Admitted.
+
+ Lemma eval_small n (p : T n) (Hsmall : small p) :
+ 0 <= eval p < uweight bound n.
+ Proof.
+ cbv [small eval] in *; intros.
+ induction n; cbv [T uweight] in *; [destruct p|rewrite (subst_left_append p)];
+ repeat match goal with
+ | _ => progress autorewrite with push_basesystem_eval
+ | _ => rewrite Z.pow_0_r
+ | _ => specialize (IHn (left_tl p))
+ | _ =>
+ let H := fresh "H" in
+ match type of IHn with
+ ?P -> _ => assert P as H by auto using In_to_list_left_tl;
+ specialize (IHn H)
+ end
+ | |- context [?b ^ Z.of_nat (S ?n)] =>
+ replace (b ^ Z.of_nat (S n)) with (b ^ Z.of_nat n * b) by
+ (rewrite Nat2Z.inj_succ, <-Z.add_1_r, Z.pow_add_r,
+ Z.pow_1_r by (omega || auto using Nat2Z.is_nonneg);
+ reflexivity)
+ | _ => omega
+ end.
+
+ specialize (Hsmall _ (In_left_hd _ p)).
+ split; [Z.zero_bounds; omega |].
+ apply Z.lt_le_trans with (m:=bound^Z.of_nat n * (left_hd p+1)).
+ { rewrite Z.mul_add_distr_l.
+ apply Z.add_le_lt_mono; omega. }
+ { apply Z.mul_le_mono_nonneg; omega. }
+ Qed.
+
Lemma eval_zero n : eval (@zero n) = 0.
Proof.
cbv [eval zero].
@@ -848,7 +864,56 @@ Section API.
Proof. apply eval_add; omega. Qed.
Hint Rewrite eval_add_same eval_add_S1 eval_add_S2 : push_basesystem_eval.
- Lemma small_add n m pred_nm a b : small (@add n m pred_nm a b).
+ Lemma to_list_left_append {n} (p:T n) x:
+ (to_list _ (left_append x p)) = to_list n p ++ x :: nil.
+ Admitted.
+
+ Local Definition compact {n} := Columns.compact (n:=n) (add_get_carry:=Z.add_get_carry_full) (div:=div) (modulo:=modulo) (uweight bound).
+ Local Definition compact_digit := Columns.compact_digit (add_get_carry:=Z.add_get_carry_full) (div:=div) (modulo:=modulo) (uweight bound).
+ Lemma small_compact {n} (p:(list Z)^n) : small (snd (compact p)).
+ Proof.
+ pose_uweight bound.
+ pose proof Z.add_get_carry_full_div.
+ pose proof Z.add_get_carry_full_mod.
+ pose proof div_correct. pose proof modulo_correct.
+ match goal with
+ |- ?G => assert (G /\ fst (compact p) = fst (compact p)); [|tauto]
+ end. (* assert a dummy second statement so that fst (compact x) is in context *)
+ cbv [compact Columns.compact Columns.compact_cps small
+ Columns.compact_step Columns.compact_step_cps];
+ autorewrite with uncps push_id.
+ change (fun i s a => Columns.compact_digit_cps (uweight bound) i (s :: a) id)
+ with (fun i s a => compact_digit i (s :: a)).
+ remember (fun i s a => compact_digit i (s :: a)) as f.
+
+ apply @mapi_with'_linvariant with (n:=n) (f:=f) (inp:=p);
+ intros; [|simpl; tauto]. split; [|reflexivity].
+ let P := fresh "H" in
+ match goal with H : _ /\ _ |- _ => destruct H end.
+ destruct n0; subst f.
+ { cbv [compact_digit uweight to_list to_list' In].
+ rewrite Columns.compact_digit_mod by assumption.
+ rewrite Z.pow_0_r, Z.pow_1_r, Z.div_1_r. intros x ?.
+ match goal with
+ H : _ \/ False |- _ => destruct H; [|exfalso; assumption] end.
+ subst x. apply Z.mod_pos_bound, Z.gt_lt, bound_pos. }
+ { rewrite to_list_left_append.
+ let H := fresh "H" in
+ intros x H; apply in_app_or in H; destruct H;
+ [solve[auto]| cbv [In] in H; destruct H;
+ [|exfalso; assumption] ].
+ subst x. cbv [compact_digit uweight].
+ rewrite Columns.compact_digit_mod by assumption.
+ rewrite !Nat2Z.inj_succ, <-Z.pow_sub_r by omega.
+ match goal with |- context [Z.succ ?a - ?a] =>
+ replace (Z.succ a - a) with 1 by omega end.
+ rewrite Z.pow_1_r.
+ apply Z.mod_pos_bound, Z.gt_lt, bound_pos. }
+ Qed.
+
+ Lemma small_add n m pred_nm a b :
+ (uweight bound n + uweight bound m <= uweight bound pred_nm) ->
+ small a -> small b -> small (@add n m pred_nm a b).
Proof.
intros. pose_uweight bound.
pose proof Z.add_get_carry_full_div.
@@ -856,15 +921,20 @@ Section API.
pose proof div_correct. pose proof modulo_correct.
cbv [small add_cps add Let_In]. repeat autounfold.
autorewrite with uncps push_id.
- destruct n, m, pred_nm; try (simpl; omega);
- rewrite Columns.hd_to_list, hd_left_append;
- (eapply Z.lt_le_trans;
- [ apply Columns.small_compact; auto
- | cbv [uweight]; simpl Z.of_nat;
- autorewrite with zsimplify;
- rewrite Z.pow_1_r; reflexivity ]).
+ rewrite to_list_left_append.
+ let H := fresh "H" in intros x H; apply in_app_or in H;
+ destruct H as [H | H];
+ [apply (small_compact _ _ H)
+ |destruct H; [|tauto] ].
+ subst x.
+ rewrite Columns.compact_div by assumption.
+ repeat match goal with
+ H : small ?x |- _ => apply eval_small in H; cbv [eval] in H
+ end.
+ destruct pred_nm; autorewrite with push_basesystem_eval;
+ rewrite Z.div_small; omega.
Qed.
-
+
Lemma eval_drop_high n v :
small v -> eval (@drop_high n v) = eval v mod (uweight bound n).
Admitted.