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

« back to all changes in this revision

Viewing changes to theories/Numbers/Natural/BigN/Nbasic.v

  • 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: Nbasic.v 10964 2008-05-22 11:08:13Z letouzey $ i*)
 
12
 
 
13
Require Import ZArith.
 
14
Require Import BigNumPrelude.
 
15
Require Import Max.
 
16
Require Import DoubleType.
 
17
Require Import DoubleBase.
 
18
Require Import CyclicAxioms.
 
19
Require Import DoubleCyclic.
 
20
 
 
21
(* To compute the necessary height *)
 
22
 
 
23
Fixpoint plength (p: positive) : positive :=
 
24
  match p with 
 
25
    xH => xH
 
26
  | xO p1 => Psucc (plength p1)
 
27
  | xI p1 => Psucc (plength p1)
 
28
  end.
 
29
 
 
30
Theorem plength_correct: forall p, (Zpos p < 2 ^ Zpos (plength p))%Z.
 
31
assert (F: (forall p, 2 ^ (Zpos (Psucc p)) = 2 * 2 ^ Zpos p)%Z).
 
32
intros p; replace (Zpos (Psucc p)) with (1 + Zpos p)%Z.
 
33
rewrite Zpower_exp; auto with zarith.
 
34
rewrite Zpos_succ_morphism; unfold Zsucc; auto with zarith.
 
35
intros p; elim p; simpl plength; auto.
 
36
intros p1 Hp1; rewrite F; repeat rewrite Zpos_xI.
 
37
assert (tmp: (forall p, 2 * p = p + p)%Z); 
 
38
  try repeat rewrite tmp; auto with zarith.
 
39
intros p1 Hp1; rewrite F; rewrite (Zpos_xO p1).
 
40
assert (tmp: (forall p, 2 * p = p + p)%Z); 
 
41
  try repeat rewrite tmp; auto with zarith.
 
42
rewrite Zpower_1_r; auto with zarith.
 
43
Qed.
 
44
 
 
45
Theorem plength_pred_correct: forall p, (Zpos p <= 2 ^ Zpos (plength (Ppred p)))%Z.
 
46
intros p; case (Psucc_pred p); intros H1.
 
47
subst; simpl plength.
 
48
rewrite Zpower_1_r; auto with zarith.
 
49
pattern p at 1; rewrite <- H1.
 
50
rewrite Zpos_succ_morphism; unfold Zsucc; auto with zarith.
 
51
generalize (plength_correct (Ppred p)); auto with zarith.
 
52
Qed.
 
53
 
 
54
Definition Pdiv p q :=
 
55
  match Zdiv (Zpos p) (Zpos q) with
 
56
    Zpos q1 => match (Zpos p) - (Zpos q) * (Zpos q1) with
 
57
                 Z0 => q1
 
58
               | _ => (Psucc q1)
 
59
               end
 
60
  |  _ => xH
 
61
  end.
 
62
 
 
63
Theorem Pdiv_le: forall p q,
 
64
  Zpos p <= Zpos q * Zpos (Pdiv p q).
 
65
intros p q.
 
66
unfold Pdiv.
 
67
assert (H1: Zpos q > 0); auto with zarith.
 
68
assert (H1b: Zpos p >= 0); auto with zarith.
 
69
generalize (Z_div_ge0 (Zpos p) (Zpos q) H1 H1b).
 
70
generalize (Z_div_mod_eq (Zpos p) (Zpos q) H1); case Zdiv.
 
71
  intros HH _; rewrite HH; rewrite Zmult_0_r; rewrite Zmult_1_r; simpl.
 
72
case (Z_mod_lt (Zpos p) (Zpos q) H1); auto with zarith.
 
73
intros q1 H2.
 
74
replace (Zpos p - Zpos q * Zpos q1) with (Zpos p mod Zpos q).
 
75
  2: pattern (Zpos p) at 2; rewrite H2; auto with zarith.
 
76
generalize H2 (Z_mod_lt (Zpos p) (Zpos q) H1); clear H2; 
 
77
  case Zmod.
 
78
  intros HH _; rewrite HH; auto with zarith.
 
79
  intros r1 HH (_,HH1); rewrite HH; rewrite Zpos_succ_morphism.
 
80
  unfold Zsucc; rewrite Zmult_plus_distr_r; auto with zarith.
 
81
  intros r1 _ (HH,_); case HH; auto.
 
82
intros q1 HH; rewrite HH.
 
83
unfold Zge; simpl Zcompare; intros HH1; case HH1; auto.
 
84
Qed.
 
85
 
 
86
Definition is_one p := match p with xH => true | _ => false end.
 
87
 
 
88
Theorem is_one_one: forall p, is_one p = true -> p = xH.
 
89
intros p; case p; auto; intros p1 H1; discriminate H1.
 
90
Qed.
 
91
 
 
92
Definition get_height digits p :=
 
93
  let r := Pdiv p digits in
 
94
   if is_one r then xH else Psucc (plength (Ppred r)).
 
95
 
 
96
Theorem get_height_correct:
 
97
  forall digits N,
 
98
   Zpos N <= Zpos digits * (2 ^ (Zpos (get_height digits N) -1)).
 
99
intros digits N.
 
100
unfold get_height.
 
101
assert (H1 := Pdiv_le N digits).
 
102
case_eq (is_one (Pdiv N digits)); intros H2.
 
103
rewrite (is_one_one _ H2) in H1.
 
104
rewrite Zmult_1_r in H1.
 
105
change (2^(1-1))%Z with 1; rewrite Zmult_1_r; auto.
 
106
clear H2.
 
107
apply Zle_trans with (1 := H1).
 
108
apply Zmult_le_compat_l; auto with zarith.
 
109
rewrite Zpos_succ_morphism; unfold Zsucc.
 
110
rewrite Zplus_comm; rewrite Zminus_plus.
 
111
apply plength_pred_correct.
 
112
Qed.
 
113
 
 
114
Definition zn2z_word_comm : forall w n, zn2z (word w n) = word (zn2z w) n.
 
115
 fix zn2z_word_comm 2.
 
116
 intros w n; case n.
 
117
  reflexivity.
 
118
  intros n0;simpl.
 
119
  case (zn2z_word_comm w n0).
 
120
  reflexivity.
 
121
Defined.
 
122
 
 
123
Fixpoint extend (n:nat) {struct n} : forall w:Type, zn2z w -> word w (S n) :=
 
124
 match n return forall w:Type, zn2z w -> word w (S n) with 
 
125
 | O => fun w x => x
 
126
 | S m => 
 
127
   let aux := extend m in
 
128
   fun w x => WW W0 (aux w x)
 
129
 end.
 
130
 
 
131
Section ExtendMax.
 
132
 
 
133
Open Scope nat_scope.
 
134
 
 
135
Fixpoint plusnS (n m: nat) {struct n} : (n + S m = S (n + m))%nat :=
 
136
  match n return  (n + S m = S (n + m))%nat with
 
137
  | 0 => refl_equal (S m)
 
138
  | S n1 =>
 
139
      let v := S (S n1 + m) in
 
140
      eq_ind_r (fun n => S n = v) (refl_equal v) (plusnS n1 m)
 
141
  end.
 
142
 
 
143
Fixpoint plusn0 n : n + 0 = n :=
 
144
  match n return (n + 0 = n) with
 
145
  | 0 => refl_equal 0
 
146
  | S n1 =>
 
147
      let v := S n1 in
 
148
      eq_ind_r (fun n : nat => S n = v) (refl_equal v) (plusn0 n1)
 
149
  end.
 
150
 
 
151
 Fixpoint diff (m n: nat) {struct m}: nat * nat :=
 
152
   match m, n with
 
153
     O, n => (O, n)
 
154
   | m, O => (m, O)
 
155
   | S m1, S n1 => diff m1 n1
 
156
   end.
 
157
 
 
158
Fixpoint diff_l (m n : nat) {struct m} : fst (diff m n) + n = max m n :=
 
159
  match m return fst (diff m n) + n = max m n with
 
160
  | 0 =>
 
161
      match n return (n = max 0 n) with
 
162
      | 0 => refl_equal _
 
163
      | S n0 => refl_equal _
 
164
      end
 
165
  | S m1 =>
 
166
      match n return (fst (diff (S m1) n) + n = max (S m1) n)
 
167
      with
 
168
      | 0 => plusn0 _
 
169
      | S n1 =>
 
170
          let v := fst (diff m1 n1) + n1 in
 
171
          let v1 := fst (diff m1 n1) + S n1 in
 
172
          eq_ind v (fun n => v1 = S n) 
 
173
            (eq_ind v1 (fun n => v1 = n) (refl_equal v1) (S v) (plusnS _ _))
 
174
            _ (diff_l _ _)
 
175
      end
 
176
  end.
 
177
 
 
178
Fixpoint diff_r (m n: nat) {struct m}: snd (diff m n) + m = max m n :=
 
179
  match m return (snd (diff m n) + m = max m n) with
 
180
  | 0 =>
 
181
      match n return (snd (diff 0 n) + 0 = max 0 n) with
 
182
      | 0 => refl_equal _
 
183
      | S _ => plusn0 _
 
184
      end
 
185
  | S m => 
 
186
      match n return (snd (diff (S m) n) + S m = max (S m) n) with
 
187
      | 0 => refl_equal (snd (diff (S m) 0) + S m)
 
188
      | S n1 =>
 
189
          let v := S (max m n1) in
 
190
          eq_ind_r (fun n => n = v)
 
191
            (eq_ind_r (fun n => S n = v)
 
192
               (refl_equal v) (diff_r _ _)) (plusnS _ _)
 
193
      end
 
194
  end.
 
195
 
 
196
 Variable w: Type.
 
197
 
 
198
 Definition castm (m n: nat) (H: m = n) (x: word w (S m)):
 
199
     (word w (S n)) :=
 
200
 match H in (_ = y) return (word w (S y)) with
 
201
 | refl_equal => x
 
202
 end.
 
203
 
 
204
Variable m: nat.
 
205
Variable v: (word w (S m)).
 
206
 
 
207
Fixpoint extend_tr (n : nat) {struct n}: (word w (S (n + m))) :=
 
208
  match n  return (word w (S (n + m))) with
 
209
  | O => v
 
210
  | S n1 => WW W0 (extend_tr n1)
 
211
  end.
 
212
 
 
213
End ExtendMax.
 
214
 
 
215
Implicit Arguments extend_tr[w m].
 
216
Implicit Arguments castm[w m n].
 
217
 
 
218
 
 
219
 
 
220
Section Reduce.
 
221
 
 
222
 Variable w : Type.
 
223
 Variable nT : Type.
 
224
 Variable N0 : nT.
 
225
 Variable eq0 : w -> bool.
 
226
 Variable reduce_n : w -> nT.
 
227
 Variable zn2z_to_Nt : zn2z w -> nT.
 
228
 
 
229
 Definition reduce_n1 (x:zn2z w) :=
 
230
  match x with
 
231
  | W0 => N0
 
232
  | WW xh xl =>
 
233
    if eq0 xh then reduce_n xl
 
234
    else zn2z_to_Nt x
 
235
  end.
 
236
 
 
237
End Reduce.
 
238
 
 
239
Section ReduceRec.
 
240
 
 
241
 Variable w : Type.
 
242
 Variable nT : Type.
 
243
 Variable N0 : nT.
 
244
 Variable reduce_1n : zn2z w -> nT.
 
245
 Variable c : forall n, word w (S n) -> nT.
 
246
 
 
247
 Fixpoint reduce_n (n:nat) : word w (S n) -> nT :=
 
248
  match n return word w (S n) -> nT with
 
249
  | O => reduce_1n
 
250
  | S m => fun x =>
 
251
    match x with
 
252
    | W0 => N0
 
253
    | WW xh xl =>
 
254
      match xh with
 
255
      | W0 => @reduce_n m xl
 
256
      | _ => @c (S m) x 
 
257
      end
 
258
    end 
 
259
  end.
 
260
 
 
261
End ReduceRec.
 
262
 
 
263
Definition opp_compare cmp :=
 
264
  match cmp with
 
265
  | Lt => Gt
 
266
  | Eq => Eq
 
267
  | Gt => Lt
 
268
  end.
 
269
 
 
270
Section CompareRec.
 
271
 
 
272
 Variable wm w : Type.
 
273
 Variable w_0 : w.
 
274
 Variable compare : w -> w -> comparison.
 
275
 Variable compare0_m : wm -> comparison.
 
276
 Variable compare_m : wm -> w -> comparison.
 
277
 
 
278
 Fixpoint compare0_mn (n:nat) : word wm n -> comparison :=
 
279
  match n return word wm n -> comparison with 
 
280
  | O => compare0_m 
 
281
  | S m => fun x =>
 
282
    match x with
 
283
    | W0 => Eq
 
284
    | WW xh xl => 
 
285
      match compare0_mn m xh with
 
286
      | Eq => compare0_mn m xl 
 
287
      | r  => Lt
 
288
      end
 
289
    end
 
290
  end.
 
291
 
 
292
 Variable wm_base: positive.
 
293
 Variable wm_to_Z: wm -> Z.
 
294
 Variable w_to_Z: w -> Z.
 
295
 Variable w_to_Z_0: w_to_Z w_0 = 0.
 
296
 Variable spec_compare0_m: forall x,
 
297
    match compare0_m x with
 
298
      Eq => w_to_Z w_0 = wm_to_Z x
 
299
    | Lt => w_to_Z w_0 < wm_to_Z x 
 
300
    | Gt => w_to_Z w_0 > wm_to_Z x
 
301
    end.
 
302
 Variable wm_to_Z_pos: forall x, 0 <= wm_to_Z x < base wm_base.
 
303
 
 
304
 Let double_to_Z := double_to_Z wm_base wm_to_Z.
 
305
 Let double_wB := double_wB wm_base.
 
306
 
 
307
 Lemma base_xO: forall n, base (xO n) = (base n)^2.
 
308
 Proof.
 
309
 intros n1; unfold base.
 
310
 rewrite (Zpos_xO n1); rewrite Zmult_comm; rewrite Zpower_mult; auto with zarith.
 
311
 Qed.
 
312
 
 
313
 Let double_to_Z_pos: forall n x, 0 <= double_to_Z n x < double_wB n :=
 
314
   (spec_double_to_Z wm_base wm_to_Z wm_to_Z_pos).
 
315
 
 
316
 
 
317
 Lemma spec_compare0_mn: forall n x,
 
318
    match compare0_mn n x with
 
319
      Eq => 0 = double_to_Z n x
 
320
    | Lt => 0 < double_to_Z n x
 
321
    | Gt => 0 > double_to_Z n x
 
322
    end.
 
323
  Proof.
 
324
  intros n; elim n; clear n; auto.
 
325
  intros x; generalize (spec_compare0_m x); rewrite w_to_Z_0; auto.
 
326
  intros n Hrec x; case x; unfold compare0_mn; fold compare0_mn; auto.
 
327
  intros xh xl.
 
328
  generalize (Hrec xh); case compare0_mn; auto.
 
329
  generalize (Hrec xl); case compare0_mn; auto.
 
330
  simpl double_to_Z; intros H1 H2; rewrite H1; rewrite <- H2; auto.
 
331
  simpl double_to_Z; intros H1 H2; rewrite <- H2; auto.
 
332
  case (double_to_Z_pos n xl); auto with zarith.
 
333
  intros H1; simpl double_to_Z.
 
334
  set (u := DoubleBase.double_wB wm_base n).
 
335
  case (double_to_Z_pos n xl); intros H2 H3.
 
336
  assert (0 < u); auto with zarith.
 
337
  unfold u, DoubleBase.double_wB, base; auto with zarith.
 
338
  change 0 with (0 + 0); apply Zplus_lt_le_compat; auto with zarith.
 
339
  apply Zmult_lt_0_compat; auto with zarith.
 
340
  case (double_to_Z_pos n xh); auto with zarith.
 
341
  Qed.
 
342
 
 
343
 Fixpoint compare_mn_1 (n:nat) : word wm n -> w -> comparison :=
 
344
  match n return word wm n -> w -> comparison with 
 
345
  | O => compare_m 
 
346
  | S m => fun x y => 
 
347
    match x with
 
348
    | W0 => compare w_0 y
 
349
    | WW xh xl => 
 
350
      match compare0_mn m xh with
 
351
      | Eq => compare_mn_1 m xl y 
 
352
      | r  => Gt
 
353
      end
 
354
    end
 
355
  end.
 
356
 
 
357
 Variable spec_compare: forall x y,
 
358
   match compare x y with
 
359
     Eq => w_to_Z x = w_to_Z y
 
360
   | Lt => w_to_Z x < w_to_Z y
 
361
   | Gt => w_to_Z x > w_to_Z y
 
362
   end.
 
363
 Variable spec_compare_m: forall x y,
 
364
   match compare_m x y with
 
365
     Eq => wm_to_Z x = w_to_Z y
 
366
   | Lt => wm_to_Z x < w_to_Z y
 
367
   | Gt => wm_to_Z x > w_to_Z y
 
368
   end.
 
369
 Variable wm_base_lt: forall x, 
 
370
   0 <= w_to_Z x < base (wm_base).
 
371
 
 
372
 Let double_wB_lt: forall n x,
 
373
   0 <= w_to_Z x < (double_wB n).
 
374
 Proof.
 
375
 intros n x; elim n; simpl; auto; clear n.
 
376
 intros n (H0, H); split; auto.
 
377
 apply Zlt_le_trans with (1:= H).
 
378
 unfold double_wB, DoubleBase.double_wB; simpl.
 
379
 rewrite base_xO.
 
380
 set (u := base (double_digits wm_base n)).
 
381
 assert (0 < u).
 
382
  unfold u, base; auto with zarith.
 
383
 replace (u^2) with (u * u); simpl; auto with zarith.
 
384
 apply Zle_trans with (1 * u); auto with zarith.
 
385
 unfold Zpower_pos; simpl; ring.
 
386
 Qed.
 
387
 
 
388
 
 
389
 Lemma spec_compare_mn_1: forall n x y,
 
390
   match compare_mn_1 n x y with
 
391
     Eq => double_to_Z n x = w_to_Z y
 
392
   | Lt => double_to_Z n x < w_to_Z y
 
393
   | Gt => double_to_Z n x > w_to_Z y
 
394
   end.
 
395
 Proof.
 
396
 intros n; elim n; simpl; auto; clear n.
 
397
 intros n Hrec x; case x; clear x; auto.
 
398
 intros y; generalize (spec_compare w_0 y); rewrite w_to_Z_0; case compare; auto.
 
399
 intros xh xl y; simpl; generalize (spec_compare0_mn n xh); case compare0_mn; intros H1b.
 
400
 rewrite <- H1b; rewrite Zmult_0_l; rewrite Zplus_0_l; auto.
 
401
 apply Hrec.
 
402
 apply Zlt_gt.
 
403
 case (double_wB_lt n y); intros _ H0.
 
404
 apply Zlt_le_trans with (1:= H0).
 
405
 fold double_wB.
 
406
 case (double_to_Z_pos n xl); intros H1 H2.
 
407
 apply Zle_trans with (double_to_Z n xh * double_wB n); auto with zarith.
 
408
 apply Zle_trans with (1 * double_wB n); auto with zarith.
 
409
 case (double_to_Z_pos n xh); auto with zarith.
 
410
 Qed.
 
411
 
 
412
End CompareRec.
 
413
 
 
414
 
 
415
Section AddS.
 
416
 
 
417
 Variable w wm : Type.
 
418
 Variable incr : wm -> carry wm.
 
419
 Variable addr : w -> wm -> carry wm.
 
420
 Variable injr : w -> zn2z wm.
 
421
 
 
422
 Variable w_0 u: w.
 
423
 Fixpoint injs  (n:nat): word w (S n) :=
 
424
  match n return (word w (S n)) with
 
425
    O => WW w_0 u
 
426
  | S n1 => (WW W0 (injs n1))
 
427
  end.
 
428
 
 
429
 Definition adds x y :=
 
430
   match y with
 
431
    W0 => C0 (injr x)
 
432
  | WW hy ly => match addr x ly with
 
433
                  C0 z => C0 (WW hy z)
 
434
                | C1 z => match incr hy with
 
435
                            C0 z1 => C0 (WW z1 z)
 
436
                          | C1 z1 => C1 (WW z1 z)
 
437
                          end  
 
438
                 end
 
439
   end.
 
440
 
 
441
End AddS.
 
442
 
 
443
 
 
444
 Lemma spec_opp: forall u x y,
 
445
  match u with
 
446
  | Eq => y = x
 
447
  | Lt => y < x
 
448
  | Gt => y > x
 
449
  end ->
 
450
  match opp_compare u with
 
451
  | Eq => x = y
 
452
  | Lt => x < y
 
453
  | Gt => x > y
 
454
  end.
 
455
 Proof.
 
456
 intros u x y; case u; simpl; auto with zarith.
 
457
 Qed.
 
458
 
 
459
 Fixpoint length_pos x :=
 
460
  match x with xH => O | xO x1 => S (length_pos x1) | xI x1 => S (length_pos x1) end.
 
461
 
 
462
 Theorem length_pos_lt: forall x y,
 
463
   (length_pos x < length_pos y)%nat -> Zpos x < Zpos y.
 
464
 Proof.
 
465
 intros x; elim x; clear x; [intros x1 Hrec | intros x1 Hrec | idtac];
 
466
   intros y; case y; clear y; intros y1 H || intros H; simpl length_pos; 
 
467
   try (rewrite (Zpos_xI x1) || rewrite (Zpos_xO x1));
 
468
   try (rewrite (Zpos_xI y1) || rewrite (Zpos_xO y1));
 
469
   try (inversion H; fail);
 
470
   try (assert (Zpos x1 < Zpos y1); [apply Hrec; apply lt_S_n | idtac]; auto with zarith);
 
471
   assert (0 < Zpos y1); auto with zarith; red; auto.
 
472
 Qed.
 
473
 
 
474
 Theorem cancel_app: forall A B (f g: A -> B) x, f = g -> f x = g x.
 
475
 Proof.
 
476
 intros A B f g x H; rewrite H; auto.
 
477
 Qed.
 
478
 
 
479
 
 
480
 Section SimplOp.
 
481
 
 
482
 Variable w: Type.
 
483
 
 
484
 Theorem digits_zop: forall w (x: znz_op w),
 
485
  znz_digits (mk_zn2z_op x) = xO (znz_digits x).
 
486
 intros ww x; auto.
 
487
 Qed.
 
488
 
 
489
 Theorem digits_kzop: forall w (x: znz_op w),
 
490
  znz_digits (mk_zn2z_op_karatsuba x) = xO (znz_digits x).
 
491
 intros ww x; auto.
 
492
 Qed.
 
493
 
 
494
 Theorem make_zop: forall w (x: znz_op w),
 
495
  znz_to_Z (mk_zn2z_op x) = 
 
496
    fun z => match z with 
 
497
                W0 => 0
 
498
             | WW xh xl => znz_to_Z x xh * base (znz_digits x) 
 
499
                                + znz_to_Z x xl
 
500
             end.
 
501
 intros ww x; auto.
 
502
 Qed.
 
503
 
 
504
 Theorem make_kzop: forall w (x: znz_op w),
 
505
  znz_to_Z (mk_zn2z_op_karatsuba x) = 
 
506
    fun z => match z with 
 
507
                W0 => 0
 
508
             | WW xh xl => znz_to_Z x xh * base (znz_digits x) 
 
509
                                + znz_to_Z x xl
 
510
             end.
 
511
 intros ww x; auto.
 
512
 Qed.
 
513
 
 
514
 End SimplOp.