1(* ========================================================================= *)
2(* Create "fieldTheory" setting up the theory of field curves                *)
3(* ========================================================================= *)
4
5(* ------------------------------------------------------------------------- *)
6(* Load and open relevant theories.                                          *)
7(* (Comment out "load"s and "quietdec"s for compilation.)                    *)
8(* ------------------------------------------------------------------------- *)
9(*
10val () = loadPath := [] @ !loadPath;
11val () = app load
12  ["Algebra",
13   "bossLib", "metisLib", "res_quanTools",
14   "optionTheory", "listTheory",
15   "arithmeticTheory", "dividesTheory", "gcdTheory",
16   "pred_setTheory", "pred_setSyntax",
17   "primalityTools"];
18val () = quietdec := true;
19*)
20
21open HolKernel Parse boolLib bossLib metisLib res_quanTools;
22open optionTheory listTheory arithmeticTheory dividesTheory gcdTheory;
23open pred_setTheory;
24open primalityTools;
25open groupTheory groupTools;
26
27(*
28val () = quietdec := false;
29*)
30
31(* ------------------------------------------------------------------------- *)
32(* Start a new theory called "field".                                        *)
33(* ------------------------------------------------------------------------- *)
34
35val _ = new_theory "field";
36
37val ERR = mk_HOL_ERR "field";
38val Bug = mlibUseful.Bug;
39val Error = ERR "";
40
41val Bug = fn s => (print ("\n\nBUG: " ^ s ^ "\n\n"); Bug s);
42
43(* ------------------------------------------------------------------------- *)
44(* Sort out the parser.                                                      *)
45(* ------------------------------------------------------------------------- *)
46
47val () = Parse.add_infix ("/", 600, HOLgrammars.LEFT);
48
49(* ------------------------------------------------------------------------- *)
50(* Show oracle tags.                                                         *)
51(* ------------------------------------------------------------------------- *)
52
53val () = show_tags := true;
54
55(* ------------------------------------------------------------------------- *)
56(* The subtype context.                                                      *)
57(* ------------------------------------------------------------------------- *)
58
59val context = group_context;
60val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
61
62(* ------------------------------------------------------------------------- *)
63(* Helper proof tools.                                                       *)
64(* ------------------------------------------------------------------------- *)
65
66infixr 0 <<
67infixr 1 ++ || THENC ORELSEC ORELSER ## orelse_bdd_conv
68infix 2 >>
69
70val op ++ = op THEN;
71val op << = op THENL;
72val op >> = op THEN1;
73val op || = op ORELSE;
74val Know = Q_TAC KNOW_TAC;
75val Suff = Q_TAC SUFF_TAC;
76val REVERSE = Tactical.REVERSE;
77val lemma = Tactical.prove;
78
79val cond_rewr_conv = subtypeTools.cond_rewr_conv;
80
81val cond_rewrs_conv = subtypeTools.cond_rewrs_conv;
82
83val named_conv_to_simpset_conv = subtypeTools.named_conv_to_simpset_conv;
84
85val norm_rule =
86    SIMP_RULE (simpLib.++ (pureSimps.pure_ss, resq_SS))
87      [GSYM LEFT_FORALL_IMP_THM, GSYM RIGHT_FORALL_IMP_THM,
88       AND_IMP_INTRO, GSYM CONJ_ASSOC];
89
90fun match_tac th =
91    let
92      val th = norm_rule th
93      val (_,tm) = strip_forall (concl th)
94    in
95      (if is_imp tm then MATCH_MP_TAC else MATCH_ACCEPT_TAC) th
96    end;
97
98(* ------------------------------------------------------------------------- *)
99(* Helper theorems.                                                          *)
100(* ------------------------------------------------------------------------- *)
101
102val DIV_THEN_MULT = store_thm
103  ("DIV_THEN_MULT",
104   ``!p q. SUC q * (p DIV SUC q) <= p``,
105   NTAC 2 STRIP_TAC
106   ++ Know `?r. p = (p DIV SUC q) * SUC q + r`
107   >> (Know `0 < SUC q` >> DECIDE_TAC
108       ++ PROVE_TAC [DIVISION])
109   ++ STRIP_TAC
110   ++ Suff `p = SUC q * (p DIV SUC q) + r`
111   >> (POP_ASSUM_LIST (K ALL_TAC) ++ DECIDE_TAC)
112   ++ PROVE_TAC [MULT_COMM]);
113
114val MOD_EXP = store_thm
115  ("MOD_EXP",
116   ``!a n m. 0 < m ==> (((a MOD m) ** n) MOD m = (a ** n) MOD m)``,
117   RW_TAC std_ss []
118   ++ Induct_on `n`
119   ++ RW_TAC std_ss [EXP]
120   ++ MP_TAC (Q.SPEC `m` MOD_TIMES2)
121   ++ ASM_REWRITE_TAC []
122   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
123   ++ ASM_SIMP_TAC std_ss [MOD_MOD]);
124
125val MULT_EXP = store_thm
126  ("MULT_EXP",
127   ``!a b n. (a * b) ** n = (a ** n) * (b ** n)``,
128   RW_TAC std_ss []
129   ++ Induct_on `n`
130   ++ RW_TAC std_ss [EXP, EQ_MULT_LCANCEL, GSYM MULT_ASSOC]
131   ++ RW_TAC std_ss
132        [EXP, ONCE_REWRITE_RULE [MULT_COMM] EQ_MULT_LCANCEL, MULT_ASSOC]
133   ++ METIS_TAC [MULT_COMM]);
134
135val EXP_EXP = store_thm
136  ("EXP_EXP",
137   ``!a b c. (a ** b) ** c = a ** (b * c)``,
138   RW_TAC std_ss []
139   ++ Induct_on `b`
140   ++ RW_TAC std_ss [EXP, MULT, EXP_1]
141   ++ RW_TAC std_ss [MULT_EXP, EXP_ADD]
142   ++ METIS_TAC [MULT_COMM]);
143
144(* ========================================================================= *)
145(* Fields                                                                    *)
146(* ========================================================================= *)
147
148(* ------------------------------------------------------------------------- *)
149(* The basic definitions                                                     *)
150(* ------------------------------------------------------------------------- *)
151
152val () = Hol_datatype
153  `field = <| carrier : 'a -> bool;
154              sum : 'a group;
155              prod : 'a group |>`;
156
157val field_accessors = fetch "-" "field_accessors";
158
159val field_zero_def = Define `field_zero (f : 'a field) = f.sum.id`;
160
161val field_one_def = Define `field_one (f : 'a field) = f.prod.id`;
162
163val field_neg_def = Define `field_neg (f : 'a field) = f.sum.inv`;
164
165val field_inv_def = Define `field_inv (f : 'a field) = f.prod.inv`;
166
167val field_add_def = Define `field_add (f : 'a field) = f.sum.mult`;
168
169val field_sub_def = Define
170  `field_sub (f : 'a field) x y = field_add f x (field_neg f y)`;
171
172val field_mult_def = Define `field_mult (f : 'a field) = f.prod.mult`;
173
174val field_div_def = Define
175  `field_div (f : 'a field) x y = field_mult f x (field_inv f y)`;
176
177val field_nonzero_def = Define
178  `field_nonzero f = f.carrier DIFF {field_zero f}`;
179
180val field_num_def = Define
181  `(field_num (f : 'a field) 0 = field_zero f) /\
182   (field_num (f : 'a field) (SUC n) =
183    field_add f (field_num f n) (field_one f))`;
184
185val field_exp_def = Define
186  `(field_exp (f : 'a field) x 0 = field_one f) /\
187   (field_exp (f : 'a field) x (SUC n) = field_mult f x (field_exp f x n))`;
188
189val Field_def = Define
190  `Field =
191   { (f : 'a field) |
192     f.sum IN AbelianGroup /\
193     f.prod IN AbelianGroup /\
194     (f.sum.carrier = f.carrier) /\
195     (f.prod.carrier = field_nonzero f) /\
196     (!x :: (f.carrier). field_mult f (field_zero f) x = field_zero f) /\
197     (!x y z :: (f.carrier).
198        field_mult f x (field_add f y z) =
199        field_add f (field_mult f x y) (field_mult f x z)) }`;
200
201val FiniteField_def = Define
202  `FiniteField = { (f : 'a field) | f IN Field /\ FINITE f.carrier }`;
203
204val context = subtypeTools.add_rewrite2'' field_sub_def context;
205(*val context = subtypeTools.add_rewrite2'' field_div_def context;*)
206val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
207
208(* ------------------------------------------------------------------------- *)
209(* Syntax operations                                                         *)
210(* ------------------------------------------------------------------------- *)
211
212val field_ty_op = "field";
213
214fun mk_field_type ty = mk_type (field_ty_op,[ty]);
215
216fun dest_field_type ty =
217    case dest_type ty of
218      (ty_op,[a]) => if ty_op = field_ty_op then a
219                     else raise ERR "dest_field_type" ""
220    | _ => raise ERR "dest_field_type" "";
221
222val is_field_type = can dest_field_type;
223
224val field_zero_tm = ``field_zero : 'a field -> 'a``;
225
226fun mk_field_zero f =
227    let
228      val ty = dest_field_type (type_of f)
229      val zero_tm = inst [{redex = alpha, residue = ty}] field_zero_tm
230    in
231      mk_comb (zero_tm,f)
232    end;
233
234fun dest_field_zero tm =
235    let
236      val (tm,f) = dest_comb tm
237      val _ = same_const tm field_zero_tm orelse raise ERR "dest_field_zero" ""
238    in
239      f
240    end;
241
242val is_field_zero = can dest_field_zero;
243
244val field_one_tm = ``field_one : 'a field -> 'a``;
245
246fun mk_field_one f =
247    let
248      val ty = dest_field_type (type_of f)
249      val one_tm = inst [{redex = alpha, residue = ty}] field_one_tm
250    in
251      mk_comb (one_tm,f)
252    end;
253
254fun dest_field_one tm =
255    let
256      val (tm,f) = dest_comb tm
257      val _ = same_const tm field_one_tm orelse raise ERR "dest_field_one" ""
258    in
259      f
260    end;
261
262val is_field_one = can dest_field_one;
263
264val field_num_tm = ``field_num : 'a field -> num -> 'a``;
265
266fun mk_field_num (f,n) =
267    let
268      val ty = dest_field_type (type_of f)
269      val num_tm = inst [{redex = alpha, residue = ty}] field_num_tm
270    in
271      list_mk_comb (num_tm,[f,n])
272    end;
273
274fun dest_field_num tm =
275    let
276      val (tm,x) = dest_comb tm
277      val (tm,f) = dest_comb tm
278      val _ = same_const tm field_num_tm orelse raise ERR "dest_field_num" ""
279    in
280      (f,x)
281    end;
282
283val is_field_num = can dest_field_num;
284
285val field_neg_tm = ``field_neg : 'a field -> 'a -> 'a``;
286
287fun mk_field_neg (f,x) =
288    let
289      val ty = dest_field_type (type_of f)
290      val neg_tm = inst [{redex = alpha, residue = ty}] field_neg_tm
291    in
292      list_mk_comb (neg_tm,[f,x])
293    end;
294
295fun dest_field_neg tm =
296    let
297      val (tm,x) = dest_comb tm
298      val (tm,f) = dest_comb tm
299      val _ = same_const tm field_neg_tm orelse raise ERR "dest_field_neg" ""
300    in
301      (f,x)
302    end;
303
304val is_field_neg = can dest_field_neg;
305
306val field_add_tm = ``field_add : 'a field -> 'a -> 'a -> 'a``;
307
308fun mk_field_add (f,x,y) =
309    let
310      val ty = dest_field_type (type_of f)
311      val add_tm = inst [{redex = alpha, residue = ty}] field_add_tm
312    in
313      list_mk_comb (add_tm,[f,x,y])
314    end;
315
316fun dest_field_add tm =
317    let
318      val (tm,y) = dest_comb tm
319      val (tm,x) = dest_comb tm
320      val (tm,f) = dest_comb tm
321      val _ = same_const tm field_add_tm orelse raise ERR "dest_field_add" ""
322    in
323      (f,x,y)
324    end;
325
326val is_field_add = can dest_field_add;
327
328val field_sub_tm = ``field_sub : 'a field -> 'a -> 'a -> 'a``;
329
330fun mk_field_sub (f,x,y) =
331    let
332      val ty = dest_field_type (type_of f)
333      val sub_tm = inst [{redex = alpha, residue = ty}] field_sub_tm
334    in
335      list_mk_comb (sub_tm,[f,x,y])
336    end;
337
338fun dest_field_sub tm =
339    let
340      val (tm,y) = dest_comb tm
341      val (tm,x) = dest_comb tm
342      val (tm,f) = dest_comb tm
343      val _ = same_const tm field_sub_tm orelse raise ERR "dest_field_sub" ""
344    in
345      (f,x,y)
346    end;
347
348val is_field_sub = can dest_field_sub;
349
350val field_inv_tm = ``field_inv : 'a field -> 'a -> 'a``;
351
352fun mk_field_inv (f,x) =
353    let
354      val ty = dest_field_type (type_of f)
355      val inv_tm = inst [{redex = alpha, residue = ty}] field_inv_tm
356    in
357      list_mk_comb (inv_tm,[f,x])
358    end;
359
360fun dest_field_inv tm =
361    let
362      val (tm,x) = dest_comb tm
363      val (tm,f) = dest_comb tm
364      val _ = same_const tm field_inv_tm orelse raise ERR "dest_field_inv" ""
365    in
366      (f,x)
367    end;
368
369val is_field_inv = can dest_field_inv;
370
371val field_mult_tm = ``field_mult : 'a field -> 'a -> 'a -> 'a``;
372
373fun mk_field_mult (f,x,y) =
374    let
375      val ty = dest_field_type (type_of f)
376      val mult_tm = inst [{redex = alpha, residue = ty}] field_mult_tm
377    in
378      list_mk_comb (mult_tm,[f,x,y])
379    end;
380
381fun dest_field_mult tm =
382    let
383      val (tm,y) = dest_comb tm
384      val (tm,x) = dest_comb tm
385      val (tm,f) = dest_comb tm
386      val _ = same_const tm field_mult_tm orelse raise ERR "dest_field_mult" ""
387    in
388      (f,x,y)
389    end;
390
391val is_field_mult = can dest_field_mult;
392
393val field_exp_tm = ``field_exp : 'a field -> 'a -> num -> 'a``;
394
395fun mk_field_exp (f,x,n) =
396    let
397      val ty = dest_field_type (type_of f)
398      val exp_tm = inst [{redex = alpha, residue = ty}] field_exp_tm
399    in
400      list_mk_comb (exp_tm,[f,x,n])
401    end;
402
403fun dest_field_exp tm =
404    let
405      val (tm,n) = dest_comb tm
406      val (tm,x) = dest_comb tm
407      val (tm,f) = dest_comb tm
408      val _ = same_const tm field_exp_tm orelse raise ERR "dest_field_exp" ""
409    in
410      (f,x,n)
411    end;
412
413val is_field_exp = can dest_field_exp;
414
415val field_div_tm = ``field_div : 'a field -> 'a -> 'a -> 'a``;
416
417fun mk_field_div (f,x,y) =
418    let
419      val ty = dest_field_type (type_of f)
420      val div_tm = inst [{redex = alpha, residue = ty}] field_div_tm
421    in
422      list_mk_comb (div_tm,[f,x,y])
423    end;
424
425fun dest_field_div tm =
426    let
427      val (tm,y) = dest_comb tm
428      val (tm,x) = dest_comb tm
429      val (tm,f) = dest_comb tm
430      val _ = same_const tm field_div_tm orelse raise ERR "dest_field_div" ""
431    in
432      (f,x,y)
433    end;
434
435val is_field_div = can dest_field_div;
436
437fun mk_field_num_mult (f,x,n) = mk_field_mult (f, mk_field_num (f,n), x);
438
439fun dest_field_num_mult tm =
440    let
441      val (f,t,x) = dest_field_mult tm
442      val (_,n) = dest_field_num t
443    in
444      (f,x,n)
445    end;
446
447val is_field_num_mult = can dest_field_num_mult;
448
449fun field_compare (x,y) =
450    case (total dest_field_num x, total dest_field_num y) of
451      (NONE,NONE) => compare (x,y)
452    | (SOME _, NONE) => LESS
453    | (NONE, SOME _) => GREATER
454    | (SOME (_,x), SOME (_,y)) => compare (x,y);
455
456(* ------------------------------------------------------------------------- *)
457(* Theorems                                                                  *)
458(* ------------------------------------------------------------------------- *)
459
460val FiniteField_Field = store_thm
461  ("FiniteField_Field",
462   ``!f. f IN FiniteField ==> f IN Field``,
463   RW_TAC std_ss [FiniteField_def, GSPECIFICATION]);
464
465val context = subtypeTools.add_judgement2 FiniteField_Field context;
466val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
467
468val field_nonzero_carrier = store_thm
469  ("field_nonzero_carrier",
470   ``!f :: Field. !x :: field_nonzero f. x IN f.carrier``,
471   RW_TAC resq_ss [field_nonzero_def, IN_DIFF]);
472
473val context = subtypeTools.add_judgement2 field_nonzero_carrier context;
474val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
475
476val field_nonzero_alt = store_thm
477  ("field_nonzero_alt",
478   ``!f x. x IN f.carrier /\ ~(x = field_zero f) ==> x IN field_nonzero f``,
479   RW_TAC std_ss [field_nonzero_def, IN_DIFF, IN_SING]);
480
481val field_nonzero_eq = store_thm
482  ("field_nonzero_eq",
483   ``!f :: Field. !x :: (f.carrier).
484       ~(x = field_zero f) = x IN field_nonzero f``,
485   RW_TAC std_ss [field_nonzero_def, IN_DIFF, IN_SING]);
486
487val field_zero_carrier = store_thm
488  ("field_zero_carrier",
489   ``!f :: Field. field_zero f IN f.carrier``,
490   RW_TAC resq_ss [Field_def, field_one_def, GSPECIFICATION, field_zero_def]
491   ++ Q.UNDISCH_TAC `f.sum IN AbelianGroup`
492   ++ RW_TAC std_ss [AbelianGroup_def, GSPECIFICATION, Group_def]);
493
494val context = subtypeTools.add_reduction2 field_zero_carrier context;
495val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
496
497val field_one_carrier = store_thm
498  ("field_one_carrier",
499   ``!f :: Field. field_one f IN f.carrier``,
500   RW_TAC resq_ss [Field_def, field_one_def, GSPECIFICATION, field_zero_def]
501   ++ Q.UNDISCH_TAC `f.prod IN AbelianGroup`
502   ++ RW_TAC std_ss
503        [AbelianGroup_def, GSPECIFICATION, Group_def, IN_DIFF,
504         field_nonzero_def]);
505
506val field_one_zero = store_thm
507  ("field_one_zero",
508   ``!f :: Field. ~(field_one f = field_zero f)``,
509   RW_TAC resq_ss
510     [Field_def, field_one_def, field_zero_def, GSPECIFICATION,
511      AbelianGroup_def, field_nonzero_def]
512   ++ Know `f.prod.id IN f.prod.carrier`
513   >> METIS_TAC [group_id_carrier]
514   ++ RW_TAC std_ss [IN_DIFF, IN_SING]);
515
516val context = subtypeTools.add_rewrite2 field_one_zero context;
517val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
518
519val field_zero_one = store_thm
520  ("field_zero_one",
521   ``!f :: Field. ~(field_zero f = field_one f)``,
522   RW_TAC alg_ss []);
523
524val field_one_nonzero = store_thm
525  ("field_one_nonzero",
526   ``!f :: Field. field_one f IN field_nonzero f``,
527   RW_TAC resq_ss
528     [field_nonzero_def, IN_DIFF, IN_SING, field_one_carrier, field_one_zero]);
529
530val context = subtypeTools.add_reduction2 field_one_nonzero context;
531val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
532
533val field_neg_carrier = store_thm
534  ("field_neg_carrier",
535   ``!f :: Field. !x :: (f.carrier). field_neg f x IN f.carrier``,
536   RW_TAC resq_ss [Field_def, GSPECIFICATION, field_neg_def, AbelianGroup_def]
537   ++ METIS_TAC [group_inv_carrier]);
538
539val context = subtypeTools.add_reduction2 field_neg_carrier context;
540val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
541
542val field_add_carrier = store_thm
543  ("field_add_carrier",
544   ``!f :: Field. !x y :: (f.carrier). field_add f x y IN f.carrier``,
545   RW_TAC resq_ss [Field_def, GSPECIFICATION, field_add_def, AbelianGroup_def]
546   ++ METIS_TAC [group_mult_carrier]);
547
548val context = subtypeTools.add_reduction2 field_add_carrier context;
549val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
550
551val field_add_assoc = store_thm
552  ("field_add_assoc",
553   ``!f :: Field. !x y z :: (f.carrier).
554       field_add f (field_add f x y) z = field_add f x (field_add f y z)``,
555   RW_TAC resq_ss
556     [Field_def, GSPECIFICATION, field_add_def, AbelianGroup_def,
557      Group_def]);
558
559val context = subtypeTools.add_rewrite2'' field_add_assoc context;
560val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
561
562val field_add_comm = store_thm
563  ("field_add_comm",
564   ``!f :: Field. !x y :: (f.carrier). field_add f x y = field_add f y x``,
565   RW_TAC resq_ss
566     [Field_def, GSPECIFICATION, field_add_def, AbelianGroup_def]);
567
568val field_add_comm' = store_thm
569  ("field_add_comm'",
570   ``!f :: Field. !x y z :: (f.carrier).
571        field_add f x (field_add f y z) = field_add f y (field_add f x z)``,
572   RW_TAC resq_ss []
573   ++ RW_TAC alg_ss [GSYM field_add_assoc]
574   ++ METIS_TAC [field_add_comm]);
575
576val field_num_zero = store_thm
577  ("field_num_zero",
578   ``!f. field_num f 0 = field_zero f``,
579   RW_TAC std_ss [field_num_def]);
580
581val context = subtypeTools.add_rewrite2 field_num_zero context;
582val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
583
584val field_add_lzero = store_thm
585  ("field_add_lzero",
586   ``!f :: Field. !x :: (f.carrier). field_add f (field_zero f) x = x``,
587   RW_TAC resq_ss
588     [Field_def, GSPECIFICATION, field_add_def, field_zero_def,
589      AbelianGroup_def]
590   ++ match_tac group_lid
591   ++ RW_TAC std_ss []);
592
593val context = subtypeTools.add_rewrite2 field_add_lzero context;
594val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
595
596val field_num_one = store_thm
597  ("field_num_one",
598   ``!f :: Field. field_num f 1 = field_one f``,
599   REWRITE_TAC [ONE, field_num_def]
600   ++ RW_TAC alg_ss []);
601
602val context = subtypeTools.add_rewrite2'' (GSYM field_num_one) context;
603val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
604
605val field_add_lzero' = store_thm
606  ("field_add_lzero'",
607   ``!f :: Field. !x :: (f.carrier). field_add f (field_num f 0) x = x``,
608   RW_TAC alg_ss [field_num_zero]);
609
610val context = subtypeTools.add_rewrite2 field_add_lzero' context;
611val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
612
613val field_add_rzero = store_thm
614  ("field_add_rzero",
615   ``!f :: Field. !x :: (f.carrier). field_add f x (field_zero f) = x``,
616   METIS_TAC [field_add_lzero, field_add_comm, field_zero_carrier]);
617
618val context = subtypeTools.add_rewrite2 field_add_rzero context;
619val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
620
621val field_add_rzero' = store_thm
622  ("field_add_rzero'",
623   ``!f :: Field. !x :: (f.carrier). field_add f x (field_num f 0) = x``,
624   RW_TAC alg_ss [field_num_zero]);
625
626val context = subtypeTools.add_rewrite2 field_add_rzero' context;
627val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
628
629val field_lneg = store_thm
630  ("field_lneg",
631   ``!f :: Field. !x :: (f.carrier).
632       (field_add f (field_neg f x) x = field_zero f)``,
633   RW_TAC resq_ss
634     [Field_def, GSPECIFICATION, field_add_def, field_zero_def,
635      AbelianGroup_def, field_neg_def]
636   ++ match_tac group_linv
637   ++ RW_TAC std_ss [IN_DIFF, IN_SING]);
638
639val context = subtypeTools.add_rewrite2 field_lneg context;
640val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
641
642val field_lneg' = store_thm
643  ("field_lneg'",
644   ``!f :: Field. !x y :: (f.carrier).
645       (field_add f (field_neg f x) (field_add f x y) = y)``,
646   RW_TAC resq_ss []
647   ++ RW_TAC alg_ss [GSYM field_add_assoc]);
648
649val context = subtypeTools.add_rewrite2 field_lneg' context;
650val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
651
652val field_rneg = store_thm
653  ("field_rneg",
654   ``!f :: Field. !x :: (f.carrier).
655       (field_add f x (field_neg f x) = field_zero f)``,
656   METIS_TAC [field_lneg, field_add_comm, field_neg_carrier]);
657
658val context = subtypeTools.add_rewrite2 field_rneg context;
659val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
660
661val field_rneg' = store_thm
662  ("field_rneg'",
663   ``!f :: Field. !x y :: (f.carrier).
664       (field_add f x (field_add f (field_neg f x) y) = y)``,
665   RW_TAC resq_ss []
666   ++ RW_TAC alg_ss [GSYM field_add_assoc]);
667
668val context = subtypeTools.add_rewrite2 field_rneg' context;
669val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
670
671val field_add_lcancel_imp = store_thm
672  ("field_add_lcancel_imp",
673   ``!f :: Field. !x y z :: (f.carrier).
674       (field_add f x y = field_add f x z) ==> (y = z)``,
675   RW_TAC resq_ss [Field_def, GSPECIFICATION, AbelianGroup_def, field_add_def]
676   ++ match_tac group_lcancel_imp
677   ++ Q.EXISTS_TAC `f.sum`
678   ++ Q.EXISTS_TAC `x`
679   ++ RW_TAC std_ss []);
680
681val field_add_lcancel = store_thm
682  ("field_add_lcancel",
683   ``!f :: Field. !x y z :: (f.carrier).
684       (field_add f x y = field_add f x z) = (y = z)``,
685   METIS_TAC [field_add_lcancel_imp]);
686
687val context = subtypeTools.add_rewrite2' field_add_lcancel context;
688val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
689
690val field_add_rcancel_imp = store_thm
691  ("field_add_rcancel_imp",
692   ``!f :: Field. !x y z :: (f.carrier).
693       (field_add f y x = field_add f z x) ==> (y = z)``,
694   METIS_TAC [field_add_lcancel_imp, field_add_comm]);
695
696val field_add_rcancel = store_thm
697  ("field_add_rcancel",
698   ``!f :: Field. !x y z :: (f.carrier).
699       (field_add f y x = field_add f z x) = (y = z)``,
700   METIS_TAC [field_add_rcancel_imp]);
701
702val context = subtypeTools.add_rewrite2' field_add_rcancel context;
703val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
704
705val field_inv_nonzero = store_thm
706  ("field_inv_nonzero",
707   ``!f :: Field. !x :: field_nonzero f. field_inv f x IN field_nonzero f``,
708   RW_TAC resq_ss [Field_def, GSPECIFICATION, field_nonzero_def]
709   ++ Suff `field_inv f x IN f.prod.carrier`
710   >> RW_TAC std_ss []
711   ++ Know `x IN f.prod.carrier`
712   >> RW_TAC std_ss [IN_DIFF, IN_INSERT, NOT_IN_EMPTY]
713   ++ Q.UNDISCH_TAC `f.prod IN AbelianGroup`
714   ++ POP_ASSUM_LIST (K ALL_TAC)
715   ++ RW_TAC std_ss
716        [AbelianGroup_def, GSPECIFICATION, Group_def, field_inv_def]);
717
718val context = subtypeTools.add_reduction2 field_inv_nonzero context;
719val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
720
721val field_mult_lzero = store_thm
722  ("field_mult_lzero",
723   ``!f :: Field. !x :: (f.carrier).
724       field_mult f (field_zero f) x = field_zero f``,
725   RW_TAC resq_ss [Field_def, GSPECIFICATION]);
726
727val context = subtypeTools.add_rewrite2 field_mult_lzero context;
728val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
729
730val field_mult_lzero' = store_thm
731  ("field_mult_lzero'",
732   ``!f :: Field. !x :: (f.carrier).
733       field_mult f (field_num f 0) x = field_zero f``,
734   RW_TAC alg_ss [field_num_zero]);
735
736val context = subtypeTools.add_rewrite2 field_mult_lzero' context;
737val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
738
739val field_distrib_ladd = store_thm
740  ("field_distrib_ladd",
741   ``!f :: Field. !x y z :: (f.carrier).
742       field_mult f x (field_add f y z) =
743       field_add f (field_mult f x y) (field_mult f x z)``,
744   RW_TAC resq_ss [Field_def, GSPECIFICATION]);
745
746(***
747val context = subtypeTools.add_rewrite2'' field_distrib_ladd context;
748val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
749***)
750
751val field_mult_rzero = store_thm
752  ("field_mult_rzero",
753   ``!f :: Field. !x :: (f.carrier).
754       field_mult f x (field_zero f) = field_zero f``,
755   RW_TAC resq_ss []
756   ++ Cases_on `x = field_zero f`
757   >> METIS_TAC [field_mult_lzero]
758   ++ Know `field_mult f x (field_zero f) IN f.carrier`
759   >> (Suff
760         `field_mult f x (field_add f (field_one f) (field_neg f (field_one f)))
761          IN f.carrier`
762       >> RW_TAC alg_ss [field_rneg]
763       ++ RW_TAC alg_ss [field_distrib_ladd]
764       ++ match_tac field_add_carrier
765       ++ Q.UNDISCH_TAC `f IN Field`
766       ++ RW_TAC std_ss
767            [GSPECIFICATION, Field_def, AbelianGroup_def, field_one_def,
768             field_mult_def, field_neg_def, field_nonzero_def]
769       >> (Suff `f.prod.mult x f.prod.id IN f.prod.carrier`
770           >> RW_TAC std_ss [IN_DIFF]
771           ++ match_tac group_mult_carrier
772           ++ RW_TAC std_ss [group_id_carrier, IN_DIFF, IN_SING])
773       ++ Suff `f.prod.mult x (f.sum.inv f.prod.id) IN f.prod.carrier`
774       >> RW_TAC std_ss [IN_DIFF]
775       ++ Q.PAT_ASSUM `f.sum.carrier = f.carrier`
776            (MP_TAC o ONCE_REWRITE_RULE [EQ_SYM_EQ])
777       ++ STRIP_TAC
778       ++ match_tac group_mult_carrier
779       ++ ASM_SIMP_TAC std_ss [IN_DIFF, IN_SING]
780       ++ Know `f.prod.id IN f.prod.carrier`
781       >> RW_TAC std_ss [group_id_carrier]
782       ++ ASM_SIMP_TAC std_ss [IN_DIFF, IN_SING]
783       ++ FULL_SIMP_TAC std_ss [field_zero_def]
784       ++ RW_TAC std_ss []
785       >> (match_tac group_inv_carrier
786           ++ RW_TAC std_ss [])
787       ++ STRIP_TAC
788       ++ Q.PAT_ASSUM `~(X = Y)` MP_TAC
789       ++ RW_TAC std_ss []
790       ++ match_tac group_lcancel_imp
791       ++ Q.EXISTS_TAC `f.sum`
792       ++ Q.EXISTS_TAC `f.sum.inv f.prod.id`
793       ++ CONJ_TAC >> METIS_TAC [group_linv, group_id_carrier]
794       ++ CONJ_TAC >> METIS_TAC [group_linv, group_id_carrier]
795       ++ CONJ_TAC >> METIS_TAC [group_linv, group_id_carrier]
796       ++ CONJ_TAC >> METIS_TAC [group_linv, group_id_carrier]
797       ++ POP_ASSUM (fn th => CONV_TAC (RAND_CONV (REWRITE_CONV [th])))
798       ++ RW_TAC std_ss [group_linv, group_lid, group_id_carrier])
799   ++ RW_TAC std_ss []
800   ++ Suff
801        `field_add f (field_mult f x (field_zero f))
802                     (field_mult f x (field_zero f)) =
803         field_add f (field_zero f) (field_mult f x (field_zero f))`
804   >> RW_TAC alg_ss []
805   ++ MATCH_MP_TAC EQ_TRANS
806   ++ Q.EXISTS_TAC
807        `field_mult f x (field_add f (field_zero f) (field_zero f))`
808   ++ REVERSE CONJ_TAC
809   >> RW_TAC alg_ss []
810   ++ MATCH_MP_TAC EQ_SYM
811   ++ match_tac field_distrib_ladd
812   ++ RW_TAC alg_ss []);
813
814val context = subtypeTools.add_rewrite2 field_mult_rzero context;
815val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
816
817val field_mult_rzero' = store_thm
818  ("field_mult_rzero'",
819   ``!f :: Field. !x :: (f.carrier).
820       field_mult f x (field_num f 0) = field_zero f``,
821   RW_TAC alg_ss [field_num_zero]);
822
823val context = subtypeTools.add_rewrite2 field_mult_rzero' context;
824val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
825
826val field_mult_nonzero = store_thm
827  ("field_mult_nonzero",
828   ``!f :: Field. !x y :: field_nonzero f.
829       field_mult f x y IN field_nonzero f``,
830   RW_TAC resq_ss
831     [Field_def, GSPECIFICATION, field_mult_def, AbelianGroup_def,
832      field_nonzero_def]
833   ++ Suff `f.prod.mult x y IN f.prod.carrier`
834   >> RW_TAC std_ss []
835   ++ match_tac group_mult_carrier
836   ++ RW_TAC std_ss []);
837
838val context = subtypeTools.add_reduction2 field_mult_nonzero context;
839val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
840
841val field_mult_carrier = store_thm
842  ("field_mult_carrier",
843   ``!f :: Field. !x y :: (f.carrier). field_mult f x y IN f.carrier``,
844   RW_TAC resq_ss []
845   ++ Cases_on `x = field_zero f`
846   >> RW_TAC std_ss [field_mult_lzero]
847   ++ Cases_on `y = field_zero f`
848   >> RW_TAC std_ss [field_mult_rzero]
849   ++ match_tac field_nonzero_carrier
850   ++ RW_TAC std_ss []
851   ++ match_tac field_mult_nonzero
852   ++ RW_TAC std_ss [field_nonzero_def, IN_DIFF, IN_SING]);
853
854val context = subtypeTools.add_reduction2 field_mult_carrier context;
855val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
856
857val field_mult_assoc = store_thm
858  ("field_mult_assoc",
859   ``!f :: Field. !x y z :: (f.carrier).
860       field_mult f (field_mult f x y) z = field_mult f x (field_mult f y z)``,
861   RW_TAC resq_ss []
862   ++ Cases_on `x = field_zero f`
863   >> RW_TAC std_ss [field_mult_lzero, field_mult_rzero, field_mult_carrier]
864   ++ Cases_on `y = field_zero f`
865   >> RW_TAC std_ss [field_mult_lzero, field_mult_rzero, field_mult_carrier]
866   ++ Cases_on `z = field_zero f`
867   >> RW_TAC std_ss [field_mult_lzero, field_mult_rzero, field_mult_carrier]
868   ++ Q.UNDISCH_TAC `f IN Field`
869   ++ RW_TAC std_ss
870        [Field_def, GSPECIFICATION, field_add_def, AbelianGroup_def,
871         Group_def, field_mult_def, field_nonzero_def]
872   ++ FIRST_ASSUM match_tac
873   ++ RW_TAC std_ss [IN_DIFF, IN_SING]);
874
875val context = subtypeTools.add_rewrite2'' field_mult_assoc context;
876val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
877
878val field_mult_comm = store_thm
879  ("field_mult_comm",
880   ``!f :: Field. !x y :: (f.carrier). field_mult f x y = field_mult f y x``,
881   RW_TAC resq_ss []
882   ++ Cases_on `x = field_zero f`
883   >> RW_TAC std_ss [field_mult_lzero, field_mult_rzero]
884   ++ Cases_on `y = field_zero f`
885   >> RW_TAC std_ss [field_mult_lzero, field_mult_rzero]
886   ++ Q.UNDISCH_TAC `f IN Field`
887   ++ RW_TAC std_ss
888        [Field_def, GSPECIFICATION, field_mult_def, AbelianGroup_def,
889         field_nonzero_def]
890   ++ Q.PAT_ASSUM `!x y :: (f.prod.carrier). P x y` match_tac
891   ++ RW_TAC std_ss [IN_DIFF, IN_INSERT, NOT_IN_EMPTY]);
892
893val field_mult_comm' = store_thm
894  ("field_mult_comm'",
895   ``!f :: Field. !x y z :: (f.carrier).
896        field_mult f x (field_mult f y z) = field_mult f y (field_mult f x z)``,
897   RW_TAC resq_ss []
898   ++ RW_TAC alg_ss [GSYM field_mult_assoc]
899   ++ METIS_TAC [field_mult_comm]);
900
901val field_entire = store_thm
902  ("field_entire",
903   ``!f :: Field. !x y :: (f.carrier).
904       (field_mult f x y = field_zero f) =
905       (x = field_zero f) \/ (y = field_zero f)``,
906   RW_TAC resq_ss []
907   ++ REVERSE EQ_TAC
908   >> (STRIP_TAC ++ RW_TAC std_ss [field_mult_lzero, field_mult_rzero])
909   ++ MATCH_MP_TAC (PROVE [] ``(~b ==> ~a) ==> (a ==> b)``)
910   ++ Know `field_mult f x y IN f.carrier`
911   >> METIS_TAC [field_mult_carrier]
912   ++ RW_TAC std_ss []
913   ++ Q.UNDISCH_TAC `f IN Field`
914   ++ RW_TAC std_ss
915        [Field_def, GSPECIFICATION, AbelianGroup_def, field_nonzero_def]
916   ++ Suff `f.prod.mult x y IN f.prod.carrier`
917   >> RW_TAC std_ss [IN_DIFF, IN_INSERT, NOT_IN_EMPTY, field_mult_def]
918   ++ match_tac group_mult_carrier
919   ++ RW_TAC std_ss [IN_DIFF, IN_INSERT, NOT_IN_EMPTY]);
920
921val context = subtypeTools.add_rewrite2' field_entire context;
922val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
923
924val field_mult_lone = store_thm
925  ("field_mult_lone",
926   ``!f :: Field. !x :: (f.carrier). field_mult f (field_one f) x = x``,
927   RW_TAC resq_ss []
928   ++ Cases_on `x = field_zero f`
929   >> RW_TAC std_ss [field_mult_rzero, field_one_carrier]
930   ++ Q.UNDISCH_TAC `f IN Field`
931   ++ RW_TAC std_ss
932        [Field_def, GSPECIFICATION, field_mult_def, field_one_def,
933         AbelianGroup_def, field_nonzero_def]
934   ++ match_tac group_lid
935   ++ RW_TAC std_ss [IN_DIFF, IN_INSERT, NOT_IN_EMPTY]);
936
937val context = subtypeTools.add_rewrite2 field_mult_lone context;
938val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
939
940val field_mult_lone' = store_thm
941  ("field_mult_lone'",
942   ``!f :: Field. !x :: (f.carrier). field_mult f (field_num f 1) x = x``,
943   RW_TAC alg_ss [field_num_one]);
944
945val context = subtypeTools.add_rewrite2 field_mult_lone' context;
946val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
947
948val field_mult_rone = store_thm
949  ("field_mult_rone",
950   ``!f :: Field. !x :: (f.carrier). field_mult f x (field_one f) = x``,
951   METIS_TAC [field_mult_lone, field_mult_comm, field_one_carrier]);
952
953val context = subtypeTools.add_rewrite2 field_mult_rone context;
954val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
955
956val field_mult_rone' = store_thm
957  ("field_mult_rone'",
958   ``!f :: Field. !x :: (f.carrier). field_mult f x (field_num f 1) = x``,
959   RW_TAC alg_ss [field_num_one]);
960
961val context = subtypeTools.add_rewrite2 field_mult_rone' context;
962val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
963
964val field_linv = store_thm
965  ("field_linv",
966   ``!f :: Field. !x :: field_nonzero f.
967       field_mult f (field_inv f x) x = field_one f``,
968   RW_TAC resq_ss
969     [Field_def, GSPECIFICATION, field_mult_def, field_one_def,
970      AbelianGroup_def, field_inv_def, field_nonzero_def]
971   ++ match_tac group_linv
972   ++ RW_TAC std_ss []);
973
974val context = subtypeTools.add_rewrite2 field_linv context;
975val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
976
977val field_linv' = store_thm
978  ("field_linv'",
979   ``!f :: Field. !x :: field_nonzero f. !y :: (f.carrier).
980       (field_mult f (field_inv f x) (field_mult f x y) = y)``,
981   RW_TAC resq_ss []
982   ++ RW_TAC alg_ss [GSYM field_mult_assoc]);
983
984val context = subtypeTools.add_rewrite2 field_linv' context;
985val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
986
987val field_rinv = store_thm
988  ("field_rinv",
989   ``!f :: Field. !x :: field_nonzero f.
990       (field_mult f x (field_inv f x) = field_one f)``,
991   METIS_TAC
992     [field_linv, field_mult_comm, field_inv_nonzero, field_nonzero_carrier]);
993
994val context = subtypeTools.add_rewrite2 field_rinv context;
995val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
996
997val field_rinv' = store_thm
998  ("field_rinv'",
999   ``!f :: Field. !x :: field_nonzero f. !y :: (f.carrier).
1000       (field_mult f x (field_mult f (field_inv f x) y) = y)``,
1001   RW_TAC resq_ss []
1002   ++ RW_TAC alg_ss [GSYM field_mult_assoc]);
1003
1004val context = subtypeTools.add_rewrite2 field_rinv' context;
1005val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1006
1007val field_mult_lcancel_imp = store_thm
1008  ("field_mult_lcancel_imp",
1009   ``!f :: Field. !x :: field_nonzero f. !y z :: (f.carrier).
1010       (field_mult f x y = field_mult f x z) ==> (y = z)``,
1011   RW_TAC resq_ss [field_nonzero_def, IN_DIFF, IN_SING]
1012   ++ POP_ASSUM MP_TAC
1013   ++ Cases_on `y = field_zero f`
1014   >> RW_TAC std_ss [field_mult_rzero, field_entire]
1015   ++ Cases_on `z = field_zero f`
1016   >> RW_TAC std_ss [field_mult_rzero, field_entire]
1017   ++ Q.UNDISCH_TAC `f IN Field`
1018   ++ RW_TAC std_ss
1019        [field_mult_def, Field_def, GSPECIFICATION, AbelianGroup_def,
1020         field_nonzero_def]
1021   ++ match_tac group_lcancel_imp
1022   ++ Q.EXISTS_TAC `f.prod`
1023   ++ Q.EXISTS_TAC `x`
1024   ++ RW_TAC std_ss [IN_DIFF, IN_INSERT, NOT_IN_EMPTY]);
1025
1026val field_mult_lcancel = store_thm
1027  ("field_mult_lcancel",
1028   ``!f :: Field. !x :: field_nonzero f. !y z :: (f.carrier).
1029       (field_mult f x y = field_mult f x z) = (y = z)``,
1030   METIS_TAC [field_mult_lcancel_imp]);
1031
1032val context = subtypeTools.add_rewrite2' field_mult_lcancel context;
1033val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1034
1035val field_mult_rcancel_imp = store_thm
1036  ("field_mult_rcancel_imp",
1037   ``!f :: Field. !x :: field_nonzero f. !y z :: (f.carrier).
1038       (field_mult f y x = field_mult f z x) ==> (y = z)``,
1039   METIS_TAC [field_mult_lcancel_imp, field_mult_comm, field_nonzero_carrier]);
1040
1041val field_mult_rcancel = store_thm
1042  ("field_mult_rcancel",
1043   ``!f :: Field. !x :: field_nonzero f. !y z :: (f.carrier).
1044       (field_mult f y x = field_mult f z x) = (y = z)``,
1045   METIS_TAC [field_mult_rcancel_imp]);
1046
1047val context = subtypeTools.add_rewrite2' field_mult_rcancel context;
1048val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1049
1050val field_neg_neg = store_thm
1051  ("field_neg_neg",
1052   ``!f :: Field. !x :: (f.carrier). field_neg f (field_neg f x) = x``,
1053   RW_TAC resq_ss [field_neg_def, Field_def, GSPECIFICATION, AbelianGroup_def]
1054   ++ METIS_TAC [group_inv_inv]);
1055
1056val context = subtypeTools.add_rewrite2 field_neg_neg context;
1057val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1058
1059val field_neg_cancel = store_thm
1060  ("field_neg_cancel",
1061   ``!f :: Field. !x y :: (f.carrier).
1062       (field_neg f x = field_neg f y) = (x = y)``,
1063   RW_TAC resq_ss [field_neg_def, Field_def, GSPECIFICATION, AbelianGroup_def]
1064   ++ METIS_TAC [group_inv_cancel]);
1065
1066val context = subtypeTools.add_rewrite2 field_neg_cancel context;
1067val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1068
1069val field_neg_cancel_imp = store_thm
1070  ("field_neg_cancel_imp",
1071   ``!f :: Field. !x y :: (f.carrier).
1072       (field_neg f x = field_neg f y) ==> (x = y)``,
1073   METIS_TAC [field_neg_cancel]);
1074
1075val field_neg_eq_swap_imp = store_thm
1076  ("field_neg_eq_swap_imp",
1077   ``!f :: Field. !x y :: (f.carrier).
1078       (field_neg f x = y) ==> (x = field_neg f y)``,
1079   METIS_TAC [field_neg_neg]);
1080
1081val field_neg_eq_swap = store_thm
1082  ("field_neg_eq_swap",
1083   ``!f :: Field. !x y :: (f.carrier).
1084       (field_neg f x = y) = (x = field_neg f y)``,
1085   METIS_TAC [field_neg_eq_swap_imp]);
1086
1087val field_neg_eq_swap_imp' = store_thm
1088  ("field_neg_eq_swap_imp'",
1089   ``!f :: Field. !x y :: (f.carrier).
1090       (x = field_neg f y) ==> (field_neg f x = y)``,
1091   METIS_TAC [field_neg_eq_swap]);
1092
1093val field_neg_eq_imp = store_thm
1094  ("field_neg_eq_imp",
1095   ``!f :: Field. !x y :: (f.carrier).
1096       (field_neg f x = y) ==> (field_add f x y = field_zero f)``,
1097   RW_TAC resq_ss [field_rneg]);
1098
1099val field_neg_eq_imp' = store_thm
1100  ("field_neg_eq_imp'",
1101   ``!f :: Field. !x y :: (f.carrier).
1102       (field_add f x y = field_zero f) ==> (field_neg f x = y)``,
1103   RW_TAC resq_ss []
1104   ++ match_tac field_add_lcancel_imp
1105   ++ Q.EXISTS_TAC `f`
1106   ++ Q.EXISTS_TAC `x`
1107   ++ RW_TAC std_ss [field_neg_carrier, field_rneg]);
1108
1109val field_neg_eq = store_thm
1110  ("field_neg_eq",
1111   ``!f :: Field. !x y :: (f.carrier).
1112       (field_neg f x = y) = (field_add f x y = field_zero f)``,
1113   METIS_TAC [field_neg_eq_imp, field_neg_eq_imp']);
1114
1115val field_neg_zero = store_thm
1116  ("field_neg_zero",
1117   ``!f :: Field. field_neg f (field_zero f) = field_zero f``,
1118   RW_TAC resq_ss
1119     [Field_def, GSPECIFICATION, AbelianGroup_def, field_zero_def,
1120      field_neg_def]
1121   ++ METIS_TAC [group_inv_id]);
1122
1123val context = subtypeTools.add_rewrite2 field_neg_zero context;
1124val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1125
1126val field_add_eq = store_thm
1127  ("field_add_eq",
1128   ``!f x1 y1 x2 y2.
1129       (x1 = x2) /\ (y1 = y2) ==> (field_add f x1 y1 = field_add f x2 y2)``,
1130   RW_TAC std_ss []);
1131
1132val field_distrib_radd = store_thm
1133  ("field_distrib_radd",
1134   ``!f :: Field. !x y z :: (f.carrier).
1135       field_mult f (field_add f y z) x =
1136       field_add f (field_mult f y x) (field_mult f z x)``,
1137   RW_TAC resq_ss []
1138   ++ METIS_TAC [field_mult_comm, field_add_carrier, field_distrib_ladd]);
1139
1140(***
1141val context = subtypeTools.add_rewrite2'' field_distrib_radd context;
1142val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1143***)
1144
1145val field_distrib = save_thm
1146  ("field_distrib", CONJ field_distrib_ladd field_distrib_radd);
1147
1148val field_mult_lneg = store_thm
1149  ("field_mult_lneg",
1150   ``!f :: Field. !x y :: (f.carrier).
1151       field_mult f (field_neg f x) y = field_neg f (field_mult f x y)``,
1152   RW_TAC resq_ss []
1153   ++ match_tac (GSYM field_neg_eq_imp')
1154   ++ RW_TAC std_ss [field_mult_carrier, field_neg_carrier]
1155   ++ RW_TAC std_ss
1156        [GSYM field_distrib_radd, field_neg_carrier, field_rneg,
1157         field_mult_lzero]);
1158
1159val context = subtypeTools.add_rewrite2 field_mult_lneg context;
1160val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1161
1162val field_mult_rneg = store_thm
1163  ("field_mult_rneg",
1164   ``!f :: Field. !x y :: (f.carrier).
1165       field_mult f x (field_neg f y) = field_neg f (field_mult f x y)``,
1166   METIS_TAC [field_mult_lneg, field_mult_comm, field_neg_carrier]);
1167
1168val context = subtypeTools.add_rewrite2 field_mult_rneg context;
1169val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1170
1171val field_inv_mult' = store_thm
1172  ("field_inv_mult'",
1173   ``!f :: Field. !x y :: field_nonzero f.
1174       field_inv f (field_mult f x y) =
1175       field_mult f (field_inv f y) (field_inv f x)``,
1176   RW_TAC resq_ss
1177     [field_mult_def, Field_def, GSPECIFICATION, field_inv_def,
1178      AbelianGroup_def, field_nonzero_def]
1179   ++ match_tac group_inv_mult
1180   ++ RW_TAC std_ss []);
1181
1182val field_inv_mult = store_thm
1183  ("field_inv_mult",
1184   ``!f :: Field. !x y :: field_nonzero f.
1185       field_inv f (field_mult f x y) =
1186       field_mult f (field_inv f x) (field_inv f y)``,
1187   METIS_TAC [field_inv_nonzero, field_nonzero_carrier, field_mult_comm,
1188              field_inv_mult']);
1189
1190val context = subtypeTools.add_rewrite2'' field_inv_mult context;
1191val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1192
1193val field_exp_carrier = store_thm
1194  ("field_exp_carrier",
1195   ``!f :: Field. !x :: (f.carrier). !n. field_exp f x n IN f.carrier``,
1196   RW_TAC resq_ss []
1197   ++ Induct_on `n`
1198   ++ RW_TAC std_ss [field_exp_def, field_one_carrier, field_mult_carrier]);
1199
1200val context = subtypeTools.add_reduction2 field_exp_carrier context;
1201val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1202
1203val field_exp_nonzero = store_thm
1204  ("field_exp_nonzero",
1205   ``!f :: Field. !x :: field_nonzero f. !n.
1206       field_exp f x n IN field_nonzero f``,
1207   RW_TAC resq_ss []
1208   ++ Induct_on `n`
1209   ++ RW_TAC std_ss [field_exp_def, field_one_nonzero, field_mult_nonzero]);
1210
1211val context = subtypeTools.add_reduction2 field_exp_nonzero context;
1212val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1213
1214val field_num_carrier = store_thm
1215  ("field_num_carrier",
1216   ``!f :: Field. !n. field_num f n IN f.carrier``,
1217   RW_TAC resq_ss []
1218   ++ Induct_on `n`
1219   ++ RW_TAC alg_ss [field_num_def]);
1220
1221val context = subtypeTools.add_reduction2 field_num_carrier context;
1222val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1223
1224val field_mult_small = store_thm
1225  ("field_mult_small",
1226   ``!f :: Field. !x :: (f.carrier).
1227       (field_mult f (field_num f 0) x = field_zero f) /\
1228       (field_mult f (field_num f 1) x = x) /\
1229       (field_mult f (field_num f 2) x = field_add f x x) /\
1230       (field_mult f (field_num f 3) x =
1231        field_add f x (field_mult f (field_num f 2) x))``,
1232   RW_TAC (simpLib.++ (std_ss, numSimps.SUC_FILTER_ss)) [field_num_def]
1233   ++ RW_TAC alg_ss [field_distrib_radd, field_add_assoc]);
1234
1235val field_exp_small = store_thm
1236  ("field_exp_small",
1237   ``!f :: Field. !x :: (f.carrier).
1238       (field_exp f x 0 = field_one f) /\
1239       (field_exp f x 1 = x) /\
1240       (field_exp f x 2 = field_mult f x x) /\
1241       (field_exp f x 3 = field_mult f x (field_exp f x 2)) /\
1242       (field_exp f x 4 = field_mult f x (field_exp f x 3)) /\
1243       (field_exp f x 5 = field_mult f x (field_exp f x 4)) /\
1244       (field_exp f x 6 = field_mult f x (field_exp f x 5)) /\
1245       (field_exp f x 7 = field_mult f x (field_exp f x 6)) /\
1246       (field_exp f x 8 = field_mult f x (field_exp f x 7)) /\
1247       (field_exp f x 9 = field_mult f x (field_exp f x 8))``,
1248   RW_TAC (simpLib.++ (std_ss, numSimps.SUC_FILTER_ss))
1249     [field_exp_def, field_mult_rone]);
1250
1251val field_inv_one = store_thm
1252  ("field_inv_one",
1253   ``!f :: Field. field_inv f (field_one f) = field_one f``,
1254   RW_TAC resq_ss [field_inv_def, field_one_def, Field_def, GSPECIFICATION]
1255   ++ RW_TAC alg_ss []);
1256
1257val context = subtypeTools.add_rewrite2 field_inv_one context;
1258val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1259
1260val field_exp_zero = store_thm
1261  ("field_exp_zero",
1262   ``!f :: Field. !x :: (f.carrier). field_exp f x 0 = field_one f``,
1263   RW_TAC alg_ss [field_exp_def]);
1264
1265val context = subtypeTools.add_rewrite2 field_exp_zero context;
1266val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1267
1268val field_exp_one = store_thm
1269  ("field_exp_one",
1270   ``!f :: Field. !x :: (f.carrier). field_exp f x 1 = x``,
1271   REWRITE_TAC [ONE, field_exp_def]
1272   ++ RW_TAC alg_ss []);
1273
1274val context = subtypeTools.add_rewrite2 field_exp_one context;
1275val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1276
1277val field_neg_add' = store_thm
1278  ("field_neg_add'",
1279   ``!f :: Field. !x y :: (f.carrier).
1280       field_neg f (field_add f x y) =
1281       field_add f (field_neg f y) (field_neg f x)``,
1282   RW_TAC resq_ss
1283     [field_add_def, Field_def, GSPECIFICATION, field_neg_def,
1284      AbelianGroup_def]
1285   ++ match_tac group_inv_mult
1286   ++ RW_TAC std_ss []);
1287
1288val field_neg_add = store_thm
1289  ("field_neg_add",
1290   ``!f :: Field. !x y :: (f.carrier).
1291       field_neg f (field_add f x y) =
1292       field_add f (field_neg f x) (field_neg f y)``,
1293   METIS_TAC [field_neg_carrier, field_add_comm, field_neg_add']);
1294
1295val context = subtypeTools.add_rewrite2'' field_neg_add context;
1296val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1297
1298val field_exp_suc = store_thm
1299  ("field_exp_suc",
1300   ``!f :: Field. !x :: (f.carrier). !n.
1301       field_exp f x (SUC n) = field_mult f (field_exp f x n) x``,
1302   RW_TAC alg_ss [field_exp_def]
1303   ++ METIS_TAC [field_mult_comm, field_exp_carrier]);
1304
1305val field_num_suc = store_thm
1306  ("field_num_suc",
1307   ``!f :: Field. !n.
1308       field_num f (SUC n) = field_add f (field_one f) (field_num f n)``,
1309   RW_TAC alg_ss [field_num_def]
1310   ++ METIS_TAC [field_add_comm, field_one_carrier, field_num_carrier]);
1311
1312val field_num_add = store_thm
1313  ("field_num_add",
1314   ``!f :: Field. !m n.
1315       field_add f (field_num f m) (field_num f n) = field_num f (m + n)``,
1316   RW_TAC resq_ss []
1317   ++ Induct_on `m`
1318   ++ RW_TAC alg_ss []
1319   ++ RW_TAC alg_ss [field_num_suc, ADD, field_add_assoc]);
1320
1321val context = subtypeTools.add_rewrite2 field_num_add context;
1322val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1323
1324val field_num_add' = store_thm
1325  ("field_num_add'",
1326   ``!f :: Field. !m n. !x :: (f.carrier).
1327       field_add f (field_num f m) (field_add f (field_num f n) x) =
1328       field_add f (field_num f (m + n)) x``,
1329   RW_TAC alg_ss [GSYM field_add_assoc, field_num_add]);
1330
1331val context = subtypeTools.add_rewrite2'' field_num_add' context;
1332val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1333
1334val field_num_mult = store_thm
1335  ("field_num_mult",
1336   ``!f :: Field. !m n.
1337       field_mult f (field_num f m) (field_num f n) = field_num f (m * n)``,
1338   RW_TAC resq_ss []
1339   ++ Induct_on `m`
1340   ++ RW_TAC alg_ss []
1341   ++ RW_TAC alg_ss [field_num_def, MULT, field_distrib_radd]);
1342
1343val context = subtypeTools.add_rewrite2 field_num_mult context;
1344val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1345
1346val field_num_mult' = store_thm
1347  ("field_num_mult'",
1348   ``!f :: Field. !m n. !x :: (f.carrier).
1349       field_mult f (field_num f m) (field_mult f (field_num f n) x) =
1350       field_mult f (field_num f (m * n)) x``,
1351   RW_TAC alg_ss [GSYM field_mult_assoc, field_num_mult]);
1352
1353val context = subtypeTools.add_rewrite2'' field_num_mult' context;
1354val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1355
1356val field_num_exp = store_thm
1357  ("field_num_exp",
1358   ``!f :: Field. !m n.
1359       field_exp f (field_num f m) n = field_num f (m ** n)``,
1360   RW_TAC resq_ss []
1361   ++ Induct_on `n`
1362   ++ RW_TAC alg_ss [EXP, field_num_one, field_exp_def]);
1363
1364val context = subtypeTools.add_rewrite2 field_num_exp context;
1365val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1366
1367val field_single_add_single = store_thm
1368  ("field_single_add_single",
1369   ``!f :: Field. !x :: (f.carrier).
1370       field_add f x x = field_mult f (field_num f 2) x``,
1371   RW_TAC alg_ss [field_mult_small]);
1372
1373val context = subtypeTools.add_rewrite2'' field_single_add_single context;
1374val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1375
1376val field_single_add_single' = store_thm
1377  ("field_single_add_single'",
1378   ``!f :: Field. !x y :: (f.carrier).
1379       field_add f x (field_add f x y) =
1380       field_add f (field_mult f (field_num f 2) x) y``,
1381   RW_TAC alg_ss [GSYM field_add_assoc, field_single_add_single]);
1382
1383val context = subtypeTools.add_rewrite2'' field_single_add_single' context;
1384val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1385
1386val field_single_add_mult = store_thm
1387  ("field_single_add_mult",
1388   ``!f :: Field. !x :: (f.carrier). !n.
1389       field_add f x (field_mult f (field_num f n) x) =
1390       field_mult f (field_num f (n + 1)) x``,
1391   RW_TAC bool_ss [field_num_suc, GSYM ADD1]
1392   ++ RW_TAC alg_ss [field_distrib_radd]);
1393
1394val context = subtypeTools.add_rewrite2'' field_single_add_mult context;
1395val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1396
1397val field_single_add_mult' = store_thm
1398  ("field_single_add_mult'",
1399   ``!f :: Field. !x y :: (f.carrier). !n.
1400       field_add f x (field_add f (field_mult f (field_num f n) x) y) =
1401       field_add f (field_mult f (field_num f (n + 1)) x) y``,
1402   RW_TAC alg_ss [GSYM field_add_assoc, field_single_add_mult]);
1403
1404val context = subtypeTools.add_rewrite2'' field_single_add_mult' context;
1405val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1406
1407val field_single_add_neg_mult = store_thm
1408  ("field_single_add_neg_mult",
1409   ``!f :: Field. !x :: (f.carrier). !n.
1410       field_add f x (field_neg f (field_mult f (field_num f n) x)) =
1411       (if n = 0 then x
1412        else field_neg f (field_mult f (field_num f (n - 1)) x))``,
1413   RW_TAC resq_ss []
1414   ++ RW_TAC alg_ss []
1415   ++ Cases_on `n`
1416   ++ RW_TAC alg_ss []
1417   ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd]
1418   ++ RW_TAC alg_ss [field_neg_add, GSYM field_add_assoc]);
1419
1420val context = subtypeTools.add_rewrite2'' field_single_add_neg_mult context;
1421val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1422
1423val field_single_add_neg_mult' = store_thm
1424  ("field_single_add_neg_mult'",
1425   ``!f :: Field. !x y :: (f.carrier). !n.
1426       field_add f x
1427         (field_add f (field_neg f (field_mult f (field_num f n) x)) y) =
1428       (if n = 0 then field_add f x y
1429        else field_add f
1430               (field_neg f (field_mult f (field_num f (n - 1)) x)) y)``,
1431   RW_TAC alg_ss [GSYM field_add_assoc, field_single_add_neg_mult]
1432   ++ RW_TAC resq_ss []
1433   ++ RW_TAC resq_ss []);
1434
1435val context = subtypeTools.add_rewrite2'' field_single_add_neg_mult' context;
1436val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1437
1438val field_mult_add_mult = store_thm
1439  ("field_mult_add_mult",
1440   ``!f :: Field. !x :: (f.carrier). !m n.
1441       field_add f (field_mult f (field_num f m) x)
1442         (field_mult f (field_num f n) x) =
1443       field_mult f (field_num f (m + n)) x``,
1444   RW_TAC resq_ss []
1445   ++ Induct_on `m`
1446   ++ RW_TAC alg_ss []
1447   ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd, ADD]
1448   ++ POP_ASSUM (fn th => REWRITE_TAC [GSYM th])
1449   ++ RW_TAC alg_ss [field_add_assoc]);
1450
1451val context = subtypeTools.add_rewrite2'' field_mult_add_mult context;
1452val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1453
1454val field_mult_add_mult' = store_thm
1455  ("field_mult_add_mult'",
1456   ``!f :: Field. !x y :: (f.carrier). !m n.
1457       field_add f (field_mult f (field_num f m) x)
1458         (field_add f (field_mult f (field_num f n) x) y) =
1459       field_add f (field_mult f (field_num f (m + n)) x) y``,
1460   RW_TAC alg_ss [GSYM field_add_assoc, field_mult_add_mult]);
1461
1462val context = subtypeTools.add_rewrite2'' field_mult_add_mult' context;
1463val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1464
1465val field_mult_add_neg = store_thm
1466  ("field_mult_add_neg",
1467   ``!f :: Field. !x :: (f.carrier). !n.
1468       field_add f (field_mult f (field_num f n) x) (field_neg f x) =
1469       (if n = 0 then field_neg f x
1470        else field_mult f (field_num f (n - 1)) x)``,
1471   RW_TAC resq_ss []
1472   ++ RW_TAC alg_ss []
1473   ++ Cases_on `n`
1474   ++ RW_TAC alg_ss []
1475   ++ RW_TAC alg_ss [field_num_def, field_distrib_radd, field_add_assoc]);
1476
1477val context = subtypeTools.add_rewrite2'' field_mult_add_neg context;
1478val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1479
1480val field_mult_add_neg' = store_thm
1481  ("field_mult_add_neg'",
1482   ``!f :: Field. !x y :: (f.carrier). !n.
1483       field_add f (field_mult f (field_num f n) x)
1484         (field_add f (field_neg f x) y) =
1485       (if n = 0 then field_add f (field_neg f x) y
1486        else field_add f (field_mult f (field_num f (n - 1)) x) y)``,
1487   RW_TAC alg_ss [GSYM field_add_assoc, field_mult_add_neg]
1488   ++ RW_TAC resq_ss []
1489   ++ RW_TAC resq_ss []);
1490
1491val context = subtypeTools.add_rewrite2'' field_mult_add_neg' context;
1492val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1493
1494val field_mult_add_neg_mult = store_thm
1495  ("field_mult_add_neg_mult",
1496   ``!f :: Field. !x :: (f.carrier). !m n.
1497       field_add f (field_mult f (field_num f m) x)
1498         (field_neg f (field_mult f (field_num f n) x)) =
1499       (if m < n then field_neg f (field_mult f (field_num f (n - m)) x)
1500        else field_mult f (field_num f (m - n)) x)``,
1501   RW_TAC resq_ss []
1502   ++ RW_TAC alg_ss []
1503   << [Know `m <= n` >> DECIDE_TAC
1504       ++ POP_ASSUM (K ALL_TAC)
1505       ++ Induct_on `m`
1506       ++ RW_TAC alg_ss []
1507       ++ Cases_on `n = SUC m` >> RW_TAC alg_ss' []
1508       ++ Q.PAT_ASSUM `X ==> Y` MP_TAC
1509       ++ MATCH_MP_TAC (PROVE [] ``a /\ (b ==> c) ==> ((a ==> b) ==> c)``)
1510       ++ CONJ_TAC >> DECIDE_TAC
1511       ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd, field_add_assoc]
1512       ++ Know `n - m = SUC (n - SUC m)` >> DECIDE_TAC
1513       ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd,
1514                         GSYM field_add_assoc, field_neg_add],
1515       Know `n <= m` >> DECIDE_TAC
1516       ++ POP_ASSUM (K ALL_TAC)
1517       ++ Induct_on `m`
1518       ++ RW_TAC alg_ss []
1519       ++ Cases_on `n = SUC m` >> RW_TAC alg_ss' []
1520       ++ Q.PAT_ASSUM `X ==> Y` MP_TAC
1521       ++ MATCH_MP_TAC (PROVE [] ``a /\ (b ==> c) ==> ((a ==> b) ==> c)``)
1522       ++ CONJ_TAC >> DECIDE_TAC
1523       ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd, field_add_assoc]
1524       ++ Know `SUC m - n = SUC (m - n)` >> DECIDE_TAC
1525       ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd,
1526                         GSYM field_add_assoc, field_neg_add]]);
1527
1528val context = subtypeTools.add_rewrite2'' field_mult_add_neg_mult context;
1529val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1530
1531val field_mult_add_neg_mult' = store_thm
1532  ("field_mult_add_neg_mult'",
1533   ``!f :: Field. !x y :: (f.carrier). !m n.
1534       field_add f (field_mult f (field_num f m) x)
1535         (field_add f (field_neg f (field_mult f (field_num f n) x)) y) =
1536       (if m < n then
1537          field_add f (field_neg f (field_mult f (field_num f (n - m)) x)) y
1538        else field_add f (field_mult f (field_num f (m - n)) x) y)``,
1539   RW_TAC alg_ss [GSYM field_add_assoc, field_mult_add_neg_mult]
1540   ++ RW_TAC resq_ss []
1541   ++ RW_TAC resq_ss []);
1542
1543val context = subtypeTools.add_rewrite2'' field_mult_add_neg_mult' context;
1544val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1545
1546val field_neg_add_neg = store_thm
1547  ("field_neg_add_neg",
1548   ``!f :: Field. !x :: (f.carrier).
1549       field_add f (field_neg f x) (field_neg f x) =
1550       field_neg f (field_mult f (field_num f 2) x)``,
1551   RW_TAC alg_ss [field_mult_small, field_neg_add]);
1552
1553val context = subtypeTools.add_rewrite2'' field_neg_add_neg context;
1554val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1555
1556val field_neg_add_neg' = store_thm
1557  ("field_neg_add_neg'",
1558   ``!f :: Field. !x y :: (f.carrier).
1559       field_add f (field_neg f x) (field_add f (field_neg f x) y) =
1560       field_add f (field_neg f (field_mult f (field_num f 2) x)) y``,
1561   RW_TAC alg_ss [GSYM field_add_assoc, field_neg_add_neg]);
1562
1563val context = subtypeTools.add_rewrite2'' field_neg_add_neg' context;
1564val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1565
1566val field_neg_add_neg_mult = store_thm
1567  ("field_neg_add_neg_mult",
1568   ``!f :: Field. !x :: (f.carrier). !n.
1569       field_add f (field_neg f x)
1570         (field_neg f (field_mult f (field_num f n) x)) =
1571       field_neg f (field_mult f (field_num f (n + 1)) x)``,
1572   RW_TAC alg_ss [GSYM field_single_add_mult]
1573   ++ RW_TAC alg_ss' []);
1574
1575val context = subtypeTools.add_rewrite2'' field_neg_add_neg_mult context;
1576val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1577
1578val field_neg_add_neg_mult' = store_thm
1579  ("field_neg_add_neg_mult'",
1580   ``!f :: Field. !x y :: (f.carrier). !n.
1581       field_add f (field_neg f x)
1582         (field_add f (field_neg f (field_mult f (field_num f n) x)) y) =
1583       field_add f (field_neg f (field_mult f (field_num f (n + 1)) x)) y``,
1584   RW_TAC alg_ss [GSYM field_add_assoc, field_neg_add_neg_mult]);
1585
1586val context = subtypeTools.add_rewrite2'' field_neg_add_neg_mult' context;
1587val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1588
1589val field_neg_mult_add_neg_mult = store_thm
1590  ("field_neg_mult_add_neg_mult",
1591   ``!f :: Field. !x :: (f.carrier). !m n.
1592       field_add f (field_neg f (field_mult f (field_num f m) x))
1593         (field_neg f (field_mult f (field_num f n) x)) =
1594       field_neg f (field_mult f (field_num f (m + n)) x)``,
1595   RW_TAC resq_ss []
1596   ++ Induct_on `m`
1597   ++ RW_TAC alg_ss []
1598   ++ RW_TAC alg_ss [field_num_suc, field_distrib_radd, ADD, field_neg_add]
1599   ++ POP_ASSUM (fn th => REWRITE_TAC [GSYM th])
1600   ++ RW_TAC alg_ss [field_add_assoc]);
1601
1602val context = subtypeTools.add_rewrite2'' field_neg_mult_add_neg_mult context;
1603val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1604
1605val field_neg_mult_add_neg_mult' = store_thm
1606  ("field_neg_mult_add_neg_mult'",
1607   ``!f :: Field. !x y :: (f.carrier). !m n.
1608       field_add f (field_neg f (field_mult f (field_num f m) x))
1609         (field_add f (field_neg f (field_mult f (field_num f n) x)) y) =
1610       field_add f (field_neg f (field_mult f (field_num f (m + n)) x)) y``,
1611   RW_TAC alg_ss [GSYM field_add_assoc, field_neg_mult_add_neg_mult]);
1612
1613val context = subtypeTools.add_rewrite2'' field_neg_mult_add_neg_mult' context;
1614val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1615
1616val field_single_mult_single = store_thm
1617  ("field_single_mult_single",
1618   ``!f :: Field. !x :: (f.carrier). field_mult f x x = field_exp f x 2``,
1619   RW_TAC alg_ss' [field_exp_small]);
1620
1621val context = subtypeTools.add_rewrite2'' field_single_mult_single context;
1622val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1623
1624val field_single_mult_single' = store_thm
1625  ("field_single_mult_single'",
1626   ``!f :: Field. !x y :: (f.carrier).
1627       field_mult f x (field_mult f x y) = field_mult f (field_exp f x 2) y``,
1628   RW_TAC alg_ss [GSYM field_mult_assoc, field_single_mult_single]);
1629
1630val context = subtypeTools.add_rewrite2'' field_single_mult_single' context;
1631val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1632
1633val field_single_mult_exp = store_thm
1634  ("field_single_mult_exp",
1635   ``!f :: Field. !x :: (f.carrier). !n.
1636       field_mult f x (field_exp f x n) = field_exp f x (n + 1)``,
1637   METIS_TAC [field_exp_def, ADD1]);
1638
1639val context = subtypeTools.add_rewrite2'' field_single_mult_exp context;
1640val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1641
1642val field_single_mult_exp' = store_thm
1643  ("field_single_mult_exp'",
1644   ``!f :: Field. !x y :: (f.carrier). !n.
1645       field_mult f x (field_mult f (field_exp f x n) y) =
1646       field_mult f (field_exp f x (n + 1)) y``,
1647   RW_TAC alg_ss [GSYM field_mult_assoc, field_single_mult_exp]);
1648
1649val context = subtypeTools.add_rewrite2'' field_single_mult_exp' context;
1650val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1651
1652val field_single_mult_inv_exp = store_thm
1653  ("field_single_mult_inv_exp",
1654   ``!f :: Field. !x :: field_nonzero f. !n.
1655       field_mult f x (field_inv f (field_exp f x n)) =
1656       (if n = 0 then x else field_inv f (field_exp f x (n - 1)))``,
1657   RW_TAC resq_ss []
1658   ++ RW_TAC alg_ss []
1659   ++ Cases_on `n`
1660   ++ RW_TAC alg_ss []
1661   ++ RW_TAC alg_ss [field_exp_def, GSYM field_mult_assoc, field_inv_mult]);
1662
1663val context = subtypeTools.add_rewrite2'' field_single_mult_inv_exp context;
1664val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1665
1666val field_single_mult_inv_exp' = store_thm
1667  ("field_single_mult_inv_exp'",
1668   ``!f :: Field. !x :: field_nonzero f. !n. !y :: (f.carrier).
1669       field_mult f x (field_mult f (field_inv f (field_exp f x n)) y) =
1670       (if n = 0 then field_mult f x y
1671        else field_mult f (field_inv f (field_exp f x (n - 1))) y)``,
1672   RW_TAC alg_ss [GSYM field_mult_assoc, field_single_mult_inv_exp]
1673   ++ RW_TAC resq_ss []
1674   ++ RW_TAC resq_ss []);
1675
1676val context = subtypeTools.add_rewrite2'' field_single_mult_inv_exp' context;
1677val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1678
1679val field_exp_mult_exp = store_thm
1680  ("field_exp_mult_exp",
1681   ``!f :: Field. !x :: (f.carrier). !m n.
1682       field_mult f (field_exp f x m) (field_exp f x n) =
1683       field_exp f x (m + n)``,
1684   RW_TAC resq_ss []
1685   ++ Induct_on `m`
1686   ++ RW_TAC alg_ss []
1687   ++ RW_TAC alg_ss [field_exp_def, ADD_CLAUSES]
1688   ++ POP_ASSUM (fn th => REWRITE_TAC [GSYM th])
1689   ++ RW_TAC alg_ss [field_mult_assoc]);
1690
1691val context = subtypeTools.add_rewrite2'' field_exp_mult_exp context;
1692val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1693
1694val field_exp_mult_exp' = store_thm
1695  ("field_exp_mult_exp'",
1696   ``!f :: Field. !x y :: (f.carrier). !m n.
1697       field_mult f (field_exp f x m) (field_mult f (field_exp f x n) y) =
1698       field_mult f (field_exp f x (m + n)) y``,
1699   RW_TAC alg_ss [GSYM field_mult_assoc, field_exp_mult_exp]);
1700
1701val context = subtypeTools.add_rewrite2'' field_exp_mult_exp' context;
1702val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1703
1704val field_exp_mult_inv = store_thm
1705  ("field_exp_mult_inv",
1706   ``!f :: Field. !x :: field_nonzero f. !n.
1707       field_mult f (field_exp f x n) (field_inv f x) =
1708       (if n = 0 then field_inv f x else field_exp f x (n - 1))``,
1709   RW_TAC resq_ss []
1710   ++ RW_TAC alg_ss []
1711   ++ Cases_on `n`
1712   ++ RW_TAC alg_ss []
1713   ++ RW_TAC alg_ss [field_exp_suc, field_mult_assoc]);
1714
1715val context = subtypeTools.add_rewrite2'' field_exp_mult_inv context;
1716val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1717
1718val field_exp_mult_inv' = store_thm
1719  ("field_exp_mult_inv'",
1720   ``!f :: Field. !x :: field_nonzero f. !n. !y :: (f.carrier).
1721       field_mult f (field_exp f x n) (field_mult f (field_inv f x) y) =
1722       (if n = 0 then field_mult f (field_inv f x) y
1723        else field_mult f (field_exp f x (n - 1)) y)``,
1724   RW_TAC alg_ss [GSYM field_mult_assoc, field_exp_mult_inv]
1725   ++ RW_TAC resq_ss []
1726   ++ RW_TAC resq_ss []);
1727
1728val context = subtypeTools.add_rewrite2'' field_exp_mult_inv' context;
1729val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1730
1731val field_exp_mult_inv_exp = store_thm
1732  ("field_exp_mult_inv_exp",
1733   ``!f :: Field. !x :: field_nonzero f. !m n.
1734       field_mult f (field_exp f x m) (field_inv f (field_exp f x n)) =
1735       (if m < n then field_inv f (field_exp f x (n - m))
1736        else field_exp f x (m - n))``,
1737   RW_TAC resq_ss []
1738   ++ RW_TAC alg_ss []
1739   << [Know `m <= n` >> DECIDE_TAC
1740       ++ POP_ASSUM (K ALL_TAC)
1741       ++ Induct_on `m`
1742       ++ RW_TAC alg_ss []
1743       ++ Cases_on `n = SUC m` >> RW_TAC alg_ss []
1744       ++ Q.PAT_ASSUM `X ==> Y` MP_TAC
1745       ++ MATCH_MP_TAC (PROVE [] ``a /\ (b ==> c) ==> ((a ==> b) ==> c)``)
1746       ++ CONJ_TAC >> DECIDE_TAC
1747       ++ RW_TAC alg_ss [field_exp_def, field_mult_assoc]
1748       ++ Know `n - m = SUC (n - SUC m)` >> DECIDE_TAC
1749       ++ RW_TAC alg_ss [field_exp_def, GSYM field_mult_assoc, field_inv_mult],
1750       Know `n <= m` >> DECIDE_TAC
1751       ++ POP_ASSUM (K ALL_TAC)
1752       ++ Induct_on `m`
1753       ++ RW_TAC alg_ss []
1754       ++ Cases_on `n = SUC m` >> RW_TAC alg_ss []
1755       ++ Q.PAT_ASSUM `X ==> Y` MP_TAC
1756       ++ MATCH_MP_TAC (PROVE [] ``a /\ (b ==> c) ==> ((a ==> b) ==> c)``)
1757       ++ CONJ_TAC >> DECIDE_TAC
1758       ++ RW_TAC alg_ss [field_exp_def, field_mult_assoc]
1759       ++ Know `SUC m - n = SUC (m - n)` >> DECIDE_TAC
1760       ++ RW_TAC alg_ss [field_exp_def, GSYM field_mult_assoc]]);
1761
1762val context = subtypeTools.add_rewrite2'' field_exp_mult_inv_exp context;
1763val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1764
1765val field_exp_mult_inv_exp' = store_thm
1766  ("field_exp_mult_inv_exp'",
1767   ``!f :: Field. !x :: field_nonzero f. !m n. !y :: (f.carrier).
1768       field_mult f (field_exp f x m)
1769         (field_mult f (field_inv f (field_exp f x n)) y) =
1770       (if m < n then field_mult f (field_inv f (field_exp f x (n - m))) y
1771        else field_mult f (field_exp f x (m - n)) y)``,
1772   RW_TAC alg_ss [GSYM field_mult_assoc, field_exp_mult_inv_exp]
1773   ++ RW_TAC resq_ss []
1774   ++ RW_TAC resq_ss []);
1775
1776val context = subtypeTools.add_rewrite2'' field_exp_mult_inv_exp' context;
1777val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1778
1779val field_inv_mult_inv = store_thm
1780  ("field_inv_mult_inv",
1781   ``!f :: Field. !x :: field_nonzero f.
1782       field_mult f (field_inv f x) (field_inv f x) =
1783       field_inv f (field_exp f x 2)``,
1784   RW_TAC alg_ss [field_exp_small, field_inv_mult]);
1785
1786val context = subtypeTools.add_rewrite2'' field_inv_mult_inv context;
1787val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1788
1789val field_inv_mult_inv' = store_thm
1790  ("field_inv_mult_inv'",
1791   ``!f :: Field. !x :: field_nonzero f. !y :: (f.carrier).
1792       field_mult f (field_inv f x) (field_mult f (field_inv f x) y) =
1793       field_mult f (field_inv f (field_exp f x 2)) y``,
1794   RW_TAC alg_ss [GSYM field_mult_assoc, field_inv_mult_inv]);
1795
1796val context = subtypeTools.add_rewrite2'' field_inv_mult_inv' context;
1797val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1798
1799val field_inv_mult_inv_exp = store_thm
1800  ("field_inv_mult_inv_exp",
1801   ``!f :: Field. !x :: field_nonzero f. !n.
1802       field_mult f (field_inv f x) (field_inv f (field_exp f x n)) =
1803       field_inv f (field_exp f x (n + 1))``,
1804   RW_TAC alg_ss [GSYM field_single_mult_exp]
1805   ++ RW_TAC alg_ss' []);
1806
1807val context = subtypeTools.add_rewrite2'' field_inv_mult_inv_exp context;
1808val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1809
1810val field_inv_mult_inv_exp' = store_thm
1811  ("field_inv_mult_inv_exp'",
1812   ``!f :: Field. !x :: field_nonzero f. !n. !y :: (f.carrier).
1813       field_mult f (field_inv f x)
1814         (field_mult f (field_inv f (field_exp f x n)) y) =
1815       field_mult f (field_inv f (field_exp f x (n + 1))) y``,
1816   RW_TAC alg_ss [GSYM field_mult_assoc, field_inv_mult_inv_exp]);
1817
1818val context = subtypeTools.add_rewrite2'' field_inv_mult_inv_exp' context;
1819val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1820
1821val field_inv_exp_mult_inv_exp = store_thm
1822  ("field_inv_exp_mult_inv_exp",
1823   ``!f :: Field. !x :: field_nonzero f. !m n.
1824       field_mult f (field_inv f (field_exp f x m))
1825         (field_inv f (field_exp f x n)) =
1826       field_inv f (field_exp f x (m + n))``,
1827   RW_TAC resq_ss []
1828   ++ Induct_on `m`
1829   ++ RW_TAC alg_ss []
1830   ++ RW_TAC alg_ss [field_exp_def, ADD_CLAUSES, field_inv_mult]
1831   ++ POP_ASSUM (fn th => REWRITE_TAC [GSYM th])
1832   ++ RW_TAC alg_ss [field_mult_assoc]);
1833
1834val context = subtypeTools.add_rewrite2'' field_inv_exp_mult_inv_exp context;
1835val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1836
1837val field_inv_exp_mult_inv_exp' = store_thm
1838  ("field_inv_exp_mult_inv_exp'",
1839   ``!f :: Field. !x :: field_nonzero f. !m n. !y :: (f.carrier).
1840       field_mult f (field_inv f (field_exp f x m))
1841         (field_mult f (field_inv f (field_exp f x n)) y) =
1842       field_mult f (field_inv f (field_exp f x (m + n))) y``,
1843   RW_TAC alg_ss [GSYM field_mult_assoc, field_inv_exp_mult_inv_exp]);
1844
1845val context = subtypeTools.add_rewrite2'' field_inv_exp_mult_inv_exp' context;
1846val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1847
1848val field_one_exp = store_thm
1849  ("field_one_exp",
1850   ``!f :: Field. !n. field_exp f (field_one f) n = field_one f``,
1851   RW_TAC resq_ss []
1852   ++ Induct_on `n`
1853   ++ RW_TAC std_ss [field_exp_def, field_mult_rone, field_one_carrier]);
1854
1855val context = subtypeTools.add_rewrite2 field_one_exp context;
1856val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1857
1858val field_zero_exp = store_thm
1859  ("field_zero_exp",
1860   ``!f :: Field. !n.
1861       field_exp f (field_zero f) n =
1862       (if n = 0 then field_one f else field_zero f)``,
1863   RW_TAC resq_ss []
1864   ++ Induct_on `n`
1865   ++ RW_TAC std_ss
1866        [field_exp_def, field_mult_rone, field_one_carrier]
1867   ++ RW_TAC alg_ss []);
1868
1869val context = subtypeTools.add_rewrite2 field_zero_exp context;
1870val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1871
1872val field_exp_eq_zero = store_thm
1873  ("field_exp_eq_zero",
1874   ``!f :: Field. !x :: (f.carrier). !n.
1875       (field_exp f x n = field_zero f) = ~(n = 0) /\ (x = field_zero f)``,
1876   RW_TAC resq_ss []
1877   ++ Induct_on `n`
1878   ++ RW_TAC std_ss
1879        [field_exp_def, field_one_zero, field_entire, field_exp_carrier]
1880   ++ METIS_TAC []);
1881
1882val context = subtypeTools.add_rewrite2 field_exp_eq_zero context;
1883val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1884
1885val field_exp_neg = store_thm
1886  ("field_exp_neg",
1887   ``!f :: Field. !x :: (f.carrier). !n.
1888       field_exp f (field_neg f x) n =
1889       if EVEN n then field_exp f x n else field_neg f (field_exp f x n)``,
1890   RW_TAC resq_ss []
1891   ++ Induct_on `n`
1892   ++ RW_TAC alg_ss [EVEN, field_exp_def]);
1893
1894val context = subtypeTools.add_rewrite2'' field_exp_neg context;
1895val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1896
1897val field_exp_exp = store_thm
1898  ("field_exp_exp",
1899   ``!f :: Field. !x :: (f.carrier). !m n.
1900       field_exp f (field_exp f x m) n = field_exp f x (m * n)``,
1901   RW_TAC resq_ss []
1902   ++ Induct_on `n`
1903   >> RW_TAC alg_ss [field_exp_def]
1904   ++ RW_TAC alg_ss [field_exp_def, ONCE_REWRITE_RULE [MULT_COMM] MULT]
1905   ++ ONCE_REWRITE_TAC [ADD_COMM]
1906   ++ RW_TAC alg_ss [GSYM field_exp_mult_exp]);
1907
1908val context = subtypeTools.add_rewrite2'' field_exp_exp context;
1909val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1910
1911val field_sub_eq_zero = store_thm
1912  ("field_sub_eq_zero",
1913   ``!f :: Field. !x y :: (f.carrier).
1914       (field_sub f x y = field_zero f) = (x = y)``,
1915   RW_TAC resq_ss []
1916   ++ RW_TAC alg_ss' []
1917   ++ RW_TAC alg_ss [GSYM field_neg_eq]);
1918
1919local
1920  val field_sub_eq_zero_conv =
1921      let
1922        val th = CONV_RULE RES_FORALL_CONV (GSYM field_sub_eq_zero)
1923      in
1924        fn f => cond_rewr_conv (ISPEC f th)
1925      end;
1926
1927  fun left_conv solver tm =
1928      let
1929        val (x,y) = dest_eq tm
1930        val _ = not (is_field_zero y) orelse
1931                raise ERR "field_sub_eq_zero_conv (left)" "looping"
1932        val (f,_,_) = dest_field_add x
1933      in
1934        field_sub_eq_zero_conv f solver
1935      end tm;
1936
1937  fun right_conv solver tm =
1938      let
1939        val (_,y) = dest_eq tm
1940        val (f,_,_) = dest_field_add y
1941(***
1942        val _ = print "right_conv\n";
1943***)
1944      in
1945        field_sub_eq_zero_conv f solver
1946      end tm;
1947in
1948  val field_sub_eq_zero_l_conv =
1949      {name = "field_sub_eq_zero_conv (left)",
1950       key = ``field_add (f : 'a field) x y = z``,
1951       conv = left_conv}
1952  and field_sub_eq_zero_r_conv =
1953      {name = "field_sub_eq_zero_conv (right)",
1954       key = ``x = field_add (f : 'a field) y z``,
1955       conv = right_conv};
1956end;
1957
1958val context = subtypeTools.add_conversion2'' field_sub_eq_zero_r_conv context;
1959val context = subtypeTools.add_conversion2'' field_sub_eq_zero_l_conv context;
1960val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1961
1962val field_sub_eq_zero_imp = store_thm
1963  ("field_sub_eq_zero_imp",
1964   ``!f :: Field. !x y :: (f.carrier).
1965       (field_sub f x y = field_zero f) ==> (x = y)``,
1966   RW_TAC std_ss [field_sub_eq_zero]);
1967
1968val field_inv_inv = store_thm
1969  ("field_inv_inv",
1970   ``!f :: Field. !x :: field_nonzero f. field_inv f (field_inv f x) = x``,
1971   RW_TAC resq_ss
1972     [field_inv_def, Field_def, GSPECIFICATION, AbelianGroup_def,
1973      field_nonzero_def]
1974   ++ METIS_TAC [group_inv_inv]);
1975
1976val context = subtypeTools.add_rewrite2 field_inv_inv context;
1977val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1978
1979val field_sub_carrier = store_thm
1980  ("field_sub_carrier",
1981   ``!f :: Field. !x y :: (f.carrier). field_sub f x y IN f.carrier``,
1982   RW_TAC resq_ss []
1983   ++ RW_TAC alg_ss' []);
1984
1985val context = subtypeTools.add_reduction2 field_sub_carrier context;
1986val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
1987
1988val field_neg_nonzero = store_thm
1989  ("field_neg_nonzero",
1990   ``!f :: Field. !x :: field_nonzero f. field_neg f x IN field_nonzero f``,
1991   RW_TAC resq_ss []
1992   ++ RW_TAC alg_ss [GSYM field_nonzero_eq]
1993   ++ POP_ASSUM MP_TAC
1994   ++ RW_TAC alg_ss [field_nonzero_def, GSPECIFICATION, IN_DIFF, IN_SING]
1995   ++ STRIP_TAC
1996   ++ Q.PAT_ASSUM `~(X = Y)` MP_TAC
1997   ++ RW_TAC alg_ss []
1998   ++ match_tac field_add_lcancel_imp
1999   ++ Q.EXISTS_TAC `f`
2000   ++ Q.EXISTS_TAC `field_neg f x`
2001   ++ RW_TAC std_ss [field_lneg]
2002   ++ RW_TAC alg_ss []);
2003
2004val context = subtypeTools.add_reduction2 field_neg_nonzero context;
2005val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2006
2007val field_inv_neg = store_thm
2008  ("field_inv_neg",
2009   ``!f :: Field. !x :: field_nonzero f.
2010       field_inv f (field_neg f x) = field_neg f (field_inv f x)``,
2011   RW_TAC resq_ss []
2012   ++ match_tac field_mult_lcancel_imp
2013   ++ Q.EXISTS_TAC `f`
2014   ++ Q.EXISTS_TAC `field_neg f x`
2015   ++ SIMP_TAC bool_ss [CONJ_ASSOC]
2016   ++ CONJ_TAC >> RW_TAC alg_ss []
2017   ++ Know
2018      `field_mult f (field_neg f x) (field_inv f (field_neg f x)) = field_one f`
2019   >> (match_tac field_rinv ++ RW_TAC alg_ss [])
2020   ++ RW_TAC std_ss []
2021   ++ RW_TAC alg_ss' []);
2022
2023val context = subtypeTools.add_rewrite2'' field_inv_neg context;
2024val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2025
2026val field_exp_mult = store_thm
2027  ("field_exp_mult",
2028   ``!f :: Field. !x y :: (f.carrier). !n.
2029       field_exp f (field_mult f x y) n =
2030       field_mult f (field_exp f x n) (field_exp f y n)``,
2031   RW_TAC resq_ss []
2032   ++ Induct_on `n`
2033   ++ RW_TAC alg_ss [field_exp_def]
2034   ++ RW_TAC alg_ss [field_mult_assoc]
2035   ++ AP_TERM_TAC
2036   ++ RW_TAC alg_ss [GSYM field_mult_assoc]
2037   ++ AP_THM_TAC
2038   ++ AP_TERM_TAC
2039   ++ match_tac field_mult_comm
2040   ++ RW_TAC alg_ss []);
2041
2042val context = subtypeTools.add_rewrite2'' field_exp_mult context;
2043val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2044
2045val field_exp_inv = store_thm
2046  ("field_exp_inv",
2047   ``!f :: Field. !x :: field_nonzero f. !n.
2048       field_exp f (field_inv f x) n = field_inv f (field_exp f x n)``,
2049   RW_TAC resq_ss []
2050   ++ Induct_on `n`
2051   ++ RW_TAC alg_ss []
2052   ++ RW_TAC alg_ss [field_exp_def]
2053   ++ RW_TAC alg_ss' []);
2054
2055val context = subtypeTools.add_rewrite2'' field_exp_inv context;
2056val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2057
2058val field_add_ac_conv =
2059    {name = "field_add_ac_conv",
2060     key = ``field_add f x y``,
2061     conv =
2062       subtypeTools.binop_ac_conv
2063         {term_compare = field_compare,
2064          dest_binop = dest_field_add,
2065          dest_inv = dest_field_neg,
2066          dest_exp = dest_field_num_mult,
2067          assoc_th = field_add_assoc,
2068          comm_th = field_add_comm,
2069          comm_th' = field_add_comm',
2070          id_ths =
2071            [field_add_lzero,
2072             field_add_lzero',
2073             field_add_rzero,
2074             field_add_rzero'],
2075          simplify_ths =
2076            [GSYM field_num_one,
2077             field_neg_zero,
2078             field_neg_neg,
2079             field_neg_add,
2080             field_mult_lzero,
2081             field_mult_lzero',
2082             field_mult_rzero,
2083             field_mult_rzero',
2084             field_mult_lone,
2085             field_mult_lone',
2086             field_mult_rone,
2087             field_mult_rone'],
2088          combine_ths =
2089            [field_single_add_single,
2090             field_single_add_mult,
2091             field_rneg,
2092             field_single_add_neg_mult,
2093             field_mult_add_mult,
2094             field_mult_add_neg,
2095             field_mult_add_neg_mult,
2096             field_neg_add_neg,
2097             field_neg_add_neg_mult,
2098             field_neg_mult_add_neg_mult],
2099          combine_ths' =
2100            [field_single_add_single',
2101             field_single_add_mult',
2102             field_rneg',
2103             field_single_add_neg_mult',
2104             field_mult_add_mult',
2105             field_mult_add_neg',
2106             field_mult_add_neg_mult',
2107             field_neg_add_neg',
2108             field_neg_add_neg_mult',
2109             field_neg_mult_add_neg_mult']}};
2110
2111val context = subtypeTools.add_conversion2'' field_add_ac_conv context;
2112val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2113
2114val field_mult_ac_conv =
2115    {name = "field_mult_ac_conv",
2116     key = ``field_mult f x y``,
2117     conv =
2118       subtypeTools.binop_ac_conv
2119         {term_compare = field_compare,
2120          dest_binop = dest_field_mult,
2121          dest_inv = dest_field_inv,
2122          dest_exp = dest_field_exp,
2123          assoc_th = field_mult_assoc,
2124          comm_th = field_mult_comm,
2125          comm_th' = field_mult_comm',
2126          id_ths =
2127            [field_mult_lone,
2128             field_mult_lone',
2129             field_mult_rone,
2130             field_mult_rone'],
2131          simplify_ths =
2132            [field_inv_one,
2133             field_inv_inv,
2134             field_inv_mult,
2135             field_exp_zero,
2136             field_exp_one,
2137             field_exp_exp,
2138             field_exp_mult,
2139             field_exp_inv],
2140          combine_ths =
2141            [field_single_mult_single,
2142             field_single_mult_exp,
2143             field_rinv,
2144             field_single_mult_inv_exp,
2145             field_exp_mult_exp,
2146             field_exp_mult_inv,
2147             field_exp_mult_inv_exp,
2148             field_inv_mult_inv,
2149             field_inv_mult_inv_exp,
2150             field_inv_exp_mult_inv_exp],
2151          combine_ths' =
2152            [field_single_mult_single',
2153             field_single_mult_exp',
2154             field_rinv',
2155             field_single_mult_inv_exp',
2156             field_exp_mult_exp',
2157             field_exp_mult_inv',
2158             field_exp_mult_inv_exp',
2159             field_inv_mult_inv',
2160             field_inv_mult_inv_exp',
2161             field_inv_exp_mult_inv_exp']}};
2162
2163val context = subtypeTools.add_conversion2'' field_mult_ac_conv context;
2164val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2165
2166val field_binomial_2 = store_thm
2167  ("field_binomial_2",
2168   ``!f :: Field. !x y :: (f.carrier).
2169       field_exp f (field_add f x y) 2 =
2170       field_add f (field_exp f x 2)
2171         (field_add f (field_mult f (field_num f 2) (field_mult f x y))
2172            (field_exp f y 2))``,
2173   RW_TAC alg_ss [field_exp_small]
2174   ++ RW_TAC alg_ss' [field_distrib]);
2175
2176val field_binomial_3 = store_thm
2177  ("field_binomial_3",
2178   ``!f :: Field. !x y :: (f.carrier).
2179       field_exp f (field_add f x y) 3 =
2180       field_add f
2181         (field_exp f x 3)
2182         (field_add f
2183           (field_mult f (field_num f 3) (field_mult f (field_exp f x 2) y))
2184           (field_add f
2185             (field_mult f (field_num f 3) (field_mult f x (field_exp f y 2)))
2186             (field_exp f y 3)))``,
2187   RW_TAC alg_ss [field_exp_small]
2188   ++ RW_TAC alg_ss' [field_distrib, field_binomial_2]);
2189
2190val field_binomial_4 = store_thm
2191  ("field_binomial_4",
2192   ``!f :: Field. !x y :: (f.carrier).
2193       field_exp f (field_add f x y) 4 =
2194       field_add f
2195         (field_exp f x 4)
2196         (field_add f
2197           (field_mult f (field_num f 4) (field_mult f (field_exp f x 3) y))
2198           (field_add f
2199             (field_mult f
2200               (field_num f 6)
2201               (field_mult f (field_exp f x 2) (field_exp f y 2)))
2202             (field_add f
2203               (field_mult f (field_num f 4) (field_mult f x (field_exp f y 3)))
2204               (field_exp f y 4))))``,
2205   RW_TAC alg_ss [field_exp_small]
2206   ++ RW_TAC alg_ss' [field_distrib, field_binomial_2, field_binomial_3]);
2207
2208val field_div_carrier = store_thm
2209  ("field_div_carrier",
2210   ``!f :: Field. !x :: (f.carrier). !y :: field_nonzero f.
2211       field_div f x y IN f.carrier``,
2212   RW_TAC resq_ss []
2213   ++ RW_TAC alg_ss' [field_div_def]);
2214
2215val context = subtypeTools.add_reduction2 field_div_carrier context;
2216val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2217
2218val field_div_nonzero = store_thm
2219  ("field_div_nonzero",
2220   ``!f :: Field. !x y :: field_nonzero f. field_div f x y IN field_nonzero f``,
2221   RW_TAC resq_ss []
2222   ++ RW_TAC alg_ss' [field_div_def]);
2223
2224val context = subtypeTools.add_reduction2 field_div_nonzero context;
2225val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2226
2227val field_div_lneg = store_thm
2228  ("field_div_lneg",
2229   ``!f :: Field. !x :: (f.carrier). !y :: field_nonzero f.
2230       field_div f (field_neg f x) y = field_neg f (field_div f x y)``,
2231   RW_TAC alg_ss' [field_div_def]);
2232
2233val field_div_rneg = store_thm
2234  ("field_div_rneg",
2235   ``!f :: Field. !x :: (f.carrier). !y :: field_nonzero f.
2236       field_div f x (field_neg f y) = field_neg f (field_div f x y)``,
2237   RW_TAC alg_ss' [field_inv_neg, field_div_def]);
2238
2239val field_div_addl = store_thm
2240  ("field_div_addl",
2241   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2242       field_add f x (field_div f y z) =
2243       field_div f (field_add f (field_mult f x z) y) z``,
2244   RW_TAC alg_ss' [field_div_def, field_distrib]);
2245
2246val field_div_addr = store_thm
2247  ("field_div_addr",
2248   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2249       field_add f (field_div f y z) x =
2250       field_div f (field_add f y (field_mult f x z)) z``,
2251   RW_TAC alg_ss' [field_div_def, field_distrib]);
2252
2253val field_div_subl = store_thm
2254  ("field_div_subl",
2255   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2256       field_sub f x (field_div f y z) =
2257       field_div f (field_sub f (field_mult f x z) y) z``,
2258   RW_TAC alg_ss' [field_div_def, field_distrib]);
2259
2260val field_div_subr = store_thm
2261  ("field_div_subr",
2262   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2263       field_sub f (field_div f y z) x =
2264       field_div f (field_sub f y (field_mult f x z)) z``,
2265   RW_TAC alg_ss' [field_div_def, field_distrib]);
2266
2267val field_div_multl = store_thm
2268  ("field_div_multl",
2269   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2270       field_mult f x (field_div f y z) =
2271       field_div f (field_mult f x y) z``,
2272   RW_TAC alg_ss' [field_div_def]);
2273
2274val field_div_multr = store_thm
2275  ("field_div_multr",
2276   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2277       field_mult f (field_div f y z) x =
2278       field_div f (field_mult f y x) z``,
2279   RW_TAC alg_ss' [field_div_def]);
2280
2281val field_div_exp = store_thm
2282  ("field_div_exp",
2283   ``!f :: Field. !x :: (f.carrier). !y :: field_nonzero f. !n.
2284       field_exp f (field_div f x y) n =
2285       field_div f (field_exp f x n) (field_exp f y n)``,
2286   RW_TAC alg_ss' [field_div_def, field_exp_mult, field_exp_inv]);
2287
2288val field_div_divl = store_thm
2289  ("field_div_divl",
2290   ``!f :: Field. !x :: (f.carrier). !y z :: field_nonzero f.
2291       field_div f (field_div f x y) z =
2292       field_div f x (field_mult f y z)``,
2293   RW_TAC alg_ss' [field_div_def]);
2294
2295val field_div_divr = store_thm
2296  ("field_div_divr",
2297   ``!f :: Field. !x :: (f.carrier). !y z :: field_nonzero f.
2298       field_div f x (field_div f y z) =
2299       field_div f (field_mult f x z) y``,
2300   RW_TAC alg_ss' [field_div_def]);
2301
2302val field_add_divl = store_thm
2303  ("field_add_divl",
2304   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2305       field_add f (field_div f y z) x =
2306       field_div f (field_add f y (field_mult f z x)) z``,
2307   RW_TAC alg_ss [field_div_def]
2308   ++ RW_TAC alg_ss' [field_distrib]);
2309
2310val field_add_divl' = store_thm
2311  ("field_add_divl'",
2312   ``!f :: Field. !x y t :: (f.carrier). !z :: field_nonzero f.
2313       field_add f (field_div f y z) (field_add f x t) =
2314       field_add f (field_div f (field_add f y (field_mult f z x)) z) t``,
2315   RW_TAC alg_ss [GSYM field_add_assoc]
2316   ++ RW_TAC resq_ss []
2317   ++ match_tac field_add_divl
2318   ++ RW_TAC alg_ss []);
2319
2320val field_add_divr = store_thm
2321  ("field_add_divr",
2322   ``!f :: Field. !x y :: (f.carrier). !z :: field_nonzero f.
2323       field_add f x (field_div f y z) =
2324       field_div f (field_add f (field_mult f z x) y) z``,
2325   RW_TAC alg_ss [field_div_def]
2326   ++ RW_TAC alg_ss' [field_distrib]);
2327
2328val field_add_divr' = store_thm
2329  ("field_add_divr'",
2330   ``!f :: Field. !x y t :: (f.carrier). !z :: field_nonzero f.
2331       field_add f x (field_add f (field_div f y z) t) =
2332       field_add f (field_div f (field_add f (field_mult f z x) y) z) t``,
2333   RW_TAC alg_ss [GSYM field_add_assoc]
2334   ++ RW_TAC resq_ss []
2335   ++ match_tac field_add_divr
2336   ++ RW_TAC alg_ss []);
2337
2338val field_add_div = store_thm
2339  ("field_add_div",
2340   ``!f :: Field. !v w :: (f.carrier). !x y z :: field_nonzero f.
2341       field_add f
2342         (field_div f v (field_mult f x y))
2343         (field_div f w (field_mult f x z)) =
2344       field_div f
2345         (field_add f (field_mult f z v) (field_mult f y w))
2346         (field_mult f x (field_mult f y z))``,
2347   RW_TAC alg_ss [field_div_def]
2348   ++ RW_TAC alg_ss' [field_distrib]);
2349
2350val field_add_div' = store_thm
2351  ("field_add_div'",
2352   ``!f :: Field. !v w t :: (f.carrier). !x y z :: field_nonzero f.
2353       field_add f
2354         (field_div f v (field_mult f x y))
2355         (field_add f (field_div f w (field_mult f x z)) t) =
2356       field_add f
2357         (field_div f
2358           (field_add f (field_mult f z v) (field_mult f y w))
2359           (field_mult f x (field_mult f y z))) t``,
2360   RW_TAC alg_ss [GSYM field_add_assoc]
2361   ++ RW_TAC resq_ss []
2362   ++ match_tac field_add_div
2363   ++ RW_TAC alg_ss []);
2364
2365val field_div_cancel = store_thm
2366  ("field_div_cancel",
2367   ``!f :: Field. !x z :: field_nonzero f. !y :: (f.carrier).
2368       (field_div f (field_mult f x y) (field_mult f x z) = field_div f y z)``,
2369   RW_TAC resq_ss [field_div_def]
2370   ++ RW_TAC alg_ss' []);
2371
2372val field_inv_eq_zero = store_thm
2373  ("field_inv_eq_zero",
2374   ``!f :: Field. !x :: field_nonzero f. ~(field_inv f x = field_zero f)``,
2375   RW_TAC resq_ss []
2376   ++ STRIP_TAC
2377   ++ Know `field_inv f x IN field_nonzero f` >> METIS_TAC [field_inv_nonzero]
2378   ++ RW_TAC alg_ss [field_nonzero_def, IN_DIFF, IN_SING]);
2379
2380val context = subtypeTools.add_rewrite2 field_inv_eq_zero context;
2381val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2382
2383val field_div_eq_zero = store_thm
2384  ("field_div_eq_zero",
2385   ``!f :: Field. !x :: (f.carrier). !y :: field_nonzero f.
2386       (field_div f x y = field_zero f) = (x = field_zero f)``,
2387   RW_TAC resq_ss [field_div_def]
2388   ++ RW_TAC alg_ss [field_entire]);
2389
2390val context = subtypeTools.add_rewrite2 field_div_eq_zero context;
2391val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2392
2393(* ------------------------------------------------------------------------- *)
2394(* Homomorphisms, isomorphisms, endomorphisms, automorphisms and subfields.  *)
2395(* ------------------------------------------------------------------------- *)
2396
2397val FieldHom_def = Define
2398  `FieldHom g h =
2399   { f |
2400     (!x :: (g.carrier). f x IN h.carrier) /\
2401     f IN GroupHom (g.sum) (h.sum) /\
2402     f IN GroupHom (g.prod) (h.prod) }`;
2403
2404val FieldIso_def = Define
2405  `FieldIso g h =
2406   { f |
2407     f IN FieldHom g h /\
2408     (!y :: (h.carrier). ?!x :: (g.carrier). f x = y) }`;
2409
2410val FieldEndo_def = Define `FieldEndo g = FieldHom g g`;
2411
2412val FieldAuto_def = Define `FieldAuto g = FieldIso g g`;
2413
2414val subfield_def = Define `subfield g h = I IN FieldHom g h`;
2415
2416(* ------------------------------------------------------------------------- *)
2417(* Polynomials over fields.                                                  *)
2418(* ------------------------------------------------------------------------- *)
2419
2420val () = type_abbrev ("poly", Type `:'a list`);
2421
2422val poly_zero_def = Define `poly_zero = ([] : 'a poly)`;
2423
2424val Poly_def = Define
2425  `Poly (f : 'a field) =
2426   { (p : 'a poly) |
2427     (p = poly_zero) \/
2428     (EVERY (\c. c IN f.carrier) p /\ ~(LAST p = field_zero f)) }`;
2429
2430val poly_degree_def = Define
2431  `poly_degree (p : 'a poly) = if (p = poly_zero) then 0 else LENGTH p - 1`;
2432
2433val poly_eval_def = Define
2434  `(poly_eval (f : 'a field) [] x = field_zero f) /\
2435   (poly_eval (f : 'a field) (c :: cs) x =
2436    field_add f c (field_mult f x (poly_eval f cs x)))`;
2437
2438val AlgebraicallyClosedField_def = Define
2439  `AlgebraicallyClosedField =
2440   { (f : 'a field) |
2441     f IN Field /\
2442     !p :: Poly f.
2443       (poly_degree p = 0) \/
2444       ?z :: (f.carrier). poly_eval f p z = field_zero f }`;
2445
2446(* ------------------------------------------------------------------------- *)
2447(* The trivial field.                                                        *)
2448(* ------------------------------------------------------------------------- *)
2449
2450val trivial_field_def = Define
2451  `(trivial_field zero_elt one_elt) : 'a field =
2452   <| carrier := {zero_elt; one_elt};
2453      sum := <| carrier := {zero_elt; one_elt};
2454                id := zero_elt;
2455                inv := (\x. x);
2456                mult := (\x y. if x = zero_elt then y
2457                               else if y = zero_elt then x
2458                               else zero_elt) |>;
2459      prod := <| carrier := {one_elt};
2460                 id := one_elt;
2461                 inv := (\x. x);
2462                 mult := (\x y. if x = zero_elt then zero_elt
2463                                else if y = zero_elt then zero_elt
2464                                else one_elt) |> |>`;
2465
2466val trivial_field = store_thm
2467  ("trivial_field",
2468   ``!zero_elt one_elt.
2469       ~(zero_elt = one_elt) ==>
2470       trivial_field zero_elt one_elt IN FiniteField``,
2471   RW_TAC resq_ss
2472     [trivial_field_def, FiniteField_def, Field_def, GSPECIFICATION,
2473      combinTheory.K_THM, field_add_def, field_mult_def, field_zero_def,
2474      AbelianGroup_def, Group_def, IN_INSERT, NOT_IN_EMPTY, EXTENSION,
2475      FINITE_INSERT, FINITE_EMPTY, IN_DIFF, field_nonzero_def]
2476   ++ RW_TAC std_ss []
2477   ++ METIS_TAC []);
2478
2479(* ------------------------------------------------------------------------- *)
2480(* GF(p).                                                                    *)
2481(* ------------------------------------------------------------------------- *)
2482
2483val modexp_def = Define
2484   `modexp a n m =
2485    if n = 0 then 1
2486    else if n MOD 2 = 0 then modexp ((a * a) MOD m) (n DIV 2) m
2487    else (a * modexp ((a * a) MOD m) (n DIV 2) m) MOD m`;
2488
2489val modexp_ind = fetch "-" "modexp_ind";
2490
2491val GF_def = Define
2492  `GF p =
2493   <| carrier := { n | n < p };
2494      sum := add_mod p;
2495      prod := mult_mod p |>`;
2496
2497val modexp = store_thm
2498  ("modexp",
2499   ``!a n m. 1 < m ==> (modexp a n m = (a ** n) MOD m)``,
2500   recInduct modexp_ind
2501   ++ RW_TAC std_ss []
2502   ++ ONCE_REWRITE_TAC [modexp_def]
2503   ++ Cases_on `n = 0` >> RW_TAC arith_ss [EXP]
2504   ++ ASM_SIMP_TAC bool_ss []
2505   ++ REPEAT (Q.PAT_ASSUM `X ==> Y` (K ALL_TAC))
2506   ++ Know `0 < m` >> DECIDE_TAC
2507   ++ STRIP_TAC
2508   ++ MP_TAC (Q.SPEC `m` MOD_TIMES2)
2509   ++ ASM_REWRITE_TAC []
2510   ++ DISCH_THEN (MP_TAC o Q.SPECL [`a`,`a`])
2511   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
2512   ++ ASM_SIMP_TAC bool_ss [MOD_MOD, MOD_EXP]
2513   ++ Know `a MOD m * a MOD m = (a MOD m) ** 2`
2514   >> RW_TAC bool_ss [TWO, ONE, EXP, REWRITE_RULE [ONE] MULT_CLAUSES]
2515   ++ DISCH_THEN (fn th => ASM_SIMP_TAC bool_ss [th])
2516   ++ ASM_SIMP_TAC bool_ss [EXP_EXP]
2517   ++ MP_TAC (Q.SPEC `m` MOD_TIMES2)
2518   ++ ASM_REWRITE_TAC []
2519   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
2520   ++ MP_TAC (Q.SPECL [`a`,`n`,`m`] MOD_EXP)
2521   ++ ASM_REWRITE_TAC []
2522   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
2523   ++ Q.SPEC_TAC (`a MOD m`,`a`)
2524   ++ MP_TAC (Q.SPEC `m` MOD_TIMES2)
2525   ++ ASM_REWRITE_TAC []
2526   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
2527   ++ ASM_SIMP_TAC bool_ss [MOD_MOD]
2528   ++ ASM_SIMP_TAC bool_ss [MOD_TIMES2, GSYM EXP]
2529   ++ Know `(n MOD 2 = 0) \/ (n MOD 2 = 1)`
2530   >> (Suff `n MOD 2 < 2` >> DECIDE_TAC
2531       ++ RW_TAC std_ss [DIVISION])
2532   ++ ASM_SIMP_TAC bool_ss [ADD1]
2533   ++ Suff `n = 2 * (n DIV 2) + n MOD 2`
2534   >> METIS_TAC [ADD_CLAUSES]
2535   ++ METIS_TAC [DIVISION, DECIDE ``0 < 2``, MULT_COMM]);
2536
2537val GF_carrier = store_thm
2538  ("GF_carrier",
2539   ``!p. (GF p).carrier = { n | n < p}``,
2540   RW_TAC std_ss [GF_def, field_accessors]);
2541
2542val GF_in_carrier = store_thm
2543  ("GF_in_carrier",
2544   ``!p x. x IN (GF p).carrier = x < p``,
2545   RW_TAC std_ss [GF_carrier, GSPECIFICATION]);
2546
2547val GF_in_carrier_imp = store_thm
2548  ("GF_in_carrier_imp",
2549   ``!p x. x < p ==> x IN (GF p).carrier``,
2550   METIS_TAC [GF_in_carrier]);
2551
2552val context = subtypeTools.add_judgement2 GF_in_carrier_imp context;
2553val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2554
2555val GF_zero = store_thm
2556  ("GF_zero",
2557   ``!p. field_zero (GF p) = 0``,
2558   RW_TAC std_ss [GF_def, field_accessors, field_zero_def, add_mod_def]);
2559
2560val GF_one = store_thm
2561  ("GF_one",
2562   ``!p. field_one (GF p) = 1``,
2563   RW_TAC std_ss [GF_def, field_accessors, field_one_def, mult_mod_def]);
2564
2565val GF_neg = store_thm
2566  ("GF_neg",
2567   ``!p x. field_neg (GF p) x = (p - x) MOD p``,
2568   RW_TAC std_ss [GF_def, field_accessors, field_neg_def, add_mod_def]);
2569
2570val GF_add = store_thm
2571  ("GF_add",
2572   ``!p x y. field_add (GF p) x y = (x + y) MOD p``,
2573   RW_TAC std_ss [GF_def, field_accessors, field_add_def, add_mod_def]);
2574
2575val GF_sub = store_thm
2576  ("GF_sub",
2577   ``!p :: Prime. !x y. field_sub (GF p) x y = (x + (p - y)) MOD p``,
2578   RW_TAC resq_ss [GF_add, GF_neg, field_sub_def, Prime_def, GSPECIFICATION]
2579   ++ Know `~(p = 0)` >> METIS_TAC [NOT_PRIME_0]
2580   ++ STRIP_TAC
2581   ++ MP_TAC (Q.SPEC `p` MOD_PLUS)
2582   ++ MATCH_MP_TAC (PROVE [] ``a /\ (b ==> c) ==> ((a ==> b) ==> c)``)
2583   ++ CONJ_TAC >> DECIDE_TAC
2584   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
2585   ++ RW_TAC arith_ss [MOD_MOD]);
2586
2587val GF_inv = store_thm
2588  ("GF_inv",
2589   ``!p :: Prime. !x y. field_inv (GF p) x = modexp x (p - 2) p``,
2590  RW_TAC resq_ss
2591    [GF_def, field_accessors, field_inv_def, mult_mod_def,
2592     combinTheory.K_THM, Prime_def, GSPECIFICATION]
2593  ++ match_tac (GSYM modexp)
2594  ++ Suff `~(p = 0) /\ ~(p = 1)` >> DECIDE_TAC
2595  ++ METIS_TAC [NOT_PRIME_0, NOT_PRIME_1]);
2596
2597val GF_mult = store_thm
2598  ("GF_mult",
2599   ``!p x y. field_mult (GF p) x y = (x * y) MOD p``,
2600  RW_TAC std_ss [GF_def, field_accessors, field_mult_def, mult_mod_def]);
2601
2602val GF_div = store_thm
2603  ("GF_div",
2604   ``!p x y. field_div (GF p) x y = field_mult (GF p) x (field_inv (GF p) y)``,
2605  RW_TAC std_ss [field_div_def]);
2606
2607val GF_exp = store_thm
2608  ("GF_exp",
2609   ``!p :: Prime. !x n. field_exp (GF p) x n = modexp x n p``,
2610   RW_TAC resq_ss [Prime_def, GSPECIFICATION]
2611   ++ Know `1 < p`
2612   >> (Suff `~(p = 0) /\ ~(p = 1)` >> DECIDE_TAC
2613       ++ METIS_TAC [NOT_PRIME_0, NOT_PRIME_1])
2614   ++ STRIP_TAC
2615   ++ Know `0 < p` >> DECIDE_TAC
2616   ++ STRIP_TAC
2617   ++ RW_TAC bool_ss [modexp]
2618   ++ (Induct_on `n`
2619       ++ RW_TAC bool_ss [field_exp_def, GF_one, GF_mult, EXP])
2620   >> METIS_TAC [LESS_MOD]
2621   ++ METIS_TAC [MOD_MOD, MOD_TIMES2]);
2622
2623val GF_num = store_thm
2624  ("GF_num",
2625   ``!p :: Prime. !n. field_num (GF p) n = n MOD p``,
2626   RW_TAC resq_ss []
2627   ++ Know `p IN Nonzero` >> RW_TAC alg_ss []
2628   ++ RW_TAC std_ss [Nonzero_def, GSPECIFICATION]
2629   ++ Know `0 < p` >> DECIDE_TAC
2630   ++ POP_ASSUM_LIST (K ALL_TAC)
2631   ++ RW_TAC std_ss []
2632   ++ Induct_on `n`
2633   ++ RW_TAC std_ss [field_num_def, GF_zero, ZERO_MOD, GF_add, GF_one]
2634   ++ REWRITE_TAC [ADD1]
2635   ++ MP_TAC (Q.SPEC `p` MOD_PLUS)
2636   ++ ASM_REWRITE_TAC []
2637   ++ DISCH_THEN (fn th => ONCE_REWRITE_TAC [GSYM th])
2638   ++ RW_TAC arith_ss [MOD_MOD]);
2639
2640val GF_alt = store_thm
2641  ("GF_alt",
2642   ``!p :: Prime. !x y n.
2643       (field_zero (GF p) = 0) /\
2644       (field_one (GF p) = 1) /\
2645       (field_neg (GF p) x = (p - x) MOD p) /\
2646       (field_add (GF p) x y = (x + y) MOD p) /\
2647       (field_sub (GF p) x y = (x + (p - y)) MOD p) /\
2648       (field_inv (GF p) x = modexp x (p - 2) p) /\
2649       (field_mult (GF p) x y = (x * y) MOD p) /\
2650       (field_div (GF p) x y = field_mult (GF p) x (field_inv (GF p) y)) /\
2651       (field_exp (GF p) x n = modexp x n p) /\
2652       (field_num (GF p) x = x MOD p)``,
2653   RW_TAC std_ss
2654     [GF_zero, GF_one, GF_neg, GF_add, GF_sub, GF_inv, GF_mult, GF_div,
2655      GF_exp, GF_num]);
2656
2657val GF = store_thm
2658  ("GF",
2659   ``!p :: Prime. GF p IN FiniteField``,
2660   RW_TAC resq_ss [FiniteField_def, GSPECIFICATION, Field_def]
2661   << [RW_TAC alg_ss [GF_def, combinTheory.K_THM],
2662       RW_TAC alg_ss [GF_def, combinTheory.K_THM],
2663       RW_TAC alg_ss [GF_def, combinTheory.K_THM, add_mod_def],
2664       RW_TAC alg_ss [GF_alt]
2665       ++ RW_TAC alg_ss
2666            [GF_def, combinTheory.K_THM, mult_mod_def,
2667             EXTENSION, IN_DIFF, GSPECIFICATION, IN_SING, field_nonzero_def,
2668             field_zero_def, add_mod_def]
2669       ++ METIS_TAC [],
2670       RW_TAC std_ss [GF_alt, MULT]
2671       ++ MATCH_MP_TAC ZERO_MOD
2672       ++ Suff `p IN Nonzero` >> RW_TAC arith_ss [Nonzero_def, GSPECIFICATION]
2673       ++ RW_TAC alg_ss [],
2674       RW_TAC std_ss [GF_alt]
2675       ++ Know `0 < p`
2676       >> (Suff `p IN Nonzero` >> RW_TAC arith_ss [Nonzero_def, GSPECIFICATION]
2677           ++ RW_TAC alg_ss [])
2678       ++ STRIP_TAC
2679       ++ RW_TAC std_ss [Once (GSYM MOD_TIMES2), MOD_MOD]
2680       ++ RW_TAC std_ss [MOD_TIMES2, LEFT_ADD_DISTRIB, MOD_PLUS],
2681       RW_TAC std_ss [GF_def, finite_num, GSPECIFICATION]
2682       ++ METIS_TAC []]);
2683
2684val context = subtypeTools.add_reduction2 GF context;
2685val {simplify = alg_ss, normalize = alg_ss'} = subtypeTools.simpset2 context;
2686
2687(* ------------------------------------------------------------------------- *)
2688(* GF(2^n).                                                                  *)
2689(* ------------------------------------------------------------------------- *)
2690
2691(* GF(2^n) = polynomials over GF(2) modulo an irreducible degree n poly *)
2692
2693(***
2694val GF_2_def = Define
2695  `GF_2 n =
2696   <| carrier := ;
2697      sum := ;
2698      prod :=  |>`;
2699***)
2700
2701val _ = html_theory "field";
2702
2703val () = export_theory ();
2704