diff options
author | Jason Gross <jgross@mit.edu> | 2018-02-23 15:21:33 -0500 |
---|---|---|
committer | Jason Gross <jasongross9@gmail.com> | 2018-03-19 14:17:26 -0400 |
commit | fcee392d96f2c2c13825b8b5d51fea4b117ef7bf (patch) | |
tree | 988639c86249e6088a3154a9a09e51218aae65cb | |
parent | 6bbb3d948da709737011cc0fc502a271aae7fb36 (diff) |
WIP cast
-rw-r--r-- | src/Experiments/SimplyTypedArithmetic.v | 1722 |
1 files changed, 994 insertions, 728 deletions
diff --git a/src/Experiments/SimplyTypedArithmetic.v b/src/Experiments/SimplyTypedArithmetic.v index 254ef5adf..5ffe9c1e8 100644 --- a/src/Experiments/SimplyTypedArithmetic.v +++ b/src/Experiments/SimplyTypedArithmetic.v @@ -15,6 +15,7 @@ Require Import Crypto.Util.ZRange.Operations. Require Import Crypto.Util.Tactics.RunTacticAsConstr. Require Import Crypto.Util.Tactics.Head. Require Import Crypto.Util.Option. +Require Import Crypto.Util.Sum. Require Import Crypto.Util.ZUtil.Tactics.LtbToLt. Require Import Crypto.Util.ZUtil.Tactics.PullPush.Modulo. Require Import Crypto.Util.Tactics.SpecializeBy. @@ -1727,6 +1728,7 @@ Module Compilers. | Z_sub_get_borrow_concrete (s:BinInt.Z) : ident (Z * Z) (Z * Z) | Z_zselect : ident (Z * Z * Z) Z | Z_add_modulo : ident (Z * Z * Z) Z + | Z_cast (range : zrange) : ident Z Z . Notation curry0 f @@ -1746,6 +1748,9 @@ Module Compilers. Notation curry3_2 f := (fun '(a, b, c) => f a (uncurry2 b) c). + Definition cast_outside_of_range (r : zrange) (v : BinInt.Z) : BinInt.Z. + Proof. exact v. Qed. + Definition interp {s d} (idc : ident s d) : type.interp s -> type.interp d := match idc in ident s d return type.interp s -> type.interp d with | primitive _ v => curry0 v @@ -1786,6 +1791,9 @@ Module Compilers. | Z_sub_get_borrow_concrete s => curry2 (Z.sub_get_borrow s) | Z_zselect => curry3 Z.zselect | Z_add_modulo => curry3 Z.add_modulo + | Z_cast r => fun x => if (lower r <=? x) && (x <=? upper r) + then x + else cast_outside_of_range r x end. Ltac reify @@ -1911,6 +1919,7 @@ Module Compilers. Notation sub_get_borrow_concrete := Z_sub_get_borrow_concrete. Notation zselect := Z_zselect. Notation add_modulo := Z_add_modulo. + Notation cast := Z_cast. End Z. Module Nat. @@ -2307,6 +2316,16 @@ Module Compilers. | None => None end. + Definition invert_Z_cast (e : @expr var type.Z) : option (zrange * @expr var type.Z) + := match invert_AppIdent e with + | Some (existT s (idc, args)) + => match idc in ident s t return expr s -> option (zrange * expr type.Z) with + | ident.Z_cast r => fun v => Some (r, v) + | _ => fun _ => None + end args + | None => None + end. + Local Notation list_expr := (fun t => match t return Type with | type.list T => list (expr T) @@ -2822,6 +2841,7 @@ Module Compilers. | ident.Z_sub_get_borrow as idc | ident.Z_zselect as idc | ident.Z_add_modulo as idc + | ident.Z_cast _ as idc => cps_of (Uncurried.expr.default.ident.interp idc) | ident.Z_mul_split_concrete s => cps_of (curry2 (Z.mul_split s)) @@ -2998,6 +3018,7 @@ Module Compilers. | ident.Z_shiftl _ as idc | ident.Z_land _ as idc | ident.Z_opp as idc + | ident.Z_cast _ as idc => λ (xyk : (* ignore this line; it's to work around lack of fixpoint refolding in type inference *) var (type.Z * (type.Z -> R))%ctype) , (ident.snd @@ (Var xyk)) @@ -3422,37 +3443,346 @@ Module Compilers. Include default. End CPS. - Module sign. - Local Set Boolean Equality Schemes. - Local Set Decidable Equality Schemes. - Inductive sign := pos | neg. - Module Z. - Definition interp (s : sign) : Z -> Z - := match s with - | pos => id - | neg => Z.opp + Module ZRange. + Module type. + Module primitive. + Definition interp (t : type.primitive) : Set + := match t with + | type.unit => unit + | type.Z => zrange + | type.nat => unit + | type.bool => unit + end. + Definition is_neg {t} : interp t -> bool + := match t with + | type.Z => fun r => (lower r <? 0) && (upper r <=? 0) + | _ => fun _ => false + end. + Definition is_tighter_than {t} : interp t -> interp t -> bool + := match t with + | type.Z => is_tighter_than_bool + | type.unit + | type.nat + | type.bool + => fun _ _ => true + end. + Definition is_bounded_by {t} : interp t -> type.interp t -> bool + := match t with + | type.Z => fun r z => (lower r <=? z) && (z <=? upper r) + | type.unit + | type.nat + | type.bool + => fun _ _ => true + end. + Module option. + Definition interp (t : type.primitive) : Set + := match t with + | type.unit => unit + | type.Z => option zrange + | type.nat => unit + | type.bool => unit + end. + Definition None {t} : interp t + := match t with + | type.Z => None + | _ => tt + end. + Definition Some {t} : primitive.interp t -> interp t + := match t with + | type.Z => Some + | _ => id + end. + Definition is_neg {t} : interp t -> bool + := match t with + | type.Z => fun v => match v with + | Datatypes.Some v => @is_neg type.Z v + | Datatypes.None => false + end + | t => @primitive.is_neg t + end. + Definition is_tighter_than {t} : interp t -> interp t -> bool + := match t with + | type.Z + => fun r1 r2 + => match r1, r2 with + | _, Datatypes.None => true + | Datatypes.None, Datatypes.Some _ => false + | Datatypes.Some r1, Datatypes.Some r2 => is_tighter_than (t:=type.Z) r1 r2 + end + | t => @is_tighter_than t + end. + Definition is_bounded_by {t} : interp t -> type.interp t -> bool + := match t with + | type.Z + => fun r + => match r with + | Datatypes.Some r => @is_bounded_by type.Z r + | Datatypes.None => fun _ => true + end + | t => @is_bounded_by t + end. + End option. + End primitive. + Fixpoint interp (t : type) : Set + := match t with + | type.type_primitive x => primitive.interp x + | type.prod A B => interp A * interp B + | type.arrow s d => interp s -> interp d + | type.list A => list (interp A) end. - End Z. - Definition of_Z (v : Z) : sign - := match v with - | Zneg _ => neg - | Zpos _ => pos - | Z0 => (* default *) pos - end. - Definition opp (s : sign) : sign - := match s with - | pos => neg - | neg => pos - end. - Definition mul (s1 s2 : sign) : sign - := match s1, s2 with - | pos, pos => pos - | neg, neg => pos - | pos, neg | neg, pos => neg - end. - End sign. - Notation sign := sign.sign. + Fixpoint fold_andb_map {A B} (f : A -> B -> bool) (ls1 : list A) (ls2 : list B) + : bool + := match ls1, ls2 with + | nil, nil => true + | nil, _ => false + | cons x xs, cons y ys => andb (f x y) (@fold_andb_map A B f xs ys) + | cons _ _, _ => false + end. + Fixpoint is_tighter_than {t} : interp t -> interp t -> bool + := match t with + | type.type_primitive x => @primitive.is_tighter_than x + | type.prod A B + => fun '((ra, rb) : interp A * interp B) + '((ra', rb') : interp A * interp B) + => @is_tighter_than A ra ra' && @is_tighter_than B rb rb' + | type.arrow s d => fun _ _ => false + | type.list A + => fold_andb_map (@is_tighter_than A) + end. + Fixpoint is_bounded_by {t} : interp t -> Compilers.type.interp t -> bool + := match t return interp t -> Compilers.type.interp t -> bool with + | type.type_primitive x => @primitive.is_bounded_by x + | type.prod A B + => fun '((ra, rb) : interp A * interp B) + '((ra', rb') : Compilers.type.interp A * Compilers.type.interp B) + => @is_bounded_by A ra ra' && @is_bounded_by B rb rb' + | type.arrow s d => fun _ _ => false + | type.list A + => fold_andb_map (@is_bounded_by A) + end. + Module option. + Fixpoint interp (t : type) : Set + := match t with + | type.type_primitive x => primitive.option.interp x + | type.prod A B => interp A * interp B + | type.arrow s d => interp s -> interp d + | type.list A => list (interp A) + end. + Fixpoint None {t : type} : interp t + := match t with + | type.type_primitive x => @primitive.option.None x + | type.prod A B => (@None A, @None B) + | type.arrow s d => fun _ => @None d + | type.list A => @nil (interp A) + end. + Fixpoint Some {t : type} : type.interp t -> interp t + := match t with + | type.type_primitive x => @primitive.option.Some x + | type.prod A B + => fun x : type.interp A * type.interp B + => (@Some A (fst x), @Some B (snd x)) + | type.arrow s d => fun _ _ => @None d + | type.list A => List.map (@Some A) + end. + Fixpoint is_tighter_than {t} : interp t -> interp t -> bool + := match t with + | type.type_primitive x => @primitive.option.is_tighter_than x + | type.prod A B + => fun '((ra, rb) : interp A * interp B) + '((ra', rb') : interp A * interp B) + => @is_tighter_than A ra ra' && @is_tighter_than B rb rb' + | type.arrow s d => fun _ _ => false + | type.list A + => fold_andb_map (@is_tighter_than A) + end. + Fixpoint is_bounded_by {t} : interp t -> Compilers.type.interp t -> bool + := match t return interp t -> Compilers.type.interp t -> bool with + | type.type_primitive x => @primitive.option.is_bounded_by x + | type.prod A B + => fun '((ra, rb) : interp A * interp B) + '((ra', rb') : Compilers.type.interp A * Compilers.type.interp B) + => @is_bounded_by A ra ra' && @is_bounded_by B rb rb' + | type.arrow s d => fun _ _ => false + | type.list A + => fold_andb_map (@is_bounded_by A) + end. + + Lemma fold_andb_map_map {A B C} f g ls1 ls2 + : @fold_andb_map A B f ls1 (@List.map C _ g ls2) + = fold_andb_map (fun a b => f a (g b)) ls1 ls2. + Proof. revert ls1 ls2; induction ls1, ls2; cbn; congruence. Qed. + + Lemma is_tighter_than_Some_is_bounded_by {t} r1 r2 val + (Htight : @is_tighter_than t r1 (Some r2) = true) + (Hbounds : is_bounded_by r1 val = true) + : type.is_bounded_by r2 val = true. + Proof. + induction t; + repeat first [ progress destruct_head'_prod + | progress destruct_head'_and + | progress destruct_head' type.primitive + | progress cbn in * + | progress destruct_head' option + | solve [ eauto with nocore ] + | progress cbv [is_tighter_than_bool] in * + | progress rewrite ?Bool.andb_true_iff in * + | discriminate + | apply conj + | Z.ltb_to_lt; omega + | rewrite @fold_andb_map_map in * ]. + { revert r1 r2 val Htight Hbounds IHt. + induction r1, r2, val; cbn; auto with nocore; try congruence; []. + rewrite !Bool.andb_true_iff; intros; destruct_head'_and; split; eauto with nocore. } + Qed. + End option. + End type. + + Module ident. + Module option. + Local Open Scope zrange_scope. + + Notation curry0 f + := (fun 'tt => f). + Notation curry2 f + := (fun '(a, b) => f a b). + Notation uncurry2 f + := (fun a b => f (a, b)). + Notation curry3 f + := (fun '(a, b, c) => f a b c). + + Definition interp {s d} (idc : ident s d) : type.option.interp s -> type.option.interp d + := match idc in ident.ident s d return type.option.interp s -> type.option.interp d with + | ident.primitive type.Z v => fun _ => Some r[v ~> v] + | ident.Let_In tx tC => fun '(x, C) => C x + | ident.primitive _ _ + | ident.Nat_succ + | ident.bool_rect _ + | ident.nat_rect _ + | ident.pred + | ident.list_rect _ _ + | ident.List_nth_default _ + | ident.Z_pow + | ident.Z_div + | ident.Z_eqb + | ident.Z_leb + | ident.Z_of_nat + | ident.Z_mul_split + | ident.Z_add_get_carry + | ident.Z_add_with_get_carry + | ident.Z_sub_get_borrow + | ident.Z_modulo + => fun _ => type.option.None + | ident.nil t => curry0 (@nil (type.option.interp t)) + | ident.cons t => curry2 (@Datatypes.cons (type.option.interp t)) + | ident.fst A B => @Datatypes.fst (type.option.interp A) (type.option.interp B) + | ident.snd A B => @Datatypes.snd (type.option.interp A) (type.option.interp B) + | ident.List_nth_default_concrete T d n + => fun ls => @nth_default (type.option.interp T) type.option.None ls n + | ident.Z_shiftr _ as idc + | ident.Z_shiftl _ as idc + | ident.Z_opp as idc + => option_map (ZRange.two_corners (ident.interp idc)) + | ident.Z_land mask + => option_map + (fun r : zrange + => ZRange.land_bounds r r[mask~>mask]) + | ident.Z_add as idc + | ident.Z_mul as idc + | ident.Z_sub as idc + => fun '((x, y) : option zrange * option zrange) + => match x, y with + | Some x, Some y + => Some (ZRange.four_corners (uncurry2 (ident.interp idc)) x y) + | Some _, None | None, Some _ | None, None => None + end + | ident.Z_cast range + => fun r : option zrange + => Some match r with + | Some r => ZRange.intersection r range + | None => range + end + | ident.Z_mul_split_concrete split_at + => fun '((x, y) : option zrange * option zrange) + => match x, y with + | Some x, Some y + => type.option.Some + (t:=(type.Z*type.Z)%ctype) + (ZRange.split_bounds (ZRange.four_corners BinInt.Z.mul x y) split_at) + | Some _, None | None, Some _ | None, None => type.option.None + end + | ident.Z_add_get_carry_concrete split_at + => fun '((x, y) : option zrange * option zrange) + => match x, y with + | Some x, Some y + => type.option.Some + (t:=(type.Z*type.Z)%ctype) + (ZRange.split_bounds (ZRange.four_corners BinInt.Z.add x y) split_at) + | Some _, None | None, Some _ | None, None => type.option.None + end + | ident.Z_add_with_get_carry_concrete split_at + => fun '((x, y, z) : option zrange * option zrange * option zrange) + => match x, y, z with + | Some x, Some y, Some z + => type.option.Some + (t:=(type.Z*type.Z)%ctype) + (ZRange.split_bounds + (ZRange.eight_corners (fun x y z => (x + y + z)%Z) x y z) + split_at) + | _, _, _ => type.option.None + end + | ident.Z_sub_get_borrow_concrete split_at + => fun '((x, y) : option zrange * option zrange) + => match x, y with + | Some x, Some y + => type.option.Some + (t:=(type.Z*type.Z)%ctype) + (ZRange.split_bounds (ZRange.four_corners BinInt.Z.sub x y) split_at) + | Some _, None | None, Some _ | None, None => type.option.None + end + | ident.Z_zselect + => fun '((x, y, z) : option zrange * option zrange * option zrange) + => match y, z with + | Some y, Some z => Some (ZRange.union y z) + | Some _, None | None, Some _ | None, None => None + end + | ident.Z_add_modulo + => fun '((x, y, z) : option zrange * option zrange * option zrange) + => match x, y, z with + | Some x, Some y, Some m + => Some (ZRange.union + (ZRange.four_corners BinInt.Z.add x y) + (ZRange.eight_corners (fun x y m => Z.max 0 (x + y - m)) + x y m)) + | _, _, _ => None + end + end. + End option. + End ident. + End ZRange. + + Module DefaultValue. + Module type. + Module primitive. + Definition default {t : type.primitive} : type.interp t + := match t with + | type.unit => tt + | type.Z => (-1)%Z + | type.nat => 0%nat + | type.bool => true + end. + End primitive. + Fixpoint default {t} : type.interp t + := match t with + | type.type_primitive x => @primitive.default x + | type.prod A B => (@default A, @default B) + | type.arrow s d => fun _ => @default d + | type.list A => @nil (type.interp A) + end. + End type. + End DefaultValue. + Module partial. + Notation Zdata := (option zrange). Section value. Context (var : type -> Type). Definition value_prestep (value : type -> Type) (t : type) @@ -3468,7 +3798,7 @@ Module Compilers. | type.arrow _ _ as t => value_prestep value t | type.type_primitive type.Z as t - => sign * @expr var t + value_prestep value t + => Zdata * @expr var t + value_prestep value t | type.prod _ _ as t | type.list _ as t | type.type_primitive _ as t @@ -3476,10 +3806,22 @@ Module Compilers. end%type. Fixpoint value (t : type) := value_step value t. + + Fixpoint value_default {t} : value t + := match t return value t with + | type.type_primitive type.Z + | type.type_primitive _ + => inr DefaultValue.type.primitive.default + | type.prod A B + => inr (@value_default A, @value_default B) + | type.arrow s d => fun _ => @value_default d + | type.list A => inr (@nil (value A)) + end. End value. Module expr. Section reify. + Context (relax_zrange : zrange -> option zrange). Context {var : type -> Type}. Fixpoint reify {t : type} {struct t} : value var t -> @expr var t @@ -3501,10 +3843,14 @@ Module Compilers. | inr v => reify_list (List.map (@reify A) v) end | type.type_primitive type.Z as t - => fun x : sign * expr t + type.interp t + => fun x : Zdata * expr t + type.interp t => match x with - | inl (sign.pos, v) => v - | inl (sign.neg, v) => ident.Z.opp @@ v + | inl (Some r, v) + => match relax_zrange r with + | Some r => ident.Z.cast r @@ v + | None => v + end + | inl (None, v) => v | inr v => ident.primitive v @@ TT end%core%expr | type.type_primitive _ as t @@ -3542,12 +3888,12 @@ Module Compilers. end | type.type_primitive type.Z as t => fun v : expr t - => let inr := @inr (sign * expr t) (value_prestep (value var) t) in - let inl := @inl (sign * expr t) (value_prestep (value var) t) in - match reflect_primitive v, invert_Z_opp v with - | Some v, _ => inr v - | None, Some v => inl (sign.neg, v) - | None, None => inl (sign.pos, v) + => let inr' := @inr (Zdata * expr t) (value_prestep (value var) t) in + let inl' := @inl (Zdata * expr t) (value_prestep (value var) t) in + match reflect_primitive v, invert_Z_cast v with + | Some v, _ => inr' v + | None, Some (r, v) => inl' (Some r, v) + | None, None => inl' (None, v) end | type.type_primitive _ as t => fun v : expr t @@ -3563,7 +3909,8 @@ Module Compilers. Module ident. Section interp. - Context {var : type -> Type}. + Context (relax_zrange : zrange -> option zrange) + {var : type -> Type}. Fixpoint is_var_like {t} (e : @expr var t) : bool := match e with | Var t v => true @@ -3605,16 +3952,19 @@ Module Compilers. => @interp_let_in _ B b (fun b => f (inr (a, b)))) - | inl e => partial.expr.reflect (expr_let y := e in partial.expr.reify (f (inl (Var y))))%expr + | inl e => partial.expr.reflect relax_zrange (expr_let y := e in partial.expr.reify relax_zrange (f (inl (Var y))))%expr end | type.type_primitive type.Z as t - => fun (x : sign * expr t + type.interp t) - (f : sign * expr t + type.interp t -> value var tC) + => fun (x : Zdata * expr t + type.interp t) + (f : Zdata * expr t + type.interp t -> value var tC) => match x with - | inl (sgn, e) + | inl (data, e) => if is_var_like e - then f (inl (sgn, e)) - else partial.expr.reflect (expr_let y := e in partial.expr.reify (f (inl (sgn, Var y)%core)))%expr + then f (inl (data, e)) + else partial.expr.reflect + relax_zrange + (expr_let y := (partial.expr.reify relax_zrange (t:=t) x) in + partial.expr.reify relax_zrange (f (inl (data, Var y)%core)))%expr | inr v => f (inr v) end | type.type_primitive _ as t @@ -3623,7 +3973,10 @@ Module Compilers. | inl e => match invert_Var e with | Some v => f (inl (Var v)) - | None => partial.expr.reflect (expr_let y := e in partial.expr.reify (f (inl (Var y))))%expr + | None => partial.expr.reflect + relax_zrange + (expr_let y := e in + partial.expr.reify relax_zrange (f (inl (Var y))))%expr end | inr v => f (inr v) (* FIXME: do not substitute [S (big stuck term)] *) end @@ -3635,7 +3988,7 @@ Module Compilers. => fun (xf : expr (tx * (tx -> tC)) + value var tx * value var (tx -> tC)) => match xf with | inr (x, f) => interp_let_in x f - | _ => expr.reflect (AppIdent idc (expr.reify (t:=tx * (tx -> tC)) xf)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=tx * (tx -> tC)) xf)) end | ident.nil t => fun _ => inr (@nil (value var t)) @@ -3647,26 +4000,26 @@ Module Compilers. => fun (x_xs : expr (t * type.list t) + value var t * (expr (type.list t) + list (value var t))) => match x_xs return expr (type.list t) + list (value var t) with | inr (x, inr xs) => inr (cons x xs) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=t * type.list t) x_xs)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=t * type.list t) x_xs)) end | ident.fst A B as idc => fun x : expr (A * B) + value var A * value var B => match x with | inr x => fst x - | _ => expr.reflect (AppIdent idc (expr.reify (t:=A*B) x)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=A*B) x)) end | ident.snd A B as idc => fun x : expr (A * B) + value var A * value var B => match x with | inr x => snd x - | _ => expr.reflect (AppIdent idc (expr.reify (t:=A*B) x)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=A*B) x)) end | ident.bool_rect T as idc => fun (true_case_false_case_b : expr (T * T * type.bool) + (expr (T * T) + value var T * value var T) * (expr type.bool + bool)) => match true_case_false_case_b with | inr (inr (true_case, false_case), inr b) => @bool_rect (fun _ => value var T) true_case false_case b - | _ => expr.reflect (AppIdent idc (expr.reify (t:=T*T*type.bool) true_case_false_case_b)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=T*T*type.bool) true_case_false_case_b)) end | ident.nat_rect P as idc => fun (O_case_S_case_n : expr (P * (type.nat * P -> P) * type.nat) + (expr (P * (type.nat * P -> P)) + value var P * value var (type.nat * P -> P)) * (expr type.nat + nat)) @@ -3676,7 +4029,7 @@ Module Compilers. O_case (fun n' rec => S_case (inr (inr n', rec))) n - | _ => expr.reflect (AppIdent idc (expr.reify (t:=P * (type.nat * P -> P) * type.nat) O_case_S_case_n)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=P * (type.nat * P -> P) * type.nat) O_case_S_case_n)) end | ident.list_rect A P as idc => fun (nil_case_cons_case_ls : expr (P * (A * type.list A * P -> P) * type.list A) + (expr (P * (A * type.list A * P -> P)) + value var P * value var (A * type.list A * P -> P)) * (expr (type.list A) + list (value var A))) @@ -3688,16 +4041,16 @@ Module Compilers. nil_case (fun x xs rec => cons_case (inr (inr (x, inr xs), rec))) ls - | _ => expr.reflect (AppIdent idc (expr.reify (t:=P * (A * type.list A * P -> P) * type.list A) nil_case_cons_case_ls)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=P * (A * type.list A * P -> P) * type.list A) nil_case_cons_case_ls)) end | ident.List.nth_default type.Z as idc - => fun (default_ls_idx : expr (type.Z * type.list type.Z * type.nat) + (expr (type.Z * type.list type.Z) + (sign * expr type.Z + type.interp type.Z) * (expr (type.list type.Z) + list (value var type.Z))) * (expr type.nat + nat)) + => fun (default_ls_idx : expr (type.Z * type.list type.Z * type.nat) + (expr (type.Z * type.list type.Z) + (_ * expr type.Z + type.interp type.Z) * (expr (type.list type.Z) + list (value var type.Z))) * (expr type.nat + nat)) => match default_ls_idx with | inr (inr (default, inr ls), inr idx) => List.nth_default default ls idx | inr (inr (inr default, ls), inr idx) - => expr.reflect (AppIdent (ident.List.nth_default_concrete default idx) (expr.reify (t:=type.list type.Z) ls)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=type.Z * type.list type.Z * type.nat) default_ls_idx)) + => expr.reflect relax_zrange (AppIdent (ident.List.nth_default_concrete default idx) (expr.reify relax_zrange (t:=type.list type.Z) ls)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=type.Z * type.list type.Z * type.nat) default_ls_idx)) end | ident.List.nth_default (type.type_primitive A) as idc => fun (default_ls_idx : expr (A * type.list A * type.nat) + (expr (A * type.list A) + (expr A + type.interp A) * (expr (type.list A) + list (value var A))) * (expr type.nat + nat)) @@ -3705,44 +4058,44 @@ Module Compilers. | inr (inr (default, inr ls), inr idx) => List.nth_default default ls idx | inr (inr (inr default, ls), inr idx) - => expr.reflect (AppIdent (ident.List.nth_default_concrete default idx) (expr.reify (t:=type.list A) ls)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=A * type.list A * type.nat) default_ls_idx)) + => expr.reflect relax_zrange (AppIdent (ident.List.nth_default_concrete default idx) (expr.reify relax_zrange (t:=type.list A) ls)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=A * type.list A * type.nat) default_ls_idx)) end | ident.List.nth_default A as idc => fun (default_ls_idx : expr (A * type.list A * type.nat) + (expr (A * type.list A) + value var A * (expr (type.list A) + list (value var A))) * (expr type.nat + nat)) => match default_ls_idx with | inr (inr (default, inr ls), inr idx) => List.nth_default default ls idx - | _ => expr.reflect (AppIdent idc (expr.reify (t:=A * type.list A * type.nat) default_ls_idx)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=A * type.list A * type.nat) default_ls_idx)) end | ident.List.nth_default_concrete A default idx as idc => fun (ls : expr (type.list A) + list (value var A)) => match ls with | inr ls - => List.nth_default (expr.reflect (t:=A) (AppIdent (ident.primitive default) TT)) ls idx - | _ => expr.reflect (AppIdent idc (expr.reify (t:=type.list A) ls)) + => List.nth_default (expr.reflect relax_zrange (t:=A) (AppIdent (ident.primitive default) TT)) ls idx + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=type.list A) ls)) end | ident.Z_mul_split as idc => fun (x_y_z : (expr (type.Z * type.Z * type.Z) + - (expr (type.Z * type.Z) + (sign * expr type.Z + Z) * (sign * expr type.Z + Z)) * (sign * expr type.Z + Z))%type) - => match x_y_z return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + (expr (type.Z * type.Z) + (_ * expr type.Z + Z) * (_ * expr type.Z + Z)) * (_ * expr type.Z + Z))%type) + => match x_y_z return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr (inr x, inr y), inr z) => let result := ident.interp idc (x, y, z) in inr (inr (fst result), inr (snd result)) | inr (inr (inr x, y), z) - => expr.reflect (AppIdent (ident.Z.mul_split_concrete x) (expr.reify (t:=type.Z*type.Z) (inr (y, z)))) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_*_) x_y_z)) + => expr.reflect relax_zrange (AppIdent (ident.Z.mul_split_concrete x) (expr.reify relax_zrange (t:=type.Z*type.Z) (inr (y, z)))) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_*_) x_y_z)) end | ident.Z_add_get_carry as idc => fun (x_y_z : (expr (type.Z * type.Z * type.Z) + - (expr (type.Z * type.Z) + (sign * expr type.Z + Z) * (sign * expr type.Z + Z)) * (sign * expr type.Z + Z))%type) - => match x_y_z return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + (expr (type.Z * type.Z) + (_ * expr type.Z + Z) * (_ * expr type.Z + Z)) * (_ * expr type.Z + Z))%type) + => match x_y_z return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr (inr x, inr y), inr z) => let result := ident.interp idc (x, y, z) in inr (inr (fst result), inr (snd result)) | inr (inr (inr x, y), z) - => let default := expr.reflect (AppIdent (ident.Z.add_get_carry_concrete x) (expr.reify (t:=type.Z*type.Z) (inr (y, z)))) in - match (y,z) with + => let default := expr.reflect relax_zrange (AppIdent (ident.Z.add_get_carry_concrete x) (expr.reify relax_zrange (t:=type.Z*type.Z) (inr (y, z)))) in + match (y, z) with | (inr xx, inl e) | (inl e, inr xx) => if Z.eqb xx 0 @@ -3750,45 +4103,45 @@ Module Compilers. else default | _ => default end - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_*_) x_y_z)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_*_) x_y_z)) end | ident.Z_add_with_get_carry as idc => fun (x_y_z_a : (expr (_ * _ * _ * _) + (expr (_ * _ * _) + - (expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) * - (sign * expr _ + type.interp _)) * (sign * expr _ + type.interp _))%type) - => match x_y_z_a return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + (expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) * + (_ * expr _ + type.interp _)) * (_ * expr _ + type.interp _))%type) + => match x_y_z_a return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr (inr (inr x, inr y), inr z), inr a) => let result := ident.interp idc (x, y, z, a) in inr (inr (fst result), inr (snd result)) | inr (inr (inr (inr x, y), z), a) - => expr.reflect (AppIdent (ident.Z.add_with_get_carry_concrete x) (expr.reify (t:=type.Z*type.Z*type.Z) (inr (inr (y, z), a)))) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_*_*_) x_y_z_a)) + => expr.reflect relax_zrange (AppIdent (ident.Z.add_with_get_carry_concrete x) (expr.reify relax_zrange (t:=type.Z*type.Z*type.Z) (inr (inr (y, z), a)))) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_*_*_) x_y_z_a)) end | ident.Z_sub_get_borrow as idc => fun (x_y_z : (expr (type.Z * type.Z * type.Z) + - (expr (type.Z * type.Z) + (sign * expr type.Z + Z) * (sign * expr type.Z + Z)) * (sign * expr type.Z + Z))%type) - => match x_y_z return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + (expr (type.Z * type.Z) + (_ * expr type.Z + Z) * (_ * expr type.Z + Z)) * (_ * expr type.Z + Z))%type) + => match x_y_z return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr (inr x, inr y), inr z) => let result := ident.interp idc (x, y, z) in inr (inr (fst result), inr (snd result)) | inr (inr (inr x, y), z) - => expr.reflect (AppIdent (ident.Z.sub_get_borrow_concrete x) (expr.reify (t:=type.Z*type.Z) (inr (y, z)))) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_*_) x_y_z)) + => expr.reflect relax_zrange (AppIdent (ident.Z.sub_get_borrow_concrete x) (expr.reify relax_zrange (t:=type.Z*type.Z) (inr (y, z)))) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_*_) x_y_z)) end | ident.Z_mul_split_concrete _ as idc | ident.Z.sub_get_borrow_concrete _ as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => match x_y return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => match x_y return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr x, inr y) => let result := ident.interp idc (x, y) in inr (inr (fst result), inr (snd result)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) end | ident.Z.add_get_carry_concrete _ as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => let default := expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) in - match x_y return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => let default := expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) in + match x_y return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr x, inr y) => let result := ident.interp idc (x, y) in inr (inr (fst result), inr (snd result)) @@ -3801,156 +4154,185 @@ Module Compilers. end | ident.Z.add_with_get_carry_concrete _ as idc => fun (x_y_z : (expr (type.Z * type.Z * type.Z) + - (expr (type.Z * type.Z) + (sign * expr type.Z + Z) * (sign * expr type.Z + Z)) * (sign * expr type.Z + Z))%type) - => match x_y_z return (expr _ + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) with + (expr (type.Z * type.Z) + (_ * expr type.Z + Z) * (_ * expr type.Z + Z)) * (_ * expr type.Z + Z))%type) + => match x_y_z return (expr _ + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) with | inr (inr (inr x, inr y), inr z) => let result := ident.interp idc (x, y, z) in inr (inr (fst result), inr (snd result)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_*_) x_y_z)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_*_) x_y_z)) end | ident.pred as idc | ident.Nat_succ as idc => fun x : expr _ + type.interp _ => match x return expr _ + type.interp _ with | inr x => inr (ident.interp idc x) - | inl x => expr.reflect (AppIdent idc x) + | inl x => expr.reflect relax_zrange (AppIdent idc x) end | ident.Z_of_nat as idc => fun x : expr _ + type.interp _ - => match x return sign * expr _ + type.interp _ with + => match x return _ * expr _ + type.interp _ with | inr x => inr (ident.interp idc x) - | inl x => expr.reflect (AppIdent idc x) + | inl x => expr.reflect relax_zrange (AppIdent idc x) end | ident.Z_opp as idc - => fun x : sign * expr _ + type.interp _ - => match x return sign * expr _ + type.interp _ with + => fun x : _ * expr _ + type.interp _ + => match x return _ * expr _ + type.interp _ with | inr x => inr (ident.interp idc x) - | inl (sgn, x) => inl (sign.opp sgn, x) + | inl (r, x) + => match invert_Z_opp x with + | Some x => inl (r, x) + | None => inl (ZRange.ident.option.interp idc r, AppIdent idc x) + end end | ident.Z_shiftr _ as idc | ident.Z_shiftl _ as idc | ident.Z_land _ as idc - => fun x : sign * expr _ + type.interp _ - => match x return sign * expr _ + type.interp _ with + => fun x : _ * expr _ + type.interp _ + => match x return _ * expr _ + type.interp _ with | inr x => inr (ident.interp idc x) - | inl _ => expr.reflect (AppIdent idc (expr.reify (t:=type.Z) x)) + | inl _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=type.Z) x)) end | ident.Nat_add as idc | ident.Nat_mul as idc | ident.Z_pow as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => match x_y return sign * expr _ + type.interp _ with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => match x_y return _ * expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) end | ident.Z_eqb as idc | ident.Z_leb as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) => match x_y return expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) end | ident.Z_div as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => let default := expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) in - match x_y return sign * expr _ + type.interp _ with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => let default := expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) in + match x_y return _ * expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) | inr (x, inr y) => if Z.eqb y (2^Z.log2 y) - then expr.reflect (AppIdent (ident.Z.shiftr (Z.log2 y)) (expr.reify (t:=type.Z) x)) + then expr.reflect relax_zrange (AppIdent (ident.Z.shiftr (Z.log2 y)) (expr.reify relax_zrange (t:=type.Z) x)) else default | _ => default end | ident.Z_modulo as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => let default := expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) in - match x_y return sign * expr _ + type.interp _ with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => let default := expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) in + match x_y return _ * expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) | inr (x, inr y) => if Z.eqb y (2^Z.log2 y) - then expr.reflect (AppIdent (ident.Z.land (y-1)) (expr.reify (t:=type.Z) x)) + then expr.reflect relax_zrange (AppIdent (ident.Z.land (y-1)) (expr.reify relax_zrange (t:=type.Z) x)) else default | _ => default end | ident.Z_mul as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => let default := expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) in - match x_y return sign * expr _ + type.interp _ with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => let default := expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y)) in + match x_y return _ * expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) - | inr (inr x, inl (sgn, e)) - | inr (inl (sgn, e), inr x) - => if Z.eqb x 0 + | inr (inr x, inl (data, e) as y) + | inr (inl (data, e) as y, inr x) + => let data' := ZRange.ident.option.interp idc (data, Some r[x~>x]%zrange) in + if Z.eqb x 0 then inr 0%Z else if Z.eqb x 1 - then inl (sgn, e) + then y else if Z.eqb x (-1) - then inl (sign.opp sgn, e) - else let sgn' := sign.mul sgn (sign.of_Z x) in - let x' := Z.abs x in - if Z.eqb x' (2^Z.log2 x') - then inl (sgn', - AppIdent (ident.Z.shiftl (Z.log2 x')) e) - else inl (sgn', - AppIdent idc (ident.primitive (t:=type.Z) x @@ TT, e)) - | inr (inl (sgna, a), inl (sgnb, b)) - => inl (sign.mul sgna sgnb, AppIdent idc (a, b)) + then inl (data', AppIdent ident.Z.opp (expr.reify relax_zrange (t:=type.Z) y)) + else if Z.eqb x (2^Z.log2 x) + then inl (data', + AppIdent (ident.Z.shiftl (Z.log2 x)) (expr.reify relax_zrange (t:=type.Z) y)) + else inl (data', + AppIdent idc (ident.primitive (t:=type.Z) x @@ TT, expr.reify relax_zrange (t:=type.Z) y)) + | inr (inl (dataa, a), inl (datab, b)) + => inl (ZRange.ident.option.interp idc (dataa, datab), + AppIdent idc (a, b)) | inl _ => default end | ident.Z_add as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => let default := expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) in - match x_y return sign * expr _ + type.interp _ with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => let default0 := AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y) in + let default := expr.reflect relax_zrange default0 in + match x_y return _ * expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) - | inr (inr x, inl (sgn, e)) - | inr (inl (sgn, e), inr x) - => if Z.eqb x 0 - then inl (sgn, e) - else match sgn with - | sign.pos => default - | sign.neg - => inl (sign.pos, - AppIdent - ident.Z.sub - (ident.primitive (t:=type.Z) x @@ TT, - e)) - end - | inr (inl (sign.pos, p), inl (sign.neg, n)) - | inr (inl (sign.neg, n), inl (sign.pos, p)) - => inl (sign.pos, AppIdent ident.Z.sub (p, n)%expr) - | inr (inl (sign.neg, a), inl (sign.neg, b)) - => inl (sign.neg, AppIdent idc (a, b)%expr) - | inr (inl (sign.pos, _), inl (sign.pos, _)) + | inr (inr x, inl (data, e) as y) + | inr (inl (data, e) as y, inr x) + => let data' := ZRange.ident.option.interp idc (data, Some r[x~>x]%zrange) in + if Z.eqb x 0 + then y + else inl (data', match invert_Z_opp e with + | Some e => AppIdent + ident.Z.sub + (ident.primitive (t:=type.Z) x @@ TT, + e) + | None => default0 + end) + | inr (inl (dataa, a), inl (datab, b)) + => let data' := ZRange.ident.option.interp idc (dataa, datab) in + match invert_Z_opp a, invert_Z_opp b with + | Some a, Some b + => inl (data', + AppIdent + ident.Z.opp + (idc @@ (a, b))) + | Some a, None + => inl (data', AppIdent ident.Z.sub (b, a)) + | None, Some b + => inl (data', AppIdent ident.Z.sub (a, b)) + | None, None => inl (data', default0) + end | inl _ => default end | ident.Z_sub as idc - => fun (x_y : expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) - => let default := expr.reflect (AppIdent idc (expr.reify (t:=_*_) x_y)) in - match x_y return sign * expr _ + type.interp _ with + => fun (x_y : expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) + => let default0 := AppIdent idc (expr.reify relax_zrange (t:=_*_) x_y) in + let default := expr.reflect relax_zrange default0 in + match x_y return _ * expr _ + type.interp _ with | inr (inr x, inr y) => inr (ident.interp idc (x, y)) - | inr (inr x, inl (sgn, e)) - => if Z.eqb x 0 - then inl (sign.opp sgn, e) - else default - | inr (inl (sgn, e), inr x) - => if Z.eqb x 0 - then inl (sgn, e) - else default - | inr (inl (sign.pos, p), inl (sign.neg, n)) - => inl (sign.pos, AppIdent ident.Z.add (p, n)) - | inr (inl (sign.neg, n), inl (sign.pos, p)) - => inl (sign.neg, AppIdent ident.Z.add (p, n)) - | inr (inl (sign.neg, a), inl (sign.neg, b)) - => inl (sign.pos, AppIdent ident.Z.sub (b, a)) - | inr (inl (sign.pos, _), inl (sign.pos, _)) + | inr (inr x, inl (data, e)) + => let data' := ZRange.ident.option.interp idc (Some r[x~>x]%zrange, data) in + if Z.eqb x 0 + then inl (data, AppIdent ident.Z.opp e) + else inl (data, default0) + | inr (inl (data, e), inr x) + => let data' := ZRange.ident.option.interp idc (data, Some r[x~>x]%zrange) in + if Z.eqb x 0 + then inl (data', e) + else inl (data', default0) + | inr (inl (dataa, a), inl (datab, b)) + => let data' := ZRange.ident.option.interp idc (dataa, datab) in + match invert_Z_opp a, invert_Z_opp b with + | Some a, Some b + => inl (data', + AppIdent + ident.Z.opp + (idc @@ (a, b))) + | Some a, None + => inl (data', AppIdent ident.Z.add (b, a)) + | None, Some b + => inl (data', AppIdent ident.Z.add (a, b)) + | None, None => inl (data', default0) + end | inl _ => default end | ident.Z_zselect as idc | ident.Z_add_modulo as idc => fun (x_y_z : (expr (_ * _ * _) + - (expr (_ * _) + (sign * expr _ + type.interp _) * (sign * expr _ + type.interp _)) * (sign * expr _ + type.interp _))%type) - => match x_y_z return sign * expr _ + type.interp _ with + (expr (_ * _) + (_ * expr _ + type.interp _) * (_ * expr _ + type.interp _)) * (_ * expr _ + type.interp _))%type) + => match x_y_z return _ * expr _ + type.interp _ with | inr (inr (inr x, inr y), inr z) => inr (ident.interp idc (x, y, z)) - | _ => expr.reflect (AppIdent idc (expr.reify (t:=_*_*_) x_y_z)) + | _ => expr.reflect relax_zrange (AppIdent idc (expr.reify relax_zrange (t:=_*_*_) x_y_z)) + end + | ident.Z_cast r as idc + => fun (x : _ * expr _ + type.interp _) + => match x with + | inr x => inr (ident.interp idc x) + | inl (data, e) + => inl (ZRange.ident.option.interp idc data, e) end end. End interp. @@ -3958,25 +4340,233 @@ Module Compilers. End partial. Section partial_reduce. - Context {var : type -> Type}. + Context (relax_zrange : zrange -> option zrange) + {var : type -> Type}. Fixpoint partial_reduce' {t} (e : @expr (partial.value var) t) : partial.value var t := match e in expr.expr t return partial.value var t with | Var t v => v | TT => inr tt - | AppIdent s d idc args => partial.ident.interp idc (@partial_reduce' _ args) + | AppIdent s d idc args => partial.ident.interp relax_zrange idc (@partial_reduce' _ args) | Pair A B a b => inr (@partial_reduce' A a, @partial_reduce' B b) | App s d f x => @partial_reduce' _ f (@partial_reduce' _ x) | Abs s d f => fun x => @partial_reduce' d (f x) end. Definition partial_reduce {t} (e : @expr (partial.value var) t) : @expr var t - := partial.expr.reify (@partial_reduce' t e). + := partial.expr.reify relax_zrange (@partial_reduce' t e). + + Fixpoint extend_concrete_list_with_obounds {t} + (extend_with_obounds : ZRange.type.option.interp t -> partial.value var t -> partial.value var t ) + (ls : list (ZRange.type.option.interp t)) + (e : list (partial.value var t)) + {struct ls} + : list (partial.value var t) + := match ls with + | nil => nil + | cons b bs + => cons (extend_with_obounds + b + (hd (partial.value_default _) e)) + (@extend_concrete_list_with_obounds + t extend_with_obounds bs (tl e)) + end. + + Fixpoint extend_list_expr_with_obounds {t} + (extend_with_obounds : ZRange.type.primitive.option.interp t -> partial.value var t -> partial.value var t ) + (starting_index : nat) + (ls : list (ZRange.type.option.interp t)) + (e : @expr var (type.list t)) + {struct ls} + : list (partial.value var t) + := match ls with + | nil => nil + | cons b bs + => cons (extend_with_obounds + b + (partial.expr.reflect + relax_zrange + (AppIdent + (ident.List_nth_default_concrete + DefaultValue.type.default starting_index) + e))) + (@extend_list_expr_with_obounds + t extend_with_obounds (S starting_index) bs e) + end. + + Fixpoint extend_with_obounds {t} : ZRange.type.option.interp t -> partial.value var t -> partial.value var t + := match t return ZRange.type.option.interp t -> partial.value var t -> partial.value var t with + | type.type_primitive type.Z + => fun (r : option zrange) (e : option zrange * expr _ + type.interp _) + => match r, e with + | Some r, inr v => inr (ident.interp (ident.Z.cast r) v) + | Some r, inl (data, e) + => inl (ZRange.ident.option.interp (ident.Z.cast r) data, e) + | None, e => e + end + | type.type_primitive t => fun _ => id + | type.prod A B + => fun '((ra, rb) : ZRange.type.option.interp A * ZRange.type.option.interp B) + (e : expr _ + partial.value var A * partial.value var B) + => match e with + | inr (a, b) + => inr (@extend_with_obounds A ra a, + @extend_with_obounds B rb b) + | inl e + => if partial.ident.is_var_like e + then inr (@extend_with_obounds A ra (partial.expr.reflect relax_zrange (AppIdent ident.fst e)), + @extend_with_obounds B rb (partial.expr.reflect relax_zrange (AppIdent ident.snd e))) + else inl e + end + | type.arrow s d => fun _ => id + | type.list A + => fun (ls : Datatypes.list (ZRange.type.option.interp A)) + (e : expr _ + list (partial.value var A)) + => match e with + | inl e + => match A return (ZRange.type.option.interp A -> partial.value var A -> partial.value var A) + -> Datatypes.list (ZRange.type.option.interp A) + -> expr (type.list A) + -> partial.value var (type.list A) + with + | type.type_primitive A + => fun extend_with_obounds ls e + => inr (extend_list_expr_with_obounds + extend_with_obounds 0 ls e) + | A' + => fun _ _ e => inl e + end (@extend_with_obounds A) ls e + | inr e => inr (extend_concrete_list_with_obounds + (@extend_with_obounds A) ls e) + end + end. + Definition extend_with_bounds {t} + (b : ZRange.type.interp t) + (e : partial.value var t) + : partial.value var t + := @extend_with_obounds t (ZRange.type.option.Some b) e. + + Section extract. + Context (fill_var : forall t, var t). + Fixpoint extract_bounds {t} : partial.value var t -> ZRange.type.option.interp t + := match t return partial.value var t -> ZRange.type.option.interp t with + | type.type_primitive type.Z + => fun (e : option zrange * _ + type.interp _) + => match e with + | inl (data, _) => data + | inr z => Some r[z~>z]%zrange + end + | type.type_primitive t => fun _ => ZRange.type.option.None + | type.prod A B + => fun (e : expr _ + partial.value var A * partial.value var B) + => match e with + | inl e => ZRange.type.option.None + | inr (a, b) => (@extract_bounds A a, @extract_bounds B b) + end + | type.arrow s d + => fun (f : partial.value var s -> partial.value var d) + (b : ZRange.type.option.interp s) + => @extract_bounds d (f (extend_with_obounds b (partial.expr.reflect relax_zrange (Var (fill_var _))))) + | type.list A + => fun (e : expr _ + list (partial.value var A)) + => match e with + | inl e => ZRange.type.option.None + | inr ls => List.map (@extract_bounds A) ls + end + end. + End extract. + + Definition partial_reduce_with_bounds1' {s d} (e : @expr (partial.value var) (s -> d)) + (b : ZRange.type.interp s) + : partial.value var (s -> d) + := fun x : partial.value var s + => partial_reduce' e (extend_with_bounds b x). + + Definition partial_reduce_with_bounds1 {s d} (e : @expr (partial.value var) (s -> d)) + (b : ZRange.type.interp s) + := partial.expr.reify relax_zrange (@partial_reduce_with_bounds1' s d e b). End partial_reduce. Definition PartialReduce {t} (e : Expr t) : Expr t - := fun var => @partial_reduce var t (e _). + := fun var => @partial_reduce (fun r => Some r) var t (e _). + + Definition PartialReduceWithBounds1 + (relax_zrange : zrange -> option zrange) + {s d} (e : Expr (s -> d)) (b : ZRange.type.interp s) + : Expr (s -> d) + := fun var => @partial_reduce_with_bounds1 relax_zrange var s d (e _) b. + + Definition CheckedPartialReduceWithBounds1 + (relax_zrange : zrange -> option zrange) + {s d} (e : Expr (s -> d)) + (b_in : ZRange.type.interp s) + (b_out : ZRange.type.interp d) + : Expr (s -> d) + ZRange.type.option.interp d + := dlet_nd v := (fun var => @partial_reduce_with_bounds1' relax_zrange var s d (e _) b_in) in + let b_computed := extract_bounds relax_zrange (@DefaultValue.type.default) (v type.interp) (ZRange.type.option.Some b_in) in + if ZRange.type.option.is_tighter_than b_computed (ZRange.type.option.Some b_out) + then @inl (Expr (s -> d)) _ (fun var => partial.expr.reify relax_zrange (v var)) + else @inr _ (ZRange.type.option.interp d) b_computed. + + Definition CheckedPartialReduceWithBounds0 + (relax_zrange : zrange -> option zrange) + {t} (e : Expr t) + (b_out : ZRange.type.interp t) + : Expr t + ZRange.type.option.interp t + := dlet_nd v := (fun var => @partial_reduce' relax_zrange var t (e _)) in + let b_computed := extract_bounds relax_zrange (@DefaultValue.type.default) (v type.interp) in + if ZRange.type.option.is_tighter_than b_computed (ZRange.type.option.Some b_out) + then @inl (Expr t) _ (fun var => partial.expr.reify relax_zrange (v var)) + else @inr _ (ZRange.type.option.interp t) b_computed. + + Axiom admit_pf : False. + Local Notation admit := (match admit_pf with end). + + Theorem CheckedPartialReduceWithBounds1_Correct + (relax_zrange : zrange -> option zrange) + (Hrelax : forall r r' z, is_tighter_than_bool z r = true + -> relax_zrange r = Some r' + -> is_tighter_than_bool z r' = true) + {s d} (e : Expr (s -> d)) + (b_in : ZRange.type.interp s) + (b_out : ZRange.type.interp d) + rv (Hrv : CheckedPartialReduceWithBounds1 relax_zrange e b_in b_out = inl rv) + : forall arg + (Harg : ZRange.type.is_bounded_by b_in arg = true), + Interp rv arg = Interp e arg + /\ ZRange.type.is_bounded_by b_out (Interp rv arg) = true. + Proof. + cbv [CheckedPartialReduceWithBounds1 Let_In] in *; + break_innermost_match_hyps; inversion_sum; subst. + intros arg Harg. + split. + { exact admit. (* correctness of interp *) } + { eapply ZRange.type.option.is_tighter_than_Some_is_bounded_by; [ eassumption | ]. + cbv [expr.Interp]. + revert Harg. + exact admit. (* boundedness *) } + Qed. + + Theorem CheckedPartialReduceWithBounds0_Correct + (relax_zrange : zrange -> option zrange) + (Hrelax : forall r r' z, is_tighter_than_bool z r = true + -> relax_zrange r = Some r' + -> is_tighter_than_bool z r' = true) + {t} (e : Expr t) + (b_out : ZRange.type.interp t) + rv (Hrv : CheckedPartialReduceWithBounds0 relax_zrange e b_out = inl rv) + : Interp rv = Interp e + /\ ZRange.type.is_bounded_by b_out (Interp rv) = true. + Proof. + cbv [CheckedPartialReduceWithBounds0 Let_In] in *; + break_innermost_match_hyps; inversion_sum; subst. + split. + { exact admit. (* correctness of interp *) } + { eapply ZRange.type.option.is_tighter_than_Some_is_bounded_by; [ eassumption | ]. + cbv [expr.Interp]. + exact admit. (* boundedness *) } + Qed. Module DeadCodeElimination. Fixpoint compute_live' {t} (e : @expr (fun _ => PositiveSet.t) t) (cur_idx : positive) @@ -4165,258 +4755,12 @@ Module Compilers. := fun var => reassociate max_const_val (e _). End ReassociateSmallConstants. - Module BoundsAnalysis. - Module type. - Local Set Boolean Equality Schemes. - Local Set Decidable Equality Schemes. - Variant primitive := unit | Z | ZBounded (lower : Z) (upper : Z). - Inductive type := type_primitive (_:primitive) | prod (A B : type) | list (A : primitive). - - Module Export Coercions. - Global Coercion type_primitive : primitive >-> type. - End Coercions. - - Fixpoint transport_positive (P : positive -> Type) - (A B : positive) - : P A -> option (P B) - := match A, B return P A -> option (P B) with - | xI x, xI y => transport_positive (fun p => P (xI p)) x y - | xI _, _ => fun _ => None - | xO x, xO y => transport_positive (fun p => P (xO p)) x y - | xO _, _ => fun _ => None - | xH, xH => fun x => Some x - | xH, _ => fun _ => None - end. - Definition transport_Z (P : BinInt.Z -> Type) - (A B : BinInt.Z) - : P A -> option (P B) - := match A, B return P A -> option (P B) with - | Z0, Z0 => fun x => Some x - | Z0, _ => fun _ => None - | Zpos x, Zpos y => transport_positive (fun p => P (Zpos p)) x y - | Zpos _, _ => fun _ => None - | Zneg x, Zneg y => transport_positive (fun p => P (Zneg p)) x y - | Zneg _, _ => fun _ => None - end. - - Definition transport_primitive (P : primitive -> Type) - (A B : primitive) - : P A -> option (P B) - := match A, B return P A -> option (P B) with - | unit, unit => fun x => Some x - | unit, _ => fun _ => None - | Z, Z => fun x => Some x - | Z, _ => fun _ => None - | ZBounded l u, ZBounded l' u' - => fun x - => match transport_Z (fun u => P (ZBounded l u)) u u' x with - | Some x => transport_Z (fun l => P (ZBounded l u')) l l' x - | None => None - end - | ZBounded _ _, _ => fun _ => None - end. - - Fixpoint transport (P : type -> Type) (A B : type) - : P A -> option (P B) - := match A, B return P A -> option (P B) with - | type_primitive x, type_primitive y => transport_primitive P x y - | type_primitive _, _ => fun _ => None - | list A, list B => transport_primitive (fun A => P (list A)) A B - | list _, _ => fun _ => None - | prod A B, prod A' B' - => fun x - => match transport (fun B => P (prod A B)) B B' x with - | Some x => transport (fun A => P (prod A B')) A A' x - | None => None - end - | prod _ _, _ => fun _ => None - end. - - (** TODO: MOVE ME *) - Record BoundedZ (lower upper : BinInt.Z) - := { value :> BinInt.Z; - value_bounded : andb (Z.min lower upper <=? value) - (value <=? Z.max upper lower) - = true }. - Global Arguments value {_ _} _. - Global Arguments value_bounded [_ _] _, _ _ _. - - Definition fix_bool {b} : b = true -> b = true - := if b as b return b = true -> b = true - then fun _ => eq_refl - else fun x => x. - - Module primitive. - Definition interp (t : primitive) - := match t with - | unit => Datatypes.unit - | Z => BinInt.Z - | ZBounded lower upper => BoundedZ lower upper - end%type. - End primitive. - - Fixpoint interp (t : type) - := match t with - | prod A B => interp A * interp B - | list A => Datatypes.list (primitive.interp A) - | type_primitive t => primitive.interp t - end%type. - - Module Export Notations. - Export Coercions. - Delimit Scope btype_scope with btype. - Bind Scope btype_scope with type. - Notation "()" := unit : btype_scope. - Notation "A * B" := (prod A B) : btype_scope. - Notation "r[ l ~> u ]" := (ZBounded l u) : btype_scope. - Notation type := type. - End Notations. - End type. - Export type.Notations. - - Module ident. + (*Module Indexed. + Module Export Range. Import type. - Inductive ident : type -> type -> Set := - | primitive {t : type.primitive} (v : interp t) : ident () t - | nil {t} : ident () (list t) - | cons {t : type.primitive} : ident (t * list t) (list t) - | fst {A B} : ident (A * B) A - | snd {A B} : ident (A * B) B - | List_nth {T : type.primitive} (n : nat) : ident (list T) T - | mul (T1 T2 Tout : type.primitive) : ident (T1 * T2) Tout - | add (T1 T2 Tout : type.primitive) : ident (T1 * T2) Tout - | sub (T1 T2 Tout : type.primitive) : ident (T1 * T2) Tout - | shiftr (T1 Tout : type.primitive) (offset : BinInt.Z) : ident T1 Tout - | shiftl (T1 Tout : type.primitive) (offset : BinInt.Z) : ident T1 Tout - | land (T1 Tout : type.primitive) (mask : BinInt.Z) : ident T1 Tout - | cast (T1 Tout : type.primitive) : ident T1 Tout - | mul_split_concrete (T1 T2 Tout1 Tout2 : type.primitive) (split_at : BinInt.Z) : ident (T1 * T2) (Tout1 * Tout2) - | add_get_carry_concrete (T1 T2 Tout1 Tout2 : type.primitive) (split_at : BinInt.Z) : ident (T1 * T2) (Tout1 * Tout2) - | add_with_get_carry_concrete (T1 T2 T3 Tout1 Tout2 : type.primitive) (split_at : BinInt.Z) : ident (T1 * T2 * T3) (Tout1 * Tout2) - | sub_get_borrow_concrete (T1 T2 Tout1 Tout2 : type.primitive) (split_at : BinInt.Z) : ident (T1 * T2) (Tout1 * Tout2) - | zselect (T1 T2 T3 Tout : type.primitive) : ident (T1 * T2 * T3) Tout - | add_modulo (T1 T2 T3 Tout : type.primitive) : ident (T1 * T2 * T3) Tout - . - Notation curry0 f - := (fun 'tt => f). - Notation curry2 f - := (fun '(a, b) => f a b). - Notation curry3 f - := (fun '(a, b, c) => f a b c). - - Axiom admit_pf : False. - Notation admit := (match admit_pf with end). - - Definition resize {T1 Tout : type.primitive} : type.interp T1 -> type.interp Tout - := match T1, Tout return type.interp T1 -> type.interp Tout with - | _, unit => fun _ => tt - | unit, Z => fun _ => 0 - | unit, ZBounded lower upper - => fun _ => {| value := lower ; value_bounded := fix_bool admit |} - | Z, Z => id - | Z, ZBounded lower upper - => fun v => {| value := lower + Z.modulo (v - lower) (1 + upper - lower) ; value_bounded := fix_bool admit |} - | ZBounded lower upper, Z => fun v => v.(value) - | ZBounded l u, ZBounded l' u' - => fun v - => {| value := l + Z.modulo (value v - l) (1 + u - l) ; value_bounded := fix_bool admit |} - end. - Definition resize1 {T1 T2 T1' T2' : type.primitive} - : (type.interp T1 -> type.interp T2) -> (type.interp T1' -> type.interp T2') - := fun f x => resize (f (resize x)). - Definition resize2uc {T1 T2 T3 T1' T2' T3' : type.primitive} - : (type.interp (T1 * T2) -> type.interp T3) -> (type.interp (T1' * T2') -> type.interp T3') - := fun f '((x, y) : type.interp T1' * type.interp T2') - => resize (f (resize x, resize y)). - Definition resize2uc2out {T1 T2 T3 T4 T1' T2' T3' T4' : type.primitive} - : (type.interp (T1 * T2) -> (type.interp T3 * type.interp T4)) -> - (type.interp (T1' * T2') -> (type.interp T3' * type.interp T4')) - := fun f '((x, y) : type.interp T1' * type.interp T2') - => (resize (Datatypes.fst (f (resize x, resize y))), - resize (Datatypes.snd (f (resize x, resize y)))). - Definition resize3uc {T1 T2 T3 T4 T1' T2' T3' T4' : type.primitive} - : (type.interp (T1 * T2 * T3) -> type.interp T4) -> - (type.interp (T1' * T2' * T3') -> type.interp T4') - := fun f '((x, y, z) : type.interp T1' * type.interp T2' * type.interp T3') - => (resize (f (resize x, resize y, resize z))). - Definition resize3uc2out {T1 T2 T3 T4 T5 T1' T2' T3' T4' T5' : type.primitive} - : (type.interp (T1 * T2 * T3) -> (type.interp T4 * type.interp T5)) -> - (type.interp (T1' * T2' * T3') -> (type.interp T4' * type.interp T5')) - := fun f '((x, y, z) : type.interp T1' * type.interp T2' * type.interp T3') - => (resize (Datatypes.fst (f (resize x, resize y, resize z))), - resize (Datatypes.snd (f (resize x, resize y, resize z)))). - - - - Fixpoint default {t : type} : type.interp t - := match t with - | unit => tt - | Z => -1 - | ZBounded lower upper => {| value := lower ; value_bounded := admit |} - | prod A B => (default, default) - | list A => Datatypes.nil - end. - - Definition interp {s d} (idc : ident s d) : type.interp s -> type.interp d - := match idc with - | primitive t v => curry0 v - | nil t => curry0 (@Datatypes.nil (type.interp t)) - | cons t => curry2 (@Datatypes.cons (type.interp t)) - | fst A B => @Datatypes.fst (type.interp A) (type.interp B) - | snd A B => @Datatypes.snd (type.interp A) (type.interp B) - | List_nth T n => fun ls => @List.nth_default (type.interp T) default ls n - | add T1 T2 Tout => @resize2uc type.Z type.Z type.Z _ _ _ (curry2 Z.add) - | sub T1 T2 Tout => @resize2uc type.Z type.Z type.Z _ _ _ (curry2 Z.sub) - | mul T1 T2 Tout => @resize2uc type.Z type.Z type.Z _ _ _ (curry2 Z.mul) - | shiftr _ _ n => @resize1 type.Z type.Z _ _ (fun v => Z.shiftr v n) - | shiftl _ _ n => @resize1 type.Z type.Z _ _ (fun v => Z.shiftl v n) - | land _ _ mask => @resize1 type.Z type.Z _ _ (fun v => Z.land v mask) - | cast _ _ => resize - | mul_split_concrete _ _ _ _ n => @resize2uc2out type.Z type.Z type.Z type.Z _ _ _ _ (curry2 (Z.mul_split n)) - | add_get_carry_concrete _ _ _ _ n => - @resize2uc2out type.Z type.Z type.Z type.Z _ _ _ _ (curry2 (Z.add_get_carry n)) - | add_with_get_carry_concrete _ _ _ _ _ n => - @resize3uc2out type.Z type.Z type.Z type.Z type.Z _ _ _ _ _ (curry3 (Z.add_with_get_carry n)) - | sub_get_borrow_concrete _ _ _ _ n => - @resize2uc2out type.Z type.Z type.Z type.Z _ _ _ _ (curry2 (Z.sub_get_borrow n)) - | zselect _ _ _ _ => - @resize3uc type.Z type.Z type.Z type.Z _ _ _ _ (curry3 Z.zselect) - | add_modulo _ _ _ _ => - @resize3uc type.Z type.Z type.Z type.Z _ _ _ _ (curry3 Z.add_modulo) - end. - - Module Z. - Notation mul := (@mul type.Z type.Z type.Z). - Notation sub := (@sub type.Z type.Z type.Z). - Notation add := (@add type.Z type.Z type.Z). - Notation shiftr := (@shiftr type.Z type.Z). - Notation shiftl := (@shiftl type.Z type.Z). - Notation land := (@land type.Z type.Z). - Notation mul_split_concrete := (@mul_split_concrete type.Z type.Z type.Z type.Z). - Notation add_get_carry_concrete := (@add_get_carry_concrete type.Z type.Z type.Z type.Z). - Notation add_with_get_carry_concrete := (@add_with_get_carry_concrete type.Z type.Z type.Z type.Z type.Z). - Notation sub_get_borrow_concrete := (@sub_get_borrow_concrete type.Z type.Z type.Z type.Z). - Notation zselect := (@zselect type.Z type.Z type.Z type.Z). - Notation add_modulo := (@add_modulo type.Z type.Z type.Z type.Z). - End Z. - - Module List. - Notation nth := List_nth. - End List. - - Module Notations. - Notation ident := ident. - End Notations. - End ident. - Export ident.Notations. - - Module Indexed. - Module Export Range. - Import type. - - Section with_relax. - Context (relax_zrange : zrange -> option zrange). + Section with_relax. + Context (relax_zrange : zrange -> option zrange). Definition primitive_for_option_zrange (v : option zrange) : type.primitive := match v with @@ -5234,7 +5578,7 @@ Module Compilers. let v := Indexed.expr.interp (@ident.interp) e ctx in option_cast_back relax_zrange v. End OfPHOAS. - End BoundsAnalysis. + End BoundsAnalysis.*) End Compilers. Import Associational Positional Compilers. Local Coercion Z.of_nat : nat >-> Z. @@ -5293,17 +5637,14 @@ Module test2. expr_let x1 := (Var x0 * Var x0) in (Var x1, Var x1))%expr) => idtac end. - Import BoundsAnalysis.ident. - Import BoundsAnalysis.Notations. - pose (projT2 (Option.invert_Some (BoundsAnalysis.OfPHOAS.AnalyzeBounds - (fun x => Some x) E' r[0~>10]%zrange))) as E''. + pose (PartialReduceWithBounds1 (fun r => Some r) E' r[0~>10]%zrange) as E''. lazy in E''. lazymatch (eval cbv delta [E''] in E'') with - | (expr_let 2%positive := mul r[0 ~> 10]%btype r[0 ~> 10]%btype r[0 ~> 100]%btype @@ - (x_ 1, x_ 1) in - expr_let 3%positive := mul r[0 ~> 100]%btype r[0 ~> 100]%btype r[0 ~> 10000]%btype @@ - (x_ 2, x_ 2) in - (x_ 3, x_ 3))%nexpr + | (fun var : type -> Type => + (λ x : var (type.type_primitive type.Z), + expr_let y := ident.Z.cast r[0 ~> 100] @@ (Var x * Var x) in + expr_let y0 := ident.Z.cast r[0 ~> 10000] @@ (Var y * Var y) in + (ident.Z.cast r[0 ~> 10000] @@ Var y0, ident.Z.cast r[0 ~> 10000] @@ Var y0))%expr) => idtac end. constructor. @@ -5332,21 +5673,16 @@ Module test3. Var x3 * Var x3)%expr) => idtac end. - Import BoundsAnalysis.ident. - Import BoundsAnalysis.Notations. - pose (projT2 (Option.invert_Some (BoundsAnalysis.OfPHOAS.AnalyzeBounds - (fun x => Some x) E' r[0~>10]%zrange))) as E'''. + pose (PartialReduceWithBounds1 (fun r => Some r) E' r[0~>10]%zrange) as E'''. lazy in E'''. lazymatch (eval cbv delta [E'''] in E''') with - | (expr_let 2 := mul r[0 ~> 10]%btype r[0 ~> 10]%btype r[0 ~> 100]%btype @@ (x_ 1, x_ 1) in - expr_let 3 := mul r[0 ~> 100]%btype r[0 ~> 100]%btype r[0 ~> 10000]%btype @@ - (x_ 2, x_ 2) in - expr_let 4 := mul r[0 ~> 10000]%btype r[0 ~> 10000]%btype r[0 ~> 100000000]%btype @@ - (x_ 3, x_ 3) in - expr_let 5 := mul r[0 ~> 100000000]%btype r[0 ~> 100000000]%btype - r[0 ~> 10000000000000000]%btype @@ (x_ 4, x_ 4) in - mul r[0 ~> 10000000000000000]%btype r[0 ~> 10000000000000000]%btype - r[0 ~> 100000000000000000000000000000000]%btype @@ (x_ 5, x_ 5))%nexpr + | (fun var : type -> Type => + (λ x : var (type.type_primitive type.Z), + expr_let y := ident.Z.cast r[0 ~> 100] @@ (Var x * Var x) in + expr_let y0 := ident.Z.cast r[0 ~> 10000] @@ (Var y * Var y) in + expr_let y1 := ident.Z.cast r[0 ~> 100000000] @@ (Var y0 * Var y0) in + expr_let y2 := ident.Z.cast r[0 ~> 10000000000000000] @@ (Var y1 * Var y1) in + ident.Z.cast r[0 ~> 100000000000000000000000000000000] @@ (Var y2 * Var y2))%expr) => idtac end. constructor. @@ -5366,20 +5702,17 @@ Module test4. pose (PartialReduce (CPS.CallFunWithIdContinuation (CPS.Translate (canonicalize_list_recursion E)))) as E'. lazy in E'. clear E. - Import BoundsAnalysis.ident. - Import BoundsAnalysis.Notations. - pose (projT2 (Option.invert_Some - (BoundsAnalysis.OfPHOAS.AnalyzeBounds - (fun x => Some x) E' ([r[0~>10]%zrange],[r[0~>10]%zrange])))) as E''. + pose (PartialReduceWithBounds1 (fun r => Some r) E' ([r[0~>10]%zrange],[r[0~>10]%zrange])) as E''. lazy in E''. lazymatch (eval cbv delta [E''] in E'') with - | (expr_let 2 := List.nth 0 @@ (fst @@ x_ 1) in - expr_let 3 := List.nth 0 @@ (snd @@ x_ 1) in - expr_let 4 := mul r[0 ~> 10]%btype r[0 ~> 10]%btype r[0 ~> 100]%btype @@ - (x_ 2, x_ 3) in - x_ 4 - :: - x_ 4 :: [])%nexpr + | (fun var : type -> Type => + (λ x : var (type.list (type.type_primitive type.Z) * type.list (type.type_primitive type.Z))%ctype, + expr_let y := ident.Z.cast r[0 ~> 10] @@ + (ident.List.nth_default_concrete (-1) 0 @@ (ident.fst @@ Var x)) in + expr_let y0 := ident.Z.cast r[0 ~> 10] @@ + (ident.List.nth_default_concrete (-1) 0 @@ (ident.snd @@ Var x)) in + expr_let y1 := ident.Z.cast r[0 ~> 100] @@ (Var y * Var y0) in + ident.Z.cast r[0 ~> 100] @@ Var y1 :: ident.Z.cast r[0 ~> 100] @@ Var y1 :: [])%expr) => idtac end. constructor. @@ -5591,7 +5924,7 @@ Proof. cache_reify (). exact admit. (* correctness of initial parts of the pipel Module Pipeline. Inductive ErrorMessage := | Computed_bounds_are_not_tight_enough - {t} (computed_bounds expected_bounds : BoundsAnalysis.Indexed.Range.range t) + {t} (computed_bounds expected_bounds : ZRange.type.option.interp t) | Bounds_analysis_failed | Return_type_mismatch {T'} (found expected : T') | Value_not_le (descr : string) {T'} (lhs rhs : T') @@ -5610,12 +5943,6 @@ Module Pipeline. | Error msg => msg end. - Definition transport_or_error P {A B} (v : P A) : ErrorT (P B) - := match BoundsAnalysis.type.transport P A B v with - | Some v => Success v - | None => Error (Return_type_mismatch A B) - end. - Definition BoundsPipeline (with_dead_code_elimination : bool) relax_zrange @@ -5623,23 +5950,22 @@ Module Pipeline. arg_bounds out_bounds (E : Expr (s -> d)) - : ErrorT (BoundsAnalysis.Indexed.expr.Notations.expr (BoundsAnalysis.Indexed.Range.type_for_range relax_zrange (t:=BoundsAnalysis.Indexed.OfPHOAS.type.compile d) out_bounds)) + : ErrorT (Expr (s -> d)) := let E := PartialReduce E in let E := if with_dead_code_elimination then DeadCodeElimination.EliminateDead E else E in let E := ReassociateSmallConstants.Reassociate (2^8) E in - let E := BoundsAnalysis.OfPHOAS.AnalyzeBounds relax_zrange E arg_bounds in + let E := CheckedPartialReduceWithBounds1 relax_zrange E arg_bounds out_bounds in let E := match E with - | Some (existT b v) - => if BoundsAnalysis.Indexed.Range.range_is_tighter_than b out_bounds - then transport_or_error BoundsAnalysis.Indexed.expr.Notations.expr v - else Error (Computed_bounds_are_not_tight_enough b out_bounds) - | None => Error Bounds_analysis_failed + | inl v => Success v + | inr b => Error (Computed_bounds_are_not_tight_enough b (ZRange.type.option.Some out_bounds)) end in E. Lemma BoundsPipeline_correct (with_dead_code_elimination : bool) relax_zrange + (Hrelax : forall r r' z : zrange, + (z <=? r)%zrange = true -> relax_zrange r = Some r' -> (z <=? r')%zrange = true) {s d} arg_bounds out_bounds @@ -5647,26 +5973,18 @@ Module Pipeline. rv (Hrv : BoundsPipeline with_dead_code_elimination relax_zrange arg_bounds out_bounds E = Success rv) : forall arg - (Harg : BoundsAnalysis.Indexed.Range.type_for_range_bounded_by - relax_zrange - arg_bounds arg = true) - (arg' := @BoundsAnalysis.OfPHOAS.cast_back - s - relax_zrange - arg_bounds - arg), - exists res, - let ctx := - BoundsAnalysis.Indexed.Context.extendb - (PositiveMap.empty _) 1 arg in - BoundsAnalysis.Indexed.expr.interp (@BoundsAnalysis.ident.interp) rv ctx - = Some res - /\ BoundsAnalysis.Indexed.Range.type_for_range_bounded_by - relax_zrange out_bounds res = true - /\ BoundsAnalysis.OfPHOAS.cast_back relax_zrange res - = Interp E arg'. + (Harg : ZRange.type.is_bounded_by arg_bounds arg = true), + ZRange.type.is_bounded_by out_bounds (Interp rv arg) = true + /\ Interp rv arg = Interp E arg. Proof. - Admitted. + cbv [BoundsPipeline] in *; edestruct (CheckedPartialReduceWithBounds1 _ _ _ _) eqn:H. + inversion Hrv; subst. + { intros; eapply CheckedPartialReduceWithBounds1_Correct in H; [ | eassumption.. ]. + destruct H as [H0 H1]. + split; [ exact H1 | rewrite H0 ]. + exact admit. (* interp correctness *) } + { congruence. } + Qed. Definition BoundsPipelineConst (with_dead_code_elimination : bool) @@ -5674,38 +5992,38 @@ Module Pipeline. {t} bounds (E : Expr t) - : ErrorT (BoundsAnalysis.Indexed.expr.Notations.expr (BoundsAnalysis.Indexed.Range.type_for_range relax_zrange (t:=BoundsAnalysis.Indexed.OfPHOAS.type.compile t) bounds)) + : ErrorT (Expr t) := let E := PartialReduce E in let E := if with_dead_code_elimination then DeadCodeElimination.EliminateDead E else E in let E := ReassociateSmallConstants.Reassociate (2^8) E in - let E := BoundsAnalysis.OfPHOAS.AnalyzeBoundsConst relax_zrange E in + let E := CheckedPartialReduceWithBounds0 relax_zrange E bounds in let E := match E with - | Some (existT b v) - => if BoundsAnalysis.Indexed.Range.range_is_tighter_than b bounds - then transport_or_error BoundsAnalysis.Indexed.expr.Notations.expr v - else Error (Computed_bounds_are_not_tight_enough b bounds) - | None => Error Bounds_analysis_failed + | inl v => Success v + | inr b => Error (Computed_bounds_are_not_tight_enough b (ZRange.type.option.Some bounds)) end in E. Lemma BoundsPipelineConst_correct (with_dead_code_elimination : bool) relax_zrange + (Hrelax : forall r r' z : zrange, + (z <=? r)%zrange = true -> relax_zrange r = Some r' -> (z <=? r')%zrange = true) {d} bounds (E : Expr d) rv (Hrv : BoundsPipelineConst with_dead_code_elimination relax_zrange bounds E = Success rv) - : exists res, - let ctx := PositiveMap.empty _ in - BoundsAnalysis.Indexed.expr.interp (@BoundsAnalysis.ident.interp) rv ctx - = Some res - /\ BoundsAnalysis.Indexed.Range.type_for_range_bounded_by - relax_zrange bounds res = true - /\ BoundsAnalysis.OfPHOAS.cast_back relax_zrange res - = Interp E. + : ZRange.type.is_bounded_by bounds (Interp rv) = true + /\ Interp rv = Interp E. Proof. - Admitted. + cbv [BoundsPipelineConst] in *; edestruct (CheckedPartialReduceWithBounds0 _ _ _) eqn:H. + inversion Hrv; subst. + { intros; eapply CheckedPartialReduceWithBounds0_Correct in H; [ | eassumption.. ]. + destruct H as [H0 H1]. + split; [ exact H1 | rewrite H0 ]. + exact admit. (* interp correctness *) } + { congruence. } + Qed. End Pipeline. Definition round_up_bitwidth_gen (possible_values : list Z) (bitwidth : Z) : option Z @@ -5795,7 +6113,7 @@ Section rcarry_mul. Let upperbound_loose := (3 * upperbound_tight)%Z. Let f_bounds_tight := List.repeat r[0~>upperbound_tight]%zrange n. Let f_bounds_loose := List.repeat r[0~>upperbound_loose]%zrange n. - Let prime_bound : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.Z)) + Let prime_bound : ZRange.type.interp (type.Z) := r[0~>(s - Associational.eval c - 1)]%zrange. Definition relax_zrange_of_machine_wordsize @@ -5811,15 +6129,37 @@ Section rcarry_mul. Let rlen_idxs := GallinaReify.Reify (List.length idxs). Let rcoef := GallinaReify.Reify 2. Let relax_zrange := relax_zrange_of_machine_wordsize. - Let tight_bounds : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.list type.Z)) + Let tight_bounds : ZRange.type.interp (type.list type.Z) := f_bounds_tight. - Let tight2_bounds : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.list type.Z * type.list type.Z)) + Let tight2_bounds : ZRange.type.interp (type.list type.Z * type.list type.Z) := (tight_bounds, tight_bounds). - Let loose_bounds : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.list type.Z)) + Let loose_bounds : ZRange.type.interp (type.list type.Z) := f_bounds_loose. - Let loose2_bounds : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.list type.Z * type.list type.Z)) + Let loose2_bounds : ZRange.type.interp (type.list type.Z * type.list type.Z) := (loose_bounds, loose_bounds). + Lemma relax_zrange_of_machine_wordsize_good + : forall r r' z : zrange, + (z <=? r)%zrange = true -> relax_zrange_of_machine_wordsize r = Some r' -> (z <=? r')%zrange = true. + Proof. + cbv [is_tighter_than_bool relax_zrange_of_machine_wordsize relax_zrange_gen]; intros *. + pose proof (Z.log2_up_nonneg (upper r + 1)). + rewrite !Bool.andb_true_iff; destruct_head' zrange; cbn [ZRange.lower ZRange.upper] in *. + cbv [round_up_bitwidth_gen fold_right option_map]. + break_innermost_match; intros; destruct_head'_and; + inversion_option; inversion_zrange; + subst; + repeat apply conj; + Z.ltb_to_lt; try omega; + destruct (Z_gt_le_dec 0 machine_wordsize); + try (rewrite <- Z.log2_up_le_pow2_full in *; omega). + Qed. + + Let relax_zrange_good + : forall r r' z : zrange, + (z <=? r)%zrange = true -> relax_zrange r = Some r' -> (z <=? r')%zrange = true + := relax_zrange_of_machine_wordsize_good. + Definition check_args {T} (res : Pipeline.ErrorT T) : Pipeline.ErrorT T := if negb (Qle_bool 1 limbwidth)%Q @@ -5846,11 +6186,9 @@ Section rcarry_mul. let rop := lazymatch type of Hrv with ?rop = Pipeline.Success _ => rop end in hnf; intros; cbv [rop] in Hrv; eapply pipeline_lem in Hrv; [ | eassumption.. ]; - let res := fresh "res" in - destruct Hrv as [res Hrv]; - exists res; do 2 try apply conj; - [ | | etransitivity ]; - [ solve [ apply Hrv ].. | ]; + let Hrv' := fresh "Hrv'" in + destruct Hrv as [Hrv Hrv']; + apply conj; [ exact Hrv | rewrite Hrv' ]; repeat match goal with H := _ |- _ => subst H end; erewrite <- gen_correct; cbv [expr.Interp]; @@ -5887,48 +6225,37 @@ Section rcarry_mul. res in res. - Definition rexpr_1_correctT_ctx - relax_zrange + Definition rexpr_1_correctT_Interp + {t} t_out - ctx + (Interp : Expr t -> _) out_bounds (f : type.interp t_out) rv - := (exists res, - BoundsAnalysis.Indexed.expr.interp (@BoundsAnalysis.ident.interp) rv ctx - = Some res - /\ BoundsAnalysis.Indexed.Range.type_for_range_bounded_by - relax_zrange out_bounds res = true - /\ BoundsAnalysis.OfPHOAS.cast_back relax_zrange res - = f). + := (ZRange.type.is_bounded_by out_bounds (Interp rv) = true + /\ Interp rv = f). Definition rexpr_n1_correctT - relax_zrange t_in t_out in_bounds out_bounds - (f : _ -> type.interp t_out) + (f : type.interp t_in -> type.interp t_out) rv := forall arg - (arg' := @BoundsAnalysis.OfPHOAS.cast_back - t_in - relax_zrange - in_bounds - arg) - (Harg : BoundsAnalysis.Indexed.Range.type_for_range_bounded_by - relax_zrange - (t:=BoundsAnalysis.Indexed.OfPHOAS.type.compile t_in) - in_bounds arg = true), - let ctx := - BoundsAnalysis.Indexed.Context.extendb - (PositiveMap.empty _) 1 arg in - @rexpr_1_correctT_ctx relax_zrange t_out ctx out_bounds (f arg') rv. + (Harg : ZRange.type.is_bounded_by in_bounds arg = true), + @rexpr_1_correctT_Interp (t_in -> t_out) t_out (fun rv => Interp rv arg) out_bounds (f arg) rv. + + Definition rexpr_1_correctT + t_out + out_bounds + (f : type.interp t_out) + rv + := @rexpr_1_correctT_Interp t_out t_out Interp out_bounds f rv. Definition rexpr_21_correctT in_bounds out_bounds (f : _ -> type.interp (type.list type.Z)) rv - := @rexpr_n1_correctT relax_zrange - (type.list type.Z * type.list type.Z) + := @rexpr_n1_correctT (type.list type.Z * type.list type.Z) (type.list type.Z) (in_bounds, in_bounds) out_bounds f rv. @@ -5936,8 +6263,7 @@ Section rcarry_mul. in_bounds out_bounds (f : _ -> type.interp (type.list type.Z)) rv - := @rexpr_n1_correctT relax_zrange - (type.list type.Z) + := @rexpr_n1_correctT (type.list type.Z) (type.list type.Z) in_bounds out_bounds f rv. @@ -5945,14 +6271,14 @@ Section rcarry_mul. in_bounds out_bounds (f : _ -> type.interp (type.list type.Z)) rv - := @rexpr_n1_correctT relax_zrange type.Z (type.list type.Z) + := @rexpr_n1_correctT type.Z (type.list type.Z) in_bounds out_bounds f rv. Definition rexpr_01_correctT out_bounds (f : type.interp (type.list type.Z)) rv - := @rexpr_1_correctT_ctx relax_zrange (type.list type.Z) (PositiveMap.empty _) out_bounds f rv. + := @rexpr_1_correctT (type.list type.Z) out_bounds f rv. Definition rcarry_mul := let res := BoundsPipeline21 @@ -6212,51 +6538,34 @@ Section rcarry_mul. : rone_correctT rv. Proof. solve_correct_const one_gen_correct. Qed. - Definition encodedT := { ls : option - (list (BoundsAnalysis.type.primitive.interp - (BoundsAnalysis.Indexed.Range.primitive_for_option_zrange - (relax_zrange (fold_right ZRange.union r[0 ~> 0]%zrange f_bounds_tight))))) - | exists res, - ls = Some res - /\ BoundsAnalysis.Indexed.Range.type_for_range_bounded_by - relax_zrange tight_bounds res = true }. - - Program Definition list_of_encodedT (v : encodedT) : list _ - := @Option.always_invert_Some - _ - (proj1_sig v) - _. - Next Obligation. - repeat match goal with H : _ |- _ => clear H end. - destruct v as [? [? [H0 H1] ] ]; cbn; subst; congruence. - Qed. + Definition encodedT + := { ls : list Z + | ZRange.type.is_bounded_by (t:=type.list type.Z) tight_bounds ls = true }. + + Definition list_of_encodedT (v : encodedT) : list _ + := proj1_sig v. Lemma length_list_of_encodedT v : List.length (list_of_encodedT v) = n. Proof. - destruct v as [v [res [Hpf H] ] ]; destruct v; cbn in *; [ | discriminate ]. + destruct v as [v H]; cbv [ZRange.type.is_bounded_by] in H; cbn in H |- *. + exact admit (*destruct v; cbn in *; [ | discriminate ]. apply BoundsAnalysis.Indexed.Range.length_list_bounded_by in H. inversion_option; subst. etransitivity; [ exact H | ]. subst tight_bounds f_bounds_tight. - rewrite repeat_length; reflexivity. + rewrite repeat_length; reflexivity*). Qed. Let m : positive := Z.to_pos (s - Associational.eval c). Definition Zdecode (v : encodedT) - := BoundsAnalysis.OfPHOAS.cast_back - (d:=type.list type.Z) - _ - (list_of_encodedT v). + := list_of_encodedT v. Definition Fdecode (v : encodedT) : F m := F.of_Z m (Positional.eval (Interp rw) n (Zdecode v)). Definition encodedT_eq (x y : encodedT) := Fdecode x = Fdecode y. Lemma length_Zdecode v : List.length (Zdecode v) = n. - Proof. - cbn [Zdecode BoundsAnalysis.OfPHOAS.cast_back]. - rewrite map_length, length_list_of_encodedT; reflexivity. - Qed. + Proof. apply length_list_of_encodedT. Qed. Section make_ring. Context (curve_good : check_args (Pipeline.Success tt) = Pipeline.Success tt) @@ -6347,75 +6656,65 @@ Section rcarry_mul. Proof. apply use_curve_good. Qed. Local Arguments Z.pow !_ !_ . - Lemma relax_is_good - : BoundsAnalysis.OfPHOAS.relax_is_good relax_zrange. - Proof. - cbn; cbv [BoundsAnalysis.OfPHOAS.relax_is_good relax_zrange_gen]; cbn. - intros [l u] [l' u']; cbn. - pose proof (Z.log2_up_nonneg (u + 1)). - destruct (Z.log2_up_null (u + 1)). - unfold is_tighter_than_bool; rewrite Bool.andb_true_iff; - break_innermost_match; cbn; Z.ltb_to_lt; intros; - inversion_option; inversion_zrange; subst; - repeat apply conj; Z.ltb_to_lt; try omega; - try (rewrite <- ZUtil.Z.log2_up_le_pow2_full in * by lia; cbn in *; lia). - Qed. - Local Notation option_interp0 f - := (BoundsAnalysis.Indexed.expr.interp - (@BoundsAnalysis.ident.interp) - f - (PositiveMap.empty _)). - - Local Notation option_interp1 f arg - := (arg' <- arg; - BoundsAnalysis.Indexed.expr.interp - (@BoundsAnalysis.ident.interp) - f - (BoundsAnalysis.Indexed.Context.extendb - (T:=BoundsAnalysis.type.list _) - (PositiveMap.empty _) - 1 arg'))%option. - - Local Notation option_interp2 f arg1 arg2 - := (x <- arg1; - y <- arg2; - BoundsAnalysis.Indexed.expr.interp - (@BoundsAnalysis.ident.interp) - f - (BoundsAnalysis.Indexed.Context.extendb - (T:=BoundsAnalysis.type.prod - (BoundsAnalysis.type.list _) - (BoundsAnalysis.type.list _)) - (PositiveMap.empty _) - 1 (x, y)))%option. + Local Ltac specialize_from_interp _ := + repeat match goal with + | [ H := Interp ?rv ?arg, Hc : context[?rv] |- _ ] + => unique pose proof (Hc arg) + end. + Local Ltac specialize_with_bounded _ := + repeat match goal with + | _ => progress cbv [Zdecode list_of_encodedT] in * + | _ => progress cbn [ZRange.type.is_bounded_by proj1_sig] in * + | [ H : context[andb ?x ?y = true] |- _ ] + => rewrite (Bool.andb_true_iff x y) in H + | [ H : _ /\ _ -> _ |- _ ] => specialize (fun a b => H (conj a b)) + | _ => progress destruct_head'_and + | [ H : ?f (proj1_sig ?v) = true -> _ |- _ ] + => specialize (H (proj2_sig v)); hnf in H + | [ H : ?x = true -> _, H' : ?x = true |- _ ] + => specialize (H H'); hnf in H + | [ H : ?x = true |- { pf : ?x = true | _ } ] => exists H + end. + Local Ltac rewrite_interp _ := + repeat match goal with + | [ H := _ |- _ ] => subst H + | [ H : ?x = _ |- context[?x] ] => rewrite H + | _ => rewrite expanding_id_id + | [ |- ?x = ?x ] => reflexivity + | [ |- List.length (proj1_sig _) = _ ] => apply length_list_of_encodedT + end. Local Ltac solve_encodedT _ := + specialize_from_interp (); + specialize_with_bounded (); + rewrite_interp (). + (*Local Ltac solve_encodedT _ := repeat match goal with | _ => progress destruct_head' encodedT | _ => progress (destruct_head'_ex; destruct_head'_and; subst) | _ => progress cbn [proj1_sig Option.bind always_invert_Some] in * | [ H : ?x = Some _ |- context[?x] ] => rewrite H | [ H : ?x = Some _, H' : context[?x] |- _ ] => rewrite H in H' - | [ |- BoundsAnalysis.Indexed.Range.type_for_range_bounded_by _ _ (_, _) = true ] - => progress cbn [BoundsAnalysis.Indexed.Range.type_for_range_bounded_by BoundsAnalysis.Indexed.OfPHOAS.type.compile] + (*| [ |- BoundsAnalysis.Indexed.Range.type_for_range_bounded_by _ _ (_, _) = true ] + => progress cbn [BoundsAnalysis.Indexed.Range.type_for_range_bounded_by BoundsAnalysis.Indexed.OfPHOAS.type.compile]*) | _ => progress cbn [BoundsAnalysis.Indexed.Range.type_for_range BoundsAnalysis.Indexed.OfPHOAS.type.compile fst snd] in * (* for getting rewrite to match *) | [ |- andb _ _ = true ] => rewrite Bool.andb_true_iff | _ => solve [ eauto ] | [ |- sig _ ] => progress rewrite expanding_id_id in * | [ |- List.length (List.map _ _) = _ ] => rewrite map_length - | [ H : BoundsAnalysis.Indexed.Range.type_for_range_bounded_by _ _ ?x = true + (*| [ H : BoundsAnalysis.Indexed.Range.type_for_range_bounded_by _ _ ?x = true |- List.length ?x = _ ] - => erewrite BoundsAnalysis.Indexed.Range.length_list_bounded_by by exact H + => erewrite BoundsAnalysis.Indexed.Range.length_list_bounded_by by exact H*) | _ => progress rewrite ?length_tight_bounds, ?length_loose_bounds | [ H : map _ ?x = map _ _ |- _ ] => rewrite H in * | [ H : map _ ?x = _ |- context[map _ ?x] ] => cbv [tight_bounds loose_bounds] in H |- *; rewrite H | _ => rewrite BoundsAnalysis.OfPHOAS.cast_back_primitive_cast_primitive in * - | [ fx := (BoundsAnalysis.Indexed.expr.interp _ ?rop (BoundsAnalysis.Indexed.Context.extendb _ _ ?x)), + (*| [ fx := (BoundsAnalysis.Indexed.expr.interp _ ?rop (BoundsAnalysis.Indexed.Context.extendb _ _ ?x)), H : forall arg, BoundsAnalysis.Indexed.Range.type_for_range_bounded_by _ ?bs arg = true -> rexpr_1_correctT_ctx _ _ _ _ _ ?rop |- _ ] - => destruct (H x); [ clear H | subst fx ] + => destruct (H x); [ clear H | subst fx ]*) | [ fx := Option.bind ?x ?f, H : ?x = Some ?v |- _ ] => let H' := fresh in let fx' := fresh fx in @@ -6424,7 +6723,7 @@ Section rcarry_mul. by (subst fx fx'; apply f_equal2; [ exact H | reflexivity ]); cbn [Option.bind] in fx'; clearbody fx; subst fx | _ => progress cbn [BoundsAnalysis.OfPHOAS.cast_back] in * (* for getting eauto to work *) - end. + end.*) Definition ring_mul_sig : forall (x y : encodedT), @@ -6433,14 +6732,12 @@ Section rcarry_mul. Proof. simple refine (fun x y - => let x' := option_interp1 rrelaxv (proj1_sig x) in - let y' := option_interp1 rrelaxv (proj1_sig y) in - let v' := option_interp2 rcarry_mulv x' y' in + => let x' := Interp rrelaxv (proj1_sig x) in + let y' := Interp rrelaxv (proj1_sig y) in + let v' := Interp rcarry_mulv (x', y') in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). - cbv [Zdecode list_of_encodedT]; cbn [proj1_sig]. - hnf in Hrrelaxv, Hrmulv. abstract solve_encodedT (). Defined. @@ -6453,13 +6750,11 @@ Section rcarry_mul. Proof. simple refine (fun x y - => let v'' := option_interp2 raddv (proj1_sig x) (proj1_sig y) in - let v' := option_interp1 rcarryv v'' in + => let v'' := Interp raddv (proj1_sig x, proj1_sig y) in + let v' := Interp rcarryv v'' in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). - cbv [Zdecode list_of_encodedT]; cbn [proj1_sig]. - hnf in Hrcarryv, Hraddv; clear -Hrcarryv Hraddv. abstract solve_encodedT (). Defined. Definition ring_sub_sig @@ -6471,13 +6766,11 @@ Section rcarry_mul. Proof. simple refine (fun x y - => let v'' := option_interp2 rsubv (proj1_sig x) (proj1_sig y) in - let v' := option_interp1 rcarryv v'' in + => let v'' := Interp rsubv (proj1_sig x, proj1_sig y) in + let v' := Interp rcarryv v'' in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). - cbv [Zdecode list_of_encodedT]; cbn [proj1_sig]. - hnf in Hrcarryv, Hrsubv. abstract solve_encodedT (). Defined. Definition ring_opp_sig @@ -6489,13 +6782,11 @@ Section rcarry_mul. Proof. simple refine (fun x - => let v'' := option_interp1 roppv (proj1_sig x) in - let v' := option_interp1 rcarryv v'' in + => let v'' := Interp roppv (proj1_sig x) in + let v' := Interp rcarryv v'' in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). - cbv [Zdecode list_of_encodedT]; cbn [proj1_sig]. - hnf in Hrcarryv, Hroppv. abstract solve_encodedT (). Defined. Definition ring_zero_sig @@ -6504,11 +6795,10 @@ Section rcarry_mul. (Interp rw) s c n (Interp rlen_c) }. Proof. simple refine - (let v' := option_interp0 rzerov in + (let v' := Interp rzerov in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). - cbv [Zdecode list_of_encodedT]; cbn [proj1_sig]. abstract ( destruct Hrzerov; subst v'; solve_encodedT () @@ -6520,7 +6810,7 @@ Section rcarry_mul. (Interp rw) s c n (Interp rlen_c) }. Proof. simple refine - (let v' := option_interp0 ronev in + (let v' := Interp ronev in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). @@ -6539,62 +6829,21 @@ Section rcarry_mul. Proof. simple refine (fun v - => let pf0 := _ in - let pf1 := _ in - let arg := BoundsAnalysis.OfPHOAS.cast_primitiveZ - relax_zrange - (F.to_Z v) relax_is_good pf0 in + => let pf1 := _ in + let arg := F.to_Z v in let Hrencodev' := Hrencodev arg pf1 in - let v' := BoundsAnalysis.Indexed.expr.interp - (@BoundsAnalysis.ident.interp) - rencodev - (BoundsAnalysis.Indexed.Context.extendb - (T:=BoundsAnalysis.type.type_primitive _) - (PositiveMap.empty _) - 1 arg) in + let v' := Interp rencodev arg in let pf : { pf0 : _ | Zdecode (exist _ v' pf0) = _ } := _ in exist _ (exist _ v' (proj1_sig pf)) (proj2_sig pf)). - { pose proof use_curve_good as keep. - clear -curve_good keep. + { generalize m_eq. + generalize sc_pos. + cbn; clear -v. abstract ( - split; [ | exact I ]; - destruct v as [v Hv]; hnf; cbn; - rewrite m_eq in Hv; rewrite Hv; - pose proof (Z.mod_pos_bound v _ sc_pos); lia - ). } - { clearbody pf0. - clear -pf0. - cbn. - (** TODO: clean up this part of the proof. It is annoying - because [BoundsAnalysis.OfPHOAS.cast_primitiveZ] and - [BoundsAnalysis.Indexed.Range.type_for_range_bounded_by] - use different notions of the "interpretation" of a - not-necessarily-Z thing as probably-a-Z *) - generalize (BoundsAnalysis.OfPHOAS.cast_back_primitive_cast_primitive - relax_zrange _ _ relax_is_good pf0). - generalize (BoundsAnalysis.OfPHOAS.cast_primitiveZ - relax_zrange (F.to_Z v) relax_is_good pf0). - generalize (relax_is_good prime_bound). - cbv [BoundsAnalysis.Indexed.Range.primitive_bounded_by]. - cbn [BoundsAnalysis.type.primitive.interp]. - cbv [BoundsAnalysis.OfPHOAS.cast_back_primitive]. - cbv [BoundsAnalysis.Indexed.Range.primitive_for_zrange]. - abstract ( - break_innermost_match; cbn; - intros; destruct_head' BoundsAnalysis.type.BoundedZ; cbn [BoundsAnalysis.type.value] in *; - subst; - hnf in pf0; - cbv [prime_bound is_tighter_than_bool] in *; - try lazymatch goal with - | [ H : forall _, Some _ = Some _ -> _ |- _ ] - => specialize (H _ eq_refl) - end; - rewrite ?Bool.andb_true_iff in *; - destruct_head'_and; - apply conj; Z.ltb_to_lt; - cbn [upper lower] in *; - try omega + intros sc_pos m_eq; + destruct v as [v Hv]; cbn; rewrite m_eq in Hv; + pose proof (Z.mod_pos_bound v _ sc_pos); + rewrite Bool.andb_true_iff; split; Z.ltb_to_lt; lia ). } { cbv [Zdecode list_of_encodedT]; cbn [proj1_sig]. subst v' arg; clearbody Hrencodev'; cbv beta zeta in *. @@ -6688,23 +6937,22 @@ Section rcarry_mul. End make_ring. End rcarry_mul. -Ltac solve_rcarry_mul _ := eapply rcarry_mul_correct; lazy; reflexivity. -Ltac solve_rcarry _ := eapply rcarry_correct; lazy; reflexivity. -Ltac solve_radd _ := eapply radd_correct; lazy; reflexivity. -Ltac solve_rsub _ := eapply rsub_correct; lazy; reflexivity. -Ltac solve_ropp _ := eapply ropp_correct; lazy; reflexivity. -Ltac solve_rencode _ := eapply rencode_correct; lazy; reflexivity. -Ltac solve_rrelax _ := eapply rrelax_correct; lazy; reflexivity. -Ltac solve_rzero _ := eapply rzero_correct; lazy; reflexivity. -Ltac solve_rone _ := eapply rone_correct; lazy; reflexivity. +Ltac solve_rop rop_correct machine_wordsizev := + eapply rop_correct with (machine_wordsize:=machine_wordsizev); lazy; reflexivity. +Ltac solve_rcarry_mul := solve_rop rcarry_mul_correct. +Ltac solve_rcarry := solve_rop rcarry_correct. +Ltac solve_radd := solve_rop radd_correct. +Ltac solve_rsub := solve_rop rsub_correct. +Ltac solve_ropp := solve_rop ropp_correct. +Ltac solve_rencode := solve_rop rencode_correct. +Ltac solve_rrelax := solve_rop rrelax_correct. +Ltac solve_rzero := solve_rop rzero_correct. +Ltac solve_rone := solve_rop rone_correct. Module PrintingNotations. Export ident. - Export BoundsAnalysis.ident. - Export BoundsAnalysis.Notations. - Open Scope btype_scope. Global Set Printing Width 100000. - Notation "'uint256'" + (*Notation "'uint256'" := (r[0 ~> 115792089237316195423570985008687907853269984665640564039457584007913129639935]%btype) : btype_scope. Notation "'uint128'" := (r[0 ~> 340282366920938463463374607431768211455]%btype) : btype_scope. @@ -6760,17 +7008,17 @@ Module PrintingNotations. := ((land _ out_t mask @@ v)%nexpr) (format "( ( out_t ) v & mask )") : nexpr_scope. - +*) (* TODO: come up with a better notation for arithmetic with carries that still distinguishes it from arithmetic without carries? *) Local Notation "'TwoPow256'" := 115792089237316195423570985008687907853269984665640564039457584007913129639936 (only parsing). - Notation "'ADD_256'" := (add_get_carry_concrete _ _ uint256 _ TwoPow256) : nexpr_scope. + (*Notation "'ADD_256'" := (add_get_carry_concrete _ _ uint256 _ TwoPow256) : nexpr_scope. Notation "'ADD_128'" := (add_get_carry_concrete _ _ uint128 _ TwoPow256) : nexpr_scope. Notation "'ADDC_256'" := (add_with_get_carry_concrete _ _ _ uint256 _ TwoPow256) : nexpr_scope. Notation "'SUB_256'" := (sub_get_borrow_concrete _ _ uint256 _ TwoPow256) : nexpr_scope. Notation "'ADDM'" := (add_modulo _ _ _ uint256) : nexpr_scope. Notation "'SELC'" := (zselect _ _ _ uint256) : nexpr_scope. - Notation "'MUL_256'" := (mul uint128 uint128 uint256) : nexpr_scope. + Notation "'MUL_256'" := (mul uint128 uint128 uint256) : nexpr_scope.*) End PrintingNotations. @@ -6780,42 +7028,60 @@ Module X25519_64. Definition c := [(1, 19)]. Definition machine_wordsize := 64. + Set Printing Width 80. + + Derive base_51_relax + SuchThat (rrelax_correctT n s c base_51_relax) + As base_51_relax_correct. + Proof. Time solve_rrelax machine_wordsize. Time Qed. Derive base_51_carry_mul - SuchThat (rcarry_mul_correctT n s c machine_wordsize base_51_carry_mul) + SuchThat (rcarry_mul_correctT n s c base_51_carry_mul) As base_51_carry_mul_correct. - Proof. Time solve_rcarry_mul (). Time Qed. + Proof. + eapply rcarry_mul_correct with (machine_wordsize:=machine_wordsize). + cbv [rcarry_mul]. + set (k := List.repeat _ _) at 1; lazy in k; subst k. + set (k := List.repeat _ _) at 1; lazy in k; subst k. + set (k := List.repeat _ _) at 1; lazy in k; subst k. + cbv [Pipeline.BoundsPipeline]. + cbv [CheckedPartialReduceWithBounds1]. + cbv [Let_In]. + set (k := extract_bounds _ _ _). + set (k' := k _); subst k. + cbv [extract_bounds] in k'. + set (k'' := partial_reduce_with_bounds1' _ _ _ _) in (value of k'). + exfalso. + lazy in k''. + + Time solve_rcarry_mul machine_wordsize. Time Qed. Derive base_51_carry SuchThat (rcarry_correctT n s c machine_wordsize base_51_carry) As base_51_carry_correct. - Proof. Time solve_rcarry (). Time Qed. - Derive base_51_relax - SuchThat (rrelax_correctT n s c machine_wordsize base_51_relax) - As base_51_relax_correct. - Proof. Time solve_rrelax (). Time Qed. + Proof. Time solve_rcarry machine_wordsize. Time Qed. Derive base_51_add SuchThat (radd_correctT n s c machine_wordsize base_51_add) As base_51_add_correct. - Proof. Time solve_radd (). Time Qed. + Proof. Time solve_radd machine_wordsize. Time Qed. Derive base_51_sub SuchThat (rsub_correctT n s c machine_wordsize base_51_sub) As base_51_sub_correct. - Proof. Time solve_rsub (). Time Qed. + Proof. Time solve_rsub machine_wordsize. Time Qed. Derive base_51_opp SuchThat (ropp_correctT n s c machine_wordsize base_51_opp) As base_51_opp_correct. - Proof. Time solve_ropp (). Time Qed. + Proof. Time solve_ropp machine_wordsize. Time Qed. Derive base_51_encode SuchThat (rencode_correctT n s c machine_wordsize base_51_encode) As base_51_encode_correct. - Proof. Time solve_rencode (). Time Qed. + Proof. Time solve_rencode machine_wordsize. Time Qed. Derive base_51_zero SuchThat (rzero_correctT n s c machine_wordsize base_51_zero) As base_51_zero_correct. - Proof. Time solve_rzero (). Time Qed. + Proof. Time solve_rzero machine_wordsize. Time Qed. Derive base_51_one SuchThat (rone_correctT n s c machine_wordsize base_51_one) As base_51_one_correct. - Proof. Time solve_rone (). Time Qed. + Proof. Time solve_rone machine_wordsize. Time Qed. Lemma base_51_curve_good : check_args n s c machine_wordsize (Pipeline.Success tt) = Pipeline.Success tt. Proof. vm_compute; reflexivity. Qed. @@ -7211,9 +7477,9 @@ Module MontgomeryReduction. Let rN' := GallinaReify.Reify N'. Let rn := GallinaReify.Reify 2%nat. Let relax_zrange := relax_zrange_of_machine_wordsize. - Let arg_bounds : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.Z * type.Z)) + Let arg_bounds : ZRange.type.interp (type.Z * type.Z)) := (bound, bound). - Let out_bounds : BoundsAnalysis.Indexed.Range.range (BoundsAnalysis.Indexed.OfPHOAS.type.compile (type.Z)) + Let out_bounds : ZRange.type.interp (type.Z)) := bound. Definition check_args {T} (res : Pipeline.ErrorT T) |