~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to theories/Numbers/Natural/BigN/NMake_gen.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
(************************************************************************)
 
2
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
3
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
4
(*   \VV/  **************************************************************)
 
5
(*    //   *      This file is distributed under the terms of the       *)
 
6
(*         *       GNU Lesser General Public License Version 2.1        *)
 
7
(************************************************************************)
 
8
(*            Benjamin Gregoire, Laurent Thery, INRIA, 2007             *)
 
9
(************************************************************************)
 
10
 
 
11
(*i $Id: NMake_gen.ml 11576 2008-11-10 19:13:15Z msozeau $ i*)
 
12
 
 
13
(*S NMake_gen.ml : this file generates NMake.v *)
 
14
 
 
15
 
 
16
(*s The two parameters that control the generation: *)
 
17
 
 
18
let size = 6 (* how many times should we repeat the Z/nZ --> Z/2nZ 
 
19
                process before relying on a generic construct *)
 
20
let gen_proof = true  (* should we generate proofs ? *)
 
21
 
 
22
 
 
23
(*s Some utilities *)
 
24
 
 
25
let t = "t"
 
26
let c = "N"
 
27
let pz n = if n == 0 then "w_0" else "W0"
 
28
let rec gen2 n = if n == 0 then "1" else if n == 1 then "2"
 
29
                 else "2 * " ^ (gen2 (n - 1))
 
30
let rec genxO n s = 
 
31
  if n == 0 then s else " (xO" ^ (genxO (n - 1) s) ^ ")"
 
32
 
 
33
(* NB: in ocaml >= 3.10, we could use Printf.ifprintf for printing to 
 
34
   /dev/null, but for being compatible with earlier ocaml and not 
 
35
   relying on system-dependent stuff like open_out "/dev/null", 
 
36
   let's use instead a magical hack *)
 
37
 
 
38
(* Standard printer, with a final newline *)
 
39
let pr s = Printf.printf (s^^"\n")
 
40
(* Printing to /dev/null *)
 
41
let pn = (fun s -> Obj.magic (fun _ _ _ _ _ _ _ _ _ _ _ _ _ _ -> ()) 
 
42
          : ('a, out_channel, unit) format -> 'a)
 
43
(* Proof printer : prints iff gen_proof is true *)
 
44
let pp = if gen_proof then pr else pn
 
45
(* Printer for admitted parts : prints iff gen_proof is false *)
 
46
let pa = if not gen_proof then pr else pn
 
47
(* Same as before, but without the final newline *)
 
48
let pr0 = Printf.printf
 
49
let pp0 = if gen_proof then pr0 else pn
 
50
 
 
51
 
 
52
(*s The actual printing *)
 
53
 
 
54
let _ = 
 
55
 
 
56
  pr "(************************************************************************)";
 
57
  pr "(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)";
 
58
  pr "(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)";
 
59
  pr "(*   \\VV/  **************************************************************)";
 
60
  pr "(*    //   *      This file is distributed under the terms of the       *)";
 
61
  pr "(*         *       GNU Lesser General Public License Version 2.1        *)";
 
62
  pr "(************************************************************************)";
 
63
  pr "(*            Benjamin Gregoire, Laurent Thery, INRIA, 2007             *)";
 
64
  pr "(************************************************************************)";
 
65
  pr "";
 
66
  pr "(** * NMake *)";
 
67
  pr "";
 
68
  pr "(** From a cyclic Z/nZ representation to arbitrary precision natural numbers.*)";
 
69
  pr "";
 
70
  pr "(** Remark: File automatically generated by NMake_gen.ml, DO NOT EDIT ! *)"; 
 
71
  pr "";
 
72
  pr "Require Import BigNumPrelude.";
 
73
  pr "Require Import ZArith.";
 
74
  pr "Require Import CyclicAxioms.";
 
75
  pr "Require Import DoubleType.";
 
76
  pr "Require Import DoubleMul.";
 
77
  pr "Require Import DoubleDivn1.";
 
78
  pr "Require Import DoubleCyclic.";
 
79
  pr "Require Import Nbasic.";
 
80
  pr "Require Import Wf_nat.";
 
81
  pr "Require Import StreamMemo.";
 
82
  pr "Require Import NSig.";
 
83
  pr "";
 
84
  pr "Module Make (Import W0:CyclicType) <: NType.";
 
85
  pr "";
 
86
 
 
87
  pr " Definition w0 := W0.w.";
 
88
  for i = 1 to size do
 
89
    pr " Definition w%i := zn2z w%i." i (i-1)
 
90
  done;
 
91
  pr "";
 
92
 
 
93
  pr " Definition w0_op := W0.w_op.";
 
94
  for i = 1 to 3 do
 
95
    pr " Definition w%i_op := mk_zn2z_op w%i_op." i (i-1)
 
96
  done;
 
97
  for i = 4 to size + 3 do
 
98
    pr " Definition w%i_op := mk_zn2z_op_karatsuba w%i_op." i (i-1)
 
99
  done;
 
100
  pr "";
 
101
 
 
102
  pr " Section Make_op.";
 
103
  pr "  Variable mk : forall w', znz_op w' -> znz_op (zn2z w').";
 
104
  pr "";
 
105
  pr "  Fixpoint make_op_aux (n:nat) : znz_op (word w%i (S n)):=" size;
 
106
  pr "   match n return znz_op (word w%i (S n)) with" size;
 
107
  pr "   | O => w%i_op" (size+1);
 
108
  pr "   | S n1 =>";
 
109
  pr "     match n1 return znz_op (word w%i (S (S n1))) with" size;
 
110
  pr "     | O => w%i_op" (size+2);
 
111
  pr "     | S n2 =>";
 
112
  pr "       match n2 return znz_op (word w%i (S (S (S n2)))) with" size;
 
113
  pr "       | O => w%i_op" (size+3);
 
114
  pr "       | S n3 => mk _ (mk _ (mk _ (make_op_aux n3)))";
 
115
  pr "       end";
 
116
  pr "     end";
 
117
  pr "   end.";
 
118
  pr "";
 
119
  pr " End Make_op.";
 
120
  pr "";
 
121
  pr " Definition omake_op := make_op_aux mk_zn2z_op_karatsuba.";
 
122
  pr "";
 
123
  pr "";
 
124
  pr " Definition make_op_list := dmemo_list _ omake_op.";
 
125
  pr "";
 
126
  pr " Definition make_op n := dmemo_get _ omake_op n make_op_list.";
 
127
  pr "";
 
128
  pr " Lemma make_op_omake: forall n, make_op n = omake_op n.";
 
129
  pr " intros n; unfold make_op, make_op_list.";
 
130
  pr " refine (dmemo_get_correct _ _ _).";
 
131
  pr " Qed.";
 
132
  pr "";
 
133
 
 
134
  pr " Inductive %s_ :=" t;
 
135
  for i = 0 to size do 
 
136
    pr "  | %s%i : w%i -> %s_" c i i t
 
137
  done;
 
138
  pr "  | %sn : forall n, word w%i (S n) -> %s_." c size t;
 
139
  pr "";
 
140
  pr " Definition %s := %s_." t t;
 
141
  pr "";
 
142
  pr " Definition w_0 := w0_op.(znz_0).";
 
143
  pr "";
 
144
 
 
145
  for i = 0 to size do
 
146
    pr " Definition one%i := w%i_op.(znz_1)." i i
 
147
  done;
 
148
  pr "";
 
149
 
 
150
 
 
151
  pr " Definition zero := %s0 w_0." c;
 
152
  pr " Definition one := %s0 one0." c;
 
153
  pr "";
 
154
 
 
155
  pr " Definition to_Z x :=";
 
156
  pr "  match x with";
 
157
  for i = 0 to size do
 
158
    pr "  | %s%i wx => w%i_op.(znz_to_Z) wx" c i i
 
159
  done;
 
160
  pr "  | %sn n wx => (make_op n).(znz_to_Z) wx" c;
 
161
  pr "  end.";
 
162
  pr "";
 
163
 
 
164
  pr " Open Scope Z_scope.";
 
165
  pr " Notation \"[ x ]\" := (to_Z x).";
 
166
  pr "";
 
167
 
 
168
  pr " Definition to_N x := Zabs_N (to_Z x).";
 
169
  pr "";
 
170
  
 
171
  pr " Definition eq x y := (to_Z x = to_Z y).";
 
172
  pr "";
 
173
 
 
174
  pp " (* Regular make op (no karatsuba) *)";
 
175
  pp " Fixpoint nmake_op (ww:Type) (ww_op: znz_op ww) (n: nat) : ";
 
176
  pp "       znz_op (word ww n) :=";
 
177
  pp "  match n return znz_op (word ww n) with ";
 
178
  pp "   O => ww_op";
 
179
  pp "  | S n1 => mk_zn2z_op (nmake_op ww ww_op n1) ";
 
180
  pp "  end.";
 
181
  pp "";
 
182
  pp " (* Simplification by rewriting for nmake_op *)";
 
183
  pp " Theorem nmake_op_S: forall ww (w_op: znz_op ww) x, ";
 
184
  pp "   nmake_op _ w_op (S x) = mk_zn2z_op (nmake_op _ w_op x).";
 
185
  pp " auto.";
 
186
  pp " Qed.";
 
187
  pp "";
 
188
 
 
189
 
 
190
  pr " (* Eval and extend functions for each level *)";
 
191
  for i = 0 to size do
 
192
    pp " Let nmake_op%i := nmake_op _ w%i_op." i i;
 
193
    pp " Let eval%in n := znz_to_Z  (nmake_op%i n)." i i;
 
194
    if i == 0 then 
 
195
      pr " Let extend%i := DoubleBase.extend  (WW w_0)." i
 
196
    else
 
197
      pr " Let extend%i := DoubleBase.extend  (WW (W0: w%i))." i i;
 
198
  done;
 
199
  pr "";
 
200
 
 
201
 
 
202
  pp " Theorem digits_doubled:forall n ww (w_op: znz_op ww), ";
 
203
  pp "    znz_digits (nmake_op _ w_op n) = ";
 
204
  pp "    DoubleBase.double_digits (znz_digits w_op) n.";
 
205
  pp " Proof.";
 
206
  pp " intros n; elim n; auto; clear n.";
 
207
  pp " intros n Hrec ww ww_op; simpl DoubleBase.double_digits.";
 
208
  pp " rewrite <- Hrec; auto.";
 
209
  pp " Qed.";
 
210
  pp "";
 
211
  pp " Theorem nmake_double: forall n ww (w_op: znz_op ww), ";
 
212
  pp "    znz_to_Z (nmake_op _ w_op n) =";
 
213
  pp "    @DoubleBase.double_to_Z _ (znz_digits w_op) (znz_to_Z w_op) n.";
 
214
  pp " Proof.";
 
215
  pp " intros n; elim n; auto; clear n.";
 
216
  pp " intros n Hrec ww ww_op; simpl DoubleBase.double_to_Z; unfold zn2z_to_Z.";
 
217
  pp " rewrite <- Hrec; auto.";
 
218
  pp " unfold DoubleBase.double_wB; rewrite <- digits_doubled; auto.";
 
219
  pp " Qed.";
 
220
  pp "";
 
221
 
 
222
 
 
223
  pp " Theorem digits_nmake:forall n ww (w_op: znz_op ww), ";
 
224
  pp "    znz_digits (nmake_op _ w_op (S n)) = ";
 
225
  pp "    xO (znz_digits (nmake_op _ w_op n)).";
 
226
  pp " Proof.";
 
227
  pp " auto.";
 
228
  pp " Qed.";
 
229
  pp "";
 
230
 
 
231
 
 
232
  pp " Theorem znz_nmake_op: forall ww ww_op n xh xl,";
 
233
  pp "  znz_to_Z (nmake_op ww ww_op (S n)) (WW xh xl) =";
 
234
  pp "   znz_to_Z (nmake_op ww ww_op n) xh *";
 
235
  pp "    base (znz_digits (nmake_op ww ww_op n)) +";
 
236
  pp "   znz_to_Z (nmake_op ww ww_op n) xl.";
 
237
  pp " Proof.";
 
238
  pp " auto.";
 
239
  pp " Qed.";
 
240
  pp "";
 
241
 
 
242
  pp " Theorem make_op_S: forall n,";
 
243
  pp "   make_op (S n) = mk_zn2z_op_karatsuba (make_op n).";
 
244
  pp " intro n.";
 
245
  pp " do 2 rewrite make_op_omake.";
 
246
  pp " pattern n; apply lt_wf_ind; clear n.";
 
247
  pp " intros n; case n; clear n.";
 
248
  pp "   intros _; unfold omake_op, make_op_aux, w%i_op; apply refl_equal." (size + 2);
 
249
  pp " intros n; case n; clear n.";
 
250
  pp "   intros _; unfold omake_op, make_op_aux, w%i_op; apply refl_equal." (size + 3);
 
251
  pp " intros n; case n; clear n.";
 
252
  pp "   intros _; unfold omake_op, make_op_aux, w%i_op, w%i_op; apply refl_equal." (size + 3) (size + 2);
 
253
  pp " intros n Hrec.";
 
254
  pp "   change (omake_op (S (S (S (S n))))) with";
 
255
  pp "          (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (omake_op (S n))))).";
 
256
  pp "   change (omake_op (S (S (S n)))) with";
 
257
  pp "         (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (mk_zn2z_op_karatsuba (omake_op n)))).";
 
258
  pp "   rewrite Hrec; auto with arith.";
 
259
  pp " Qed.";
 
260
  pp " ";
 
261
 
 
262
 
 
263
  for i = 1 to size + 2 do
 
264
    pp " Let znz_to_Z_%i: forall x y," i;
 
265
    pp "   znz_to_Z w%i_op (WW x y) = " i;
 
266
    pp "    znz_to_Z w%i_op x * base (znz_digits w%i_op) + znz_to_Z w%i_op y." (i-1) (i-1) (i-1);
 
267
    pp " Proof.";
 
268
    pp " auto.";
 
269
    pp " Qed. ";
 
270
    pp "";
 
271
  done;
 
272
 
 
273
  pp " Let znz_to_Z_n: forall n x y,";
 
274
  pp "   znz_to_Z (make_op (S n)) (WW x y) = ";
 
275
  pp "    znz_to_Z (make_op n) x * base (znz_digits (make_op n)) + znz_to_Z (make_op n) y.";
 
276
  pp " Proof.";
 
277
  pp " intros n x y; rewrite make_op_S; auto.";
 
278
  pp " Qed. ";
 
279
  pp "";
 
280
 
 
281
  pp " Let w0_spec: znz_spec w0_op := W0.w_spec.";
 
282
  for i = 1 to 3 do
 
283
    pp " Let w%i_spec: znz_spec w%i_op := mk_znz2_spec w%i_spec." i i (i-1) 
 
284
  done;
 
285
  for i = 4 to size + 3 do
 
286
    pp " Let w%i_spec : znz_spec w%i_op := mk_znz2_karatsuba_spec w%i_spec." i i (i-1)
 
287
  done;
 
288
  pp "";
 
289
 
 
290
  pp " Let wn_spec: forall n, znz_spec (make_op n).";
 
291
  pp "  intros n; elim n; clear n.";
 
292
  pp "    exact w%i_spec." (size + 1);
 
293
  pp "  intros n Hrec; rewrite make_op_S.";
 
294
  pp "  exact (mk_znz2_karatsuba_spec Hrec).";
 
295
  pp " Qed.";
 
296
  pp "";
 
297
 
 
298
  for i = 0 to size do
 
299
    pr " Definition w%i_eq0 := w%i_op.(znz_eq0)." i i;
 
300
    pr " Let spec_w%i_eq0: forall x, if w%i_eq0 x then [%s%i x] = 0 else True." i i c i;
 
301
    pa " Admitted.";
 
302
    pp " Proof.";
 
303
    pp " intros x; unfold w%i_eq0, to_Z; generalize (spec_eq0 w%i_spec x);" i i;
 
304
    pp "    case znz_eq0; auto.";
 
305
    pp " Qed.";
 
306
    pr "";
 
307
  done;
 
308
  pr "";
 
309
 
 
310
 
 
311
  for i = 0 to size do
 
312
    pp " Theorem digits_w%i:  znz_digits w%i_op = znz_digits (nmake_op _ w0_op %i)." i i i; 
 
313
    if i == 0 then
 
314
      pp " auto."
 
315
    else
 
316
      pp " rewrite digits_nmake; rewrite <- digits_w%i; auto." (i - 1);
 
317
    pp " Qed.";
 
318
    pp "";
 
319
    pp " Let spec_double_eval%in: forall n, eval%in n = DoubleBase.double_to_Z (znz_digits w%i_op) (znz_to_Z w%i_op) n." i i i i; 
 
320
    pp " Proof.";
 
321
    pp "  intros n; exact (nmake_double n w%i w%i_op)." i i;
 
322
    pp " Qed.";
 
323
    pp "";
 
324
  done;
 
325
 
 
326
  for i = 0 to size do
 
327
    for j = 0 to (size - i) do
 
328
      pp " Theorem digits_w%in%i: znz_digits w%i_op = znz_digits (nmake_op _ w%i_op %i)." i j (i + j) i j; 
 
329
      pp " Proof.";
 
330
      if j == 0 then
 
331
        if i == 0 then
 
332
          pp " auto."
 
333
        else
 
334
          begin
 
335
            pp " apply trans_equal with (xO (znz_digits w%i_op))." (i + j -1);
 
336
            pp "  auto.";
 
337
            pp "  unfold nmake_op; auto.";
 
338
          end
 
339
      else
 
340
        begin
 
341
          pp " apply trans_equal with (xO (znz_digits w%i_op))." (i + j -1);
 
342
          pp "  auto.";
 
343
          pp " rewrite digits_nmake.";
 
344
          pp " rewrite digits_w%in%i." i (j - 1);
 
345
          pp " auto.";
 
346
        end;
 
347
      pp " Qed.";
 
348
      pp "";
 
349
      pp " Let spec_eval%in%i: forall x, [%s%i x] = eval%in %i x." i j c (i + j) i j; 
 
350
      pp " Proof.";
 
351
      if j == 0 then
 
352
        pp " intros x; rewrite spec_double_eval%in; unfold DoubleBase.double_to_Z, to_Z; auto." i
 
353
      else
 
354
        begin
 
355
          pp " intros x; case x.";
 
356
          pp "   auto.";
 
357
          pp " intros xh xl; unfold to_Z; rewrite znz_to_Z_%i." (i + j);
 
358
          pp " rewrite digits_w%in%i." i (j - 1);
 
359
          pp " generalize (spec_eval%in%i); unfold to_Z; intros HH; repeat rewrite HH." i (j - 1);
 
360
          pp " unfold eval%in, nmake_op%i." i i;
 
361
          pp " rewrite (znz_nmake_op _ w%i_op %i); auto." i (j - 1);
 
362
        end;
 
363
      pp " Qed.";
 
364
      if i + j <> size  then
 
365
        begin
 
366
          pp " Let spec_extend%in%i: forall x, [%s%i x] = [%s%i (extend%i %i x)]." i (i + j + 1) c i c (i + j + 1) i j; 
 
367
          if j == 0 then
 
368
            begin
 
369
              pp " intros x; change (extend%i 0 x) with (WW (znz_0 w%i_op) x)." i (i + j);
 
370
              pp " unfold to_Z; rewrite znz_to_Z_%i." (i + j + 1);
 
371
              pp " rewrite (spec_0 w%i_spec); auto." (i + j);
 
372
            end
 
373
          else
 
374
            begin
 
375
              pp " intros x; change (extend%i %i x) with (WW (znz_0 w%i_op) (extend%i %i x))." i j (i + j) i (j - 1);
 
376
              pp " unfold to_Z; rewrite znz_to_Z_%i." (i + j + 1);
 
377
              pp " rewrite (spec_0 w%i_spec)." (i + j);
 
378
              pp " generalize (spec_extend%in%i x); unfold to_Z." i (i + j);
 
379
              pp " intros HH; rewrite <- HH; auto.";
 
380
            end;
 
381
          pp " Qed.";
 
382
          pp "";
 
383
        end;
 
384
    done;
 
385
 
 
386
    pp " Theorem digits_w%in%i: znz_digits w%i_op = znz_digits (nmake_op _ w%i_op %i)." i (size - i + 1) (size + 1) i (size - i + 1);
 
387
    pp " Proof.";
 
388
    pp " apply trans_equal with (xO (znz_digits w%i_op))." size;
 
389
    pp "  auto.";
 
390
    pp " rewrite digits_nmake.";
 
391
    pp " rewrite digits_w%in%i." i (size - i);
 
392
    pp " auto.";
 
393
    pp " Qed.";
 
394
    pp "";
 
395
 
 
396
    pp " Let spec_eval%in%i: forall x, [%sn 0  x] = eval%in %i x." i (size - i + 1) c i (size - i + 1); 
 
397
    pp " Proof.";
 
398
    pp " intros x; case x.";
 
399
    pp "   auto.";
 
400
    pp " intros xh xl; unfold to_Z; rewrite znz_to_Z_%i." (size + 1);
 
401
    pp " rewrite digits_w%in%i." i (size - i);
 
402
    pp " generalize (spec_eval%in%i); unfold to_Z; intros HH; repeat rewrite HH." i (size - i);
 
403
    pp " unfold eval%in, nmake_op%i." i i;
 
404
    pp " rewrite (znz_nmake_op _ w%i_op %i); auto." i (size - i);
 
405
    pp " Qed.";
 
406
    pp "";
 
407
 
 
408
    pp " Let spec_eval%in%i: forall x, [%sn 1  x] = eval%in %i x." i (size - i + 2) c i (size - i + 2); 
 
409
    pp " intros x; case x.";
 
410
    pp "   auto.";
 
411
    pp " intros xh xl; unfold to_Z; rewrite znz_to_Z_%i." (size + 2);
 
412
    pp " rewrite digits_w%in%i." i (size + 1 - i);
 
413
    pp " generalize (spec_eval%in%i); unfold to_Z; change (make_op 0) with (w%i_op); intros HH; repeat rewrite HH." i (size + 1 - i) (size + 1);
 
414
    pp " unfold eval%in, nmake_op%i." i i;
 
415
    pp " rewrite (znz_nmake_op _ w%i_op %i); auto." i (size + 1 - i);
 
416
    pp " Qed.";
 
417
    pp "";
 
418
  done;
 
419
 
 
420
  pp " Let digits_w%in: forall n," size;
 
421
  pp "   znz_digits (make_op n) = znz_digits (nmake_op _ w%i_op (S n))." size;
 
422
  pp " intros n; elim n; clear n.";
 
423
  pp "  change (znz_digits (make_op 0)) with (xO (znz_digits w%i_op))." size;
 
424
  pp "  rewrite nmake_op_S; apply sym_equal; auto.";
 
425
  pp "  intros  n Hrec.";
 
426
  pp "  replace (znz_digits (make_op (S n))) with (xO (znz_digits (make_op n))).";
 
427
  pp "  rewrite Hrec.";
 
428
  pp "  rewrite nmake_op_S; apply sym_equal; auto.";
 
429
  pp "  rewrite make_op_S; apply sym_equal; auto.";
 
430
  pp " Qed.";
 
431
  pp "";
 
432
 
 
433
  pp " Let spec_eval%in: forall n x, [%sn n x] = eval%in (S n) x." size c size; 
 
434
  pp " intros n; elim n; clear n.";
 
435
  pp "   exact spec_eval%in1." size;
 
436
  pp " intros n Hrec x; case x; clear x.";
 
437
  pp "  unfold to_Z, eval%in, nmake_op%i." size size;
 
438
  pp "    rewrite make_op_S; rewrite nmake_op_S; auto.";
 
439
  pp " intros xh xl.";
 
440
  pp "  unfold to_Z in Hrec |- *.";
 
441
  pp "  rewrite znz_to_Z_n.";
 
442
  pp "  rewrite digits_w%in." size;
 
443
  pp "  repeat rewrite Hrec.";
 
444
  pp "  unfold eval%in, nmake_op%i." size size;
 
445
  pp "  apply sym_equal; rewrite nmake_op_S; auto.";
 
446
  pp " Qed.";
 
447
  pp "";
 
448
 
 
449
  pp " Let spec_extend%in: forall n x, [%s%i x] = [%sn n (extend%i n x)]." size c size c size ; 
 
450
  pp " intros n; elim n; clear n.";
 
451
  pp "   intros x; change (extend%i 0 x) with (WW (znz_0 w%i_op) x)." size size;
 
452
  pp "   unfold to_Z.";
 
453
  pp "   change (make_op 0) with w%i_op." (size + 1);
 
454
  pp "   rewrite znz_to_Z_%i; rewrite (spec_0 w%i_spec); auto." (size + 1) size;
 
455
  pp " intros n Hrec x.";
 
456
  pp "   change (extend%i (S n) x) with (WW W0 (extend%i n x))." size size;
 
457
  pp "   unfold to_Z in Hrec |- *; rewrite znz_to_Z_n; auto.";
 
458
  pp "   rewrite <- Hrec.";
 
459
  pp "  replace (znz_to_Z (make_op n) W0) with 0; auto.";
 
460
  pp "  case n; auto; intros; rewrite make_op_S; auto.";
 
461
  pp " Qed.";
 
462
  pp "";
 
463
 
 
464
  pr " Theorem spec_pos: forall x, 0 <= [x].";
 
465
  pa " Admitted.";
 
466
  pp " Proof.";
 
467
  pp " intros x; case x; clear x.";
 
468
  for i = 0 to size do
 
469
    pp " intros x; case (spec_to_Z w%i_spec x); auto." i;
 
470
  done;
 
471
  pp " intros n x; case (spec_to_Z (wn_spec n) x); auto.";
 
472
  pp " Qed.";
 
473
  pr "";
 
474
 
 
475
  pp " Let spec_extendn_0: forall n wx, [%sn n (extend n _ wx)] = [%sn 0 wx]." c c;
 
476
  pp " intros n; elim n; auto.";
 
477
  pp " intros n1 Hrec wx; simpl extend; rewrite <- Hrec; auto.";
 
478
  pp " unfold to_Z.";
 
479
  pp " case n1; auto; intros n2; repeat rewrite make_op_S; auto.";
 
480
  pp " Qed.";
 
481
  pp " Hint Rewrite spec_extendn_0: extr.";
 
482
  pp "";
 
483
  pp " Let spec_extendn0_0: forall n wx, [%sn (S n) (WW W0 wx)] = [%sn n wx]." c c;
 
484
  pp " Proof.";
 
485
  pp " intros n x; unfold to_Z.";
 
486
  pp " rewrite znz_to_Z_n.";
 
487
  pp " rewrite <- (Zplus_0_l (znz_to_Z (make_op n) x)).";
 
488
  pp " apply (f_equal2 Zplus); auto.";
 
489
  pp " case n; auto.";
 
490
  pp " intros n1; rewrite make_op_S; auto.";
 
491
  pp " Qed.";
 
492
  pp " Hint Rewrite spec_extendn_0: extr.";
 
493
  pp "";
 
494
  pp " Let spec_extend_tr: forall m n (w: word _ (S n)),";
 
495
  pp " [%sn (m + n) (extend_tr w m)] = [%sn n w]." c c;
 
496
  pp " Proof.";
 
497
  pp " induction m; auto.";
 
498
  pp " intros n x; simpl extend_tr.";
 
499
  pp " simpl plus; rewrite spec_extendn0_0; auto.";
 
500
  pp " Qed.";
 
501
  pp " Hint Rewrite spec_extend_tr: extr.";
 
502
  pp "";
 
503
  pp " Let spec_cast_l: forall n m x1,";
 
504
  pp " [%sn (Max.max n m)" c;
 
505
  pp " (castm (diff_r n m) (extend_tr x1 (snd (diff n m))))] =";
 
506
  pp " [%sn n x1]." c;
 
507
  pp " Proof.";
 
508
  pp " intros n m x1; case (diff_r n m); simpl castm.";
 
509
  pp " rewrite spec_extend_tr; auto.";
 
510
  pp " Qed.";
 
511
  pp " Hint Rewrite spec_cast_l: extr.";
 
512
  pp "";
 
513
  pp " Let spec_cast_r: forall n m x1,";
 
514
  pp " [%sn (Max.max n m)" c;
 
515
  pp "  (castm (diff_l n m) (extend_tr x1 (fst (diff n m))))] =";
 
516
  pp " [%sn m x1]." c;
 
517
  pp " Proof.";
 
518
  pp " intros n m x1; case (diff_l n m); simpl castm.";
 
519
  pp " rewrite spec_extend_tr; auto.";
 
520
  pp " Qed.";
 
521
  pp " Hint Rewrite spec_cast_r: extr.";
 
522
  pp "";
 
523
 
 
524
 
 
525
  pr " Section LevelAndIter.";
 
526
  pr "";
 
527
  pr "  Variable res: Type.";
 
528
  pr "  Variable xxx: res.";
 
529
  pr "  Variable P: Z -> Z -> res -> Prop.";
 
530
  pr "  (* Abstraction function for each level *)";
 
531
  for i = 0 to size do
 
532
    pr "  Variable f%i: w%i -> w%i -> res." i i i;
 
533
    pr "  Variable f%in: forall n, w%i -> word w%i (S n) -> res." i i i;
 
534
    pr "  Variable fn%i: forall n, word w%i (S n) -> w%i -> res." i i i;
 
535
    pp "  Variable Pf%i: forall x y, P [%s%i x] [%s%i y] (f%i x y)." i c i c i i;
 
536
    if i == size then
 
537
      begin
 
538
        pp "  Variable Pf%in: forall n x y, P [%s%i x] (eval%in (S n) y) (f%in n x y)." i c i i i;
 
539
        pp "  Variable Pfn%i: forall n x y, P (eval%in (S n) x) [%s%i y] (fn%i n x y)." i i c i i;
 
540
      end
 
541
    else
 
542
      begin
 
543
        pp "  Variable Pf%in: forall n x y, Z_of_nat n <= %i -> P [%s%i x] (eval%in (S n) y) (f%in n x y)." i (size - i) c i i i;
 
544
        pp "  Variable Pfn%i: forall n x y, Z_of_nat n <= %i -> P (eval%in (S n) x) [%s%i y] (fn%i n x y)." i (size - i) i c i i;
 
545
      end;
 
546
    pr "";
 
547
  done;
 
548
  pr "  Variable fnn: forall n, word w%i (S n) -> word w%i (S n) -> res." size size;
 
549
  pp "  Variable Pfnn: forall n x y, P [%sn n x] [%sn n y] (fnn n x y)." c c;
 
550
  pr "  Variable fnm: forall n m, word w%i (S n) -> word w%i (S m) -> res." size size;
 
551
  pp "  Variable Pfnm: forall n m x y, P [%sn n x] [%sn m y] (fnm n m x y)." c c;
 
552
  pr "";
 
553
  pr "  (* Special zero functions *)";
 
554
  pr "  Variable f0t:  t_ -> res.";
 
555
  pp "  Variable Pf0t: forall x, P 0 [x] (f0t x).";
 
556
  pr "  Variable ft0:  t_ -> res.";
 
557
  pp "  Variable Pft0: forall x, P [x] 0 (ft0 x).";
 
558
  pr "";
 
559
 
 
560
 
 
561
  pr "  (* We level the two arguments before applying *)";
 
562
  pr "  (* the functions at each leval                *)";
 
563
  pr "  Definition same_level (x y: t_): res :=";
 
564
  pr0 "    Eval lazy zeta beta iota delta [";
 
565
  for i = 0 to size do
 
566
    pr0 "extend%i " i;
 
567
  done;
 
568
  pr "";
 
569
  pr "                                         DoubleBase.extend DoubleBase.extend_aux";
 
570
  pr "                                         ] in";
 
571
  pr "  match x, y with";
 
572
  for i = 0 to size do
 
573
    for j = 0 to i - 1 do
 
574
      pr "  | %s%i wx, %s%i wy => f%i wx (extend%i %i wy)" c i c j i j (i - j -1);
 
575
    done;
 
576
    pr "  | %s%i wx, %s%i wy => f%i wx wy" c i c i i;
 
577
    for j = i + 1 to size do
 
578
      pr "  | %s%i wx, %s%i wy => f%i (extend%i %i wx) wy" c i c j j i (j - i - 1);
 
579
    done;
 
580
    if i == size then
 
581
      pr "  | %s%i wx, %sn m wy => fnn m (extend%i m wx) wy" c size c size 
 
582
    else 
 
583
      pr "  | %s%i wx, %sn m wy => fnn m (extend%i m (extend%i %i wx)) wy" c i c size i (size - i - 1);
 
584
  done;
 
585
  for i = 0 to size do
 
586
    if i == size then
 
587
      pr "  | %sn n wx, %s%i wy => fnn n wx (extend%i n wy)" c c size size 
 
588
    else 
 
589
      pr "  | %sn n wx, %s%i wy => fnn n wx (extend%i n (extend%i %i wy))" c c i size i (size - i - 1);
 
590
  done;
 
591
  pr "  | %sn n wx, Nn m wy =>" c;
 
592
  pr "    let mn := Max.max n m in";
 
593
  pr "    let d := diff n m in";
 
594
  pr "     fnn mn";
 
595
  pr "       (castm (diff_r n m) (extend_tr wx (snd d)))";
 
596
  pr "       (castm (diff_l n m) (extend_tr wy (fst d)))";
 
597
  pr "  end.";
 
598
  pr "";
 
599
 
 
600
  pp "  Lemma spec_same_level: forall x y, P [x] [y] (same_level x y).";
 
601
  pp "  Proof.";
 
602
  pp "  intros x; case x; clear x; unfold same_level.";
 
603
  for i = 0 to size do
 
604
    pp "    intros x y; case y; clear y.";
 
605
    for j = 0 to i - 1 do
 
606
      pp "     intros y; rewrite spec_extend%in%i; apply Pf%i." j i i;
 
607
    done;
 
608
    pp "     intros y; apply Pf%i." i;
 
609
    for j = i + 1 to size do
 
610
      pp "     intros y; rewrite spec_extend%in%i; apply Pf%i." i j j;
 
611
    done;
 
612
    if i == size then
 
613
      pp "     intros m y; rewrite (spec_extend%in m); apply Pfnn." size
 
614
    else 
 
615
      pp "     intros m y; rewrite spec_extend%in%i; rewrite (spec_extend%in m); apply Pfnn." i size size;
 
616
  done;
 
617
  pp "    intros n x y; case y; clear y.";
 
618
  for i = 0 to size do
 
619
    if i == size then
 
620
      pp "    intros y; rewrite (spec_extend%in n); apply Pfnn." size
 
621
    else 
 
622
      pp "    intros y; rewrite spec_extend%in%i; rewrite (spec_extend%in n); apply Pfnn." i size size;
 
623
  done;
 
624
  pp "    intros m y; rewrite <- (spec_cast_l n m x); ";
 
625
  pp "          rewrite <- (spec_cast_r n m y); apply Pfnn.";
 
626
  pp "  Qed.";
 
627
  pp "";
 
628
 
 
629
  pr "  (* We level the two arguments before applying      *)";
 
630
  pr "  (* the functions at each level (special zero case) *)";
 
631
  pr "  Definition same_level0 (x y: t_): res :=";
 
632
  pr0 "    Eval lazy zeta beta iota delta [";
 
633
  for i = 0 to size do
 
634
    pr0 "extend%i " i;
 
635
  done;
 
636
  pr "";
 
637
  pr "                                         DoubleBase.extend DoubleBase.extend_aux";
 
638
  pr "                                         ] in";
 
639
  pr "  match x with";
 
640
  for i = 0 to size do
 
641
    pr "  | %s%i wx =>" c i;
 
642
    if i == 0 then
 
643
      pr "    if w0_eq0 wx then f0t y else";
 
644
    pr "    match y with";
 
645
    for j = 0 to i - 1 do
 
646
      pr "    | %s%i wy =>" c j;
 
647
      if j == 0 then 
 
648
        pr "       if w0_eq0 wy then ft0 x else";
 
649
      pr "       f%i wx (extend%i %i wy)" i j (i - j -1);
 
650
    done;
 
651
    pr "    | %s%i wy => f%i wx wy" c i i;
 
652
    for j = i + 1 to size do
 
653
      pr "    | %s%i wy => f%i (extend%i %i wx) wy" c j j i (j - i - 1);
 
654
    done;
 
655
    if i == size then
 
656
      pr "    | %sn m wy => fnn m (extend%i m wx) wy" c size 
 
657
    else 
 
658
      pr "    | %sn m wy => fnn m (extend%i m (extend%i %i wx)) wy" c size i (size - i - 1);
 
659
    pr"    end";
 
660
  done;
 
661
  pr "  |  %sn n wx =>" c;
 
662
  pr "     match y with";
 
663
  for i = 0 to size do
 
664
    pr "     | %s%i wy =>" c i;
 
665
    if i == 0 then
 
666
      pr "      if w0_eq0 wy then ft0 x else";
 
667
    if i == size then
 
668
      pr "      fnn n wx (extend%i n wy)" size 
 
669
    else 
 
670
      pr "      fnn n wx (extend%i n (extend%i %i wy))" size i (size - i - 1);
 
671
  done;
 
672
  pr "        | %sn m wy =>" c;
 
673
  pr "            let mn := Max.max n m in";
 
674
  pr "            let d := diff n m in";
 
675
  pr "              fnn mn";
 
676
  pr "              (castm (diff_r n m) (extend_tr wx (snd d)))";
 
677
  pr "              (castm (diff_l n m) (extend_tr wy (fst d)))";
 
678
  pr "    end";
 
679
  pr "  end.";
 
680
  pr "";
 
681
 
 
682
  pp "  Lemma spec_same_level0: forall x y, P [x] [y] (same_level0 x y).";
 
683
  pp "  Proof.";
 
684
  pp "  intros x; case x; clear x; unfold same_level0.";
 
685
  for i = 0 to size do
 
686
    pp "    intros x.";
 
687
    if i == 0 then
 
688
      begin
 
689
        pp "    generalize (spec_w0_eq0 x); case w0_eq0; intros H.";
 
690
        pp "      intros y; rewrite H; apply Pf0t.";
 
691
        pp "    clear H.";
 
692
      end;
 
693
    pp "    intros y; case y; clear y.";
 
694
    for j = 0 to i - 1 do
 
695
      pp "     intros y.";
 
696
      if j == 0 then
 
697
        begin
 
698
          pp "     generalize (spec_w0_eq0 y); case w0_eq0; intros H.";
 
699
          pp "       rewrite H; apply Pft0.";
 
700
          pp "     clear H.";
 
701
        end;
 
702
      pp "     rewrite spec_extend%in%i; apply Pf%i." j i i;
 
703
    done;
 
704
    pp "     intros y; apply Pf%i." i;
 
705
    for j = i + 1 to size do
 
706
      pp "     intros y; rewrite spec_extend%in%i; apply Pf%i." i j j;
 
707
    done;
 
708
    if i == size then
 
709
      pp "     intros m y; rewrite (spec_extend%in m); apply Pfnn." size
 
710
    else 
 
711
      pp "     intros m y; rewrite spec_extend%in%i; rewrite (spec_extend%in m); apply Pfnn." i size size;
 
712
  done;
 
713
  pp "    intros n x y; case y; clear y.";
 
714
  for i = 0 to size do
 
715
    pp "    intros y.";
 
716
    if i = 0 then
 
717
      begin
 
718
        pp "     generalize (spec_w0_eq0 y); case w0_eq0; intros H.";
 
719
        pp "       rewrite H; apply Pft0.";
 
720
        pp "     clear H.";
 
721
      end;
 
722
    if i == size then
 
723
      pp "    rewrite (spec_extend%in n); apply Pfnn." size
 
724
    else 
 
725
      pp "    rewrite spec_extend%in%i; rewrite (spec_extend%in n); apply Pfnn." i size size;
 
726
  done;
 
727
  pp "  intros m y; rewrite <- (spec_cast_l n m x); ";
 
728
  pp "          rewrite <- (spec_cast_r n m y); apply Pfnn.";
 
729
  pp "  Qed.";
 
730
  pp "";
 
731
 
 
732
  pr "  (* We iter the smaller argument with the bigger  *)";
 
733
  pr "  Definition iter (x y: t_): res := ";
 
734
  pr0 "    Eval lazy zeta beta iota delta [";
 
735
  for i = 0 to size do
 
736
    pr0 "extend%i " i;
 
737
  done;
 
738
  pr "";
 
739
  pr "                                         DoubleBase.extend DoubleBase.extend_aux";
 
740
  pr "                                         ] in";
 
741
  pr "  match x, y with";
 
742
  for i = 0 to size do
 
743
    for j = 0 to i - 1 do
 
744
      pr "  | %s%i wx, %s%i wy => fn%i %i wx wy" c i c j j (i - j - 1);
 
745
    done;
 
746
    pr "  | %s%i wx, %s%i wy => f%i wx wy" c i c i i;
 
747
    for j = i + 1 to size do
 
748
      pr "  | %s%i wx, %s%i wy => f%in %i wx wy" c i c j i (j - i - 1);
 
749
    done;
 
750
    if i == size then
 
751
      pr "  | %s%i wx, %sn m wy => f%in m wx wy" c size c size 
 
752
    else 
 
753
      pr "  | %s%i wx, %sn m wy => f%in m (extend%i %i wx) wy" c i c size i (size - i - 1);
 
754
  done;
 
755
  for i = 0 to size do
 
756
    if i == size then
 
757
      pr "  | %sn n wx, %s%i wy => fn%i n wx wy" c c size size 
 
758
    else 
 
759
      pr "  | %sn n wx, %s%i wy => fn%i n wx (extend%i %i wy)" c c i size i (size - i - 1);
 
760
  done;
 
761
  pr "  | %sn n wx, %sn m wy => fnm n m wx wy" c c;
 
762
  pr "  end.";
 
763
  pr "";
 
764
 
 
765
  pp "  Ltac zg_tac := try";
 
766
  pp "    (red; simpl Zcompare; auto;";
 
767
  pp "     let t := fresh \"H\" in (intros t; discriminate t)).";
 
768
  pp "  Lemma spec_iter: forall x y, P [x] [y] (iter x y).";
 
769
  pp "  Proof.";
 
770
  pp "  intros x; case x; clear x; unfold iter.";
 
771
  for i = 0 to size do
 
772
    pp "    intros x y; case y; clear y.";
 
773
    for j = 0 to i - 1 do
 
774
      pp "     intros y; rewrite spec_eval%in%i;  apply (Pfn%i %i); zg_tac." j (i - j) j (i - j - 1);
 
775
    done;
 
776
    pp "     intros y; apply Pf%i." i;
 
777
    for j = i + 1 to size do
 
778
      pp "     intros y; rewrite spec_eval%in%i; apply (Pf%in %i); zg_tac." i (j - i) i (j - i - 1);
 
779
    done;
 
780
    if i == size then
 
781
      pp "     intros m y; rewrite spec_eval%in; apply Pf%in." size size
 
782
    else 
 
783
      pp "     intros m y; rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pf%in." i size size size;
 
784
  done;
 
785
  pp "    intros n x y; case y; clear y.";
 
786
  for i = 0 to size do
 
787
    if i == size then
 
788
      pp "     intros y; rewrite spec_eval%in; apply Pfn%i." size size
 
789
    else 
 
790
      pp "      intros y; rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pfn%i." i size size size;
 
791
  done;
 
792
  pp "  intros m y; apply Pfnm.";
 
793
  pp "  Qed.";
 
794
  pp "";
 
795
 
 
796
 
 
797
  pr "  (* We iter the smaller argument with the bigger  (zero case) *)";
 
798
  pr "  Definition iter0 (x y: t_): res :=";
 
799
  pr0 "    Eval lazy zeta beta iota delta [";
 
800
  for i = 0 to size do
 
801
    pr0 "extend%i " i;
 
802
  done;
 
803
  pr "";
 
804
  pr "                                         DoubleBase.extend DoubleBase.extend_aux";
 
805
  pr "                                         ] in";
 
806
  pr "  match x with";
 
807
  for i = 0 to size do
 
808
    pr "  | %s%i wx =>" c i;
 
809
    if i == 0 then
 
810
      pr "    if w0_eq0 wx then f0t y else";
 
811
    pr "    match y with";
 
812
    for j = 0 to i - 1 do
 
813
      pr "    | %s%i wy =>" c j;
 
814
      if j == 0 then
 
815
        pr "       if w0_eq0 wy then ft0 x else";
 
816
      pr "       fn%i %i wx wy" j (i - j - 1);
 
817
    done;
 
818
    pr "    | %s%i wy => f%i wx wy" c i i;
 
819
    for j = i + 1 to size do
 
820
      pr "    | %s%i wy => f%in %i wx wy" c j i (j - i - 1);
 
821
    done;
 
822
    if i == size then
 
823
      pr "    | %sn m wy => f%in m wx wy" c size 
 
824
    else 
 
825
      pr "    | %sn m wy => f%in m (extend%i %i wx) wy" c size i (size - i - 1);
 
826
    pr "    end";
 
827
  done;
 
828
  pr "  | %sn n wx =>" c;
 
829
  pr "    match y with";
 
830
  for i = 0 to size do
 
831
    pr "    | %s%i wy =>" c i;
 
832
    if i == 0 then
 
833
      pr "      if w0_eq0 wy then ft0 x else";
 
834
    if i == size then
 
835
      pr "      fn%i n wx wy" size 
 
836
    else 
 
837
      pr "      fn%i n wx (extend%i %i wy)" size i (size - i - 1);
 
838
  done;
 
839
  pr "    | %sn m wy => fnm n m wx wy" c;
 
840
  pr "    end";
 
841
  pr "  end.";
 
842
  pr "";
 
843
 
 
844
  pp "  Lemma spec_iter0: forall x y, P [x] [y] (iter0 x y).";
 
845
  pp "  Proof.";
 
846
  pp "  intros x; case x; clear x; unfold iter0.";
 
847
  for i = 0 to size do
 
848
    pp "    intros x.";
 
849
    if i == 0 then
 
850
      begin
 
851
        pp "    generalize (spec_w0_eq0 x); case w0_eq0; intros H.";
 
852
        pp "      intros y; rewrite H; apply Pf0t.";
 
853
        pp "    clear H.";
 
854
      end;
 
855
    pp "    intros y; case y; clear y.";
 
856
    for j = 0 to i - 1 do
 
857
      pp "     intros y.";
 
858
      if j == 0 then
 
859
        begin
 
860
          pp "     generalize (spec_w0_eq0 y); case w0_eq0; intros H.";
 
861
          pp "       rewrite H; apply Pft0.";
 
862
          pp "     clear H.";
 
863
        end;
 
864
      pp "     rewrite spec_eval%in%i;  apply (Pfn%i %i); zg_tac." j (i - j) j (i - j - 1);
 
865
    done;
 
866
    pp "     intros y; apply Pf%i." i;
 
867
    for j = i + 1 to size do
 
868
      pp "     intros y; rewrite spec_eval%in%i; apply (Pf%in %i); zg_tac." i (j - i) i (j - i - 1);
 
869
    done;
 
870
    if i == size then
 
871
      pp "     intros m y; rewrite spec_eval%in; apply Pf%in." size size
 
872
    else 
 
873
      pp "     intros m y; rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pf%in." i size size size;
 
874
  done;
 
875
  pp "    intros n x y; case y; clear y.";
 
876
  for i = 0 to size do
 
877
    pp "    intros y.";
 
878
    if i = 0 then
 
879
      begin
 
880
        pp "     generalize (spec_w0_eq0 y); case w0_eq0; intros H.";
 
881
        pp "       rewrite H; apply Pft0.";
 
882
        pp "     clear H.";
 
883
      end;
 
884
    if i == size then
 
885
      pp "     rewrite spec_eval%in; apply Pfn%i." size size
 
886
    else 
 
887
      pp "      rewrite spec_extend%in%i; rewrite spec_eval%in; apply Pfn%i." i size size size;
 
888
  done;
 
889
  pp "  intros m y; apply Pfnm.";
 
890
  pp "  Qed.";
 
891
  pp "";
 
892
 
 
893
 
 
894
  pr "  End LevelAndIter.";
 
895
  pr "";
 
896
 
 
897
 
 
898
  pr " (***************************************************************)";
 
899
  pr " (*                                                             *)";
 
900
  pr " (*                           Reduction                         *)";
 
901
  pr " (*                                                             *)";
 
902
  pr " (***************************************************************)";
 
903
  pr "";
 
904
 
 
905
  pr " Definition reduce_0 (x:w) := %s0 x." c; 
 
906
  pr " Definition reduce_1 :=";
 
907
  pr "  Eval lazy beta iota delta[reduce_n1] in";
 
908
  pr "   reduce_n1 _ _ zero w0_eq0 %s0 %s1." c c;
 
909
  for i = 2 to size do
 
910
    pr " Definition reduce_%i :=" i;
 
911
    pr "  Eval lazy beta iota delta[reduce_n1] in";
 
912
    pr "   reduce_n1 _ _ zero w%i_eq0 reduce_%i %s%i." 
 
913
      (i-1) (i-1)  c i
 
914
  done;
 
915
  pr " Definition reduce_%i :=" (size+1);
 
916
  pr "  Eval lazy beta iota delta[reduce_n1] in";
 
917
  pr "   reduce_n1 _ _ zero w%i_eq0 reduce_%i (%sn 0)." 
 
918
    size size c; 
 
919
 
 
920
  pr " Definition reduce_n n := ";
 
921
  pr "  Eval lazy beta iota delta[reduce_n] in";
 
922
  pr "   reduce_n _ _ zero reduce_%i %sn n." (size + 1) c;
 
923
  pr "";
 
924
 
 
925
  pp " Let spec_reduce_0: forall x, [reduce_0 x] = [%s0 x]." c;
 
926
  pp " Proof.";
 
927
  pp " intros x; unfold to_Z, reduce_0.";
 
928
  pp " auto.";
 
929
  pp " Qed.";
 
930
  pp " ";
 
931
 
 
932
  for i = 1 to size + 1 do
 
933
    if i == size + 1 then
 
934
      pp " Let spec_reduce_%i: forall x, [reduce_%i x] = [%sn 0 x]." i i c
 
935
    else
 
936
      pp " Let spec_reduce_%i: forall x, [reduce_%i x] = [%s%i x]." i i c i;
 
937
    pp " Proof.";
 
938
    pp " intros x; case x; unfold reduce_%i." i;
 
939
    pp " exact (spec_0 w0_spec).";
 
940
    pp " intros x1 y1.";
 
941
    pp " generalize (spec_w%i_eq0 x1); " (i - 1);
 
942
    pp "   case w%i_eq0; intros H1; auto." (i - 1);
 
943
    if i <> 1 then 
 
944
      pp " rewrite spec_reduce_%i." (i - 1);
 
945
    pp " unfold to_Z; rewrite znz_to_Z_%i." i;
 
946
    pp " unfold to_Z in H1; rewrite H1; auto.";
 
947
    pp " Qed.";
 
948
    pp " ";
 
949
  done;
 
950
 
 
951
  pp " Let spec_reduce_n: forall n x, [reduce_n n x] = [%sn n x]." c;
 
952
  pp " Proof.";
 
953
  pp " intros n; elim n; simpl reduce_n.";
 
954
  pp "   intros x; rewrite <- spec_reduce_%i; auto." (size + 1);
 
955
  pp " intros n1 Hrec x; case x.";
 
956
  pp " unfold to_Z; rewrite make_op_S; auto.";
 
957
  pp " exact (spec_0 w0_spec).";
 
958
  pp " intros x1 y1; case x1; auto.";
 
959
  pp " rewrite Hrec.";
 
960
  pp " rewrite spec_extendn0_0; auto.";
 
961
  pp " Qed.";
 
962
  pp " ";
 
963
 
 
964
  pr " (***************************************************************)";
 
965
  pr " (*                                                             *)";
 
966
  pr " (*                           Successor                         *)";
 
967
  pr " (*                                                             *)";
 
968
  pr " (***************************************************************)";
 
969
  pr "";
 
970
 
 
971
  for i = 0 to size do
 
972
    pr " Definition w%i_succ_c := w%i_op.(znz_succ_c)." i i
 
973
  done;
 
974
  pr "";
 
975
 
 
976
  for i = 0 to size do
 
977
    pr " Definition w%i_succ := w%i_op.(znz_succ)." i i
 
978
  done;
 
979
  pr "";
 
980
 
 
981
  pr " Definition succ x :=";
 
982
  pr "  match x with";
 
983
  for i = 0 to size-1 do
 
984
    pr "  | %s%i wx =>" c i;
 
985
    pr "    match w%i_succ_c wx with" i;
 
986
    pr "    | C0 r => %s%i r" c i; 
 
987
    pr "    | C1 r => %s%i (WW one%i r)" c (i+1) i;
 
988
    pr "    end";
 
989
  done;
 
990
  pr "  | %s%i wx =>" c size;
 
991
  pr "    match w%i_succ_c wx with" size;
 
992
  pr "    | C0 r => %s%i r" c size; 
 
993
  pr "    | C1 r => %sn 0 (WW one%i r)" c size ;
 
994
  pr "    end";
 
995
  pr "  | %sn n wx =>" c;
 
996
  pr "    let op := make_op n in";
 
997
  pr "    match op.(znz_succ_c) wx with";
 
998
  pr "    | C0 r => %sn n r" c; 
 
999
  pr "    | C1 r => %sn (S n) (WW op.(znz_1) r)" c;
 
1000
  pr "    end";
 
1001
  pr "  end.";
 
1002
  pr "";
 
1003
 
 
1004
  pr " Theorem spec_succ: forall n, [succ n] = [n] + 1.";
 
1005
  pa " Admitted.";
 
1006
  pp " Proof.";
 
1007
  pp "  intros n; case n; unfold succ, to_Z.";
 
1008
  for i = 0 to size do
 
1009
    pp  "  intros n1; generalize (spec_succ_c w%i_spec n1);" i;
 
1010
    pp  "  unfold succ, to_Z, w%i_succ_c; case znz_succ_c; auto." i;
 
1011
    pp  "     intros ww H; rewrite <- H.";
 
1012
    pp "     (rewrite znz_to_Z_%i; unfold interp_carry;" (i + 1);
 
1013
    pp "           apply f_equal2 with (f := Zplus); auto;";
 
1014
    pp "           apply f_equal2 with (f := Zmult); auto;";
 
1015
    pp "           exact (spec_1 w%i_spec))." i;
 
1016
  done;
 
1017
  pp "  intros k n1; generalize (spec_succ_c (wn_spec k) n1).";
 
1018
  pp "  unfold succ, to_Z; case znz_succ_c; auto.";
 
1019
  pp "  intros ww H; rewrite <- H.";
 
1020
  pp "     (rewrite (znz_to_Z_n k); unfold interp_carry;";
 
1021
  pp "           apply f_equal2 with (f := Zplus); auto;";
 
1022
  pp "           apply f_equal2 with (f := Zmult); auto;";
 
1023
  pp "           exact (spec_1 (wn_spec k))).";
 
1024
  pp " Qed.";
 
1025
  pr "";
 
1026
 
 
1027
 
 
1028
  pr " (***************************************************************)";
 
1029
  pr " (*                                                             *)";
 
1030
  pr " (*                           Adddition                         *)";
 
1031
  pr " (*                                                             *)";
 
1032
  pr " (***************************************************************)";
 
1033
  pr "";
 
1034
 
 
1035
  for i = 0 to size do
 
1036
    pr " Definition w%i_add_c := znz_add_c w%i_op." i i; 
 
1037
    pr " Definition w%i_add x y :=" i;
 
1038
    pr "  match w%i_add_c x y with" i;
 
1039
    pr "  | C0 r => %s%i r" c i;
 
1040
    if i == size then
 
1041
      pr "  | C1 r => %sn 0 (WW one%i r)" c size
 
1042
    else
 
1043
      pr "  | C1 r => %s%i (WW one%i r)" c (i + 1) i;
 
1044
    pr "  end.";
 
1045
    pr "";
 
1046
  done ;
 
1047
  pr " Definition addn n (x y : word w%i (S n)) :=" size;
 
1048
  pr "  let op := make_op n in";
 
1049
  pr "  match op.(znz_add_c) x y with";
 
1050
  pr "  | C0 r => %sn n r" c;
 
1051
  pr "  | C1 r => %sn (S n) (WW op.(znz_1) r)  end." c;
 
1052
  pr "";
 
1053
 
 
1054
 
 
1055
  for i = 0 to size do
 
1056
    pp " Let spec_w%i_add: forall x y, [w%i_add x y] = [%s%i x] + [%s%i y]." i i c i c i;
 
1057
    pp " Proof.";
 
1058
    pp " intros n m; unfold to_Z, w%i_add, w%i_add_c." i i;
 
1059
    pp "  generalize (spec_add_c w%i_spec n m); case znz_add_c; auto." i;
 
1060
    pp " intros ww H; rewrite <- H."; 
 
1061
    pp "    rewrite znz_to_Z_%i; unfold interp_carry;" (i + 1);
 
1062
    pp "    apply f_equal2 with (f := Zplus); auto;";
 
1063
    pp "    apply f_equal2 with (f := Zmult); auto;";
 
1064
    pp "    exact (spec_1 w%i_spec)." i;
 
1065
    pp " Qed.";
 
1066
    pp " Hint Rewrite spec_w%i_add: addr." i;
 
1067
    pp "";
 
1068
  done;
 
1069
  pp " Let spec_wn_add: forall n x y, [addn n x y] = [%sn n x] + [%sn n y]." c c;
 
1070
  pp " Proof.";
 
1071
  pp " intros k n m; unfold to_Z, addn.";
 
1072
  pp "  generalize (spec_add_c (wn_spec k) n m); case znz_add_c; auto.";
 
1073
  pp " intros ww H; rewrite <- H."; 
 
1074
  pp " rewrite (znz_to_Z_n k); unfold interp_carry;";
 
1075
  pp "        apply f_equal2 with (f := Zplus); auto;";
 
1076
  pp "        apply f_equal2 with (f := Zmult); auto;";
 
1077
  pp "        exact (spec_1 (wn_spec k)).";
 
1078
  pp " Qed.";
 
1079
  pp " Hint Rewrite spec_wn_add: addr.";
 
1080
 
 
1081
  pr " Definition add := Eval lazy beta delta [same_level] in";
 
1082
  pr0 "   (same_level t_ ";
 
1083
  for i = 0 to size do
 
1084
    pr0 "w%i_add " i;
 
1085
  done;
 
1086
  pr "addn).";
 
1087
  pr "";
 
1088
 
 
1089
  pr " Theorem spec_add: forall x y, [add x y] = [x] + [y].";
 
1090
  pa " Admitted.";
 
1091
  pp " Proof.";
 
1092
  pp " unfold add.";
 
1093
  pp " generalize (spec_same_level t_ (fun x y res => [res] = x + y)).";
 
1094
  pp " unfold same_level; intros HH; apply HH; clear HH.";
 
1095
  for i = 0 to size do
 
1096
    pp " exact spec_w%i_add." i;
 
1097
  done;
 
1098
  pp " exact spec_wn_add.";
 
1099
  pp " Qed.";
 
1100
  pr "";
 
1101
 
 
1102
  pr " (***************************************************************)";
 
1103
  pr " (*                                                             *)";
 
1104
  pr " (*                           Predecessor                       *)";
 
1105
  pr " (*                                                             *)";
 
1106
  pr " (***************************************************************)";
 
1107
  pr "";
 
1108
 
 
1109
  for i = 0 to size do
 
1110
    pr " Definition w%i_pred_c := w%i_op.(znz_pred_c)." i i
 
1111
  done;
 
1112
  pr "";
 
1113
 
 
1114
  pr " Definition pred x :=";
 
1115
  pr "  match x with";
 
1116
  for i = 0 to size do
 
1117
    pr "  | %s%i wx =>" c i;
 
1118
    pr "    match w%i_pred_c wx with" i;
 
1119
    pr "    | C0 r => reduce_%i r" i; 
 
1120
    pr "    | C1 r => zero";
 
1121
    pr "    end";
 
1122
  done;
 
1123
  pr "  | %sn n wx =>" c;
 
1124
  pr "    let op := make_op n in";
 
1125
  pr "    match op.(znz_pred_c) wx with";
 
1126
  pr "    | C0 r => reduce_n n r"; 
 
1127
  pr "    | C1 r => zero";
 
1128
  pr "    end";
 
1129
  pr "  end.";
 
1130
  pr "";
 
1131
 
 
1132
  pr " Theorem spec_pred: forall x, 0 < [x] -> [pred x] = [x] - 1.";
 
1133
  pa " Admitted.";
 
1134
  pp " Proof.";
 
1135
  pp " intros x; case x; unfold pred.";
 
1136
  for i = 0 to size do
 
1137
    pp " intros x1 H1; unfold w%i_pred_c; " i;
 
1138
    pp " generalize (spec_pred_c w%i_spec x1); case znz_pred_c; intros y1." i;
 
1139
    pp " rewrite spec_reduce_%i; auto." i;
 
1140
    pp " unfold interp_carry; unfold to_Z.";
 
1141
    pp " case (spec_to_Z w%i_spec x1); intros HH1 HH2." i;
 
1142
    pp " case (spec_to_Z w%i_spec y1); intros HH3 HH4 HH5." i;
 
1143
    pp " assert (znz_to_Z w%i_op x1 - 1 < 0); auto with zarith." i;
 
1144
    pp " unfold to_Z in H1; auto with zarith.";
 
1145
  done;
 
1146
  pp " intros n x1 H1;  ";
 
1147
  pp "   generalize (spec_pred_c (wn_spec n) x1); case znz_pred_c; intros y1.";
 
1148
  pp "   rewrite spec_reduce_n; auto.";
 
1149
  pp " unfold interp_carry; unfold to_Z.";
 
1150
  pp " case (spec_to_Z (wn_spec n) x1); intros HH1 HH2.";
 
1151
  pp " case (spec_to_Z (wn_spec n) y1); intros HH3 HH4 HH5.";
 
1152
  pp " assert (znz_to_Z (make_op n) x1 - 1 < 0); auto with zarith.";
 
1153
  pp " unfold to_Z in H1; auto with zarith.";
 
1154
  pp " Qed.";
 
1155
  pp " ";
 
1156
  
 
1157
  pp " Let spec_pred0: forall x, [x] = 0 -> [pred x] = 0.";
 
1158
  pp " Proof.";
 
1159
  pp " intros x; case x; unfold pred.";
 
1160
  for i = 0 to size do
 
1161
    pp " intros x1 H1; unfold w%i_pred_c; " i;
 
1162
    pp "   generalize (spec_pred_c w%i_spec x1); case znz_pred_c; intros y1." i;
 
1163
    pp " unfold interp_carry; unfold to_Z.";
 
1164
    pp " unfold to_Z in H1; auto with zarith.";
 
1165
    pp " case (spec_to_Z w%i_spec y1); intros HH3 HH4; auto with zarith." i;
 
1166
    pp " intros; exact (spec_0 w0_spec).";
 
1167
  done;
 
1168
  pp " intros n x1 H1; ";
 
1169
  pp "   generalize (spec_pred_c (wn_spec n) x1); case znz_pred_c; intros y1.";
 
1170
  pp " unfold interp_carry; unfold to_Z.";
 
1171
  pp " unfold to_Z in H1; auto with zarith.";
 
1172
  pp " case (spec_to_Z (wn_spec n) y1); intros HH3 HH4; auto with zarith.";
 
1173
  pp " intros; exact (spec_0 w0_spec).";
 
1174
  pp " Qed.";
 
1175
  pr " ";
 
1176
 
 
1177
 
 
1178
  pr " (***************************************************************)";
 
1179
  pr " (*                                                             *)";
 
1180
  pr " (*                           Subtraction                       *)";
 
1181
  pr " (*                                                             *)";
 
1182
  pr " (***************************************************************)";
 
1183
  pr "";
 
1184
 
 
1185
  for i = 0 to size do
 
1186
    pr " Definition w%i_sub_c := w%i_op.(znz_sub_c)." i i
 
1187
  done;
 
1188
  pr "";
 
1189
 
 
1190
  for i = 0 to size do 
 
1191
    pr " Definition w%i_sub x y :=" i;
 
1192
    pr "  match w%i_sub_c x y with" i;
 
1193
    pr "  | C0 r => reduce_%i r" i;
 
1194
    pr "  | C1 r => zero";
 
1195
    pr "  end."
 
1196
  done;
 
1197
  pr "";
 
1198
 
 
1199
  pr " Definition subn n (x y : word w%i (S n)) :=" size;
 
1200
  pr "  let op := make_op n in";
 
1201
  pr "  match op.(znz_sub_c) x y with";
 
1202
  pr "  | C0 r => %sn n r" c;
 
1203
  pr "  | C1 r => N0 w_0";
 
1204
  pr "  end.";
 
1205
  pr "";
 
1206
 
 
1207
  for i = 0 to size do
 
1208
    pp " Let spec_w%i_sub: forall x y, [%s%i y] <= [%s%i x] -> [w%i_sub x y] = [%s%i x] - [%s%i y]." i c i c i i c i c i;
 
1209
    pp " Proof.";
 
1210
    pp " intros n m; unfold w%i_sub, w%i_sub_c." i i;
 
1211
    pp "  generalize (spec_sub_c w%i_spec n m); case znz_sub_c; " i;
 
1212
    if i == 0 then 
 
1213
      pp "    intros x; auto."
 
1214
    else
 
1215
      pp "   intros x; try rewrite spec_reduce_%i; auto." i;
 
1216
    pp " unfold interp_carry; unfold zero, w_0, to_Z.";
 
1217
    pp " rewrite (spec_0 w0_spec).";
 
1218
    pp " case (spec_to_Z w%i_spec x); intros; auto with zarith." i;
 
1219
    pp " Qed.";
 
1220
    pp "";
 
1221
  done;
 
1222
  
 
1223
  pp " Let spec_wn_sub: forall n x y, [%sn n y] <= [%sn n x] -> [subn n x y] = [%sn n x] - [%sn n y]." c c c c;
 
1224
  pp " Proof.";
 
1225
  pp " intros k n m; unfold subn.";
 
1226
  pp " generalize (spec_sub_c (wn_spec k) n m); case znz_sub_c; ";
 
1227
  pp "   intros x; auto.";
 
1228
  pp " unfold interp_carry, to_Z.";
 
1229
  pp " case (spec_to_Z (wn_spec k) x); intros; auto with zarith.";
 
1230
  pp " Qed.";
 
1231
  pp "";
 
1232
 
 
1233
  pr " Definition sub := Eval lazy beta delta [same_level] in";
 
1234
  pr0 "   (same_level t_ ";
 
1235
  for i = 0 to size do
 
1236
    pr0 "w%i_sub " i;
 
1237
  done;
 
1238
  pr "subn).";
 
1239
  pr "";
 
1240
 
 
1241
  pr " Theorem spec_sub: forall x y, [y] <= [x] -> [sub x y] = [x] - [y].";
 
1242
  pa " Admitted.";
 
1243
  pp " Proof.";
 
1244
  pp " unfold sub.";
 
1245
  pp " generalize (spec_same_level t_ (fun x y res => y <= x -> [res] = x - y)).";
 
1246
  pp " unfold same_level; intros HH; apply HH; clear HH.";
 
1247
  for i = 0 to size do
 
1248
    pp " exact spec_w%i_sub." i;
 
1249
  done;
 
1250
  pp " exact spec_wn_sub.";
 
1251
  pp " Qed.";
 
1252
  pr "";
 
1253
 
 
1254
  for i = 0 to size do
 
1255
    pp " Let spec_w%i_sub0: forall x y, [%s%i x] < [%s%i y] -> [w%i_sub x y] = 0." i c i c i i;
 
1256
    pp " Proof.";
 
1257
    pp " intros n m; unfold w%i_sub, w%i_sub_c." i i;
 
1258
    pp "  generalize (spec_sub_c w%i_spec n m); case znz_sub_c; " i;
 
1259
    pp "   intros x; unfold interp_carry.";
 
1260
    pp "   unfold to_Z; case (spec_to_Z w%i_spec x); intros; auto with zarith." i;
 
1261
    pp " intros; unfold to_Z, zero, w_0; rewrite (spec_0 w0_spec); auto.";
 
1262
    pp " Qed.";
 
1263
    pp "";
 
1264
  done;
 
1265
 
 
1266
  pp " Let spec_wn_sub0: forall n x y, [%sn n x] < [%sn n y] -> [subn n x y] = 0." c c;
 
1267
  pp " Proof.";
 
1268
  pp " intros k n m; unfold subn.";
 
1269
  pp " generalize (spec_sub_c (wn_spec k) n m); case znz_sub_c; ";
 
1270
  pp "   intros x; unfold interp_carry.";
 
1271
  pp "   unfold to_Z; case (spec_to_Z (wn_spec k) x); intros; auto with zarith.";
 
1272
  pp " intros; unfold to_Z, w_0; rewrite (spec_0 (w0_spec)); auto.";
 
1273
  pp " Qed.";
 
1274
  pp "";
 
1275
 
 
1276
  pr " Theorem spec_sub0: forall x y, [x] < [y] -> [sub x y] = 0.";
 
1277
  pa " Admitted.";
 
1278
  pp " Proof.";
 
1279
  pp " unfold sub.";
 
1280
  pp " generalize (spec_same_level t_ (fun x y res => x < y -> [res] = 0)).";
 
1281
  pp " unfold same_level; intros HH; apply HH; clear HH.";
 
1282
  for i = 0 to size do
 
1283
    pp " exact spec_w%i_sub0." i;
 
1284
  done;
 
1285
  pp " exact spec_wn_sub0.";
 
1286
  pp " Qed.";
 
1287
  pr "";
 
1288
 
 
1289
 
 
1290
  pr " (***************************************************************)";
 
1291
  pr " (*                                                             *)";
 
1292
  pr " (*                           Comparison                        *)";
 
1293
  pr " (*                                                             *)";
 
1294
  pr " (***************************************************************)";
 
1295
  pr "";
 
1296
 
 
1297
  for i = 0 to size do
 
1298
    pr " Definition compare_%i := w%i_op.(znz_compare)." i i;
 
1299
    pr " Definition comparen_%i :=" i;
 
1300
    pr "  compare_mn_1 w%i w%i %s compare_%i (compare_%i %s) compare_%i." i i (pz i) i i (pz i) i
 
1301
  done;
 
1302
  pr ""; 
 
1303
 
 
1304
  pr " Definition comparenm n m wx wy :=";
 
1305
  pr "    let mn := Max.max n m in";
 
1306
  pr "    let d := diff n m in";
 
1307
  pr "    let op := make_op mn in";
 
1308
  pr "     op.(znz_compare)";
 
1309
  pr "       (castm (diff_r n m) (extend_tr wx (snd d)))";
 
1310
  pr "       (castm (diff_l n m) (extend_tr wy (fst d))).";
 
1311
  pr "";
 
1312
 
 
1313
  pr " Definition compare := Eval lazy beta delta [iter] in ";
 
1314
  pr "   (iter _ ";
 
1315
  for i = 0 to size do
 
1316
    pr "      compare_%i" i;
 
1317
    pr "      (fun n x y => opp_compare (comparen_%i (S n) y x))" i;
 
1318
    pr "      (fun n => comparen_%i (S n))" i;
 
1319
  done;
 
1320
  pr "      comparenm).";
 
1321
  pr "";
 
1322
 
 
1323
  pr " Definition lt n m := compare n m = Lt.";
 
1324
  pr " Definition le n m := compare n m <> Gt.";
 
1325
  pr " Definition min n m := match compare n m with Gt => m | _ => n end.";
 
1326
  pr " Definition max n m := match compare n m with Lt => m | _ => n end.";
 
1327
  pr "";
 
1328
 
 
1329
  for i = 0 to size do
 
1330
    pp " Let spec_compare_%i: forall x y," i;
 
1331
    pp "    match compare_%i x y with " i;
 
1332
    pp "      Eq => [%s%i x] = [%s%i y]" c i c i;
 
1333
    pp "    | Lt => [%s%i x] < [%s%i y]" c i c i;
 
1334
    pp "    | Gt => [%s%i x] > [%s%i y]" c i c i;
 
1335
    pp "    end.";
 
1336
    pp "  Proof.";
 
1337
    pp "  unfold compare_%i, to_Z; exact (spec_compare w%i_spec)." i i;
 
1338
    pp "  Qed.";
 
1339
    pp "";
 
1340
    
 
1341
    pp "  Let spec_comparen_%i:" i;
 
1342
    pp "  forall (n : nat) (x : word w%i n) (y : w%i)," i i;
 
1343
    pp "  match comparen_%i n x y with" i;
 
1344
    pp "  | Eq => eval%in n x = [%s%i y]" i c i;
 
1345
    pp "  | Lt => eval%in n x < [%s%i y]" i c i;
 
1346
    pp "  | Gt => eval%in n x > [%s%i y]" i c i;
 
1347
    pp "  end.";
 
1348
    pp "  intros n x y.";
 
1349
    pp "  unfold comparen_%i, to_Z; rewrite spec_double_eval%in." i i;
 
1350
    pp "  apply spec_compare_mn_1.";
 
1351
    pp "  exact (spec_0 w%i_spec)." i;
 
1352
    pp "  intros x1; exact (spec_compare w%i_spec %s x1)." i (pz i);
 
1353
    pp "  exact (spec_to_Z w%i_spec)." i;
 
1354
    pp "  exact (spec_compare w%i_spec)." i;
 
1355
    pp "  exact (spec_compare w%i_spec)." i;
 
1356
    pp "  exact (spec_to_Z w%i_spec)." i;
 
1357
    pp "  Qed.";
 
1358
    pp "";
 
1359
  done;
 
1360
 
 
1361
  pp " Let spec_opp_compare: forall c (u v: Z),";
 
1362
  pp "  match c with Eq => u = v | Lt => u < v | Gt => u > v end ->";
 
1363
  pp "  match opp_compare c with Eq => v = u | Lt => v < u | Gt => v > u end.";
 
1364
  pp " Proof.";
 
1365
  pp " intros c u v; case c; unfold opp_compare; auto with zarith.";
 
1366
  pp " Qed.";
 
1367
  pp "";
 
1368
 
 
1369
 
 
1370
  pr " Theorem spec_compare: forall x y,";
 
1371
  pr "    match compare x y with ";
 
1372
  pr "      Eq => [x] = [y]";
 
1373
  pr "    | Lt => [x] < [y]";
 
1374
  pr "    | Gt => [x] > [y]";
 
1375
  pr "    end.";
 
1376
  pa " Admitted.";
 
1377
  pp " Proof.";
 
1378
  pp " refine (spec_iter _ (fun x y res => ";
 
1379
  pp "                       match res with ";
 
1380
  pp "                        Eq => x = y";
 
1381
  pp "                      | Lt => x < y";
 
1382
  pp "                      | Gt => x > y";
 
1383
  pp "                      end)";
 
1384
  for i = 0 to size do
 
1385
    pp "      compare_%i" i;
 
1386
    pp "      (fun n x y => opp_compare (comparen_%i (S n) y x))" i;
 
1387
    pp "      (fun n => comparen_%i (S n)) _ _ _" i;
 
1388
  done;
 
1389
  pp "      comparenm _).";
 
1390
  
 
1391
  for i = 0 to size - 1 do
 
1392
    pp "  exact spec_compare_%i." i;
 
1393
    pp "  intros n x y H;apply spec_opp_compare; apply spec_comparen_%i." i;
 
1394
    pp "  intros n x y H; exact (spec_comparen_%i (S n) x y)." i;
 
1395
  done; 
 
1396
  pp "  exact spec_compare_%i." size;
 
1397
  pp "  intros n x y;apply spec_opp_compare; apply spec_comparen_%i." size;
 
1398
  pp "  intros n; exact (spec_comparen_%i (S n))." size;
 
1399
  pp "  intros n m x y; unfold comparenm.";
 
1400
  pp "  rewrite <- (spec_cast_l n m x); rewrite <- (spec_cast_r n m y).";
 
1401
  pp "  unfold to_Z; apply (spec_compare  (wn_spec (Max.max n m))).";
 
1402
  pp "  Qed.";
 
1403
  pr "";
 
1404
 
 
1405
  pr " Definition eq_bool x y :=";
 
1406
  pr "  match compare x y with";
 
1407
  pr "  | Eq => true";
 
1408
  pr "  | _  => false";
 
1409
  pr "  end.";
 
1410
  pr "";
 
1411
 
 
1412
 
 
1413
  pr " Theorem spec_eq_bool: forall x y,";
 
1414
  pr "    if eq_bool x y then [x] = [y] else [x] <> [y].";
 
1415
  pa " Admitted.";
 
1416
  pp " Proof.";
 
1417
  pp " intros x y; unfold eq_bool.";
 
1418
  pp " generalize (spec_compare x y); case compare; auto with zarith.";
 
1419
  pp "  Qed.";
 
1420
  pr "";
 
1421
 
 
1422
 
 
1423
 
 
1424
  pr " (***************************************************************)";
 
1425
  pr " (*                                                             *)";
 
1426
  pr " (*                           Multiplication                    *)";
 
1427
  pr " (*                                                             *)";
 
1428
  pr " (***************************************************************)";
 
1429
  pr "";
 
1430
 
 
1431
  for i = 0 to size do
 
1432
    pr " Definition w%i_mul_c := w%i_op.(znz_mul_c)." i i
 
1433
  done;
 
1434
  pr "";
 
1435
 
 
1436
  for i = 0 to size do
 
1437
    pr " Definition w%i_mul_add :=" i;
 
1438
    pr "   Eval lazy beta delta [w_mul_add] in";
 
1439
    pr "     @w_mul_add w%i %s w%i_succ w%i_add_c w%i_mul_c." i (pz i) i i i
 
1440
  done;
 
1441
  pr "";
 
1442
 
 
1443
  for i = 0 to size do
 
1444
    pr " Definition w%i_0W := znz_0W w%i_op." i i
 
1445
  done;
 
1446
  pr "";
 
1447
 
 
1448
  for i = 0 to size do
 
1449
    pr " Definition w%i_WW := znz_WW w%i_op." i i
 
1450
  done;
 
1451
  pr "";
 
1452
 
 
1453
  for i = 0 to size do
 
1454
    pr " Definition w%i_mul_add_n1 :=" i;
 
1455
    pr "  @double_mul_add_n1 w%i %s w%i_WW w%i_0W w%i_mul_add."  i (pz i) i i i
 
1456
  done;
 
1457
  pr "";
 
1458
 
 
1459
  for i = 0 to size - 1 do
 
1460
    pr "  Let to_Z%i n :=" i;
 
1461
    pr "  match n return word w%i (S n) -> t_ with" i;
 
1462
    for j = 0 to size - i do
 
1463
      if (i + j) == size then
 
1464
        begin 
 
1465
          pr "  | %i%s => fun x => %sn 0 x" j "%nat" c;
 
1466
          pr "  | %i%s => fun x => %sn 1 x" (j + 1) "%nat" c
 
1467
        end
 
1468
      else
 
1469
        pr "  | %i%s => fun x => %s%i x" j "%nat" c (i + j + 1)
 
1470
    done;
 
1471
    pr   "  | _   => fun _ => N0 w_0";
 
1472
    pr "  end.";
 
1473
    pr "";
 
1474
  done; 
 
1475
 
 
1476
 
 
1477
  for i = 0 to size - 1 do
 
1478
    pp "Theorem to_Z%i_spec:" i;
 
1479
    pp "  forall n x, Z_of_nat n <= %i -> [to_Z%i n x] = znz_to_Z (nmake_op _ w%i_op (S n)) x." (size + 1 - i) i i;
 
1480
    for j = 1 to size + 2 - i do
 
1481
      pp " intros n; case n; clear n.";
 
1482
      pp "   unfold to_Z%i." i;
 
1483
      pp "   intros x H; rewrite spec_eval%in%i; auto." i j;
 
1484
    done;
 
1485
    pp " intros n x.";
 
1486
    pp " repeat rewrite inj_S; unfold Zsucc; auto with zarith.";
 
1487
    pp " Qed.";
 
1488
    pp "";
 
1489
  done; 
 
1490
 
 
1491
 
 
1492
  for i = 0 to size do
 
1493
    pr " Definition w%i_mul n x y :=" i;
 
1494
    pr " let (w,r) := w%i_mul_add_n1 (S n) x y %s in" i (pz i);
 
1495
    if i == size then
 
1496
      begin
 
1497
        pr " if w%i_eq0 w then %sn n r" i c;
 
1498
        pr " else %sn (S n) (WW (extend%i n w) r)." c i;
 
1499
      end
 
1500
    else 
 
1501
      begin 
 
1502
        pr " if w%i_eq0 w then to_Z%i n r" i i;
 
1503
        pr " else to_Z%i (S n) (WW (extend%i n w) r)." i i;
 
1504
      end;
 
1505
    pr "";
 
1506
  done;
 
1507
 
 
1508
  pr " Definition mulnm n m x y :=";
 
1509
  pr "    let mn := Max.max n m in";
 
1510
  pr "    let d := diff n m in";
 
1511
  pr "    let op := make_op mn in";
 
1512
  pr "     reduce_n (S mn) (op.(znz_mul_c)";
 
1513
  pr "       (castm (diff_r n m) (extend_tr x (snd d)))";
 
1514
  pr "       (castm (diff_l n m) (extend_tr y (fst d)))).";
 
1515
  pr "";
 
1516
 
 
1517
  pr " Definition mul := Eval lazy beta delta [iter0] in ";
 
1518
  pr "  (iter0 t_ ";
 
1519
  for i = 0 to size do
 
1520
    pr "    (fun x y => reduce_%i (w%i_mul_c x y)) " (i + 1) i;
 
1521
    pr "    (fun n x y => w%i_mul n y x)" i;
 
1522
    pr "    w%i_mul" i;
 
1523
  done;
 
1524
  pr "    mulnm";
 
1525
  pr "    (fun _ => N0 w_0)";
 
1526
  pr "    (fun _ => N0 w_0)";
 
1527
  pr "  ).";
 
1528
  pr "";
 
1529
  for i = 0 to size do
 
1530
    pp " Let spec_w%i_mul_add: forall x y z," i;
 
1531
    pp "  let (q,r) := w%i_mul_add x y z in" i;
 
1532
    pp "  znz_to_Z w%i_op q * (base (znz_digits w%i_op))  +  znz_to_Z w%i_op r =" i i i;
 
1533
    pp "  znz_to_Z w%i_op x * znz_to_Z w%i_op y + znz_to_Z w%i_op z :=" i i i ;
 
1534
    pp "   (spec_mul_add w%i_spec)." i;
 
1535
    pp "";
 
1536
  done;
 
1537
 
 
1538
  for i = 0 to size do
 
1539
    pp " Theorem spec_w%i_mul_add_n1: forall n x y z," i;
 
1540
    pp "  let (q,r) := w%i_mul_add_n1 n x y z in" i;
 
1541
    pp "  znz_to_Z w%i_op q * (base (znz_digits (nmake_op _ w%i_op n)))  +" i i;
 
1542
    pp "  znz_to_Z (nmake_op _ w%i_op n) r =" i;
 
1543
    pp "  znz_to_Z (nmake_op _ w%i_op n) x * znz_to_Z w%i_op y +" i i;
 
1544
    pp "  znz_to_Z w%i_op z." i;
 
1545
    pp " Proof.";
 
1546
    pp " intros n x y z; unfold w%i_mul_add_n1." i;
 
1547
    pp " rewrite nmake_double.";
 
1548
    pp " rewrite digits_doubled.";
 
1549
    pp " change (base (DoubleBase.double_digits (znz_digits w%i_op) n)) with" i;
 
1550
    pp "        (DoubleBase.double_wB (znz_digits w%i_op) n)." i;
 
1551
    pp " apply spec_double_mul_add_n1; auto.";
 
1552
    if i == 0 then pp " exact (spec_0 w%i_spec)." i;
 
1553
    pp " exact (spec_WW w%i_spec)." i;
 
1554
    pp " exact (spec_0W w%i_spec)." i;
 
1555
    pp " exact (spec_mul_add w%i_spec)." i;
 
1556
    pp " Qed.";
 
1557
    pp "";
 
1558
  done;
 
1559
  
 
1560
  pp "  Lemma nmake_op_WW: forall ww ww1 n x y,";
 
1561
  pp "    znz_to_Z (nmake_op ww ww1 (S n)) (WW x y) =";
 
1562
  pp "    znz_to_Z (nmake_op ww ww1 n) x * base (znz_digits (nmake_op ww ww1 n)) +";
 
1563
  pp "    znz_to_Z (nmake_op ww ww1 n) y.";
 
1564
  pp "    auto.";
 
1565
  pp "  Qed.";
 
1566
  pp "";
 
1567
  
 
1568
  for i = 0 to size do
 
1569
    pp "  Lemma extend%in_spec: forall n x1," i;
 
1570
    pp "  znz_to_Z (nmake_op _ w%i_op (S n)) (extend%i n x1) = " i i;
 
1571
    pp "  znz_to_Z w%i_op x1." i;
 
1572
    pp "  Proof.";
 
1573
    pp "    intros n1 x2; rewrite nmake_double.";
 
1574
    pp "    unfold extend%i." i;
 
1575
    pp "    rewrite DoubleBase.spec_extend; auto.";
 
1576
    if i == 0 then 
 
1577
      pp "    intros l; simpl; unfold w_0; rewrite (spec_0 w0_spec); ring.";
 
1578
    pp "  Qed.";
 
1579
    pp "";
 
1580
  done;
 
1581
  
 
1582
  pp "  Lemma spec_muln:";
 
1583
  pp "    forall n (x: word _ (S n)) y,";
 
1584
  pp "     [%sn (S n) (znz_mul_c (make_op n) x y)] = [%sn n x] * [%sn n y]." c c c;
 
1585
  pp "  Proof.";
 
1586
  pp "    intros n x y; unfold to_Z.";
 
1587
  pp "    rewrite <- (spec_mul_c (wn_spec n)).";
 
1588
  pp "    rewrite make_op_S.";
 
1589
  pp "    case znz_mul_c; auto.";
 
1590
  pp "  Qed.";
 
1591
 
 
1592
  pr "  Theorem spec_mul: forall x y, [mul x y] = [x] * [y].";
 
1593
  pa "  Admitted.";
 
1594
  pp "  Proof.";
 
1595
  for i = 0 to size do
 
1596
    pp "    assert(F%i: " i;
 
1597
    pp "    forall n x y,";
 
1598
    if i <> size then
 
1599
      pp0 "    Z_of_nat n <= %i -> "   (size - i);
 
1600
    pp "    [w%i_mul n x y] = eval%in (S n) x * [%s%i y])." i i c i;
 
1601
    if i == size then
 
1602
      pp "    intros n x y; unfold w%i_mul." i
 
1603
    else
 
1604
      pp "    intros n x y H; unfold w%i_mul." i;
 
1605
    pp "    generalize (spec_w%i_mul_add_n1 (S n) x y %s)." i (pz i);
 
1606
    pp "    case w%i_mul_add_n1; intros x1 y1." i;
 
1607
    pp "    change (znz_to_Z (nmake_op _ w%i_op (S n)) x) with (eval%in (S n) x)." i i;
 
1608
    pp "    change (znz_to_Z w%i_op y) with ([%s%i y])." i c i;
 
1609
    if i == 0 then
 
1610
      pp "    unfold w_0; rewrite (spec_0 w0_spec); rewrite Zplus_0_r."
 
1611
    else
 
1612
      pp "    change (znz_to_Z w%i_op W0) with 0; rewrite Zplus_0_r." i;
 
1613
    pp "    intros H1; rewrite <- H1; clear H1.";
 
1614
    pp "    generalize (spec_w%i_eq0 x1); case w%i_eq0; intros HH." i i;
 
1615
    pp "    unfold to_Z in HH; rewrite HH.";
 
1616
    if i == size then
 
1617
      begin 
 
1618
        pp "    rewrite spec_eval%in; unfold eval%in, nmake_op%i; auto." i i i;
 
1619
        pp "    rewrite spec_eval%in; unfold eval%in, nmake_op%i." i i i
 
1620
      end
 
1621
    else
 
1622
      begin
 
1623
        pp "    rewrite to_Z%i_spec; auto with zarith." i;
 
1624
        pp "    rewrite to_Z%i_spec; try (rewrite inj_S; auto with zarith)." i
 
1625
      end;
 
1626
    pp "    rewrite nmake_op_WW; rewrite extend%in_spec; auto." i;
 
1627
  done;
 
1628
  pp "    refine (spec_iter0 t_ (fun x y res => [res] = x * y)";
 
1629
  for i = 0 to size do
 
1630
    pp "    (fun x y => reduce_%i (w%i_mul_c x y)) " (i + 1) i;
 
1631
    pp "    (fun n x y => w%i_mul n y x)" i;
 
1632
    pp "    w%i_mul _ _ _" i;
 
1633
  done;
 
1634
  pp "    mulnm _";
 
1635
  pp "    (fun _ => N0 w_0) _";
 
1636
  pp "    (fun _ => N0 w_0) _";
 
1637
  pp "  ).";
 
1638
  for i = 0 to size do
 
1639
    pp "    intros x y; rewrite spec_reduce_%i." (i + 1);
 
1640
    pp "    unfold w%i_mul_c, to_Z." i;
 
1641
    pp "    generalize (spec_mul_c w%i_spec x y)." i;
 
1642
    pp "    intros HH; rewrite <- HH; clear HH; auto.";
 
1643
    if i == size then
 
1644
      begin
 
1645
        pp "    intros n x y; rewrite F%i; auto with zarith." i;
 
1646
        pp "    intros n x y; rewrite F%i; auto with zarith. " i;
 
1647
      end
 
1648
    else
 
1649
      begin
 
1650
        pp "    intros n x y H; rewrite F%i; auto with zarith." i;
 
1651
        pp "    intros n x y H; rewrite F%i; auto with zarith. " i;
 
1652
      end;
 
1653
  done;
 
1654
  pp "    intros n m x y; unfold mulnm.";
 
1655
  pp "    rewrite spec_reduce_n.";
 
1656
  pp "    rewrite <- (spec_cast_l n m x).";
 
1657
  pp "    rewrite <- (spec_cast_r n m y).";
 
1658
  pp "    rewrite spec_muln; rewrite spec_cast_l; rewrite spec_cast_r; auto.";
 
1659
  pp "    intros x; unfold to_Z, w_0; rewrite (spec_0 w0_spec); ring.";
 
1660
  pp "    intros x; unfold to_Z, w_0; rewrite (spec_0 w0_spec); ring.";
 
1661
  pp "  Qed.";
 
1662
  pr "";
 
1663
 
 
1664
  pr " (***************************************************************)";
 
1665
  pr " (*                                                             *)";
 
1666
  pr " (*                           Square                            *)";
 
1667
  pr " (*                                                             *)";
 
1668
  pr " (***************************************************************)";
 
1669
  pr "";
 
1670
 
 
1671
  for i = 0 to size do
 
1672
    pr " Definition w%i_square_c := w%i_op.(znz_square_c)." i i
 
1673
  done;
 
1674
  pr "";
 
1675
 
 
1676
  pr " Definition square x :=";
 
1677
  pr "  match x with";
 
1678
  pr "  | %s0 wx => reduce_1 (w0_square_c wx)" c;
 
1679
  for i = 1 to size - 1 do
 
1680
    pr "  | %s%i wx => %s%i (w%i_square_c wx)" c i c (i+1) i
 
1681
  done;
 
1682
  pr "  | %s%i wx => %sn 0 (w%i_square_c wx)" c size c size;
 
1683
  pr "  | %sn n wx =>" c;
 
1684
  pr "    let op := make_op n in";
 
1685
  pr "    %sn (S n) (op.(znz_square_c) wx)" c;
 
1686
  pr "  end.";
 
1687
  pr "";
 
1688
 
 
1689
  pr " Theorem spec_square: forall x, [square x] = [x] * [x].";
 
1690
  pa " Admitted.";
 
1691
  pp " Proof.";
 
1692
  pp "  intros x; case x; unfold square; clear x.";
 
1693
  pp "  intros x; rewrite spec_reduce_1; unfold to_Z.";
 
1694
  pp "   exact (spec_square_c w%i_spec x)." 0;
 
1695
  for i = 1 to size do
 
1696
    pp "  intros x; unfold to_Z.";
 
1697
    pp "    exact (spec_square_c w%i_spec x)." i;
 
1698
  done;
 
1699
  pp "  intros n x; unfold to_Z.";
 
1700
  pp "    rewrite make_op_S.";
 
1701
  pp "    exact (spec_square_c (wn_spec n) x).";
 
1702
  pp "Qed.";
 
1703
  pr "";
 
1704
 
 
1705
 
 
1706
  pr " (***************************************************************)";
 
1707
  pr " (*                                                             *)";
 
1708
  pr " (*                           Power                             *)";
 
1709
  pr " (*                                                             *)";
 
1710
  pr " (***************************************************************)";
 
1711
  pr ""; 
 
1712
 
 
1713
  pr " Fixpoint power_pos (x:%s) (p:positive) {struct p} : %s :=" t t;
 
1714
  pr "  match p with";
 
1715
  pr "  | xH => x";
 
1716
  pr "  | xO p => square (power_pos x p)";
 
1717
  pr "  | xI p => mul (square (power_pos x p)) x";
 
1718
  pr "  end.";
 
1719
  pr "";
 
1720
 
 
1721
  pr " Theorem spec_power_pos: forall x n, [power_pos x n] = [x] ^ Zpos n.";
 
1722
  pa " Admitted.";  
 
1723
  pp " Proof.";
 
1724
  pp " intros x n; generalize x; elim n; clear n x; simpl power_pos.";
 
1725
  pp " intros; rewrite spec_mul; rewrite spec_square; rewrite H.";
 
1726
  pp " rewrite Zpos_xI; rewrite Zpower_exp; auto with zarith.";
 
1727
  pp " rewrite (Zmult_comm 2); rewrite Zpower_mult; auto with zarith.";
 
1728
  pp " rewrite Zpower_2; rewrite Zpower_1_r; auto.";
 
1729
  pp " intros; rewrite spec_square; rewrite H.";
 
1730
  pp " rewrite Zpos_xO; auto with zarith.";
 
1731
  pp " rewrite (Zmult_comm 2); rewrite Zpower_mult; auto with zarith.";
 
1732
  pp " rewrite Zpower_2; auto.";
 
1733
  pp " intros; rewrite Zpower_1_r; auto.";
 
1734
  pp " Qed.";
 
1735
  pp "";
 
1736
  pr "";
 
1737
 
 
1738
  pr " (***************************************************************)";
 
1739
  pr " (*                                                             *)";
 
1740
  pr " (*                           Square root                       *)";
 
1741
  pr " (*                                                             *)";
 
1742
  pr " (***************************************************************)";
 
1743
  pr "";
 
1744
 
 
1745
  for i = 0 to size do
 
1746
    pr " Definition w%i_sqrt := w%i_op.(znz_sqrt)." i i
 
1747
  done;
 
1748
  pr "";
 
1749
 
 
1750
  pr " Definition sqrt x :=";
 
1751
  pr "  match x with";
 
1752
  for i = 0 to size do
 
1753
    pr "  | %s%i wx => reduce_%i (w%i_sqrt wx)" c i i i;
 
1754
  done;
 
1755
  pr "  | %sn n wx =>" c;
 
1756
  pr "    let op := make_op n in";
 
1757
  pr "    reduce_n n (op.(znz_sqrt) wx)";
 
1758
  pr "  end.";
 
1759
  pr "";
 
1760
 
 
1761
  pr " Theorem spec_sqrt: forall x, [sqrt x] ^ 2 <= [x] < ([sqrt x] + 1) ^ 2.";
 
1762
  pa " Admitted.";
 
1763
  pp " Proof.";
 
1764
  pp " intros x; unfold sqrt; case x; clear x.";
 
1765
  for i = 0 to size do
 
1766
    pp " intros x; rewrite spec_reduce_%i; exact (spec_sqrt w%i_spec x)." i i;
 
1767
  done;
 
1768
  pp " intros n x; rewrite spec_reduce_n; exact (spec_sqrt (wn_spec n) x).";
 
1769
  pp " Qed.";
 
1770
  pr "";
 
1771
 
 
1772
 
 
1773
  pr " (***************************************************************)";
 
1774
  pr " (*                                                             *)";
 
1775
  pr " (*                           Division                          *)";
 
1776
  pr " (*                                                             *)";
 
1777
  pr " (***************************************************************)";
 
1778
  pr ""; 
 
1779
 
 
1780
  for i = 0 to size do
 
1781
    pr " Definition w%i_div_gt := w%i_op.(znz_div_gt)." i i
 
1782
  done;
 
1783
  pr "";
 
1784
 
 
1785
  pp " Let spec_divn1 ww (ww_op: znz_op ww) (ww_spec: znz_spec ww_op) := ";
 
1786
  pp "   (spec_double_divn1 ";
 
1787
  pp "    ww_op.(znz_zdigits) ww_op.(znz_0)";
 
1788
  pp "    (znz_WW ww_op) ww_op.(znz_head0)";
 
1789
  pp "    ww_op.(znz_add_mul_div) ww_op.(znz_div21)";
 
1790
  pp "    ww_op.(znz_compare) ww_op.(znz_sub) (znz_to_Z ww_op)";
 
1791
  pp "    (spec_to_Z ww_spec) ";
 
1792
  pp "    (spec_zdigits ww_spec)";
 
1793
  pp "   (spec_0 ww_spec) (spec_WW ww_spec) (spec_head0 ww_spec)";
 
1794
  pp "   (spec_add_mul_div ww_spec) (spec_div21 ww_spec) ";
 
1795
  pp "    (CyclicAxioms.spec_compare ww_spec) (CyclicAxioms.spec_sub ww_spec)).";
 
1796
  pp "";
 
1797
 
 
1798
  for i = 0 to size do
 
1799
    pr " Definition w%i_divn1 n x y :="  i;
 
1800
    pr "  let (u, v) :=";
 
1801
    pr "  double_divn1 w%i_op.(znz_zdigits) w%i_op.(znz_0)" i i;
 
1802
    pr "    (znz_WW w%i_op) w%i_op.(znz_head0)" i i;
 
1803
    pr "    w%i_op.(znz_add_mul_div) w%i_op.(znz_div21)" i i;
 
1804
    pr "    w%i_op.(znz_compare) w%i_op.(znz_sub) (S n) x y in" i i;
 
1805
    if i == size then
 
1806
      pr "   (%sn _ u, %s%i v)." c c i
 
1807
    else
 
1808
      pr "   (to_Z%i _ u, %s%i v)." i c i;
 
1809
  done;
 
1810
  pr "";
 
1811
 
 
1812
  for i = 0 to size do
 
1813
    pp " Lemma spec_get_end%i: forall n x y," i;
 
1814
    pp "    eval%in n x  <= [%s%i y] -> " i c i;
 
1815
    pp "     [%s%i (DoubleBase.get_low %s n x)] = eval%in n x." c i (pz i) i;
 
1816
    pp " Proof.";
 
1817
    pp " intros n x y H.";
 
1818
    pp " rewrite spec_double_eval%in; unfold to_Z." i;
 
1819
    pp " apply DoubleBase.spec_get_low.";
 
1820
    pp " exact (spec_0 w%i_spec)." i;
 
1821
    pp " exact (spec_to_Z w%i_spec)." i;
 
1822
    pp " apply Zle_lt_trans with [%s%i y]; auto." c i;
 
1823
    pp "   rewrite <- spec_double_eval%in; auto." i;
 
1824
    pp " unfold to_Z; case (spec_to_Z w%i_spec y); auto." i;
 
1825
    pp " Qed.";
 
1826
    pp "";
 
1827
  done;
 
1828
 
 
1829
  for i = 0 to size do
 
1830
    pr " Let div_gt%i x y := let (u,v) := (w%i_div_gt x y) in (reduce_%i u, reduce_%i v)." i i i i;
 
1831
  done;
 
1832
  pr "";
 
1833
 
 
1834
 
 
1835
  pr " Let div_gtnm n m wx wy :=";
 
1836
  pr "    let mn := Max.max n m in";
 
1837
  pr "    let d := diff n m in";
 
1838
  pr "    let op := make_op mn in";
 
1839
  pr "    let (q, r):= op.(znz_div_gt)";
 
1840
  pr "         (castm (diff_r n m) (extend_tr wx (snd d)))";
 
1841
  pr "         (castm (diff_l n m) (extend_tr wy (fst d))) in";
 
1842
  pr "    (reduce_n mn q, reduce_n mn r).";
 
1843
  pr "";
 
1844
 
 
1845
  pr " Definition div_gt := Eval lazy beta delta [iter] in";
 
1846
  pr "   (iter _ ";
 
1847
  for i = 0 to size do 
 
1848
    pr "      div_gt%i" i;
 
1849
    pr "      (fun n x y => div_gt%i x (DoubleBase.get_low %s (S n) y))" i (pz i);
 
1850
    pr "      w%i_divn1" i;
 
1851
  done;
 
1852
  pr "      div_gtnm).";
 
1853
  pr "";
 
1854
 
 
1855
  pr " Theorem spec_div_gt: forall x y,";
 
1856
  pr "       [x] > [y] -> 0 < [y] ->";
 
1857
  pr "      let (q,r) := div_gt x y in";
 
1858
  pr "      [q] = [x] / [y] /\\ [r] = [x] mod [y].";
 
1859
  pa " Admitted.";
 
1860
  pp " Proof.";
 
1861
  pp " assert (FO:";
 
1862
  pp "   forall x y, [x] > [y] -> 0 < [y] ->";
 
1863
  pp "      let (q,r) := div_gt x y in";
 
1864
  pp "      [x] = [q] * [y] + [r] /\\ 0 <= [r] < [y]).";
 
1865
  pp "  refine (spec_iter (t_*t_) (fun x y res => x > y -> 0 < y ->";  
 
1866
  pp "      let (q,r) := res in";
 
1867
  pp "      x = [q] * y + [r] /\\ 0 <= [r] < y)";
 
1868
  for i = 0 to size do 
 
1869
    pp "      div_gt%i" i;
 
1870
    pp "      (fun n x y => div_gt%i x (DoubleBase.get_low %s (S n) y))" i (pz i);
 
1871
    pp "      w%i_divn1 _ _ _" i;
 
1872
  done;
 
1873
  pp "      div_gtnm _).";
 
1874
  for i = 0 to size do
 
1875
    pp "  intros x y H1 H2; unfold div_gt%i, w%i_div_gt." i i;
 
1876
    pp "    generalize (spec_div_gt w%i_spec x y H1 H2); case znz_div_gt." i;
 
1877
    pp "    intros xx yy; repeat rewrite spec_reduce_%i; auto." i;
 
1878
    if i == size then
 
1879
      pp "  intros n x y H2 H3; unfold div_gt%i, w%i_div_gt." i i
 
1880
    else
 
1881
      pp "  intros n x y H1 H2 H3; unfold div_gt%i, w%i_div_gt." i i;
 
1882
    pp "    generalize (spec_div_gt w%i_spec x " i;
 
1883
    pp "                (DoubleBase.get_low %s (S n) y))." (pz i);
 
1884
    pp0 "    ";
 
1885
    for j = 0 to i do
 
1886
      pp0 "unfold w%i; " (i-j); 
 
1887
    done;
 
1888
    pp "case znz_div_gt.";
 
1889
    pp "    intros xx yy H4; repeat rewrite spec_reduce_%i." i;
 
1890
    pp "    generalize (spec_get_end%i (S n) y x); unfold to_Z; intros H5." i;
 
1891
    pp "    unfold to_Z in H2; rewrite H5 in H4; auto with zarith.";
 
1892
    if i == size then
 
1893
      pp "  intros n x y H2 H3."
 
1894
    else
 
1895
      pp "  intros n x y H1 H2 H3.";
 
1896
    pp "    generalize";
 
1897
    pp "     (spec_divn1 w%i w%i_op w%i_spec (S n) x y H3)." i i i;
 
1898
    pp0 "    unfold w%i_divn1; " i;
 
1899
    for j = 0 to i do
 
1900
      pp0 "unfold w%i; " (i-j); 
 
1901
    done;
 
1902
    pp "case double_divn1.";
 
1903
    pp "    intros xx yy H4.";
 
1904
    if i == size then
 
1905
      begin
 
1906
        pp "    repeat rewrite <- spec_double_eval%in in H4; auto." i;
 
1907
        pp "    rewrite spec_eval%in; auto." i;
 
1908
      end
 
1909
    else
 
1910
      begin
 
1911
        pp "    rewrite to_Z%i_spec; auto with zarith." i;
 
1912
        pp "    repeat rewrite <- spec_double_eval%in in H4; auto." i;
 
1913
      end;
 
1914
  done;
 
1915
  pp "  intros n m x y H1 H2; unfold div_gtnm.";
 
1916
  pp "    generalize (spec_div_gt (wn_spec (Max.max n m))";
 
1917
  pp "                   (castm (diff_r n m)";
 
1918
  pp "                     (extend_tr x (snd (diff n m))))";
 
1919
  pp "                   (castm (diff_l n m)";
 
1920
  pp "                     (extend_tr y (fst (diff n m))))).";
 
1921
  pp "    case znz_div_gt.";
 
1922
  pp "    intros xx yy HH.";
 
1923
  pp "    repeat rewrite spec_reduce_n.";
 
1924
  pp "    rewrite <- (spec_cast_l n m x).";
 
1925
  pp "    rewrite <- (spec_cast_r n m y).";
 
1926
  pp "    unfold to_Z; apply HH.";
 
1927
  pp "    rewrite <- (spec_cast_l n m x) in H1; auto.";
 
1928
  pp "    rewrite <- (spec_cast_r n m y) in H1; auto.";
 
1929
  pp "    rewrite <- (spec_cast_r n m y) in H2; auto.";
 
1930
  pp "  intros x y H1 H2; generalize (FO x y H1 H2); case div_gt.";
 
1931
  pp "  intros q r (H3, H4); split.";
 
1932
  pp "  apply (Zdiv_unique [x] [y] [q] [r]); auto.";
 
1933
  pp "  rewrite Zmult_comm; auto.";
 
1934
  pp "  apply (Zmod_unique [x] [y] [q] [r]); auto.";
 
1935
  pp "  rewrite Zmult_comm; auto.";
 
1936
  pp "  Qed.";
 
1937
  pr "";
 
1938
 
 
1939
  pr " Definition div_eucl x y :=";
 
1940
  pr "  match compare x y with";
 
1941
  pr "  | Eq => (one, zero)";
 
1942
  pr "  | Lt => (zero, x)";
 
1943
  pr "  | Gt => div_gt x y";
 
1944
  pr "  end.";
 
1945
  pr "";
 
1946
 
 
1947
  pr " Theorem spec_div_eucl: forall x y,";
 
1948
  pr "      0 < [y] ->";
 
1949
  pr "      let (q,r) := div_eucl x y in";
 
1950
  pr "      ([q], [r]) = Zdiv_eucl [x] [y].";
 
1951
  pa " Admitted.";
 
1952
  pp " Proof.";
 
1953
  pp " assert (F0: [zero] = 0).";
 
1954
  pp "   exact (spec_0 w0_spec).";
 
1955
  pp " assert (F1: [one] = 1).";
 
1956
  pp "   exact (spec_1 w0_spec).";
 
1957
  pp " intros x y H; generalize (spec_compare x y);";
 
1958
  pp "   unfold div_eucl; case compare; try rewrite F0;";
 
1959
  pp "   try rewrite F1; intros; auto with zarith.";
 
1960
  pp " rewrite H0; generalize (Z_div_same [y] (Zlt_gt _ _ H))";
 
1961
  pp "                        (Z_mod_same [y] (Zlt_gt _ _ H));";
 
1962
  pp "  unfold Zdiv, Zmod; case Zdiv_eucl; intros; subst; auto.";
 
1963
  pp " assert (F2: 0 <= [x] < [y]).";
 
1964
  pp "   generalize (spec_pos x); auto.";
 
1965
  pp " generalize (Zdiv_small _ _ F2)";
 
1966
  pp "            (Zmod_small _ _ F2);";
 
1967
  pp "  unfold Zdiv, Zmod; case Zdiv_eucl; intros; subst; auto.";
 
1968
  pp " generalize (spec_div_gt _ _ H0 H); auto.";
 
1969
  pp " unfold Zdiv, Zmod; case Zdiv_eucl; case div_gt.";
 
1970
  pp " intros a b c d (H1, H2); subst; auto.";
 
1971
  pp " Qed.";
 
1972
  pr "";
 
1973
 
 
1974
  pr " Definition div x y := fst (div_eucl x y).";
 
1975
  pr "";
 
1976
 
 
1977
  pr " Theorem spec_div:";
 
1978
  pr "   forall x y, 0 < [y] -> [div x y] = [x] / [y].";
 
1979
  pa " Admitted.";
 
1980
  pp " Proof.";
 
1981
  pp " intros x y H1; unfold div; generalize (spec_div_eucl x y H1);";
 
1982
  pp "   case div_eucl; simpl fst.";
 
1983
  pp " intros xx yy; unfold Zdiv; case Zdiv_eucl; intros qq rr H; ";
 
1984
  pp "  injection H; auto.";
 
1985
  pp " Qed.";
 
1986
  pr "";
 
1987
 
 
1988
  pr " (***************************************************************)";
 
1989
  pr " (*                                                             *)";
 
1990
  pr " (*                           Modulo                            *)";
 
1991
  pr " (*                                                             *)";
 
1992
  pr " (***************************************************************)";
 
1993
  pr ""; 
 
1994
 
 
1995
  for i = 0 to size do
 
1996
    pr " Definition w%i_mod_gt := w%i_op.(znz_mod_gt)." i i
 
1997
  done;
 
1998
  pr "";
 
1999
 
 
2000
  for i = 0 to size do
 
2001
    pr " Definition w%i_modn1 :=" i;
 
2002
    pr "  double_modn1 w%i_op.(znz_zdigits) w%i_op.(znz_0)" i i;
 
2003
    pr "    w%i_op.(znz_head0) w%i_op.(znz_add_mul_div) w%i_op.(znz_div21)" i i i;
 
2004
    pr "    w%i_op.(znz_compare) w%i_op.(znz_sub)." i i;
 
2005
  done;
 
2006
  pr "";
 
2007
 
 
2008
  pr " Let mod_gtnm n m wx wy :=";
 
2009
  pr "    let mn := Max.max n m in";
 
2010
  pr "    let d := diff n m in";
 
2011
  pr "    let op := make_op mn in";
 
2012
  pr "    reduce_n mn (op.(znz_mod_gt)";
 
2013
  pr "         (castm (diff_r n m) (extend_tr wx (snd d)))";
 
2014
  pr "         (castm (diff_l n m) (extend_tr wy (fst d)))).";
 
2015
  pr "";
 
2016
 
 
2017
  pr " Definition mod_gt := Eval lazy beta delta[iter] in";
 
2018
  pr "   (iter _ ";
 
2019
  for i = 0 to size do
 
2020
    pr "      (fun x y => reduce_%i (w%i_mod_gt x y))" i i;
 
2021
    pr "      (fun n x y => reduce_%i (w%i_mod_gt x (DoubleBase.get_low %s (S n) y)))" i i (pz i);
 
2022
    pr "      (fun n x y => reduce_%i (w%i_modn1 (S n) x y))" i i;
 
2023
  done;
 
2024
  pr "      mod_gtnm).";
 
2025
  pr "";
 
2026
 
 
2027
  pp " Let spec_modn1 ww (ww_op: znz_op ww) (ww_spec: znz_spec ww_op) := ";
 
2028
  pp "   (spec_double_modn1 ";
 
2029
  pp "    ww_op.(znz_zdigits) ww_op.(znz_0)";
 
2030
  pp "    (znz_WW ww_op) ww_op.(znz_head0)";
 
2031
  pp "    ww_op.(znz_add_mul_div) ww_op.(znz_div21)";
 
2032
  pp "    ww_op.(znz_compare) ww_op.(znz_sub) (znz_to_Z ww_op)";
 
2033
  pp "    (spec_to_Z ww_spec) ";
 
2034
  pp "    (spec_zdigits ww_spec)";
 
2035
  pp "   (spec_0 ww_spec) (spec_WW ww_spec) (spec_head0 ww_spec)";
 
2036
  pp "   (spec_add_mul_div ww_spec) (spec_div21 ww_spec) ";
 
2037
  pp "    (CyclicAxioms.spec_compare ww_spec) (CyclicAxioms.spec_sub ww_spec)).";
 
2038
  pp "";
 
2039
 
 
2040
  pr " Theorem spec_mod_gt:";
 
2041
  pr "   forall x y, [x] > [y] -> 0 < [y] -> [mod_gt x y] = [x] mod [y].";
 
2042
  pa " Admitted.";
 
2043
  pp " Proof.";
 
2044
  pp " refine (spec_iter _ (fun x y res => x > y -> 0 < y ->";
 
2045
  pp "      [res] = x mod y)";
 
2046
  for i = 0 to size do
 
2047
    pp "      (fun x y => reduce_%i (w%i_mod_gt x y))" i i;
 
2048
    pp "      (fun n x y => reduce_%i (w%i_mod_gt x (DoubleBase.get_low %s (S n) y)))" i i (pz i);
 
2049
    pp "      (fun n x y => reduce_%i (w%i_modn1 (S n) x y)) _ _ _" i i;
 
2050
  done;
 
2051
  pp "      mod_gtnm _).";
 
2052
  for i = 0 to size do
 
2053
    pp " intros x y H1 H2; rewrite spec_reduce_%i." i;
 
2054
    pp "   exact (spec_mod_gt w%i_spec x y H1 H2)." i;
 
2055
    if i == size then
 
2056
      pp " intros n x y H2 H3; rewrite spec_reduce_%i." i
 
2057
    else
 
2058
      pp " intros n x y H1 H2 H3; rewrite spec_reduce_%i." i;
 
2059
    pp " unfold w%i_mod_gt." i;
 
2060
    pp " rewrite <- (spec_get_end%i (S n) y x); auto with zarith." i;
 
2061
    pp " unfold to_Z; apply (spec_mod_gt w%i_spec); auto." i;
 
2062
    pp " rewrite <- (spec_get_end%i (S n) y x) in H2; auto with zarith." i;
 
2063
    pp " rewrite <- (spec_get_end%i (S n) y x) in H3; auto with zarith." i;
 
2064
    if i == size then
 
2065
      pp " intros n x y H2 H3; rewrite spec_reduce_%i." i
 
2066
    else 
 
2067
      pp " intros n x y H1 H2 H3; rewrite spec_reduce_%i." i;
 
2068
    pp " unfold w%i_modn1, to_Z; rewrite spec_double_eval%in." i i;
 
2069
    pp " apply (spec_modn1 _ _ w%i_spec); auto." i;
 
2070
  done;
 
2071
  pp " intros n m x y H1 H2; unfold mod_gtnm.";
 
2072
  pp "    repeat rewrite spec_reduce_n.";
 
2073
  pp "    rewrite <- (spec_cast_l n m x).";
 
2074
  pp "    rewrite <- (spec_cast_r n m y).";
 
2075
  pp "    unfold to_Z; apply (spec_mod_gt (wn_spec (Max.max n m))).";
 
2076
  pp "    rewrite <- (spec_cast_l n m x) in H1; auto.";
 
2077
  pp "    rewrite <- (spec_cast_r n m y) in H1; auto.";
 
2078
  pp "    rewrite <- (spec_cast_r n m y) in H2; auto.";
 
2079
  pp " Qed.";
 
2080
  pr "";
 
2081
 
 
2082
  pr " Definition modulo x y := ";
 
2083
  pr "  match compare x y with";
 
2084
  pr "  | Eq => zero";
 
2085
  pr "  | Lt => x";
 
2086
  pr "  | Gt => mod_gt x y";
 
2087
  pr "  end.";
 
2088
  pr "";
 
2089
 
 
2090
  pr " Theorem spec_modulo:";
 
2091
  pr "   forall x y, 0 < [y] -> [modulo x y] = [x] mod [y].";
 
2092
  pa " Admitted.";
 
2093
  pp " Proof.";
 
2094
  pp " assert (F0: [zero] = 0).";
 
2095
  pp "   exact (spec_0 w0_spec).";
 
2096
  pp " assert (F1: [one] = 1).";
 
2097
  pp "   exact (spec_1 w0_spec).";
 
2098
  pp " intros x y H; generalize (spec_compare x y);";
 
2099
  pp "   unfold modulo; case compare; try rewrite F0;";
 
2100
  pp "   try rewrite F1; intros; try split; auto with zarith.";
 
2101
  pp " rewrite H0; apply sym_equal; apply Z_mod_same; auto with zarith.";
 
2102
  pp " apply sym_equal; apply Zmod_small; auto with zarith.";
 
2103
  pp " generalize (spec_pos x); auto with zarith.";
 
2104
  pp " apply spec_mod_gt; auto.";
 
2105
  pp " Qed.";
 
2106
  pr "";
 
2107
 
 
2108
  pr " (***************************************************************)";
 
2109
  pr " (*                                                             *)";
 
2110
  pr " (*                           Gcd                               *)";
 
2111
  pr " (*                                                             *)";
 
2112
  pr " (***************************************************************)";
 
2113
  pr ""; 
 
2114
 
 
2115
  pr " Definition digits x :=";
 
2116
  pr "  match x with";
 
2117
  for i = 0 to size do
 
2118
    pr "  | %s%i _ => w%i_op.(znz_digits)" c i i;
 
2119
  done;
 
2120
  pr "  | %sn n _ => (make_op n).(znz_digits)" c;
 
2121
  pr "  end.";
 
2122
  pr "";
 
2123
 
 
2124
  pr " Theorem spec_digits: forall x, 0 <= [x] < 2 ^  Zpos (digits x).";
 
2125
  pa " Admitted.";
 
2126
  pp " Proof.";
 
2127
  pp " intros x; case x; clear x.";
 
2128
  for i = 0 to size do
 
2129
    pp "  intros x; unfold to_Z, digits;";
 
2130
    pp "   generalize (spec_to_Z w%i_spec x); unfold base; intros H; exact H." i;
 
2131
  done;
 
2132
  pp "  intros n x; unfold to_Z, digits;";
 
2133
  pp "   generalize (spec_to_Z (wn_spec n) x); unfold base; intros H; exact H.";
 
2134
  pp " Qed.";
 
2135
  pr "";
 
2136
 
 
2137
  pr " Definition gcd_gt_body a b cont :=";
 
2138
  pr "  match compare b zero with";
 
2139
  pr "  | Gt =>";
 
2140
  pr "    let r := mod_gt a b in";
 
2141
  pr "    match compare r zero with";
 
2142
  pr "    | Gt => cont r (mod_gt b r)";
 
2143
  pr "    | _ => b";
 
2144
  pr "    end";
 
2145
  pr "  | _ => a";
 
2146
  pr "  end.";
 
2147
  pr "";
 
2148
 
 
2149
  pp " Theorem Zspec_gcd_gt_body: forall a b cont p,";
 
2150
  pp "    [a] > [b] -> [a] < 2 ^ p ->";
 
2151
  pp "      (forall a1 b1, [a1] < 2 ^ (p - 1) -> [a1] > [b1] ->";
 
2152
  pp "         Zis_gcd  [a1] [b1] [cont a1 b1]) ->                   ";
 
2153
  pp "      Zis_gcd [a] [b] [gcd_gt_body a b cont].";
 
2154
  pp " Proof.";
 
2155
  pp " assert (F1: [zero] = 0).";
 
2156
  pp "   unfold zero, w_0, to_Z; rewrite (spec_0 w0_spec); auto.";
 
2157
  pp " intros a b cont p H2 H3 H4; unfold gcd_gt_body.";
 
2158
  pp " generalize (spec_compare b zero); case compare; try rewrite F1.";
 
2159
  pp "   intros HH; rewrite HH; apply Zis_gcd_0.";
 
2160
  pp " intros HH; absurd (0 <= [b]); auto with zarith.";
 
2161
  pp " case (spec_digits b); auto with zarith.";
 
2162
  pp " intros H5; generalize (spec_compare (mod_gt a b) zero); ";
 
2163
  pp "   case compare; try rewrite F1.";
 
2164
  pp " intros H6; rewrite <- (Zmult_1_r [b]).";
 
2165
  pp " rewrite (Z_div_mod_eq [a] [b]); auto with zarith.";
 
2166
  pp " rewrite <- spec_mod_gt; auto with zarith.";
 
2167
  pp " rewrite H6; rewrite Zplus_0_r.";
 
2168
  pp " apply Zis_gcd_mult; apply Zis_gcd_1.";
 
2169
  pp " intros; apply False_ind.";
 
2170
  pp " case (spec_digits (mod_gt a b)); auto with zarith.";
 
2171
  pp " intros H6; apply DoubleDiv.Zis_gcd_mod; auto with zarith.";
 
2172
  pp " apply DoubleDiv.Zis_gcd_mod; auto with zarith.";
 
2173
  pp " rewrite <- spec_mod_gt; auto with zarith.";
 
2174
  pp " assert (F2: [b] > [mod_gt a b]).";
 
2175
  pp "   case (Z_mod_lt [a] [b]); auto with zarith.";
 
2176
  pp "   repeat rewrite <- spec_mod_gt; auto with zarith.";
 
2177
  pp " assert (F3: [mod_gt a b] > [mod_gt b  (mod_gt a b)]).";
 
2178
  pp "   case (Z_mod_lt [b] [mod_gt a b]); auto with zarith.";
 
2179
  pp "   rewrite <- spec_mod_gt; auto with zarith.";
 
2180
  pp " repeat rewrite <- spec_mod_gt; auto with zarith.";
 
2181
  pp " apply H4; auto with zarith.";
 
2182
  pp " apply Zmult_lt_reg_r with 2; auto with zarith.";
 
2183
  pp " apply Zle_lt_trans with ([b] + [mod_gt a b]); auto with zarith.";
 
2184
  pp " apply Zle_lt_trans with (([a]/[b]) * [b] + [mod_gt a b]); auto with zarith.";
 
2185
  pp "   apply Zplus_le_compat_r.";
 
2186
  pp " pattern [b] at 1; rewrite <- (Zmult_1_l [b]).";
 
2187
  pp " apply Zmult_le_compat_r; auto with zarith.";
 
2188
  pp " case (Zle_lt_or_eq 0 ([a]/[b])); auto with zarith.";
 
2189
  pp " intros HH; rewrite (Z_div_mod_eq [a] [b]) in H2;";
 
2190
  pp "   try rewrite <- HH in H2; auto with zarith.";
 
2191
  pp " case (Z_mod_lt [a] [b]); auto with zarith.";
 
2192
  pp " rewrite Zmult_comm; rewrite spec_mod_gt; auto with zarith.";
 
2193
  pp " rewrite <- Z_div_mod_eq; auto with zarith.";
 
2194
  pp " pattern 2 at 2; rewrite <- (Zpower_1_r 2).";
 
2195
  pp " rewrite <- Zpower_exp; auto with zarith.";
 
2196
  pp " ring_simplify (p - 1 + 1); auto.";
 
2197
  pp " case (Zle_lt_or_eq 0 p); auto with zarith.";
 
2198
  pp " generalize H3; case p; simpl Zpower; auto with zarith.";
 
2199
  pp " intros HH; generalize H3; rewrite <- HH; simpl Zpower; auto with zarith.";
 
2200
  pp " Qed.";
 
2201
  pp "";
 
2202
 
 
2203
  pr " Fixpoint gcd_gt_aux (p:positive) (cont:t->t->t) (a b:t) {struct p} : t :=";
 
2204
  pr "  gcd_gt_body a b";
 
2205
  pr "    (fun a b =>";
 
2206
  pr "       match p with";
 
2207
  pr "       | xH => cont a b";
 
2208
  pr "       | xO p => gcd_gt_aux p (gcd_gt_aux p cont) a b";
 
2209
  pr "       | xI p => gcd_gt_aux p (gcd_gt_aux p cont) a b";
 
2210
  pr "       end).";
 
2211
  pr "";
 
2212
 
 
2213
  pp " Theorem Zspec_gcd_gt_aux: forall p n a b cont,";
 
2214
  pp "    [a] > [b] -> [a] < 2 ^ (Zpos p + n) ->";
 
2215
  pp "      (forall a1 b1, [a1] < 2 ^ n -> [a1] > [b1] ->";
 
2216
  pp "            Zis_gcd [a1] [b1] [cont a1 b1]) ->";
 
2217
  pp "          Zis_gcd [a] [b] [gcd_gt_aux p cont a b].";
 
2218
  pp " intros p; elim p; clear p.";
 
2219
  pp " intros p Hrec n a b cont H2 H3 H4.";
 
2220
  pp "   unfold gcd_gt_aux; apply Zspec_gcd_gt_body with (Zpos (xI p) + n); auto.";
 
2221
  pp "   intros a1 b1 H6 H7.";
 
2222
  pp "     apply Hrec with (Zpos p + n); auto.";
 
2223
  pp "       replace (Zpos p + (Zpos p + n)) with";
 
2224
  pp "         (Zpos (xI p) + n  - 1); auto.";
 
2225
  pp "       rewrite Zpos_xI; ring.";
 
2226
  pp "   intros a2 b2 H9 H10.";
 
2227
  pp "     apply Hrec with n; auto.";
 
2228
  pp " intros p Hrec n a b cont H2 H3 H4.";
 
2229
  pp "   unfold gcd_gt_aux; apply Zspec_gcd_gt_body with (Zpos (xO p) + n); auto.";
 
2230
  pp "   intros a1 b1 H6 H7.";
 
2231
  pp "     apply Hrec with (Zpos p + n - 1); auto.";
 
2232
  pp "       replace (Zpos p + (Zpos p + n - 1)) with";
 
2233
  pp "         (Zpos (xO p) + n  - 1); auto.";
 
2234
  pp "       rewrite Zpos_xO; ring.";
 
2235
  pp "   intros a2 b2 H9 H10.";
 
2236
  pp "     apply Hrec with (n - 1); auto.";
 
2237
  pp "       replace (Zpos p + (n - 1)) with";
 
2238
  pp "         (Zpos p + n  - 1); auto with zarith.";
 
2239
  pp "   intros a3 b3 H12 H13; apply H4; auto with zarith.";
 
2240
  pp "    apply Zlt_le_trans with (1 := H12).";
 
2241
  pp "    case (Zle_or_lt 1 n); intros HH.";
 
2242
  pp "    apply Zpower_le_monotone; auto with zarith.";
 
2243
  pp "    apply Zle_trans with 0; auto with zarith.";
 
2244
  pp "    assert (HH1: n - 1 < 0); auto with zarith.";
 
2245
  pp "    generalize HH1; case (n - 1); auto with zarith.";
 
2246
  pp "    intros p1 HH2; discriminate.";
 
2247
  pp " intros n a b cont H H2 H3.";
 
2248
  pp "  simpl gcd_gt_aux.";
 
2249
  pp "  apply Zspec_gcd_gt_body with (n + 1); auto with zarith.";
 
2250
  pp "  rewrite Zplus_comm; auto.";
 
2251
  pp "  intros a1 b1 H5 H6; apply H3; auto.";
 
2252
  pp "  replace n with (n + 1 - 1); auto; try ring.";
 
2253
  pp " Qed.";
 
2254
  pp "";
 
2255
 
 
2256
  pr " Definition gcd_cont a b :=";
 
2257
  pr "  match compare one b with";
 
2258
  pr "  | Eq => one";
 
2259
  pr "  | _ => a";
 
2260
  pr "  end.";
 
2261
  pr "";
 
2262
 
 
2263
  pr " Definition gcd_gt a b := gcd_gt_aux (digits a) gcd_cont a b.";
 
2264
  pr "";
 
2265
 
 
2266
  pr " Theorem spec_gcd_gt: forall a b,";
 
2267
  pr "   [a] > [b] -> [gcd_gt a b] = Zgcd [a] [b].";
 
2268
  pa " Admitted.";
 
2269
  pp " Proof.";
 
2270
  pp " intros a b H2.";
 
2271
  pp " case (spec_digits (gcd_gt a b)); intros H3 H4.";
 
2272
  pp " case (spec_digits a); intros H5 H6.";
 
2273
  pp " apply sym_equal; apply Zis_gcd_gcd; auto with zarith.";
 
2274
  pp " unfold gcd_gt; apply Zspec_gcd_gt_aux with 0; auto with zarith.";
 
2275
  pp " intros a1 a2; rewrite Zpower_0_r.";
 
2276
  pp " case (spec_digits a2); intros H7 H8;";
 
2277
  pp "   intros; apply False_ind; auto with zarith.";
 
2278
  pp " Qed.";
 
2279
  pr "";
 
2280
 
 
2281
  pr " Definition gcd a b :=";
 
2282
  pr "  match compare a b with";
 
2283
  pr "  | Eq => a";
 
2284
  pr "  | Lt => gcd_gt b a";
 
2285
  pr "  | Gt => gcd_gt a b";
 
2286
  pr "  end.";
 
2287
  pr "";
 
2288
 
 
2289
  pr " Theorem spec_gcd: forall a b, [gcd a b] = Zgcd [a] [b].";
 
2290
  pa " Admitted.";
 
2291
  pp " Proof.";
 
2292
  pp " intros a b.";
 
2293
  pp " case (spec_digits a); intros H1 H2.";
 
2294
  pp " case (spec_digits b); intros H3 H4.";
 
2295
  pp " unfold gcd; generalize (spec_compare a b); case compare.";
 
2296
  pp " intros HH; rewrite HH; apply sym_equal; apply Zis_gcd_gcd; auto.";
 
2297
  pp "   apply Zis_gcd_refl.";
 
2298
  pp " intros; apply trans_equal with (Zgcd [b] [a]).";
 
2299
  pp "   apply spec_gcd_gt; auto with zarith.";
 
2300
  pp " apply Zis_gcd_gcd; auto with zarith.";
 
2301
  pp " apply Zgcd_is_pos.";
 
2302
  pp " apply Zis_gcd_sym; apply Zgcd_is_gcd.";
 
2303
  pp " intros; apply spec_gcd_gt; auto.";
 
2304
  pp " Qed.";
 
2305
  pr "";
 
2306
 
 
2307
 
 
2308
  pr " (***************************************************************)";
 
2309
  pr " (*                                                             *)";
 
2310
  pr " (*                          Conversion                         *)";
 
2311
  pr " (*                                                             *)";
 
2312
  pr " (***************************************************************)";
 
2313
  pr "";
 
2314
 
 
2315
  pr " Definition pheight p := ";
 
2316
  pr "   Peano.pred (nat_of_P (get_height w0_op.(znz_digits) (plength p))).";
 
2317
  pr "";
 
2318
 
 
2319
  pr " Theorem pheight_correct: forall p, ";
 
2320
  pr "    Zpos p < 2 ^ (Zpos (znz_digits w0_op) * 2 ^ (Z_of_nat (pheight p))).";
 
2321
  pr " Proof.";
 
2322
  pr " intros p; unfold pheight.";
 
2323
  pr " assert (F1: forall x, Z_of_nat (Peano.pred (nat_of_P x)) = Zpos x - 1).";
 
2324
  pr "  intros x.";
 
2325
  pr "  assert (Zsucc (Z_of_nat (Peano.pred (nat_of_P x))) = Zpos x); auto with zarith.";
 
2326
  pr "    rewrite <- inj_S.";
 
2327
  pr "    rewrite <- (fun x => S_pred x 0); auto with zarith.";
 
2328
  pr "    rewrite Zpos_eq_Z_of_nat_o_nat_of_P; auto.";
 
2329
  pr "    apply lt_le_trans with 1%snat; auto with zarith." "%";
 
2330
  pr "    exact (le_Pmult_nat x 1).";
 
2331
  pr "  rewrite F1; clear F1.";
 
2332
  pr " assert (F2:= (get_height_correct (znz_digits w0_op) (plength p))).";
 
2333
  pr " apply Zlt_le_trans with (Zpos (Psucc p)).";
 
2334
  pr "   rewrite Zpos_succ_morphism; auto with zarith.";
 
2335
  pr "  apply Zle_trans with (1 := plength_pred_correct (Psucc p)).";
 
2336
  pr " rewrite Ppred_succ.";
 
2337
  pr " apply Zpower_le_monotone; auto with zarith.";
 
2338
  pr " Qed.";
 
2339
  pr "";
 
2340
 
 
2341
  pr " Definition of_pos x :=";
 
2342
  pr "  let h := pheight x in";
 
2343
  pr "  match h with";
 
2344
  for i = 0 to size do
 
2345
    pr "  | %i%snat => reduce_%i (snd (w%i_op.(znz_of_pos) x))" i "%" i i;
 
2346
  done;
 
2347
  pr "  | _ =>";
 
2348
  pr "    let n := minus h %i in" (size + 1);
 
2349
  pr "    reduce_n n (snd ((make_op n).(znz_of_pos) x))";
 
2350
  pr "  end.";
 
2351
  pr "";
 
2352
 
 
2353
  pr " Theorem spec_of_pos: forall x,";
 
2354
  pr "   [of_pos x] = Zpos x.";
 
2355
  pa " Admitted.";
 
2356
  pp " Proof.";
 
2357
  pp " assert (F := spec_more_than_1_digit w0_spec).";
 
2358
  pp " intros x; unfold of_pos; case_eq (pheight x).";
 
2359
  for i = 0 to size do
 
2360
    if i <> 0 then
 
2361
      pp " intros n; case n; clear n.";
 
2362
    pp " intros H1; rewrite spec_reduce_%i; unfold to_Z." i;
 
2363
    pp " apply (znz_of_pos_correct w%i_spec)." i;
 
2364
    pp " apply Zlt_le_trans with (1 := pheight_correct x).";
 
2365
    pp "   rewrite H1; simpl Z_of_nat; change (2^%i) with (%s)." i (gen2 i);
 
2366
    pp "   unfold base.";
 
2367
    pp "   apply Zpower_le_monotone; split; auto with zarith.";
 
2368
    if i <> 0 then
 
2369
      begin
 
2370
        pp "   rewrite Zmult_comm; repeat rewrite <- Zmult_assoc.";
 
2371
        pp "     repeat rewrite <- Zpos_xO.";
 
2372
        pp "   refine (Zle_refl _).";
 
2373
      end;
 
2374
  done;
 
2375
  pp " intros n.";
 
2376
  pp " intros H1; rewrite spec_reduce_n; unfold to_Z.";
 
2377
  pp " simpl minus; rewrite <- minus_n_O.";
 
2378
  pp " apply (znz_of_pos_correct (wn_spec n)).";
 
2379
  pp " apply Zlt_le_trans with (1 := pheight_correct x).";
 
2380
  pp "   unfold base.";
 
2381
  pp "   apply Zpower_le_monotone; auto with zarith.";
 
2382
  pp "   split; auto with zarith.";
 
2383
  pp "   rewrite H1.";
 
2384
  pp "  elim n; clear n H1.";
 
2385
  pp "   simpl Z_of_nat; change (2^%i) with (%s)." (size + 1) (gen2 (size + 1));
 
2386
  pp "   rewrite Zmult_comm; repeat rewrite <- Zmult_assoc.";
 
2387
  pp "     repeat rewrite <- Zpos_xO.";
 
2388
  pp "   refine (Zle_refl _).";
 
2389
  pp "  intros n Hrec.";
 
2390
  pp "  rewrite make_op_S.";
 
2391
  pp "  change (@znz_digits (word _ (S (S n))) (mk_zn2z_op_karatsuba (make_op n))) with";
 
2392
  pp "    (xO (znz_digits (make_op n))).";
 
2393
  pp "  rewrite (fun x y => (Zpos_xO (@znz_digits x y))).";
 
2394
  pp "  rewrite inj_S; unfold Zsucc.";
 
2395
  pp "  rewrite Zplus_comm; rewrite Zpower_exp; auto with zarith.";
 
2396
  pp "  rewrite Zpower_1_r.";
 
2397
  pp "  assert (tmp: forall x y z, x * (y * z) = y * (x * z));";
 
2398
  pp "   [intros; ring | rewrite tmp; clear tmp].";
 
2399
  pp "  apply Zmult_le_compat_l; auto with zarith.";
 
2400
  pp "  Qed.";
 
2401
  pr "";
 
2402
 
 
2403
  pr " Definition of_N x :=";
 
2404
  pr "  match x with";
 
2405
  pr "  | BinNat.N0 => zero";
 
2406
  pr "  | Npos p => of_pos p";
 
2407
  pr "  end.";
 
2408
  pr "";
 
2409
 
 
2410
  pr " Theorem spec_of_N: forall x,";
 
2411
  pr "   [of_N x] = Z_of_N x.";
 
2412
  pa " Admitted.";
 
2413
  pp " Proof.";
 
2414
  pp " intros x; case x.";
 
2415
  pp "  simpl of_N.";
 
2416
  pp "  unfold zero, w_0, to_Z; rewrite (spec_0 w0_spec); auto.";
 
2417
  pp " intros p; exact (spec_of_pos p).";
 
2418
  pp " Qed.";
 
2419
  pr "";
 
2420
 
 
2421
  pr " (***************************************************************)";
 
2422
  pr " (*                                                             *)";
 
2423
  pr " (*                          Shift                              *)";
 
2424
  pr " (*                                                             *)";
 
2425
  pr " (***************************************************************)";
 
2426
  pr ""; 
 
2427
 
 
2428
  (* Head0 *)
 
2429
  pr " Definition head0 w := match w with";
 
2430
  for i = 0 to size do
 
2431
    pr " | %s%i w=> reduce_%i (w%i_op.(znz_head0) w)"  c i i i;
 
2432
  done;
 
2433
  pr " | %sn n w=> reduce_n n ((make_op n).(znz_head0) w)" c;
 
2434
  pr " end.";
 
2435
  pr "";
 
2436
 
 
2437
  pr " Theorem spec_head00: forall x, [x] = 0 ->[head0 x] = Zpos (digits x).";
 
2438
  pa " Admitted.";
 
2439
  pp " Proof.";
 
2440
  pp " intros x; case x; unfold head0; clear x.";
 
2441
  for i = 0 to size do
 
2442
    pp "   intros x; rewrite spec_reduce_%i; exact (spec_head00 w%i_spec x)." i i;
 
2443
  done;
 
2444
  pp " intros n x; rewrite spec_reduce_n; exact (spec_head00 (wn_spec n) x).";
 
2445
  pp " Qed.";
 
2446
  pr "  ";
 
2447
 
 
2448
  pr " Theorem spec_head0: forall x, 0 < [x] ->";
 
2449
  pr "   2 ^ (Zpos (digits x) - 1) <= 2 ^ [head0 x] * [x] < 2 ^ Zpos (digits x).";
 
2450
  pa " Admitted.";
 
2451
  pp " Proof.";
 
2452
  pp " assert (F0: forall x, (x - 1) + 1 = x).";
 
2453
  pp "   intros; ring. ";
 
2454
  pp " intros x; case x; unfold digits, head0; clear x.";
 
2455
  for i = 0 to size do
 
2456
    pp " intros x Hx; rewrite spec_reduce_%i." i;
 
2457
    pp " assert (F1:= spec_more_than_1_digit w%i_spec)." i;
 
2458
    pp " generalize (spec_head0 w%i_spec x Hx)." i;
 
2459
    pp " unfold base.";
 
2460
    pp " pattern (Zpos (znz_digits w%i_op)) at 1; " i;
 
2461
    pp " rewrite <- (fun x => (F0 (Zpos x))).";
 
2462
    pp " rewrite Zpower_exp; auto with zarith.";
 
2463
    pp " rewrite Zpower_1_r; rewrite Z_div_mult; auto with zarith.";
 
2464
  done;
 
2465
  pp " intros n x Hx; rewrite spec_reduce_n.";
 
2466
  pp " assert (F1:= spec_more_than_1_digit (wn_spec n)).";
 
2467
  pp " generalize (spec_head0 (wn_spec n) x Hx).";
 
2468
  pp " unfold base.";
 
2469
  pp " pattern (Zpos (znz_digits (make_op n))) at 1; ";
 
2470
  pp " rewrite <- (fun x => (F0 (Zpos x))).";
 
2471
  pp " rewrite Zpower_exp; auto with zarith.";
 
2472
  pp " rewrite Zpower_1_r; rewrite Z_div_mult; auto with zarith.";
 
2473
  pp " Qed.";
 
2474
  pr "";
 
2475
 
 
2476
 
 
2477
  (* Tail0 *)
 
2478
  pr " Definition tail0 w := match w with";
 
2479
  for i = 0 to size do
 
2480
    pr " | %s%i w=> reduce_%i (w%i_op.(znz_tail0) w)"  c i i i;
 
2481
  done;
 
2482
  pr " | %sn n w=> reduce_n n ((make_op n).(znz_tail0) w)" c;
 
2483
  pr " end.";
 
2484
  pr "";
 
2485
 
 
2486
 
 
2487
  pr " Theorem spec_tail00: forall x, [x] = 0 ->[tail0 x] = Zpos (digits x).";
 
2488
  pa " Admitted.";
 
2489
  pp " Proof.";
 
2490
  pp " intros x; case x; unfold tail0; clear x.";
 
2491
  for i = 0 to size do
 
2492
    pp "   intros x; rewrite spec_reduce_%i; exact (spec_tail00 w%i_spec x)." i i;
 
2493
  done;
 
2494
  pp " intros n x; rewrite spec_reduce_n; exact (spec_tail00 (wn_spec n) x).";
 
2495
  pp " Qed.";
 
2496
  pr "  ";
 
2497
 
 
2498
 
 
2499
  pr " Theorem spec_tail0: forall x,";
 
2500
  pr "   0 < [x] -> exists y, 0 <= y /\\ [x] = (2 * y + 1) * 2 ^ [tail0 x].";
 
2501
  pa " Admitted.";
 
2502
  pp " Proof.";
 
2503
  pp " intros x; case x; clear x; unfold tail0.";
 
2504
  for i = 0 to size do
 
2505
    pp " intros x Hx; rewrite spec_reduce_%i; exact (spec_tail0 w%i_spec x Hx)." i  i;
 
2506
  done;
 
2507
  pp " intros n x Hx; rewrite spec_reduce_n; exact (spec_tail0 (wn_spec n) x Hx).";
 
2508
  pp " Qed.";
 
2509
  pr "";
 
2510
 
 
2511
 
 
2512
  (* Number of digits *)
 
2513
  pr " Definition %sdigits x :=" c;
 
2514
  pr "  match x with";
 
2515
  pr "  | %s0 _ => %s0 w0_op.(znz_zdigits)" c c;
 
2516
  for i = 1 to size do 
 
2517
    pr "  | %s%i _ => reduce_%i w%i_op.(znz_zdigits)" c i i i;
 
2518
  done;
 
2519
  pr "  | %sn n _ => reduce_n n (make_op n).(znz_zdigits)" c;
 
2520
  pr "  end.";
 
2521
  pr "";
 
2522
 
 
2523
  pr " Theorem spec_Ndigits: forall x, [Ndigits x] = Zpos (digits x).";
 
2524
  pa " Admitted.";
 
2525
  pp " Proof.";
 
2526
  pp " intros x; case x; clear x; unfold Ndigits, digits.";
 
2527
  for i = 0 to size do
 
2528
    pp " intros _; try rewrite spec_reduce_%i; exact (spec_zdigits w%i_spec)." i i;
 
2529
  done;
 
2530
  pp " intros n _; try rewrite spec_reduce_n; exact (spec_zdigits (wn_spec n)).";
 
2531
  pp " Qed.";
 
2532
  pr "";
 
2533
 
 
2534
 
 
2535
  (* Shiftr *)
 
2536
  for i = 0 to size do
 
2537
    pr " Definition shiftr%i n x := w%i_op.(znz_add_mul_div) (w%i_op.(znz_sub) w%i_op.(znz_zdigits) n) w%i_op.(znz_0) x." i i i i i;
 
2538
  done;
 
2539
  pr " Definition shiftrn n p x := (make_op n).(znz_add_mul_div) ((make_op n).(znz_sub) (make_op n).(znz_zdigits) p) (make_op n).(znz_0) x.";
 
2540
  pr "";
 
2541
 
 
2542
  pr " Definition shiftr := Eval lazy beta delta [same_level] in ";
 
2543
  pr "     same_level _ (fun n x => %s0 (shiftr0 n x))" c;
 
2544
  for i = 1 to size do
 
2545
    pr "           (fun n x => reduce_%i (shiftr%i n x))" i i;
 
2546
  done;
 
2547
  pr "           (fun n p x => reduce_n n (shiftrn n p x)).";
 
2548
  pr "";
 
2549
 
 
2550
 
 
2551
  pr " Theorem spec_shiftr: forall n x,";
 
2552
  pr "  [n] <= [Ndigits x] -> [shiftr n x] = [x] / 2 ^ [n].";
 
2553
  pa " Admitted.";
 
2554
  pp " Proof.";
 
2555
  pp " assert (F0: forall x y, x - (x - y) = y).";
 
2556
  pp "   intros; ring.";
 
2557
  pp " assert (F2: forall x y z, 0 <= x -> 0 <= y -> x < z -> 0 <= x / 2 ^ y < z).";
 
2558
  pp "   intros x y z HH HH1 HH2.";
 
2559
  pp "   split; auto with zarith.";
 
2560
  pp "   apply Zle_lt_trans with (2 := HH2); auto with zarith.";
 
2561
  pp "   apply Zdiv_le_upper_bound; auto with zarith.";
 
2562
  pp "   pattern x at 1; replace x with (x * 2 ^ 0); auto with zarith.";
 
2563
  pp "   apply Zmult_le_compat_l; auto.";
 
2564
  pp "   apply Zpower_le_monotone; auto with zarith.";
 
2565
  pp "   rewrite Zpower_0_r; ring.";
 
2566
  pp "  assert (F3: forall x y, 0 <= y -> y <= x -> 0 <= x - y < 2 ^ x).";
 
2567
  pp "    intros xx y HH HH1.";
 
2568
  pp "    split; auto with zarith.";
 
2569
  pp "    apply Zle_lt_trans with xx; auto with zarith.";
 
2570
  pp "    apply Zpower2_lt_lin; auto with zarith.";
 
2571
  pp "  assert (F4: forall ww ww1 ww2 ";
 
2572
  pp "         (ww_op: znz_op ww) (ww1_op: znz_op ww1) (ww2_op: znz_op ww2)";
 
2573
  pp "           xx yy xx1 yy1,";
 
2574
  pp "  znz_to_Z ww2_op yy <= znz_to_Z ww1_op (znz_zdigits ww1_op) ->";
 
2575
  pp "  znz_to_Z ww1_op (znz_zdigits ww1_op) <= znz_to_Z ww_op (znz_zdigits ww_op) ->";
 
2576
  pp "  znz_spec ww_op -> znz_spec ww1_op -> znz_spec ww2_op ->";
 
2577
  pp "  znz_to_Z ww_op xx1 = znz_to_Z ww1_op xx ->";
 
2578
  pp "  znz_to_Z ww_op yy1 = znz_to_Z ww2_op yy ->";
 
2579
  pp "  znz_to_Z ww_op";
 
2580
  pp "  (znz_add_mul_div ww_op (znz_sub ww_op (znz_zdigits ww_op)  yy1)";
 
2581
  pp "     (znz_0 ww_op) xx1) = znz_to_Z ww1_op xx / 2 ^ znz_to_Z ww2_op yy).";
 
2582
  pp "  intros ww ww1 ww2 ww_op ww1_op ww2_op xx yy xx1 yy1 Hl Hl1 Hw Hw1 Hw2 Hx Hy.";
 
2583
  pp "     case (spec_to_Z Hw xx1); auto with zarith; intros HH1 HH2.";
 
2584
  pp "     case (spec_to_Z Hw yy1); auto with zarith; intros HH3 HH4.";
 
2585
  pp "     rewrite <- Hx.";
 
2586
  pp "     rewrite <- Hy.";
 
2587
  pp "     generalize (spec_add_mul_div Hw";
 
2588
  pp "                  (znz_0 ww_op) xx1";
 
2589
  pp "                  (znz_sub ww_op (znz_zdigits ww_op) ";
 
2590
  pp "                    yy1)";
 
2591
  pp "                ).";
 
2592
  pp "     rewrite (spec_0 Hw).";
 
2593
  pp "     rewrite Zmult_0_l; rewrite Zplus_0_l.";
 
2594
  pp "     rewrite (CyclicAxioms.spec_sub Hw).";
 
2595
  pp "     rewrite Zmod_small; auto with zarith.";
 
2596
  pp "     rewrite (spec_zdigits Hw).";
 
2597
  pp "     rewrite F0.";
 
2598
  pp "     rewrite Zmod_small; auto with zarith.";
 
2599
  pp "     unfold base; rewrite (spec_zdigits Hw) in Hl1 |- *;";
 
2600
  pp "      auto with zarith.";
 
2601
  pp "  assert (F5: forall n m, (n <= m)%snat ->" "%";
 
2602
  pp "     Zpos (znz_digits (make_op n)) <= Zpos (znz_digits (make_op m))).";
 
2603
  pp "    intros n m HH; elim HH; clear m HH; auto with zarith.";
 
2604
  pp "    intros m HH Hrec; apply Zle_trans with (1 := Hrec).";
 
2605
  pp "    rewrite make_op_S.";
 
2606
  pp "    match goal with |- Zpos ?Y <= ?X => change X with (Zpos (xO Y)) end.";
 
2607
  pp "    rewrite Zpos_xO.";
 
2608
  pp "    assert (0 <= Zpos (znz_digits (make_op n))); auto with zarith.";
 
2609
  pp "  assert (F6: forall n, Zpos (znz_digits w%i_op) <= Zpos (znz_digits (make_op n)))." size;
 
2610
  pp "    intros n ; apply Zle_trans with (Zpos (znz_digits (make_op 0))).";
 
2611
  pp "    change (znz_digits (make_op 0)) with (xO (znz_digits w%i_op))." size;
 
2612
  pp "    rewrite Zpos_xO.";
 
2613
  pp "    assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." size;
 
2614
  pp "    apply F5; auto with arith.";
 
2615
  pp "  intros x; case x; clear x; unfold shiftr, same_level.";
 
2616
  for i = 0 to size do
 
2617
    pp "    intros x y; case y; clear y.";
 
2618
    for j = 0 to i - 1 do
 
2619
      pp "     intros y; unfold shiftr%i, Ndigits." i;
 
2620
      pp "       repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j;
 
2621
      pp "       apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i j i;
 
2622
      pp "       rewrite (spec_zdigits w%i_spec)." i;
 
2623
      pp "       rewrite (spec_zdigits w%i_spec)." j;
 
2624
      pp "       change (znz_digits w%i_op) with %s." i (genxO (i - j) (" (znz_digits w"^(string_of_int j)^"_op)"));
 
2625
      pp "       repeat rewrite (fun x => Zpos_xO (xO x)).";
 
2626
      pp "       repeat rewrite (fun x y => Zpos_xO (@znz_digits x y)).";
 
2627
      pp "       assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." j;
 
2628
      pp "       try (apply sym_equal; exact (spec_extend%in%i y))." j i;
 
2629
 
 
2630
    done;
 
2631
    pp "     intros y; unfold shiftr%i, Ndigits." i;
 
2632
    pp "     repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i;
 
2633
    pp "       apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i i i;
 
2634
    for j = i + 1 to size do
 
2635
      pp "     intros y; unfold shiftr%i, Ndigits." j;
 
2636
      pp "       repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j;
 
2637
      pp "       apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." j j i;
 
2638
      pp "       try (apply sym_equal; exact (spec_extend%in%i x))." i j;
 
2639
    done;
 
2640
    if i == size then
 
2641
      begin
 
2642
        pp "     intros m y; unfold shiftrn, Ndigits.";
 
2643
        pp "       repeat rewrite spec_reduce_n; unfold to_Z; intros H1.";
 
2644
        pp "       apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." size;
 
2645
        pp "       try (apply sym_equal; exact (spec_extend%in m x))." size;
 
2646
      end
 
2647
    else 
 
2648
      begin
 
2649
        pp "     intros m y; unfold shiftrn, Ndigits.";
 
2650
        pp "       repeat rewrite spec_reduce_n; unfold to_Z; intros H1.";
 
2651
        pp "       apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." i;
 
2652
        pp "       change ([Nn m (extend%i m (extend%i %i x))] = [N%i x])." size i (size - i - 1) i;
 
2653
        pp "       rewrite <- (spec_extend%in m); rewrite <- spec_extend%in%i; auto." size i size;
 
2654
      end
 
2655
  done;
 
2656
  pp "    intros n x y; case y; clear y;";
 
2657
  pp "     intros y; unfold shiftrn, Ndigits; try rewrite spec_reduce_n.";
 
2658
  for i = 0 to size do
 
2659
    pp "     try rewrite spec_reduce_%i; unfold to_Z; intros H1." i;
 
2660
    pp "       apply F4 with (3:=(wn_spec n))(4:=w%i_spec)(5:=wn_spec n); auto with zarith." i;
 
2661
    pp "       rewrite (spec_zdigits w%i_spec)." i;
 
2662
    pp "       rewrite (spec_zdigits (wn_spec n)).";
 
2663
    pp "       apply Zle_trans with (2 := F6 n).";
 
2664
    pp "       change (znz_digits w%i_op) with %s." size (genxO (size - i) ("(znz_digits w" ^ (string_of_int i) ^ "_op)"));
 
2665
    pp "       repeat rewrite (fun x => Zpos_xO (xO x)).";
 
2666
    pp "       repeat rewrite (fun x y => Zpos_xO (@znz_digits x y)).";
 
2667
    pp "       assert (H: 0 <= Zpos (znz_digits w%i_op)); auto with zarith." i;
 
2668
    if i == size then
 
2669
      pp "       change ([Nn n (extend%i n y)] = [N%i y])." size i
 
2670
    else
 
2671
      pp "       change ([Nn n (extend%i n (extend%i %i y))] = [N%i y])." size i (size - i - 1) i;
 
2672
    pp "       rewrite <- (spec_extend%in n); auto." size;
 
2673
    if i <> size then
 
2674
      pp "       try (rewrite <- spec_extend%in%i; auto)." i size;
 
2675
  done;
 
2676
  pp "     generalize y; clear y; intros m y.";
 
2677
  pp "     rewrite spec_reduce_n; unfold to_Z; intros H1.";
 
2678
  pp "       apply F4 with (3:=(wn_spec (Max.max n m)))(4:=wn_spec m)(5:=wn_spec n); auto with zarith.";
 
2679
  pp "     rewrite (spec_zdigits (wn_spec m)).";
 
2680
  pp "     rewrite (spec_zdigits (wn_spec (Max.max n m))).";
 
2681
  pp "     apply F5; auto with arith.";
 
2682
  pp "     exact (spec_cast_r n m y).";
 
2683
  pp "     exact (spec_cast_l n m x).";
 
2684
  pp " Qed.";
 
2685
  pr "";
 
2686
 
 
2687
  pr " Definition safe_shiftr n x := ";
 
2688
  pr "   match compare n (Ndigits x) with";
 
2689
  pr "   |  Lt => shiftr n x ";
 
2690
  pr "   | _ => %s0 w_0" c;
 
2691
  pr "   end.";
 
2692
  pr "";
 
2693
 
 
2694
 
 
2695
  pr " Theorem spec_safe_shiftr: forall n x,";
 
2696
  pr "   [safe_shiftr n x] = [x] / 2 ^ [n].";
 
2697
  pa " Admitted.";
 
2698
  pp " Proof.";
 
2699
  pp " intros n x; unfold safe_shiftr;";
 
2700
  pp "    generalize (spec_compare n (Ndigits x)); case compare; intros H.";
 
2701
  pp " apply trans_equal with (1 := spec_0 w0_spec).";
 
2702
  pp " apply sym_equal; apply Zdiv_small; rewrite H.";
 
2703
  pp " rewrite spec_Ndigits; exact (spec_digits x).";
 
2704
  pp " rewrite <- spec_shiftr; auto with zarith.";
 
2705
  pp " apply trans_equal with (1 := spec_0 w0_spec).";
 
2706
  pp " apply sym_equal; apply Zdiv_small.";
 
2707
  pp " rewrite spec_Ndigits in H; case (spec_digits x); intros H1 H2.";
 
2708
  pp " split; auto.";
 
2709
  pp " apply Zlt_le_trans with (1 := H2).";
 
2710
  pp " apply Zpower_le_monotone; auto with zarith.";
 
2711
  pp " Qed.";
 
2712
  pr "";
 
2713
 
 
2714
  pr "";
 
2715
 
 
2716
  (* Shiftl *)
 
2717
  for i = 0 to size do
 
2718
    pr " Definition shiftl%i n x := w%i_op.(znz_add_mul_div) n x w%i_op.(znz_0)." i i i
 
2719
  done;
 
2720
  pr " Definition shiftln n p x := (make_op n).(znz_add_mul_div) p x (make_op n).(znz_0).";
 
2721
  pr " Definition shiftl := Eval lazy beta delta [same_level] in";
 
2722
  pr "    same_level _ (fun n x => %s0 (shiftl0 n x))" c;
 
2723
  for i = 1 to size do
 
2724
    pr "           (fun n x => reduce_%i (shiftl%i n x))" i i;
 
2725
  done;
 
2726
  pr "           (fun n p x => reduce_n n (shiftln n p x)).";
 
2727
  pr "";
 
2728
  pr "";
 
2729
 
 
2730
 
 
2731
  pr " Theorem spec_shiftl: forall n x,";
 
2732
  pr "  [n] <= [head0 x] -> [shiftl n x] = [x] * 2 ^ [n].";
 
2733
  pa " Admitted.";
 
2734
  pp " Proof.";
 
2735
  pp " assert (F0: forall x y, x - (x - y) = y).";
 
2736
  pp "   intros; ring.";
 
2737
  pp " assert (F2: forall x y z, 0 <= x -> 0 <= y -> x < z -> 0 <= x / 2 ^ y < z).";
 
2738
  pp "   intros x y z HH HH1 HH2.";
 
2739
  pp "   split; auto with zarith.";
 
2740
  pp "   apply Zle_lt_trans with (2 := HH2); auto with zarith.";
 
2741
  pp "   apply Zdiv_le_upper_bound; auto with zarith.";
 
2742
  pp "   pattern x at 1; replace x with (x * 2 ^ 0); auto with zarith.";
 
2743
  pp "   apply Zmult_le_compat_l; auto.";
 
2744
  pp "   apply Zpower_le_monotone; auto with zarith.";
 
2745
  pp "   rewrite Zpower_0_r; ring.";
 
2746
  pp "  assert (F3: forall x y, 0 <= y -> y <= x -> 0 <= x - y < 2 ^ x).";
 
2747
  pp "    intros xx y HH HH1.";
 
2748
  pp "    split; auto with zarith.";
 
2749
  pp "    apply Zle_lt_trans with xx; auto with zarith.";
 
2750
  pp "    apply Zpower2_lt_lin; auto with zarith.";
 
2751
  pp "  assert (F4: forall ww ww1 ww2 ";
 
2752
  pp "         (ww_op: znz_op ww) (ww1_op: znz_op ww1) (ww2_op: znz_op ww2)";
 
2753
  pp "           xx yy xx1 yy1,";
 
2754
  pp "  znz_to_Z ww2_op yy <= znz_to_Z ww1_op (znz_head0 ww1_op xx) ->";
 
2755
  pp "  znz_to_Z ww1_op (znz_zdigits ww1_op) <= znz_to_Z ww_op (znz_zdigits ww_op) ->";
 
2756
  pp "  znz_spec ww_op -> znz_spec ww1_op -> znz_spec ww2_op ->";
 
2757
  pp "  znz_to_Z ww_op xx1 = znz_to_Z ww1_op xx ->";
 
2758
  pp "  znz_to_Z ww_op yy1 = znz_to_Z ww2_op yy ->";
 
2759
  pp "  znz_to_Z ww_op";
 
2760
  pp "  (znz_add_mul_div ww_op yy1";
 
2761
  pp "     xx1 (znz_0 ww_op)) = znz_to_Z ww1_op xx * 2 ^ znz_to_Z ww2_op yy).";
 
2762
  pp "  intros ww ww1 ww2 ww_op ww1_op ww2_op xx yy xx1 yy1 Hl Hl1 Hw Hw1 Hw2 Hx Hy.";
 
2763
  pp "     case (spec_to_Z Hw xx1); auto with zarith; intros HH1 HH2.";
 
2764
  pp "     case (spec_to_Z Hw yy1); auto with zarith; intros HH3 HH4.";
 
2765
  pp "     rewrite <- Hx.";
 
2766
  pp "     rewrite <- Hy.";
 
2767
  pp "     generalize (spec_add_mul_div Hw xx1 (znz_0 ww_op) yy1).";
 
2768
  pp "     rewrite (spec_0 Hw).";
 
2769
  pp "     assert (F1: znz_to_Z ww1_op (znz_head0 ww1_op xx) <= Zpos (znz_digits ww1_op)).";
 
2770
  pp "     case (Zle_lt_or_eq _ _ HH1); intros HH5.";
 
2771
  pp "     apply Zlt_le_weak.";
 
2772
  pp "     case (CyclicAxioms.spec_head0 Hw1 xx).";
 
2773
  pp "       rewrite <- Hx; auto.";
 
2774
  pp "     intros _ Hu; unfold base in Hu.";
 
2775
  pp "     case (Zle_or_lt (Zpos (znz_digits ww1_op))";
 
2776
  pp "                     (znz_to_Z ww1_op (znz_head0 ww1_op xx))); auto; intros H1.";
 
2777
  pp "     absurd (2 ^  (Zpos (znz_digits ww1_op)) <= 2 ^ (znz_to_Z ww1_op (znz_head0 ww1_op xx))).";
 
2778
  pp "       apply Zlt_not_le.";
 
2779
  pp "       case (spec_to_Z Hw1 xx); intros HHx3 HHx4.";
 
2780
  pp "       rewrite <- (Zmult_1_r (2 ^ znz_to_Z ww1_op (znz_head0 ww1_op xx))).";
 
2781
  pp "       apply Zle_lt_trans with (2 := Hu).";
 
2782
  pp "       apply Zmult_le_compat_l; auto with zarith.";
 
2783
  pp "     apply Zpower_le_monotone; auto with zarith.";
 
2784
  pp "     rewrite (CyclicAxioms.spec_head00 Hw1 xx); auto with zarith.";
 
2785
  pp "     rewrite Zdiv_0_l; auto with zarith.";
 
2786
  pp "     rewrite Zplus_0_r.";
 
2787
  pp "     case (Zle_lt_or_eq _ _ HH1); intros HH5.";
 
2788
  pp "     rewrite Zmod_small; auto with zarith.";
 
2789
  pp "     intros HH; apply HH.";
 
2790
  pp "     rewrite Hy; apply Zle_trans with (1:= Hl).";
 
2791
  pp "     rewrite <- (spec_zdigits Hw). ";
 
2792
  pp "     apply Zle_trans with (2 := Hl1); auto.";
 
2793
  pp "     rewrite  (spec_zdigits Hw1); auto with zarith.";
 
2794
  pp "     split; auto with zarith .";
 
2795
  pp "     apply Zlt_le_trans with (base (znz_digits ww1_op)).";
 
2796
  pp "     rewrite Hx.";
 
2797
  pp "     case (CyclicAxioms.spec_head0 Hw1 xx); auto.";
 
2798
  pp "       rewrite <- Hx; auto.";
 
2799
  pp "     intros _ Hu; rewrite Zmult_comm in Hu.";
 
2800
  pp "     apply Zle_lt_trans with (2 := Hu).";
 
2801
  pp "     apply Zmult_le_compat_l; auto with zarith.";
 
2802
  pp "     apply Zpower_le_monotone; auto with zarith.";
 
2803
  pp "     unfold base; apply Zpower_le_monotone; auto with zarith.";
 
2804
  pp "     split; auto with zarith.";
 
2805
  pp "     rewrite <- (spec_zdigits Hw); auto with zarith.";
 
2806
  pp "     rewrite <- (spec_zdigits Hw1); auto with zarith.";
 
2807
  pp "     rewrite <- HH5.";
 
2808
  pp "     rewrite Zmult_0_l.";
 
2809
  pp "     rewrite Zmod_small; auto with zarith.";
 
2810
  pp "     intros HH; apply HH.";
 
2811
  pp "     rewrite Hy; apply Zle_trans with (1 := Hl).";
 
2812
  pp "     rewrite (CyclicAxioms.spec_head00 Hw1 xx); auto with zarith.";
 
2813
  pp "     rewrite <- (spec_zdigits Hw); auto with zarith.";
 
2814
  pp "     rewrite <- (spec_zdigits Hw1); auto with zarith.";
 
2815
  pp "  assert (F5: forall n m, (n <= m)%snat ->" "%";
 
2816
  pp "     Zpos (znz_digits (make_op n)) <= Zpos (znz_digits (make_op m))).";
 
2817
  pp "    intros n m HH; elim HH; clear m HH; auto with zarith.";
 
2818
  pp "    intros m HH Hrec; apply Zle_trans with (1 := Hrec).";
 
2819
  pp "    rewrite make_op_S.";
 
2820
  pp "    match goal with |- Zpos ?Y <= ?X => change X with (Zpos (xO Y)) end.";
 
2821
  pp "    rewrite Zpos_xO.";
 
2822
  pp "    assert (0 <= Zpos (znz_digits (make_op n))); auto with zarith.";
 
2823
  pp "  assert (F6: forall n, Zpos (znz_digits w%i_op) <= Zpos (znz_digits (make_op n)))." size;
 
2824
  pp "    intros n ; apply Zle_trans with (Zpos (znz_digits (make_op 0))).";
 
2825
  pp "    change (znz_digits (make_op 0)) with (xO (znz_digits w%i_op))." size;
 
2826
  pp "    rewrite Zpos_xO.";
 
2827
  pp "    assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." size;
 
2828
  pp "    apply F5; auto with arith.";
 
2829
  pp "  intros x; case x; clear x; unfold shiftl, same_level.";
 
2830
  for i = 0 to size do
 
2831
    pp "    intros x y; case y; clear y.";
 
2832
    for j = 0 to i - 1 do
 
2833
      pp "     intros y; unfold shiftl%i, head0." i;
 
2834
      pp "       repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j;
 
2835
      pp "       apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i j i;
 
2836
      pp "       rewrite (spec_zdigits w%i_spec)." i;
 
2837
      pp "       rewrite (spec_zdigits w%i_spec)." j;
 
2838
      pp "       change (znz_digits w%i_op) with %s." i (genxO (i - j) (" (znz_digits w"^(string_of_int j)^"_op)"));
 
2839
      pp "       repeat rewrite (fun x => Zpos_xO (xO x)).";
 
2840
      pp "       repeat rewrite (fun x y => Zpos_xO (@znz_digits x y)).";
 
2841
      pp "       assert (0 <= Zpos (znz_digits w%i_op)); auto with zarith." j;
 
2842
      pp "       try (apply sym_equal; exact (spec_extend%in%i y))." j i;
 
2843
    done;
 
2844
    pp "     intros y; unfold shiftl%i, head0." i;
 
2845
    pp "     repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i;
 
2846
    pp "       apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." i i i;
 
2847
    for j = i + 1 to size do
 
2848
      pp "     intros y; unfold shiftl%i, head0." j;
 
2849
      pp "       repeat rewrite spec_reduce_%i; repeat rewrite spec_reduce_%i; unfold to_Z; intros H1." i j;
 
2850
      pp "       apply F4 with (3:=w%i_spec)(4:=w%i_spec)(5:=w%i_spec); auto with zarith." j j i;
 
2851
      pp "       try (apply sym_equal; exact (spec_extend%in%i x))." i j;
 
2852
    done;
 
2853
    if i == size then
 
2854
      begin
 
2855
        pp "     intros m y; unfold shiftln, head0.";
 
2856
        pp "       repeat rewrite spec_reduce_n; unfold to_Z; intros H1.";
 
2857
        pp "       apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." size;
 
2858
        pp "       try (apply sym_equal; exact (spec_extend%in m x))." size;
 
2859
      end
 
2860
    else 
 
2861
      begin
 
2862
        pp "     intros m y; unfold shiftln, head0.";
 
2863
        pp "       repeat rewrite spec_reduce_n; unfold to_Z; intros H1.";
 
2864
        pp "       apply F4 with (3:=(wn_spec m))(4:=wn_spec m)(5:=w%i_spec); auto with zarith." i;
 
2865
        pp "       change ([Nn m (extend%i m (extend%i %i x))] = [N%i x])." size i (size - i - 1) i;
 
2866
        pp "       rewrite <- (spec_extend%in m); rewrite <- spec_extend%in%i; auto." size i size;
 
2867
      end
 
2868
  done;
 
2869
  pp "    intros n x y; case y; clear y;";
 
2870
  pp "     intros y; unfold shiftln, head0; try rewrite spec_reduce_n.";
 
2871
  for i = 0 to size do
 
2872
    pp "     try rewrite spec_reduce_%i; unfold to_Z; intros H1." i;
 
2873
    pp "       apply F4 with (3:=(wn_spec n))(4:=w%i_spec)(5:=wn_spec n); auto with zarith." i;
 
2874
    pp "       rewrite (spec_zdigits w%i_spec)." i;
 
2875
    pp "       rewrite (spec_zdigits (wn_spec n)).";
 
2876
    pp "       apply Zle_trans with (2 := F6 n).";
 
2877
    pp "       change (znz_digits w%i_op) with %s." size (genxO (size - i) ("(znz_digits w" ^ (string_of_int i) ^ "_op)"));
 
2878
    pp "       repeat rewrite (fun x => Zpos_xO (xO x)).";
 
2879
    pp "       repeat rewrite (fun x y => Zpos_xO (@znz_digits x y)).";
 
2880
    pp "       assert (H: 0 <= Zpos (znz_digits w%i_op)); auto with zarith." i;
 
2881
    if i == size then
 
2882
      pp "       change ([Nn n (extend%i n y)] = [N%i y])." size i
 
2883
    else
 
2884
      pp "       change ([Nn n (extend%i n (extend%i %i y))] = [N%i y])." size i (size - i - 1) i;
 
2885
    pp "       rewrite <- (spec_extend%in n); auto." size;
 
2886
    if i <> size then
 
2887
      pp "       try (rewrite <- spec_extend%in%i; auto)." i size;
 
2888
  done;
 
2889
  pp "     generalize y; clear y; intros m y.";
 
2890
  pp "     repeat rewrite spec_reduce_n; unfold to_Z; intros H1.";
 
2891
  pp "       apply F4 with (3:=(wn_spec (Max.max n m)))(4:=wn_spec m)(5:=wn_spec n); auto with zarith.";
 
2892
  pp "     rewrite (spec_zdigits (wn_spec m)).";
 
2893
  pp "     rewrite (spec_zdigits (wn_spec (Max.max n m))).";
 
2894
  pp "     apply F5; auto with arith.";
 
2895
  pp "     exact (spec_cast_r n m y).";
 
2896
  pp "     exact (spec_cast_l n m x).";
 
2897
  pp " Qed.";
 
2898
  pr "";
 
2899
 
 
2900
  (* Double size *)
 
2901
  pr " Definition double_size w := match w with";
 
2902
  for i = 0 to size-1 do
 
2903
    pr " | %s%i x => %s%i (WW (znz_0 w%i_op) x)" c i c (i + 1) i;
 
2904
  done;
 
2905
  pr " | %s%i x => %sn 0 (WW (znz_0 w%i_op) x)" c size c size;
 
2906
  pr " | %sn n x => %sn (S n) (WW (znz_0 (make_op n)) x)" c c;
 
2907
  pr " end.";
 
2908
  pr "";
 
2909
 
 
2910
  pr " Theorem spec_double_size_digits: ";
 
2911
  pr "   forall x, digits (double_size x) = xO (digits x).";
 
2912
  pa " Admitted.";
 
2913
  pp " Proof.";
 
2914
  pp " intros x; case x; unfold double_size, digits; clear x; auto.";
 
2915
  pp " intros n x; rewrite make_op_S; auto.";
 
2916
  pp " Qed.";
 
2917
  pr "";
 
2918
 
 
2919
 
 
2920
  pr " Theorem spec_double_size: forall x, [double_size x] = [x].";
 
2921
  pa " Admitted.";
 
2922
  pp " Proof.";
 
2923
  pp " intros x; case x; unfold double_size; clear x.";
 
2924
  for i = 0 to size do
 
2925
    pp "   intros x; unfold to_Z, make_op; ";
 
2926
    pp "     rewrite znz_to_Z_%i; rewrite (spec_0 w%i_spec); auto with zarith." (i + 1) i;
 
2927
  done;
 
2928
  pp "   intros n x; unfold to_Z;";
 
2929
  pp "     generalize (znz_to_Z_n n); simpl word.";
 
2930
  pp "     intros HH; rewrite HH; clear HH.";
 
2931
  pp "     generalize (spec_0 (wn_spec n)); simpl word.";
 
2932
  pp "     intros HH; rewrite HH; clear HH; auto with zarith.";
 
2933
  pp " Qed.";
 
2934
  pr "";
 
2935
 
 
2936
 
 
2937
  pr " Theorem spec_double_size_head0: ";
 
2938
  pr "   forall x, 2 * [head0 x] <= [head0 (double_size x)].";
 
2939
  pa " Admitted.";
 
2940
  pp " Proof.";
 
2941
  pp " intros x.";
 
2942
  pp " assert (F1:= spec_pos (head0 x)).";
 
2943
  pp " assert (F2: 0 < Zpos (digits x)).";
 
2944
  pp "   red; auto.";
 
2945
  pp " case (Zle_lt_or_eq _ _ (spec_pos x)); intros HH.";
 
2946
  pp " generalize HH; rewrite <- (spec_double_size x); intros HH1.";
 
2947
  pp " case (spec_head0 x HH); intros _ HH2.";
 
2948
  pp " case (spec_head0 _ HH1).";
 
2949
  pp " rewrite (spec_double_size x); rewrite (spec_double_size_digits x).";
 
2950
  pp " intros HH3 _.";
 
2951
  pp " case (Zle_or_lt ([head0 (double_size x)]) (2 * [head0 x])); auto; intros HH4.";
 
2952
  pp " absurd (2 ^ (2 * [head0 x] )* [x] < 2 ^ [head0 (double_size x)] * [x]); auto.";
 
2953
  pp " apply Zle_not_lt.";
 
2954
  pp " apply Zmult_le_compat_r; auto with zarith.";
 
2955
  pp " apply Zpower_le_monotone; auto; auto with zarith.";
 
2956
  pp " generalize (spec_pos (head0 (double_size x))); auto with zarith.";
 
2957
  pp " assert (HH5: 2 ^[head0 x] <= 2 ^(Zpos (digits x) - 1)).";
 
2958
  pp "   case (Zle_lt_or_eq 1 [x]); auto with zarith; intros HH5.";
 
2959
  pp "   apply Zmult_le_reg_r with (2 ^ 1); auto with zarith.";
 
2960
  pp "   rewrite <- (fun x y z => Zpower_exp x (y - z)); auto with zarith.";
 
2961
  pp "   assert (tmp: forall x, x - 1 + 1 = x); [intros; ring | rewrite tmp; clear tmp].";
 
2962
  pp "   apply Zle_trans with (2 := Zlt_le_weak _ _ HH2).";
 
2963
  pp "   apply Zmult_le_compat_l; auto with zarith.";
 
2964
  pp "   rewrite Zpower_1_r; auto with zarith.";
 
2965
  pp "   apply Zpower_le_monotone; auto with zarith.";
 
2966
  pp "   split; auto with zarith. ";
 
2967
  pp "   case (Zle_or_lt (Zpos (digits x)) [head0 x]); auto with zarith; intros HH6.";
 
2968
  pp "   absurd (2 ^ Zpos (digits x) <= 2 ^ [head0 x] * [x]); auto with zarith.";
 
2969
  pp "   rewrite <- HH5; rewrite Zmult_1_r.";
 
2970
  pp "   apply Zpower_le_monotone; auto with zarith.";
 
2971
  pp " rewrite (Zmult_comm 2).";
 
2972
  pp " rewrite Zpower_mult; auto with zarith.";
 
2973
  pp " rewrite Zpower_2.";
 
2974
  pp " apply Zlt_le_trans with (2 := HH3).";
 
2975
  pp " rewrite <- Zmult_assoc.";
 
2976
  pp " replace (Zpos (xO (digits x)) - 1) with";
 
2977
  pp "   ((Zpos (digits x) - 1) + (Zpos (digits x))).";
 
2978
  pp " rewrite Zpower_exp; auto with zarith.";
 
2979
  pp " apply Zmult_lt_compat2; auto with zarith.";
 
2980
  pp " split; auto with zarith.";
 
2981
  pp " apply Zmult_lt_0_compat; auto with zarith.";
 
2982
  pp " rewrite Zpos_xO; ring.";
 
2983
  pp " apply Zlt_le_weak; auto.";
 
2984
  pp " repeat rewrite spec_head00; auto.";
 
2985
  pp " rewrite spec_double_size_digits.";
 
2986
  pp " rewrite Zpos_xO; auto with zarith.";
 
2987
  pp " rewrite spec_double_size; auto.";
 
2988
  pp " Qed.";
 
2989
  pr "";
 
2990
 
 
2991
  pr " Theorem spec_double_size_head0_pos: ";
 
2992
  pr "   forall x, 0 < [head0 (double_size x)].";
 
2993
  pa " Admitted.";
 
2994
  pp " Proof.";
 
2995
  pp " intros x.";
 
2996
  pp " assert (F: 0 < Zpos (digits x)).";
 
2997
  pp "  red; auto.";
 
2998
  pp " case (Zle_lt_or_eq _ _ (spec_pos (head0 (double_size x)))); auto; intros F0.";
 
2999
  pp " case (Zle_lt_or_eq _ _ (spec_pos (head0 x))); intros F1.";
 
3000
  pp "   apply Zlt_le_trans with (2 := (spec_double_size_head0 x)); auto with zarith.";
 
3001
  pp " case (Zle_lt_or_eq _ _ (spec_pos x)); intros F3.";
 
3002
  pp " generalize F3; rewrite <- (spec_double_size x); intros F4.";
 
3003
  pp " absurd (2 ^ (Zpos (xO (digits x)) - 1) < 2 ^ (Zpos (digits x))).";
 
3004
  pp "   apply Zle_not_lt.";
 
3005
  pp "   apply Zpower_le_monotone; auto with zarith.";
 
3006
  pp "   split; auto with zarith.";
 
3007
  pp "   rewrite Zpos_xO; auto with zarith.";
 
3008
  pp " case (spec_head0 x F3).";
 
3009
  pp " rewrite <- F1; rewrite Zpower_0_r; rewrite Zmult_1_l; intros _ HH.";
 
3010
  pp " apply Zle_lt_trans with (2 := HH).";
 
3011
  pp " case (spec_head0 _ F4).";
 
3012
  pp " rewrite (spec_double_size x); rewrite (spec_double_size_digits x).";
 
3013
  pp " rewrite <- F0; rewrite Zpower_0_r; rewrite Zmult_1_l; auto.";
 
3014
  pp " generalize F1; rewrite (spec_head00 _ (sym_equal F3)); auto with zarith.";
 
3015
  pp " Qed.";
 
3016
  pr "";
 
3017
 
 
3018
 
 
3019
  (* Safe shiftl *)
 
3020
 
 
3021
  pr " Definition safe_shiftl_aux_body cont n x :=";
 
3022
  pr "   match compare n (head0 x)  with";
 
3023
  pr "      Gt => cont n (double_size x)";
 
3024
  pr "   |  _ => shiftl n x";
 
3025
  pr "   end.";
 
3026
  pr "";
 
3027
 
 
3028
  pr " Theorem spec_safe_shift_aux_body: forall n p x cont,";
 
3029
  pr "       2^ Zpos p  <=  [head0 x]  ->";
 
3030
  pr "      (forall x, 2 ^ (Zpos p + 1) <= [head0 x]->";
 
3031
  pr "         [cont n x] = [x] * 2 ^ [n]) ->";
 
3032
  pr "      [safe_shiftl_aux_body cont n x] = [x] * 2 ^ [n].";
 
3033
  pa " Admitted.";  
 
3034
  pp " Proof.";
 
3035
  pp " intros n p x cont H1 H2; unfold safe_shiftl_aux_body.";
 
3036
  pp " generalize (spec_compare n (head0 x)); case compare; intros H.";
 
3037
  pp "  apply spec_shiftl; auto with zarith.";
 
3038
  pp "  apply spec_shiftl; auto with zarith.";
 
3039
  pp " rewrite H2.";
 
3040
  pp " rewrite spec_double_size; auto.";
 
3041
  pp " rewrite Zplus_comm; rewrite Zpower_exp; auto with zarith.";
 
3042
  pp " apply Zle_trans with (2 := spec_double_size_head0 x).";
 
3043
  pp " rewrite Zpower_1_r; apply Zmult_le_compat_l; auto with zarith.";
 
3044
  pp " Qed.";
 
3045
  pr "";
 
3046
 
 
3047
  pr " Fixpoint safe_shiftl_aux p cont n x  {struct p} :=";
 
3048
  pr "   safe_shiftl_aux_body ";
 
3049
  pr "       (fun n x => match p with";
 
3050
  pr "        | xH => cont n x";
 
3051
  pr "        | xO p => safe_shiftl_aux p (safe_shiftl_aux p cont) n x";
 
3052
  pr "        | xI p => safe_shiftl_aux p (safe_shiftl_aux p cont) n x";
 
3053
  pr "        end) n x.";
 
3054
  pr "";
 
3055
 
 
3056
  pr " Theorem spec_safe_shift_aux: forall p q n x cont,";
 
3057
  pr "    2 ^ (Zpos q) <= [head0 x] ->";
 
3058
  pr "      (forall x, 2 ^ (Zpos p + Zpos q) <= [head0 x] ->";
 
3059
  pr "         [cont n x] = [x] * 2 ^ [n]) ->      ";
 
3060
  pr "      [safe_shiftl_aux p cont n x] = [x] * 2 ^ [n].";
 
3061
  pa " Admitted.";
 
3062
  pp " Proof.";
 
3063
  pp " intros p; elim p; unfold safe_shiftl_aux; fold safe_shiftl_aux; clear p.";
 
3064
  pp " intros p Hrec q n x cont H1 H2.";
 
3065
  pp " apply spec_safe_shift_aux_body with (q); auto.";
 
3066
  pp " intros x1 H3; apply Hrec with (q + 1)%spositive; auto." "%";
 
3067
  pp " intros x2 H4; apply Hrec with (p + q + 1)%spositive; auto." "%";
 
3068
  pp " rewrite <- Pplus_assoc.";
 
3069
  pp " rewrite Zpos_plus_distr; auto.";
 
3070
  pp " intros x3 H5; apply H2.";
 
3071
  pp " rewrite Zpos_xI.";
 
3072
  pp " replace (2 * Zpos p + 1 + Zpos q) with (Zpos p + Zpos (p + q + 1));";
 
3073
  pp "   auto.";
 
3074
  pp " repeat rewrite Zpos_plus_distr; ring.";
 
3075
  pp " intros p Hrec q n x cont H1 H2.";
 
3076
  pp " apply spec_safe_shift_aux_body with (q); auto.";
 
3077
  pp " intros x1 H3; apply Hrec with (q); auto.";
 
3078
  pp " apply Zle_trans with (2 := H3); auto with zarith.";
 
3079
  pp " apply Zpower_le_monotone; auto with zarith.";
 
3080
  pp " intros x2 H4; apply Hrec with (p + q)%spositive; auto." "%";
 
3081
  pp " intros x3 H5; apply H2.";
 
3082
  pp " rewrite (Zpos_xO p).";
 
3083
  pp " replace (2 * Zpos p + Zpos q) with (Zpos p + Zpos (p + q));";
 
3084
  pp "   auto.";
 
3085
  pp " repeat rewrite Zpos_plus_distr; ring.";
 
3086
  pp " intros q n x cont H1 H2.";
 
3087
  pp " apply spec_safe_shift_aux_body with (q); auto.";
 
3088
  pp " rewrite Zplus_comm; auto.";
 
3089
  pp " Qed.";
 
3090
  pr "";
 
3091
 
 
3092
 
 
3093
  pr " Definition safe_shiftl n x :=";
 
3094
  pr "  safe_shiftl_aux_body";
 
3095
  pr "   (safe_shiftl_aux_body";
 
3096
  pr "    (safe_shiftl_aux (digits n) shiftl)) n x.";
 
3097
  pr "";
 
3098
 
 
3099
  pr " Theorem spec_safe_shift: forall n x,";
 
3100
  pr "   [safe_shiftl n x] = [x] * 2 ^ [n].";
 
3101
  pa " Admitted.";
 
3102
  pp " Proof.";
 
3103
  pp " intros n x; unfold safe_shiftl, safe_shiftl_aux_body.";
 
3104
  pp " generalize (spec_compare n (head0 x)); case compare; intros H.";
 
3105
  pp "  apply spec_shiftl; auto with zarith.";
 
3106
  pp "  apply spec_shiftl; auto with zarith.";
 
3107
  pp " rewrite <- (spec_double_size x).";
 
3108
  pp " generalize (spec_compare n (head0 (double_size x))); case compare; intros H1.";
 
3109
  pp "  apply spec_shiftl; auto with zarith.";
 
3110
  pp "  apply spec_shiftl; auto with zarith.";
 
3111
  pp " rewrite <- (spec_double_size (double_size x)).";
 
3112
  pp " apply spec_safe_shift_aux with 1%spositive." "%";
 
3113
  pp " apply Zle_trans with (2 := spec_double_size_head0 (double_size x)).";
 
3114
  pp " replace (2 ^ 1) with (2 * 1).";
 
3115
  pp " apply Zmult_le_compat_l; auto with zarith.";
 
3116
  pp " generalize (spec_double_size_head0_pos x); auto with zarith.";
 
3117
  pp " rewrite Zpower_1_r; ring.";
 
3118
  pp " intros x1 H2; apply spec_shiftl.";
 
3119
  pp " apply Zle_trans with (2 := H2).";
 
3120
  pp " apply Zle_trans with (2 ^ Zpos (digits n)); auto with zarith.";
 
3121
  pp " case (spec_digits n); auto with zarith.";
 
3122
  pp " apply Zpower_le_monotone; auto with zarith.";
 
3123
  pp " Qed.";
 
3124
  pr "";
 
3125
 
 
3126
  (* even *)
 
3127
  pr " Definition is_even x :=";
 
3128
  pr "  match x with";
 
3129
  for i = 0 to size do
 
3130
    pr "  | %s%i wx => w%i_op.(znz_is_even) wx" c i i
 
3131
  done;
 
3132
  pr "  | %sn n wx => (make_op n).(znz_is_even) wx" c;
 
3133
  pr "  end.";
 
3134
  pr "";
 
3135
 
 
3136
 
 
3137
  pr " Theorem spec_is_even: forall x,";
 
3138
  pr "   if is_even x then [x] mod 2 = 0 else [x] mod 2 = 1.";
 
3139
  pa " Admitted.";
 
3140
  pp " Proof.";
 
3141
  pp " intros x; case x; unfold is_even, to_Z; clear x.";
 
3142
  for i = 0 to size do
 
3143
    pp "   intros x; exact (spec_is_even w%i_spec x)." i;
 
3144
  done;
 
3145
  pp "  intros n x; exact (spec_is_even (wn_spec n) x).";
 
3146
  pp " Qed.";
 
3147
  pr "";
 
3148
 
 
3149
  pr " Theorem spec_0: [zero] = 0.";
 
3150
  pa " Admitted.";
 
3151
  pp " Proof.";
 
3152
  pp " exact (spec_0 w0_spec).";
 
3153
  pp " Qed.";
 
3154
  pr "";
 
3155
 
 
3156
  pr " Theorem spec_1: [one] = 1.";
 
3157
  pa " Admitted.";
 
3158
  pp " Proof.";
 
3159
  pp " exact (spec_1 w0_spec).";
 
3160
  pp " Qed.";
 
3161
  pr "";
 
3162
 
 
3163
  pr "End Make.";
 
3164
  pr "";
 
3165