1 (* ------------------------------------------------------------------ *)
2 (* Author and Copyright: Thomas C. Hales *)
3 (* License: GPL http://www.gnu.org/copyleft/gpl.html *)
4 (* Project: FLYSPECK http://www.math.pitt.edu/~thales/flyspeck/ *)
5 (* ------------------------------------------------------------------ *)
11 let add_test,test = new_test_suite();;
15 `twopow x = if (?n. (x = (int_of_num n)))
16 then ((&2) pow (nabs x))
17 else inv((&2) pow (nabs x))`);;
21 `float x n = (real_of_int x)*(twopow n)`);;
25 `interval x f eps = ((abs (x-f)) <= eps)`);;
27 (*--------------------------------------------------------------------*)
29 let mk_interval a b ex =
30 mk_comb(mk_comb (mk_comb (`interval`,a),b),ex);;
32 add_test("mk_interval",
33 mk_interval `#3` `#4` `#1` = `interval #3 #4 #1`);;
35 let dest_interval intv =
36 let (h1,ex) = dest_comb intv in
37 let (h2,f) = dest_comb h1 in
38 let (h3,a) = dest_comb h2 in
39 let _ = assert(h3 = `interval`) in
42 add_test("dest_interval",
43 let a = `#3` and b = `#4` and c = `#1` in
44 dest_interval (mk_interval a b c) = (a,b,c));;
46 (*--------------------------------------------------------------------*)
48 let (dest_int:term-> Num.num) =
51 let (op,nat) = dest_comb a in
52 if (fst (dest_const op) = "int_of_num") then (dest_numeral nat)
54 let (op',u) = (dest_comb b) in
55 try (if (fst (dest_const op') = "int_neg") then
56 minus_num (dest_pos_int u) else
58 Failure _ -> failwith "dest_int ";;
61 let (mk_int:Num.num -> term) =
63 let sgn = Num.sign_num a in
64 let abv = Num.abs_num a in
65 let r = mk_comb(`&:`,mk_numeral abv) in
66 try (if (sgn<0) then mk_comb (`--:`,r) else r) with
67 Failure _ -> failwith ("dest_int "^(string_of_num a));;
70 (mk_int (Int (-1443)) = `--: (&:1443)`) &&
71 (mk_int (Int 37) = `(&:37)`));;
73 (* ------------------------------------------------------------------ *)
75 let (split_ratio:Num.num -> Num.num*Num.num) =
77 (Ratio r) -> (Big_int (Ratio.numerator_ratio r)),
78 (Big_int (Ratio.denominator_ratio r))|
81 add_test("split_ratio",
82 let (a,b) = split_ratio ((Int 4)//(Int 20)) in
83 (a =/ (Int 1)) && (b =/ (Int 5)));;
85 (* ------------------------------------------------------------------ *)
87 (* break nonzero int r into a*(C**b) with a prime to C . *)
88 let (factor_C:int -> Num.num -> Num.num*Num.num) =
92 if ((Int 0) =/ mod_num a intC) then (divC (a//intC,b+/(Int 1)))
95 if ((Num.is_integer_num r)&& not((Num.sign_num r) = 0)) then
96 divC (r,(Int 0)) else failwith "factor_C";;
99 (factor_C 2 (Int (4096+32)) = (Int 129,Int 5)) &&
100 (factor_C 10 (Int (5000)) = (Int 5,Int 3)) &&
101 (cannot (factor_C 2) ((Int 50)//(Int 3))));;
103 (*--------------------------------------------------------------------*)
105 let (dest_float:term -> Num.num) =
107 let (a,b) = dest_binop `float` f in
108 (dest_int a)*/ ((Int 2) **/ (dest_int b));;
110 add_test("dest_float",
111 dest_float `float (&:3) (&:17)` = (Int 393216));;
113 add_test("dest_float2", (* must express as numeral first *)
114 cannot dest_float `float ((&:3)+:(&:1)) (&:17)`);;
116 (* ------------------------------------------------------------------ *)
117 (* creates float of the form `float a b` with a odd *)
118 let (mk_float:Num.num -> term) =
120 let (a,b) = split_ratio r in
121 let (a',exp_a) = if (a=/(Int 0)) then ((Int 0),(Int 0)) else factor_C 2 a in
122 let (b',exp_b) = factor_C 2 b in
124 if (Num.is_integer_num c) then
125 mk_binop `float` (mk_int c) (mk_int (exp_a -/ exp_b))
126 else failwith "mk_float";;
129 mk_float (Int (4096+32)) = `float (&:129) (&:5)` &&
130 (mk_float (Int 0) = `float (&:0) (&:0)`));;
132 add_test("mk_float2", (* throws exception exactly when denom != 2^k *)
133 let rtest = fun t -> (t =/ dest_float (mk_float t)) in
134 rtest ((Int 3)//(Int 1024)) &&
135 (cannot rtest ((Int 1)//(Int 3))));;
137 add_test("mk_float dest_float", (* constructs canonical form of float *)
138 mk_float (dest_float `float (&:4) (&:3)`) = `float (&:1) (&:5)`);;
140 (* ------------------------------------------------------------------ *)
141 (* creates decimal of the form `DECIMAL a b` with a prime to 10 *)
142 let (mk_pos_decimal:Num.num -> term) =
144 let _ = assert (r >=/ (Int 0)) in
145 let (a,b) = split_ratio r in
146 if (a=/(Int 0)) then `#0` else
147 let (a1,exp_a5) = factor_C 5 a in
148 let (a2,exp_a2) = factor_C 2 a1 in
149 let (b1,exp_b5) = factor_C 5 b in
150 let (b2,exp_b2) = factor_C 2 b1 in
151 let _ = assert(b2 =/ (Int 1)) in
152 let c = end_itlist Num.max_num [exp_b5-/exp_a5;exp_b2-/exp_a2;(Int 0)] in
153 let a' = a2*/((Int 2)**/ (c +/ exp_a2 -/ exp_b2))*/
154 ((Int 5)**/(c +/ exp_a5 -/ exp_b5)) in
155 let b' = (Int 10) **/ c in
156 mk_binop `DECIMAL` (mk_numeral a') (mk_numeral b');;
158 add_test("mk_pos_decimal",
159 mk_pos_decimal (Int (5000)) = `#5000` &&
160 (mk_pos_decimal ((Int 30)//(Int 40)) = `#0.75`) &&
161 (mk_pos_decimal (Int 0) = `#0`) &&
162 (mk_pos_decimal ((Int 15)//(Int 25)) = `#0.6`) &&
163 (mk_pos_decimal ((Int 25)//(Int 4)) = `#6.25`) &&
164 (mk_pos_decimal ((Int 2)//(Int 25)) = `#0.08`));;
166 let (mk_decimal:Num.num->term) =
168 let a = Num.sign_num r in
169 let b = mk_pos_decimal (Num.abs_num r) in
170 if (a < 0) then (mk_comb (`--.`, b)) else b;;
172 add_test("mk_decimal",
173 (mk_decimal (Int 3) = `#3`) &&
174 (mk_decimal (Int (-3)) = `--. (#3)`));;
178 (*--------------------------------------------------------------------*)
180 let (dest_decimal:term -> Num.num) =
182 let (a,b) = dest_binop `DECIMAL` f in
183 let a1 = dest_numeral a in
184 let b1 = dest_numeral b in
187 add_test("dest_decimal",
188 dest_decimal `#3.4` =/ ((Int 34)//(Int 10)));;
189 add_test("dest_decimal2",
190 cannot dest_decimal `--. (#3.4)`);;
196 (*--------------------------------------------------------------------*)
197 (* Properties of integer powers of 2. *)
198 (* ------------------------------------------------------------------ *)
201 let TWOPOW_POS = prove(`!n. (twopow (int_of_num n) = (&2) pow n)`,
202 (REWRITE_TAC[twopow])
205 THENL [AP_TERM_TAC;ALL_TAC]
206 THEN (REWRITE_TAC[NABS_POS])
207 THEN (UNDISCH_EL_TAC 0)
208 THEN (TAUT_TAC (` ( A ) ==> (~ A ==> B)`))
209 THEN (MESON_TAC[]));;
211 let TWOPOW_NEG = prove(`!n. (twopow (--(int_of_num n)) = inv((&2) pow n))`,
213 THEN (REWRITE_TAC[twopow])
214 THEN (COND_CASES_TAC THENL [ALL_TAC;REWRITE_TAC[NABS_NEG]])
215 THEN (POP_ASSUM CHOOSE_TAC)
216 THEN (REWRITE_TAC[NABS_NEG])
217 THEN (UNDISCH_EL_TAC 0)
218 THEN (REWRITE_TAC[int_eq;int_neg_th;INT_NUM_REAL])
219 THEN (REWRITE_TAC[prove (`! u y.((--(real_of_num u) = (real_of_num y))=
220 ((real_of_num u) +(real_of_num y) = (&0)))`,REAL_ARITH_TAC)])
221 THEN (REWRITE_TAC[REAL_OF_NUM_ADD;REAL_OF_NUM_EQ;ADD_EQ_0])
223 THEN (ASM_REWRITE_TAC[real_pow;REAL_INV_1]));;
226 let TWOPOW_INV = prove(`!a. (twopow (--: a) = (inv (twopow a)))`,
228 THEN ((ASSUME_TAC (SPEC `a:int` INT_REP2)))
229 THEN ((POP_ASSUM CHOOSE_TAC))
230 THEN ((POP_ASSUM DISJ_CASES_TAC))
231 THEN ((ASM_REWRITE_TAC[TWOPOW_POS;TWOPOW_NEG;REAL_INV_INV;INT_NEG_NEG])));;
233 let INT_REP3 = prove(`!a .(?n.( (a = &: n) \/ (a = --: (&: (n+1)))))`,
235 THEN ((ASSUME_TAC (SPEC `a:int` INT_REP2)))
236 THEN ((POP_ASSUM CHOOSE_TAC))
237 THEN ((DISJ_CASES_TAC (prove (`((a:int) = (&: 0)) \/ ~((a:int) =(&: 0))`, MESON_TAC[]))))
239 THENL[ ((EXISTS_TAC `0`)) THEN ((ASM_REWRITE_TAC[]));ALL_TAC]
240 THEN ((UNDISCH_EL_TAC 0))
241 THEN ((POP_ASSUM DISJ_CASES_TAC))
242 THENL [DISCH_TAC THEN ((ASM MESON_TAC)[]);ALL_TAC]
244 THEN ((EXISTS_TAC `PRE n`))
246 THEN ((ASM_REWRITE_TAC[INT_EQ_NEG2]))
247 (*** Changed by JRH, 2006/03/28 to avoid PRE_ELIM_TAC ***)
248 THEN (FIRST_X_ASSUM(MP_TAC o check(is_neg o concl)))
249 THEN (ASM_REWRITE_TAC[INT_NEG_EQ_0; INT_OF_NUM_EQ])
252 let REAL_EQ_INV = prove(`!x y. ((x:real = y) <=> (inv(x) = inv (y)))`,
255 THENL [((DISCH_TAC THEN (ASM_REWRITE_TAC[])));
256 (* branch 2*) ((DISCH_TAC))
257 THEN ((ONCE_REWRITE_TAC [(GSYM REAL_INV_INV)]))
258 THEN ((ASM_REWRITE_TAC[]))]);;
261 prove(`!a. (twopow (a +: (&:1)) = twopow (a) *. (twopow (&:1)))`,
264 CHOOSE_TAC (SPEC `a:int` INT_REP3);
265 POP_ASSUM DISJ_CASES_TAC
267 ASM_REWRITE_TAC[TWOPOW_POS;INT_OF_NUM_ADD;REAL_POW_ADD];
269 ASM_REWRITE_TAC[GSYM INT_OF_NUM_ADD;INT_NEG_ADD;GSYM INT_ADD_ASSOC;INT_ADD_LINV;INT_ADD_RID];
270 REWRITE_TAC[GSYM INT_NEG_ADD;INT_OF_NUM_ADD;TWOPOW_NEG;TWOPOW_POS];
271 ONCE_REWRITE_TAC[SPEC `(&. 2) pow 1` (GSYM REAL_INV_INV)];
272 REWRITE_TAC[GSYM REAL_INV_MUL;GSYM REAL_EQ_INV;REAL_POW_ADD;GSYM REAL_MUL_ASSOC;REAL_POW_1];
273 REWRITE_TAC[MATCH_MP REAL_MUL_RINV (REAL_ARITH `~((&. 2) = (&. 0))`); REAL_MUL_RID]
278 let REAL_INV2 = prove(
279 `(inv(&. 2)*(&. 2) = (&.1)) /\ ((&. 2)*inv(&. 2) = (&.1))`,
280 SUBGOAL_TAC `~((&.2) = (&.0))`
283 SIMP_TAC[REAL_MUL_RINV;REAL_MUL_LINV]]);;
285 let TWOPOW_0 = prove(`twopow (&: 0) = (&. 1)`,
286 (REWRITE_TAC[TWOPOW_POS;real_pow]));;
288 let TWOPOW_SUB_NUM = prove(`!m n.( twopow((&:m) - (&: n)) = twopow((&:m))*. twopow(--: (&:n)))`,
290 THENL [REWRITE_TAC[INT_SUB_LZERO;REAL_MUL_LID;TWOPOW_0];ALL_TAC]
291 THEN ((INDUCT_TAC THEN
292 ( (ASM_REWRITE_TAC[INT_SUB_RZERO;TWOPOW_0;REAL_MUL_RID;INT_NEG_0;ADD1;GSYM INT_OF_NUM_ADD]))))
293 THEN ((ASM_REWRITE_TAC [TWOPOW_ADD_1;TWOPOW_INV;prove (`((&:m)+(&:1)) -: ((&:n) +: (&:1)) = ((&:m)-: (&:n))`,INT_ARITH_TAC)]))
294 THEN ((REWRITE_TAC[REAL_INV_MUL]))
295 THEN ((ABBREV_TAC `a:real = twopow (&: m)`))
296 THEN ((ABBREV_TAC `b:real = inv(twopow (&: n))`))
297 THEN ((REWRITE_TAC[TWOPOW_POS;REAL_POW_1;GSYM REAL_MUL_ASSOC;prove (`!(x:real). ((&.2)*x = x*(&.2))`,REAL_ARITH_TAC)]))
298 THEN ((REWRITE_TAC[REAL_INV2;REAL_MUL_RID])));;
300 let TWOPOW_ADD_NUM = prove(
301 `!m n. (twopow ((&:m) + (&:n)) = twopow((&:m))*. twopow((&:n)))`,
302 (REWRITE_TAC[TWOPOW_POS;REAL_POW_ADD;INT_OF_NUM_ADD]));;
304 let TWOPOW_ADD_INT = prove(
305 `!a b. (twopow (a +: b) = twopow(a) *. (twopow(b)))`,
307 THEN ((ASSUME_TAC (SPEC `a:int` INT_REP)))
308 THEN ((POP_ASSUM CHOOSE_TAC))
309 THEN ((POP_ASSUM CHOOSE_TAC))
310 THEN ((ASSUME_TAC (SPEC `b:int` INT_REP)))
311 THEN ((REPEAT (POP_ASSUM CHOOSE_TAC)))
312 THEN ((ASM_REWRITE_TAC[]))
313 THEN ((SUBGOAL_TAC `&: n -: &: m +: &: n' -: &: m' = (&: (n+n')) -: (&: (m+m'))`))
315 THENL[ ((REWRITE_TAC[GSYM INT_OF_NUM_ADD]))
316 THEN ((INT_ARITH_TAC));ALL_TAC]
319 THEN ((ASM_REWRITE_TAC[TWOPOW_SUB_NUM;TWOPOW_INV;TWOPOW_POS;REAL_POW_ADD;REAL_INV_MUL;GSYM REAL_MUL_ASSOC]))
320 THEN ((ABBREV_TAC `a':real = inv ((&. 2) pow m)`))
321 THEN ((ABBREV_TAC `c :real = (&. 2) pow n`))
322 THEN ((ABBREV_TAC `d :real = (&. 2) pow n'`))
323 THEN ((ABBREV_TAC `e :real = inv ((&. 2) pow m')`))
324 THEN (MESON_TAC[REAL_MUL_AC]));;
326 let TWOPOW_ABS = prove(`!a. ||. (twopow a) = (twopow a)`,
328 THEN ((CHOOSE_THEN DISJ_CASES_TAC (SPEC `a:int` INT_REP2)))
330 THEN ((ASM_REWRITE_TAC[TWOPOW_POS;TWOPOW_NEG;REAL_ABS_POW;REAL_ABS_NUM;REAL_ABS_INV])));;
332 let REAL_POW_POW = prove(
333 `!x m n . (x **. m) **. n = x **. (m *| n)`,
334 ((GEN_TAC THEN GEN_TAC THEN INDUCT_TAC))
336 THENL[ ((REWRITE_TAC[real_pow;MULT_0]));
338 ((REWRITE_TAC[real_pow]))
339 THEN ((ASM_REWRITE_TAC[ADD1;LEFT_ADD_DISTRIB;REAL_POW_ADD;REAL_MUL_AC;MULT_CLAUSES]))]);;
341 let INT_POW_POW = INT_OF_REAL_THM REAL_POW_POW;;
343 let TWOPOW_POW = prove(
344 `!a n. (twopow a) pow n = twopow (a *: (&: n))`,
346 THEN ((CHOOSE_THEN DISJ_CASES_TAC (SPEC `a:int` INT_REP2)))
348 THEN ((ASM_REWRITE_TAC[TWOPOW_POS;INT_OF_NUM_MUL;
349 REAL_POW_POW;TWOPOW_NEG;REAL_POW_INV;INT_OF_NUM_MUL;GSYM INT_NEG_LMUL])));;
351 (* ------------------------------------------------------------------ *)
352 (* Arithmetic operations on float *)
353 (* ------------------------------------------------------------------ *)
354 let FLOAT_NEG = prove(`!a m. --. (float a m) = float (--: a) m`,
356 REWRITE_TAC[float;GSYM REAL_MUL_LNEG;int_neg_th]);;
360 let FLOAT_MUL = prove(`!a b m n. (float a m) *. (float b n) = (float (a *: b) (m +: n))`,
362 THEN ((REWRITE_TAC[float;GSYM REAL_MUL_ASSOC;TWOPOW_ADD_INT;int_mul_th]))
363 THEN ((MESON_TAC[REAL_MUL_AC])));;
365 let FLOAT_ADD = prove(
366 `!a b c m. (float a (m+: (&:c))) +. (float b m)
367 = (float ( (&:(2 EXP c))*a +: b) m)`,
368 ((REWRITE_TAC[float;int_add_th;REAL_ADD_RDISTRIB;int_mul_th;TWOPOW_ADD_INT]))
369 THEN ((REPEAT GEN_TAC))
370 THEN ((REWRITE_TAC[TWOPOW_POS;INT_NUM_REAL;GSYM REAL_OF_NUM_POW]))
371 THEN ((MESON_TAC[REAL_MUL_AC])));;
373 let FLOAT_ADD_EQ = prove(
374 `!a b m. (float a m) +. (float b m) =
377 THEN ((REWRITE_TAC[REWRITE_RULE[INT_ADD_RID] (SPEC `m:int` (SPEC `0` (SPEC `b:int` (SPEC `a:int` FLOAT_ADD))))]))
378 THEN ((REWRITE_TAC[EXP;INT_MUL_LID])));;
380 let FLOAT_ADD_NP = prove(
381 `!a b m n. (float b (--:(&: n))) +. (float a (&: m)) = (float a (&: m)) +. (float b (--:(&: n)))`,
382 (REWRITE_TAC[REAL_ADD_AC]));;
384 let FLOAT_ADD_PN = prove(
385 `!a b m n. (float a (&: m)) +. (float b (--(&: n))) = (float ( (&:(2 EXP (m+| n)))*a + b) (--:(&: n)))`,
387 THEN ((SUBGOAL_TAC `&: m = (--:(&: n)) + (&:(m+n))`))
388 THENL[ ((REWRITE_TAC[GSYM INT_OF_NUM_ADD]))
389 THEN ((INT_ARITH_TAC));
392 THEN ((ASM_REWRITE_TAC[FLOAT_ADD]))]);;
394 let FLOAT_ADD_PP = prove(
395 `!a b m n. ((n <=| m) ==>( (float a (&: m)) +. (float b (&: n)) = (float ((&:(2 EXP (m -| n))) *a + b) (&: n))))`,
398 THEN ((SUBGOAL_TAC `&: m = (&: n) + (&: (m-n))`))
399 THENL[ ((REWRITE_TAC[INT_OF_NUM_ADD]))
401 THEN ((REWRITE_TAC[prove (`!(m:num) n. (n+m-n) = (m-n)+n`,REWRITE_TAC[ADD_AC])]))
402 THEN ((UNDISCH_EL_TAC 0))
403 THEN ((MATCH_ACCEPT_TAC(GSYM SUB_ADD)));
406 THEN ((ASM_REWRITE_TAC[FLOAT_ADD]))]);;
408 let FLOAT_ADD_PPv2 = prove(
409 `!a b m n. ((m <| n) ==>( (float a (&: m)) +. (float b (&: n)) = (float ((&:(2 EXP (n -| m))) *b + a) (&: m))))`,
412 THEN ((H_MATCH_MP (THM (prove(`!m n. m<|n ==> m <=|n`,MESON_TAC[LT_LE]))) (HYP_INT 0)))
413 THEN ((UNDISCH_EL_TAC 0))
414 THEN ((SIMP_TAC[GSYM FLOAT_ADD_PP]))
416 THEN ((REWRITE_TAC[REAL_ADD_AC])));;
418 let FLOAT_ADD_NN = prove(
419 `!a b m n. ((n <=| m) ==>( (float a (--:(&: m))) +. (float b (--:(&: n)))
420 = (float ((&:(2 EXP (m -| n))) *b + a) (--:(&: m)))))`,
423 THEN ((SUBGOAL_TAC `--: (&: n) = --: (&: m) + (&: (m-n))`))
424 THENL [((UNDISCH_EL_TAC 0))
425 THEN ((SIMP_TAC [INT_OF_REAL_THM (GSYM REAL_OF_NUM_SUB)]))
427 THEN ((INT_ARITH_TAC));
430 THEN (ASM_REWRITE_TAC[GSYM FLOAT_ADD;REAL_ADD_AC])]);;
432 let FLOAT_ADD_NNv2 = prove(
433 `!a b m n. ((m <| n) ==>( (float a (--:(&: m))) +. (float b (--:(&: n)))
434 = (float ((&:(2 EXP (n -| m))) *a + b) (--:(&: n)))))`,
437 THEN (((H_MATCH_MP (THM (prove(`!m n. m<|n ==> m <=|n`,MESON_TAC[LT_LE]))) (HYP_INT 0))))
438 THEN (((UNDISCH_EL_TAC 0)))
439 THEN (((SIMP_TAC[GSYM FLOAT_ADD_NN])))
441 THEN (((REWRITE_TAC[REAL_ADD_AC]))));;
443 let FLOAT_SUB = prove(
444 `!a b n m. (float a n) -. (float b m)
445 = (float a n) +. (float (--: b) m)`,
446 REWRITE_TAC[float;int_neg_th;real_sub;REAL_NEG_LMUL]);;
448 let FLOAT_ABS = prove(
449 `!a n. ||. (float a n) = (float (||: a) n)`,
450 (REWRITE_TAC[float;int_abs_th;REAL_ABS_MUL;TWOPOW_ABS]));;
453 let FLOAT_POW = prove(
454 `!a n m. (float a n) **. m = (float (a **: m) (n *: (&:m)))`,
455 (REWRITE_TAC[float;REAL_POW_MUL;int_pow_th;TWOPOW_POW]));;
458 `!a b. (a -: b) = (a +: (--: b))`,
459 (REWRITE_TAC[GSYM INT_SUB_RNEG;INT_NEG_NEG]));;
461 let INT_ABS_NUM = prove(
462 `!n. ||: (&: n) = (&: n)`,
463 (REWRITE_TAC[int_eq;int_abs_th;INT_NUM_REAL;REAL_ABS_NUM]));;
465 let INT_ABS_NEG_NUM = prove(
466 `!n. ||: (--: (&: n)) = (&: n)`,
467 (REWRITE_TAC[int_eq;int_abs_th;int_neg_th;INT_NUM_REAL;REAL_ABS_NUM;REAL_ABS_NEG]));;
469 let INT_ADD_NEG_NUM = prove(`!x y. --: (&: x) +: (&: y) = (&: y) +: (--: (&: x))`,
470 (REWRITE_TAC[INT_ADD_AC]));;
472 let INT_POW_MUL = INT_OF_REAL_THM REAL_POW_MUL;;
474 let INT_POW_NEG1 = prove (
475 `!x n. (--: (&: x)) **: n = ((--: (&: 1)) **: n) *: ((&: x) **: n)`,
476 (REWRITE_TAC[GSYM INT_POW_MUL; GSYM INT_NEG_MINUS1]));;
480 let INT_POW_EVEN_NEG1 = prove(
481 `!x n. (--: (&: x)) **: (NUMERAL (BIT0 n)) = ((&: x) **: (NUMERAL (BIT0 n)))`,
483 THEN ((ONCE_REWRITE_TAC[INT_POW_NEG1]))
484 THEN ((ABBREV_TAC `a = &: 1`))
485 THEN ((ABBREV_TAC `b = (&: x)**: (NUMERAL (BIT0 n))`))
486 THEN ((REWRITE_TAC[NUMERAL;BIT0]))
487 THEN ((REWRITE_TAC[GSYM MULT_2;GSYM INT_POW_POW;INT_OF_REAL_THM REAL_POW_2;INT_NEG_MUL2]))
488 THEN ((EXPAND_TAC "a"))
489 THEN ((REWRITE_TAC[INT_MUL_RID;INT_MUL_LID;INT_OF_REAL_THM REAL_POW_ONE])));;
491 let INT_POW_ODD_NEG1 = prove(
492 `!x n. (--: (&: x)) **: (NUMERAL (BIT1 n)) = --: ((&: x) **: (NUMERAL (BIT1 n)))`,
494 THEN ((ONCE_REWRITE_TAC[INT_POW_NEG1]))
495 THEN (((ABBREV_TAC `a = &: 1`)))
496 THEN (((ABBREV_TAC `b = (&: x)**: (NUMERAL (BIT1 n))`)))
497 THEN ((REWRITE_TAC[NUMERAL;BIT1]))
498 THEN ((ONCE_REWRITE_TAC[ADD1]))
499 THEN ((EXPAND_TAC "a"))
500 THEN ((REWRITE_TAC[GSYM MULT_2]))
501 THEN ((REWRITE_TAC[INT_OF_REAL_THM POW_MINUS1;INT_OF_REAL_THM REAL_POW_ADD]))
502 THEN ((REWRITE_TAC[INT_OF_REAL_THM POW_1;INT_MUL_LID;INT_MUL_LNEG])));;
504 (* subtraction of integers *)
506 let INT_ADD_NEG = prove(
507 `!x y. (x < y ==> ((&: x) +: (--: (&: y)) = --: (&: (y - x))))`,
510 THEN ((SUBGOAL_TAC `&: (y-x ) = (&: y) - (&: x)`))
511 THENL [((SUBGOAL_TAC `x <=| y`))
513 THENL [(((ASM MESON_TAC)[LE_LT]));((SIMP_TAC[GSYM (INT_OF_REAL_THM REAL_OF_NUM_SUB)]))]
516 THEN ((ASM_REWRITE_TAC[]))
517 THEN (ACCEPT_TAC(INT_ARITH `&: x +: --: (&: y) = --: (&: y -: &: x)`))]);;
519 let INT_ADD_NEGv2 = prove(
520 `!x y. (y <= x ==> ((&: x) +: (--: (&: y)) = (&: (x - y))))`,
523 THEN ((SUBGOAL_TAC `&: (x - y) = (&: x) - (&: y)`))
525 ((UNDISCH_EL_TAC 0)) THEN ((SIMP_TAC[GSYM (INT_OF_REAL_THM REAL_OF_NUM_SUB)]));
526 ((DISCH_TAC)) THEN ((ASM_REWRITE_TAC[INT_SUB]))
530 (* assumes a term of the form &:a +: (--: (&: b)) *)
532 let a,b = dest_binop `(+:)` t in
533 let (_,a) = dest_comb a in
534 let (_,b) = dest_comb b in
535 let (_,b) = dest_comb b in
536 let a = dest_numeral a in
537 let b = dest_numeral b in
538 let thm = if (b <=/ a) then
541 (ARITH_SIMP_CONV[thm]) t;; (* (SIMP_CONV[thm;ARITH]) t;; *)
544 (* ------------------------------------------------------------------ *)
545 (* Simplifies an arithmetic expression in floats *)
547 (* ------------------------------------------------------------------ *)
550 (ARITH_SIMP_CONV[FLOAT_MUL;FLOAT_SUB;FLOAT_ABS;FLOAT_POW;
551 FLOAT_ADD_NN;FLOAT_ADD_NNv2;FLOAT_ADD_PP;FLOAT_ADD_PPv2;
552 FLOAT_ADD_NP;FLOAT_ADD_PN;FLOAT_NEG;
554 INT_ABS_NUM;INT_ABS_NEG_NUM;
555 INT_MUL_LNEG;INT_MUL_RNEG;INT_NEG_MUL2;INT_OF_NUM_MUL;
556 INT_OF_NUM_ADD;GSYM INT_NEG_ADD;INT_ADD_NEG_NUM;
557 INT_OF_NUM_POW;INT_POW_ODD_NEG1;INT_POW_EVEN_NEG1;
558 INT_ADD_NEG;INT_ADD_NEGv2 (* ; ARITH *)
561 add_test("FLOAT_CONV1",
563 let (x,y) = dest_eq z in
564 let (u,v) = dest_thm (FLOAT_CONV x) in
566 f `float (&:3) (&:0) = float (&:3) (&:0)` &&
567 f `float (&:3) (&:3) = float (&:3) (&:3)` &&
568 f `float (&:3) (&:0) +. (float (&:4) (&:0)) = (float (&:7) (&:0))` &&
569 f `float (&:1 + (&:3)) (&:4) = float (&:4) (&:4)` &&
570 f `float (&:3 - (&:7)) (&:0) = float (--:(&:4)) (&:0)` &&
571 f `float (&:3) (&:4) *. (float (--: (&:2)) (&:3)) = float (--: (&:6))
573 f `--. (float (--: (&:3)) (&:0)) = float (&:3) (&:0)`
576 (* ------------------------------------------------------------------ *)
577 (* Operations on interval. Preliminary stuff to deal with *)
578 (* chains of inequalities. *)
579 (* ------------------------------------------------------------------ *)
582 let REAL_ADD_LE_SUBST_RHS = prove(
583 `!a b c P. ((a <=. ((P b)) /\ (!x. (P x) = x + (P (&. 0))) /\ (b <=. c)) ==> (a <=. (P c)))`,
585 THEN (((REPEAT (TAUT_TAC `(b ==> a==> c) ==> (a /\ b ==> c)`))))
586 THEN (((REPEAT DISCH_TAC)))
587 THEN ((((H_RULER(ONCE_REWRITE_RULE))[HYP_INT 1] (HYP_INT 0))))
588 THEN ((((ASM ONCE_REWRITE_TAC)[])))
589 THEN ((((ASM MESON_TAC)[REAL_LE_RADD;REAL_LE_TRANS]))));;
591 let REAL_ADD_LE_SUBST_LHS = prove(
592 `!a b c P. (((P(a) <=. b /\ (!x. (P x) = x + (P (&. 0))) /\ (c <=. a)))
596 THEN (((H_RULER(ONCE_REWRITE_RULE)) [HYP_INT 1] (HYP_INT 0)))
597 THEN (((ASM ONCE_REWRITE_TAC)[]))
598 THEN (((ASM MESON_TAC)[REAL_LE_RADD;REAL_LE_TRANS])));;
602 (a::b) -> fun thm ->(SPECL b (SPEC a thm));;
611 condition: REAL_ARITH must be able to prove !x. P(x) = x+. P(&.0).
612 condition: the term `a` must appear exactly once the lhs of the thm.
615 let IWRITE_REAL_LE_RHS rel thm =
616 let bvar = genvar `:real` in
617 let (bt,_) = dest_binop `(<=.)` (concl rel) in
618 let sub = SUBS_CONV[ASSUME (mk_eq(bt,bvar))] in
619 let rule = (fun th -> EQ_MP (sub (concl th)) th) in
620 let (subrel,subthm) = (rule rel,rule thm) in
621 let (a,p) = dest_binop `(<=.)` (concl subthm) in
622 let (_,c) = dest_binop `(<=.)` (concl subrel) in
623 let pfn = mk_abs (bvar,p) in
624 let imp_th = BETA_RULE (SPECL [a;bvar;c;pfn] REAL_ADD_LE_SUBST_RHS) in
625 let ppart = REAL_ARITH
626 (fst(dest_conj(snd(dest_conj(fst(dest_imp(concl imp_th))))))) in
627 let prethm = MATCH_MP imp_th (CONJ subthm (CONJ ppart subrel)) in
628 let prethm2 = SPEC bt (GEN bvar (DISCH
629 (find (fun x -> try(bvar = rhs x) with failure -> false) (hyp prethm)) prethm)) in
630 MATCH_MP prethm2 (REFL bt);;
639 condition: REAL_ARITH must be able to prove !x. P(x) = x+. P(&.0).
640 condition: the term `a` must appear exactly once the lhs of the thm.
643 let IWRITE_REAL_LE_LHS rel thm =
644 let avar = genvar `:real` in
645 let (_,at) = dest_binop `(<=.)` (concl rel) in
646 let sub = SUBS_CONV[ASSUME (mk_eq(at,avar))] in
647 let rule = (fun th -> EQ_MP (sub (concl th)) th) in
648 let (subrel,subthm) = (rule rel,rule thm) in
649 let (p,b) = dest_binop `(<=.)` (concl subthm) in
650 let (c,_) = dest_binop `(<=.)` (concl subrel) in
651 let pfn = mk_abs (avar,p) in
652 let imp_th = BETA_RULE (SPECL [avar;b;c;pfn] REAL_ADD_LE_SUBST_LHS) in
653 let ppart = REAL_ARITH
654 (fst(dest_conj(snd(dest_conj(fst(dest_imp(concl imp_th))))))) in
655 let prethm = MATCH_MP imp_th (CONJ subthm (CONJ ppart subrel)) in
656 let prethm2 = SPEC at (GEN avar (DISCH
657 (find (fun x -> try(avar = rhs x) with failure -> false) (hyp prethm)) prethm)) in
658 MATCH_MP prethm2 (REFL at);;
660 (* ------------------------------------------------------------------ *)
661 (* INTERVAL ADD, NEG, SUBTRACT *)
662 (* ------------------------------------------------------------------ *)
665 let INTERVAL_ADD = prove(
666 `!x f ex y g ey. interval x f ex /\ interval y g ey ==>
667 interval (x +. y) (f +. g) (ex +. ey)`,
670 TAUT_TAC `(A==>B==>C)==>(A/\ B ==> C)`;
671 REWRITE_TAC[interval];
672 REWRITE_TAC[prove(`(x+.y) -. (f+.g) = (x-.f) +. (y-.g)`,REAL_ARITH_TAC)];
673 ABBREV_TAC `a = x-.f`;
674 ABBREV_TAC `b = y-.g`;
675 ASSUME_TAC (SPEC `b:real` (SPEC `a:real` ABS_TRIANGLE));
677 ABBREV_TAC `a':real = abs a`;
678 ABBREV_TAC `b':real = abs b`;
680 (H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 2);
681 (H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 2) (HYP_INT 0);
682 ASM_REWRITE_TAC[]]);;
684 let INTERVAL_NEG = prove(
685 `!x f ex. interval x f ex = interval (--. x) (--. f) ex`,
686 (REWRITE_TAC[interval;REAL_ABS_NEG;REAL_ARITH `!x y. -- x -. (-- y) = --. (x -. y)`]));;
688 let INTERVAL_NEG2 = prove(
689 `!x f ex. interval (--. x) f ex = interval x (--. f) ex`,
690 (REWRITE_TAC[interval;REAL_ABS_NEG;REAL_ARITH `!x y. -- x -. y = --. (x -. (--. y))`]));;
693 let INTERVAL_SUB = prove(
694 `!x f ex y g ey. interval x f ex /\ interval y g ey ==> interval (x -. y) (f -. g) (ex +. ey)`,
695 ((REWRITE_TAC[real_sub]))
697 THEN (((H_RULER (ONCE_REWRITE_RULE))[THM(INTERVAL_NEG)] (HYP_INT 1)))
698 THEN (((ASM MESON_TAC)[INTERVAL_ADD])));;
700 (* ------------------------------------------------------------------ *)
701 (* INTERVAL MULTIPLICATION *)
702 (* ------------------------------------------------------------------ *)
705 let REAL_PROP_LE_LABS = prove(
706 `!x y z. (y <=. z) ==> ((abs x)* y <=. (abs x) *z)`,(SIMP_TAC[REAL_LE_LMUL_IMP;ABS_POS]));;
708 (* renamed from REAL_LE_ABS_RMUL *)
709 let REAL_PROP_LE_RABS = prove(
710 `!x y z. (y <=. z) ==> ( y * (abs x) <=. z *(abs x))`,(SIMP_TAC[REAL_LE_RMUL_IMP;ABS_POS]));;
712 let REAL_LE_ABS_MUL = prove(
713 `!x y z w. (( x <=. y) /\ (abs z <=. w)) ==> (x*.w <=. y*.w) `,
715 THEN ((ASSUME_TAC (REAL_ARITH `abs z <=. w ==> (&.0) <=. w`)))
716 THEN (((ASM MESON_TAC)[REAL_LE_RMUL_IMP])));;
718 let INTERVAL_MUL = prove(
719 `!x f ex y g ey. (interval x f ex) /\ (interval y g ey) ==>
720 (interval (x *. y) (f *. g) (abs(f)*.ey +. ex*. abs(g) +. ex*.ey))`,
722 THEN ((REWRITE_TAC[interval]))
723 THEN ((REWRITE_TAC[REAL_ARITH `(x*. y -. f*. g) = (f *.(y -. g) +. (x -. f)*.g +. (x-.f)*.(y-. g))`]))
725 THEN ((ASSUME_TAC (SPECL [`f*.(y-g)`;`(x-f)*g +. (x-f)*.(y-g)`] ABS_TRIANGLE)))
726 THEN ((ASSUME_TAC (SPECL [`(x-f)*.g`;`(x-f)*.(y-g)`] ABS_TRIANGLE)))
727 THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
728 THEN ((H_REWRITE_RULE [THM ABS_MUL] (HYP_INT 0)))
729 THEN ((H_MATCH_MP (THM (SPECL [`g:real`; `abs (x -. f)`; `ex:real`] REAL_PROP_LE_RABS)) (HYP_INT 4)))
730 THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
731 THEN ((H_MATCH_MP (THM (SPECL [`f:real`; `abs (y -. g)`; `ey:real`] REAL_PROP_LE_LABS)) (HYP_INT 7)))
732 THEN (((H_VAL2 (IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
733 THEN ((H_MATCH_MP (THM (SPECL [`x-.f`; `abs (y -. g)`; `ey:real`] REAL_PROP_LE_LABS)) (HYP_INT 9)))
734 THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 1)))
735 THEN ((ASSUME_TAC (SPECL [`abs(x-.f)`;`ex:real`;`y-.g`;`ey:real`] REAL_LE_ABS_MUL)))
736 THEN ((H_CONJ (HYP_INT 11) (HYP_INT 12)))
737 THEN ((H_MATCH_MP (HYP_INT 1) (HYP_INT 0)))
738 THEN (((H_VAL2(IWRITE_REAL_LE_RHS)) (HYP_INT 0) (HYP_INT 3)))
739 THEN ((POP_ASSUM ACCEPT_TAC)));;
741 (* ------------------------------------------------------------------ *)
742 (* INTERVAL BASIC OPERATIONS *)
743 (* ------------------------------------------------------------------ *)
746 let INTERVAL_NUM = prove(
747 `!n. (interval(&.n) (float(&:n) (&:0)) (float (&: 0) (&:0)))`,
748 (REWRITE_TAC[interval;float;TWOPOW_POS;pow;REAL_MUL_RID;INT_NUM_REAL;REAL_SUB_REFL;REAL_ABS_0;REAL_LE_REFL]));;
750 let INTERVAL_CENTER = prove(
751 `!x f ex g. (interval x f ex) ==> (interval x g (abs(f-g)+.ex))`,
752 ((REWRITE_TAC[interval]))
754 THEN ((ASSUME_TAC (REAL_ARITH `abs(x -. g) <=. abs(f-.g) +. abs(x -. f)`)))
755 THEN ((H_VAL2 IWRITE_REAL_LE_RHS (HYP_INT 1) (HYP_INT 0)))
756 THEN ((ASM_REWRITE_TAC[])));;
758 let INTERVAL_WIDTH = prove(
759 `!x f ex ex'. (ex <=. ex') ==> (interval x f ex) ==> (interval x f ex')`,
760 ((REWRITE_TAC[interval]))
762 THEN ((H_VAL2 IWRITE_REAL_LE_RHS (HYP_INT 1) (HYP_INT 0)))
763 THEN ((ASM_REWRITE_TAC[])));;
765 let INTERVAL_MAX = prove(
766 `!x f ex. interval x f ex ==> (x <=. f+.ex)`,
767 (REWRITE_TAC[interval]) THEN REAL_ARITH_TAC);;
769 let INTERVAL_MIN = prove(
770 `!x f ex. interval x f ex ==> (f-. ex <=. x)`,
771 (REWRITE_TAC[interval]) THEN REAL_ARITH_TAC);;
773 let INTERVAL_ABS_MIN = prove(
774 `!x f ex. interval x f ex ==> (abs(f)-. ex <=. abs(x))`,
775 (REWRITE_TAC[interval] THEN REAL_ARITH_TAC)
778 let INTERVAL_ABS_MAX = prove(
779 `!x f ex. interval x f ex ==> (abs(x) <=. abs(f)+. ex)`,
780 (REWRITE_TAC[interval] THEN REAL_ARITH_TAC)
783 let REAL_RINV_2 = prove(
784 `&.2 *. (inv (&.2 )) = &. 1`,
786 MATCH_MP_TAC REAL_MUL_RINV;
789 let INTERVAL_MK = prove(
790 `let half = float(&:1)(--:(&:1)) in
791 !x xmin xmax. ((xmin <=. x) /\ (x <=. xmax)) ==>
794 ((xmax-.xmin)*.half)`,
796 REWRITE_TAC[LET_DEF;LET_END_DEF];
798 REWRITE_TAC[interval;float;TWOPOW_NEG;INT_NUM_REAL;REAL_POW_1;REAL_MUL_LID];
799 REWRITE_TAC[GSYM INTERVAL_ABS];
804 REWRITE_TAC[GSYM REAL_SUB_RDISTRIB];
805 REWRITE_TAC[REAL_ARITH `(b+.a)-.(a-.b)=b*.(&.2)`;GSYM REAL_MUL_ASSOC];
806 ASM_REWRITE_TAC[REAL_RINV_2;REAL_MUL_RID]
809 REWRITE_TAC[GSYM REAL_ADD_RDISTRIB];
810 REWRITE_TAC[REAL_ARITH `(b+.a)+. a -. b=a*.(&.2)`;GSYM REAL_MUL_ASSOC];
811 ASM_REWRITE_TAC[REAL_RINV_2;REAL_MUL_RID]
815 let INTERVAL_EPS_POS = prove(`!x f ex.
816 (interval x f ex) ==> (&.0 <=. ex)`,
818 REWRITE_TAC[interval];
820 DISCH_THEN(fun x -> (MP_TAC (CONJ (SPEC `x-.f` REAL_ABS_POS) x)));
821 MATCH_ACCEPT_TAC REAL_LE_TRANS]);;
823 let INTERVAL_EPS_0 = prove(
824 `!x f n. (interval x f (float (&:0) n)) ==> (x = f)`,
826 REWRITE_TAC[interval;float;int_of_num_th;REAL_MUL_LZERO];
831 let REAL_EQ_RCANCEL_IMP' = prove(`!x y z.(x * z = y * z) ==> (~(z = &0) ==> (x=y))`,
832 MESON_TAC[REAL_EQ_RCANCEL_IMP]);;
834 (* renamed from REAL_ABS_POS *)
835 let REAL_MK_POS_ABS_' = prove (`!x. (~(x=(&.0))) ==> (&.0 < abs(x))`,
836 MESON_TAC[REAL_PROP_NZ_ABS;ABS_POS;REAL_LT_LE]);;
838 (* ------------------------------------------------------------------ *)
839 (* INTERVAL DIVIDE *)
840 (* ------------------------------------------------------------------ *)
842 let INTERVAL_DIV = prove(`!x f ex y g ey h ez.
843 (((interval x f ex) /\ (interval y g ey) /\ (ey <. (abs g)) /\
844 ((ex +. (abs (f -. (h*.g))) +. (abs h)*. ey) <=. (ez*.((abs g) -. ey))))
845 ==> (interval (x / y) h ez))`,
847 let lemma1 = prove( `&.0 < u /\ ||. z <=. e*. u ==> (&.0) <=. e`,
850 ASSUME_TAC (SPEC `z:real` REAL_MK_NN_ABS);
851 H_MATCH_MP (THM REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 0) (HYP_INT 2));
852 H_MATCH_MP (THM REAL_PROP_NN_RCANCEL) (H_RULE2 CONJ (HYP_INT 2) (HYP_INT 0));
857 SUBGOAL_TAC `~(y= (&.0))`
861 REWRITE_TAC[interval];
865 REWRITE_TAC[interval];
866 DISCH_TAC THEN (H I (HYP_INT 0)) THEN (UNDISCH_EL_TAC 0);
867 DISCH_THEN (fun th -> (MP_TAC(MATCH_MP REAL_MK_POS_ABS_' th)));
868 MATCH_MP_TAC REAL_MUL_RTIMES_LE;
869 REWRITE_TAC[GSYM ABS_MUL;REAL_SUB_RDISTRIB;real_div;GSYM REAL_MUL_ASSOC];
870 ASM_SIMP_TAC[REAL_MUL_LINV;REAL_MUL_RID];
871 H (REWRITE_RULE[interval]) (HYP_INT 1);
872 H (REWRITE_RULE[interval]) (HYP_INT 3);
873 H (MATCH_MP INTERVAL_ABS_MIN) (HYP_INT 4);
875 H_VAL2 (IWRITE_REAL_LE_LHS) (HYP_INT 2) (HYP_INT 4);
876 H (REWRITE_RULE[ REAL_ADD_ASSOC]) (HYP_INT 0);
877 H_VAL2 (IWRITE_REAL_LE_LHS) (THM (SPEC `f-. h*g` (SPEC `x-.f` ABS_TRIANGLE))) (HYP_INT 0);
878 H (ONCE_REWRITE_RULE[REAL_ABS_SUB]) (HYP_INT 4);
879 H (MATCH_MP (SPEC `h:real` REAL_PROP_LE_LABS)) (HYP_INT 0);
880 H (REWRITE_RULE[GSYM ABS_MUL]) (HYP_INT 0);
881 H_VAL2 (IWRITE_REAL_LE_LHS) (HYP_INT 0) (HYP_INT 3);
882 H_VAL2 (IWRITE_REAL_LE_LHS) (THM (SPEC `h*.(g-.y)` (SPEC`(x-.f)+(f-. h*g)` ABS_TRIANGLE))) (HYP_INT 0);
883 POPL_TAC[1;2;3;4;5;6;7;9;10;12];
884 H (ONCE_REWRITE_RULE[REAL_ARITH `((x-.f) +. (f -. h*. g)) +. h*.(g-. y) = x -. h*. y `]) (HYP_INT 0);
885 ABBREV_TAC `z = x -. h*.y`;
886 H (ONCE_REWRITE_RULE[GSYM REAL_SUB_LT]) (HYP_INT 4);
887 ABBREV_TAC `u = abs(g) -. ey`;
889 H (MATCH_MP lemma1 ) (H_RULE2 CONJ (HYP_INT 0) (HYP_INT 1));
890 H (MATCH_MP REAL_PROP_LE_LMUL) (H_RULE2 CONJ (HYP_INT 0) (HYP_INT 3));
891 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 3) (HYP_INT 0));
896 (* ------------------------------------------------------------------ *)
897 (* INTERVAL ABS VALUE *)
898 (* ------------------------------------------------------------------ *)
900 let INTERVAL_ABSV = prove(`!x f ex. interval x f ex ==> (interval (abs x) (abs f) ex)`,
902 REWRITE_TAC[interval];
904 ASSUME_TAC (SPECL [`x:real`;`f:real`] REAL_ABS_SUB_ABS);
905 ASM_MESON_TAC[REAL_LE_TRANS]
908 (* ------------------------------------------------------------------ *)
910 (* This requires some preliminaries. Extend sqrt by 0 on negatives *)
911 (* ------------------------------------------------------------------ *)
913 let ssqrt = new_definition `ssqrt x = if (x <. (&.0)) then (&.0) else sqrt x`;; (*2m*)
915 let LET_TAC = REWRITE_TAC[LET_DEF;LET_END_DEF];;
918 let REAL_SSQRT_NEG = prove(`!x. (x <. (&.0)) ==> (ssqrt x = (&.0))`,
924 ACCEPT_TAC (REFL `&.0`);
930 let REAL_SSQRT_NN = prove(`!x. (&.0) <=. x ==> (ssqrt x = (sqrt x))`,
936 ASM_MESON_TAC[real_lt];
937 ACCEPT_TAC (REFL `sqrt x`)
939 ]);; (* 12 min, mostly spent loading *index-shell* *)
943 let REAL_MK_NN_SSQRT = prove(`!x. (&.0) <=. (ssqrt x)`,
946 DISJ_CASES_TAC (SPECL[`x:real`;`&.0`] REAL_LTE_TOTAL)
948 POP_ASSUM (fun th -> MP_TAC(MATCH_MP (REAL_SSQRT_NEG) th)) THEN
949 MESON_TAC[REAL_LE_REFL];
950 POP_ASSUM (fun th -> ASSUME_TAC(CONJ th (MATCH_MP (REAL_SSQRT_NN) th))) THEN
951 ASM_MESON_TAC[REAL_PROP_NN_SQRT]
955 let REAL_SV_SSQRT_0 = prove(`!x. ssqrt (&.0) = (&.0)`,
958 MP_TAC (SPEC `&.0` REAL_LE_REFL);
959 DISCH_THEN(fun th -> REWRITE_TAC[MATCH_MP REAL_SSQRT_NN th]);
960 ACCEPT_TAC REAL_SV_SQRT_0
964 let REAL_SSQRT_EQ_0 = prove(`!(x:real). (ssqrt(x) = (&.0)) ==> (x <=. (&.0))`,
967 DISJ_CASES_TAC (SPECL[`x:real`;`&.0`] REAL_LTE_TOTAL)
969 ASM_MESON_TAC[REAL_LT_IMP_LE];
970 ASM_SIMP_TAC[REAL_SSQRT_NN] THEN
971 ASM_MESON_TAC[SQRT_EQ_0;REAL_EQ_IMP_LE]
973 ]);; (* 15 minutes *)
976 let REAL_SSQRT_MONO = prove(`!x. (x<=. y) ==> (ssqrt x <=. (ssqrt y))`,
979 DISJ_CASES_TAC (SPECL[`x:real`;`&.0`] REAL_LTE_TOTAL)
981 ASM_MESON_TAC[REAL_SSQRT_NEG;REAL_MK_NN_SSQRT];
982 ASM_MESON_TAC[REAL_LE_TRANS;REAL_SSQRT_NN;REAL_PROP_LE_SQRT];
986 let REAL_SSQRT_CHAR = prove(`!x t. (&.0 <=. t /\ (t*t = x)) ==> (t = (ssqrt x))`,
989 H_ASSUME_TAC (H_RULE_LIST REWRITE_RULE[HYP_INT 1] (THM (SPEC `t:real` REAL_MK_NN_SQUARE)));
990 ASM_MESON_TAC[REAL_SSQRT_NN;SQRT_MUL;POW_2_SQRT_ABS;REAL_POW_2;REAL_ABS_REFL];
991 ]);; (* 13 minutes *)
993 let REAL_SSQRT_SQUARE = prove(`!x. (&.0 <=. x) ==> ((ssqrt x)*.(ssqrt x) = x)`,
994 MESON_TAC[REAL_SSQRT_NN;POW_2;SQRT_POW_2]);;(* 7min *)
996 let REAL_SSQRT_SQUARE' = prove(`!x. (&.0<=. x) ==> (ssqrt (x*.x) = x)`,
998 REWRITE_TAC[(MATCH_MP REAL_SSQRT_NN (SPEC `x:real` REAL_MK_NN_SQUARE))] THEN
999 ASM_SIMP_TAC[SQRT_MUL;GSYM POW_2;SQRT_POW_2]);; (*20min*)
1002 (* an alternate proof appears in RCS *)
1003 let INTERVAL_SSQRT = prove(`!x f ex u ey ez v. (interval x f ex) /\ (interval (u*.u) f ey) /\
1004 (ex +.ey <=. ez*.(v+.u)) /\ (v*.v <=. f-.ex) /\ (&.0 <. u) /\ (&.0 <=. v) ==>
1005 (interval (ssqrt x) u ez)`,
1008 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (THM (SPEC `v:real` REAL_MK_NN_SQUARE)) (HYP_INT 3));
1009 H (MATCH_MP (INTERVAL_MIN)) (HYP_INT 1);
1010 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 1) (HYP_INT 0));
1011 H (MATCH_MP INTERVAL_EPS_POS) (HYP_INT 3);
1012 H (MATCH_MP INTERVAL_EPS_POS) (HYP_INT 5);
1013 H (MATCH_MP REAL_PROP_NN_ADD2) (H_RULE2 CONJ (HYP_INT 1) (HYP_INT 0));
1014 H (MATCH_MP REAL_PROP_POS_LADD) (H_RULE2 CONJ (HYP_INT 11) (HYP_INT 10));
1015 H (MATCH_MP REAL_PROP_POS_LADD) (H_RULE2 CONJ (THM (SPEC `x:real` REAL_MK_NN_SSQRT)) (HYP_INT 11));
1016 H (MATCH_MP REAL_PROP_POS_INV) (HYP_INT 0);
1017 ASSUME_TAC (REAL_ARITH `(ssqrt x -. u) = (ssqrt x -. u)*.(&.1)`);
1018 H (MATCH_MP REAL_MK_NZ_POS) (HYP_INT 2);
1019 H (MATCH_MP REAL_MUL_RINV) (HYP_INT 0);
1020 H_REWRITE_RULE[(H_RULE GSYM) (HYP_INT 0)] (HYP_INT 2);
1022 H (REWRITE_RULE[REAL_MUL_ASSOC]) (HYP_INT 0);
1023 H (REWRITE_RULE[ONCE_REWRITE_RULE[REAL_MUL_SYM] REAL_DIFFSQ]) (HYP_INT 0);
1025 H_SIMP_RULE[HYP_INT 7;THM REAL_SSQRT_SQUARE] (HYP_INT 0);
1026 ASSUME_TAC (REAL_ARITH `abs(x -. u*.u) <=. abs(x -. f) + abs(f-. u*.u)`);
1027 H (REWRITE_RULE[interval]) (HYP_INT 12);
1028 H (ONCE_REWRITE_RULE[interval]) (HYP_INT 14);
1029 H (ONCE_REWRITE_RULE[REAL_ABS_SUB]) (HYP_INT 0);
1030 POPL_TAC[1;5;15;16];
1031 H (MATCH_MP REAL_LE_ADD2) (H_RULE2 CONJ (HYP_INT 1) (HYP_INT 0));
1032 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 3) (HYP_INT 0));
1034 H (AP_TERM `||.`) (HYP_INT 1);
1035 H (REWRITE_RULE[ABS_MUL]) (HYP_INT 0);
1036 H (MATCH_MP REAL_LT_IMP_LE) (HYP_INT 4);
1037 H (REWRITE_RULE[GSYM REAL_ABS_REFL]) (HYP_INT 0);
1038 H_REWRITE_RULE [HYP_INT 0] (HYP_INT 2);
1039 H (MATCH_MP REAL_LE_RMUL) (H_RULE2 CONJ (HYP_INT 5) (HYP_INT 2));
1040 H_REWRITE_RULE [H_RULE GSYM (HYP_INT 1)] (HYP_INT 0);
1041 POPL_TAC[1;2;3;5;6;7;8];
1042 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 12) (HYP_INT 9));
1043 H (MATCH_MP REAL_SSQRT_MONO) (HYP_INT 0);
1044 H (MATCH_MP REAL_SSQRT_SQUARE') (HYP_INT 16);
1045 H_REWRITE_RULE [HYP_INT 0] (HYP_INT 1);
1046 H (ONCE_REWRITE_RULE[GSYM (SPECL[`v:real`;`ssqrt x`;`u:real`] REAL_LE_RADD)]) (HYP_INT 0);
1047 H (MATCH_MP REAL_LE_INV2) (H_RULE2 CONJ (HYP_INT 9) (HYP_INT 0));
1048 POPL_TAC[1;2;3;4;5;7;8;9;12;13];
1049 H (MATCH_MP REAL_LE_LMUL) (H_RULE2 CONJ (HYP_INT 3) (HYP_INT 0));
1050 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 2) (HYP_INT 0));
1051 H (MATCH_MP REAL_PROP_POS_INV) (HYP_INT 4);
1052 H (MATCH_MP REAL_LT_IMP_LE) (HYP_INT 0);
1053 H (MATCH_MP REAL_LE_RMUL) (H_RULE2 CONJ (HYP_INT 11) (HYP_INT 0));
1054 H (REWRITE_RULE[GSYM REAL_MUL_ASSOC]) (HYP_INT 0);
1055 H (MATCH_MP REAL_MK_NZ_POS) (HYP_INT 8);
1056 H (MATCH_MP REAL_MUL_RINV) (HYP_INT 0);
1057 H_REWRITE_RULE[HYP_INT 0; THM REAL_MUL_RID] (HYP_INT 2);
1058 H (MATCH_MP REAL_LE_TRANS) (H_RULE2 CONJ (HYP_INT 7) (HYP_INT 0));
1059 ASM_REWRITE_TAC[interval]
1067 (* conversion for interval *)
1069 (* ------------------------------------------------------------------ *)
1070 (* Take a term x of type real. Convert to a thm of the form *)
1071 (* interval x f eps *)
1073 (* ------------------------------------------------------------------ *)
1075 let DOUBLE_CONV_FILE=true;;
1077 let add_test,test = new_test_suite();;
1079 (* Num package docs at http://caml.inria.fr/ocaml/htmlman/libref/Num.html *)
1081 (* ------------------------------------------------------------------ *)
1083 Take the absolute value of input.
1084 Write it as a*2^k, where 1 <= a < 2, return k.
1087 num_exponent (Int 0) is -1.
1089 let (num_exponent:Num.num -> Num.num) =
1091 let afloat = float_of_num (abs_num a) in
1092 Int ((snd (frexp afloat)) - 1);;
1094 (*test*)let f (u,v) = ((num_exponent u) =(Int v)) in
1095 add_test("num_exponenwt",
1097 [Int 1,0; Int 65,6; Int (-65),6;
1098 Int 0,-1; (Int 3)//(Int 4),-1]);;
1099 (* ------------------------------------------------------------------ *)
1101 let dest_unary op tm =
1102 try let xop,r = dest_comb tm in
1103 if xop = op then r else fail()
1104 with Failure _ -> failwith "dest_unary";;
1107 (* ------------------------------------------------------------------ *)
1110 (* finds a nearby (outward-rounded) Int with only prec_b significant bits *)
1111 let (round_outward: int -> Num.num -> Num.num) =
1113 let b = abs_num a in
1114 let sign = if (a =/ b) then I else minus_num in
1115 let throw_bits = Num.max_num (Int 0) ((num_exponent b)-/ (Int prec_b)) in
1116 let twoexp = power_num (Int 2) throw_bits in
1117 (sign (ceiling_num (b // twoexp)))*/twoexp;;
1119 let (round_inward: int-> Num.num -> Num.num) =
1121 let b = abs_num a in
1122 let sign = if (a=/b) then I else minus_num in
1123 let throw_bits = Num.max_num (Int 0) ((num_exponent b)-/ (Int prec_b)) in
1124 let twoexp = power_num (Int 2) throw_bits in
1125 (sign (floor_num (b // twoexp)))*/twoexp;;
1127 let round_rat bprec n =
1128 let b = abs_num n in
1129 let sign = if (b =/ n) then I else minus_num in
1130 let powt = ((Int 2) **/ (Int bprec)) in
1131 sign ((round_outward bprec (Num.ceiling_num (b */ powt)))//powt);;
1133 let round_inward_rat bprec n =
1134 let b = abs_num n in
1135 let sign = if (b =/ n) then I else minus_num in
1136 let powt = ((Int 2) **/ (Int bprec)) in
1137 sign ((round_inward bprec (Num.floor_num (b */ powt)))//powt);;
1139 let (round_outward_float: int -> float -> Num.num) =
1141 if (f=0.0) then (Int 0) else
1143 let b = abs_float f in
1144 let sign = if (f >= 0.0) then I else minus_num in
1145 let (x,n) = frexp b in
1146 let u = int_of_float( ceil (ldexp x bprec)) in
1147 sign ((Int u)*/ ((Int 2) **/ (Int (n - bprec))))
1150 let (round_inward_float: int -> float -> Num.num) =
1152 if (f=0.0) then (Int 0) else
1154 (* avoid overflow on 30 bit integers *)
1155 let bprec = if (bprec > 25) then 25 else bprec in
1156 let b = abs_float f in
1157 let sign = if (f >= 0.0) then I else minus_num in
1158 let (x,n) = frexp b in
1159 let u = int_of_float( floor (ldexp x bprec)) in
1160 sign ((Int u)*/ ((Int 2) **/ (Int (n - bprec))))
1163 (* ------------------------------------------------------------------ *)
1165 (* This doesn't belong here. A general term substitution function *)
1166 let SUBST_TERM sublist tm =
1167 rhs (concl ((SPECL (map fst sublist)) (GENL (map snd sublist)
1170 add_test("SUBST_TERM",
1171 SUBST_TERM [(`#1`,`a:real`);(`#2`,`b:real`)] (`a +. b +. c`) =
1174 (* ------------------------------------------------------------------ *)
1176 (* take a term of the form `interval x f ex` and clean up the f and ex *)
1178 let INTERVAL_CLEAN_CONV:conv =
1180 let (ixf,ex) = dest_comb interv in
1181 let (ix,f) = dest_comb ixf in
1182 let fthm = FLOAT_CONV f in
1183 let exthm = FLOAT_CONV ex in
1184 let ixfthm = AP_TERM ix fthm in
1185 MK_COMB (ixfthm, exthm);;
1187 (*test*) add_test("INTERVAL_CLEAN_CONV",
1188 let testval = INTERVAL_CLEAN_CONV `interval ((&.1) +. (&.1))
1189 (float (&:3) (&:4) +. (float (&:2) (--: (&:3))))
1190 (float (&:1) (&:2) *. (float (&:3) (--: (&:2))))` in
1191 let hypval = hyp testval in
1192 let concval = concl testval in
1193 (length hypval = 0) &&
1195 `interval (&1 + &1) (float (&:3) (&:4) + float (&:2) (--: (&:3)))
1196 (float (&:1) (&:2) * float (&:3) (--: (&:2))) =
1197 interval (&1 + &1) (float (&:386) (--: (&:3))) (float (&:3) (&:0))`
1200 (* ------------------------------------------------------------------ *)
1201 (* GENERAL lemmas *)
1202 (* ------------------------------------------------------------------ *)
1205 (* verifies statement of the form `float a b = float a' b'` *)
1207 let FLOAT_EQ = prove(
1208 `!a b a' b'. (float a b = (float a' b')) <=>
1209 ((float a b) -. (float a' b') = (&.0))`,MESON_TAC[REAL_SUB_0]);;
1211 let FLOAT_LT = prove(
1212 `!a b a' b'. (float a b <. (float a' b')) <=>
1213 ((&.0) <. (float a' b') -. (float a b))`,MESON_TAC[REAL_SUB_LT]);;
1215 let FLOAT_LE = prove(
1216 `!a b a' b'. (float a b <=. (float a' b')) <=>
1217 ((&.0) <=. (float a' b') -. (float a b))`,MESON_TAC[REAL_SUB_LE]);;
1219 let TWOPOW_MK_POS = prove(
1220 `!a. (&.0 <. ( twopow a))`,
1223 CHOOSE_TAC (SPEC `a:int` INT_REP2);
1224 POP_ASSUM DISJ_CASES_TAC;
1225 ASM_REWRITE_TAC[TWOPOW_POS;TWOPOW_NEG];
1226 TRY (MATCH_MP_TAC REAL_INV_POS);
1227 MATCH_MP_TAC REAL_POW_LT ;
1231 let TWOPOW_NZ = prove(
1232 `!a. ~(twopow a = (&.0))`,
1234 ACCEPT_TAC (MATCH_MP REAL_MK_NZ_POS (SPEC `a:int` TWOPOW_MK_POS)));;
1236 let FLOAT_ZERO = prove(
1237 `!a b. (float a b = (&.0)) <=> (a = (&:0))`,
1239 REWRITE_TAC[float;REAL_ENTIRE;INT_OF_NUM_DEST];
1240 MESON_TAC[TWOPOW_NZ];
1243 let INT_ZERO = prove(
1244 `!n. ((&:n = (&:0)) = (n=0))`,REWRITE_TAC[INT_OF_NUM_EQ]);;
1246 let INT_ZERO_NEG=prove(
1247 `!n. ((--: (&:n) = (&:0))) <=> (n=0)`,
1248 REWRITE_TAC[INT_NEG_EQ_0;INT_ZERO]);;
1250 let FLOAT_NN = prove(
1251 `!a b. ((&.0) <=. (float a b)) <=> (&:0 <=: a)`,
1253 REWRITE_TAC[float;INT_OF_NUM_DEST];
1257 INPUT_COMBO[THM REAL_PROP_NN_RCANCEL;THM (SPEC `b:int` TWOPOW_MK_POS) &&& (HYP"0")];
1258 ASM_MESON_TAC[int_le;int_of_num_th]];
1261 INPUT_COMBO[THM REAL_PROP_NN_POS;THM(SPEC`b:int`TWOPOW_MK_POS)];
1262 INPUT_COMBO[THM int_of_num_th ; THM int_le ;(HYP"0")];
1263 INPUT_COMBO[THM REAL_PROP_NN_MUL2; (HYP"2")&&&(HYP"1")];
1267 let INT_NN = INT_POS;;
1269 let INT_NN_NEG = prove(`!n. ((&:0) <=: (--:(&:n))) <=> (n = 0)`,
1270 REWRITE_TAC[INT_NEG_GE0;INT_OF_NUM_LE] THEN ARITH_TAC
1273 let FLOAT_POS = prove(`!a b. ((&.0) <. (float a b)) <=> (&:0 <: a)`,
1274 MESON_TAC[FLOAT_NN;FLOAT_ZERO;INT_LT_LE;REAL_LT_LE]);;
1276 let INT_POS' = prove(`!n. (&:0) <: (&:n) <=> (~(n=0) )`,
1277 REWRITE_TAC[INT_OF_NUM_LT] THEN ARITH_TAC);;
1279 let INT_POS_NEG =prove(`!n. ((&:0) <: (--:(&:n))) <=> F`,
1280 REWRITE_TAC[INT_OF_NUM_LT] THEN ARITH_TAC);;
1282 let RAT_LEMMA1_SUB = prove(`~(y1 = &0) /\ ~(y2 = &0) ==>
1283 ((x1 / y1) - (x2 / y2) = (x1 * y2 - x2 * y1) * inv(y1) * inv(y2))`,
1284 EVERY[REWRITE_TAC[real_div];
1285 REWRITE_TAC[real_sub;GSYM REAL_MUL_LNEG];
1286 REWRITE_TAC[GSYM real_div];
1287 SIMP_TAC[RAT_LEMMA1];
1289 MESON_TAC[real_div]]);;
1291 let INTERVAL_0 = prove(`! a f ex. (interval a f ex <=> (&.0 <= (ex - (abs (a -. f)))))`,
1292 MESON_TAC[interval;REAL_SUB_LE]);;
1296 let ABS_NUM = prove (`!m n. abs (&. n -. (&. m)) = &.((m-|n) + (n-|m))`,
1298 DISJ_CASES_TAC (SPECL [`m:num`;`n:num`] LTE_CASES) THENL[
1300 EVERY[ LABEL_ALL_TAC;
1301 H_REWRITE_RULE [THM (GSYM REAL_OF_NUM_LT)] (HYP "0");
1303 H_ONCE_REWRITE_RULE[THM (GSYM REAL_SUB_LT)] (HYP "1");
1305 H_MATCH_MP (THM REAL_LT_IMP_LE) (HYP "2");
1307 H_REWRITE_RULE [THM (GSYM ABS_REFL)] (HYP "3");
1309 H_MATCH_MP (THM LT_IMP_LE) (HYP "0");
1310 ASM_SIMP_TAC[REAL_OF_NUM_SUB];
1311 REWRITE_TAC[REAL_OF_NUM_EQ];
1312 ONCE_REWRITE_TAC[ARITH_RULE `!x:num y:num. (x = y) = (y = x)`];
1313 REWRITE_TAC[EQ_ADD_RCANCEL_0];
1314 ASM_REWRITE_TAC[SUB_EQ_0]];
1316 EVERY[LABEL_ALL_TAC;
1317 H_REWRITE_RULE [THM (GSYM REAL_OF_NUM_LE)] (HYP "0");
1319 H_ONCE_REWRITE_RULE[THM (GSYM REAL_SUB_LE)] (HYP "1");
1321 H_REWRITE_RULE [THM (GSYM ABS_REFL)] (HYP "2");
1322 ONCE_REWRITE_TAC[GSYM REAL_ABS_NEG];
1323 REWRITE_TAC[REAL_ARITH `!x y. --.(x -. y) = (y-x)`];
1325 ASM_SIMP_TAC[REAL_OF_NUM_SUB];
1326 REWRITE_TAC[REAL_OF_NUM_EQ];
1327 ONCE_REWRITE_TAC[ARITH_RULE `!x:num y:num. (x = y) <=> (y = x)`];
1328 REWRITE_TAC[EQ_ADD_LCANCEL_0];
1329 ASM_REWRITE_TAC[SUB_EQ_0]]]);;
1331 let INTERVAL_TO_LESS = prove(
1332 `!a f ex b g ey. ((interval a f ex) /\ (interval b g ey) /\
1333 (&.0 <. (g -. (ey +. ex +. f)))) ==> (a <. b)`,
1334 let lemma1 = REAL_ARITH `!ex ey f g. (&.0 <.
1335 (g -. (ey +. ex +. f))) ==> ((f +. ex)<. (g -. ey)) ` in
1339 H_MATCH_MP (THM lemma1) (HYP "2");
1340 H_MATCH_MP (THM INTERVAL_MAX) (HYP "0");
1341 H_MATCH_MP (THM INTERVAL_MIN) (HYP "1");
1343 H_MATCH_MP (THM REAL_LET_TRANS) (H_RULE2 CONJ (HYP "4") (HYP "5"));
1345 H_MATCH_MP (THM REAL_LTE_TRANS) (H_RULE2 CONJ (HYP "6") (HYP "3"));
1349 let ABS_TO_INTERVAL = prove(
1350 `!c u k. (abs (c - u) <=. k) ==> (!f g ex ey.((interval u f ex) /\ (interval k g ey) ==> (interval c f (g+.ey+.ex))))`,
1352 REWRITE_TAC[interval];
1356 ONCE_REWRITE_TAC [REAL_ARITH `c -. f = (c-. u) + (u-. f)`];
1357 ONCE_REWRITE_TAC [REAL_ADD_ASSOC];
1358 ASSUME_TAC (SPECL [`c-.u`;`u-.f`] ABS_TRIANGLE);
1359 IMP_RES_THEN ASSUME_TAC (REAL_ARITH `||.(k-.g) <=. ey ==> (k <=. (g +. ey))`);
1360 MATCH_MP_TAC (REAL_ARITH `(?a b.((x <=. (a+.b)) /\ (a <=. u) /\ (b <=. v))) ==> (x <=. (u +. v))`);
1361 EXISTS_TAC `abs (c-.u)`;
1362 EXISTS_TAC `abs(u-.f)`;
1364 ASM_MESON_TAC[REAL_LE_TRANS];
1368 (* end of general lemmas *)
1369 (* ------------------------------------------------------------------ *)
1372 (* ------------------------------------------------------------------ *)
1373 (* Cache of computed constants (abs (c - u) <= k) *)
1374 (* ------------------------------------------------------------------ *)
1376 let calculated_constants = ref ([]:(term*thm) list);;
1378 let add_real_constant ineq =
1380 let (abst,k) = dest_binop `(<=.)` (concl ineq) in
1381 let (absh,cmu) = dest_comb abst in
1382 let (c,u) = dest_binop `(-.)` cmu in
1383 calculated_constants := (c,ineq)::(!calculated_constants))
1386 let (c,f,ex) = dest_interval (concl ineq) in
1387 calculated_constants := (c,ineq)::(!calculated_constants))
1388 with _ -> failwith "calculated_constants format : abs(c - u) <= k");;
1390 let get_real_constant tm =
1391 assoc tm !calculated_constants;;
1393 let remove_real_constant tm =
1394 calculated_constants :=
1395 filter (fun t -> not ((fst t) = tm)) !calculated_constants;;
1399 (* ------------------------------------------------------------------ *)
1401 (* term of the form '&.n'. Assume error checking done already. *)
1402 let INTERVAL_OF_NUM:conv =
1404 let tm1 = snd (dest_comb tm) in
1405 let th1 = (ARITH_REWRITE_CONV[] tm1) in
1406 ONCE_REWRITE_RULE[AP_TERM `&.` (GSYM th1)]
1407 (SPEC (rhs (concl th1)) INTERVAL_NUM);;
1409 add_test("INTERVAL_OF_NUM",
1410 dest_thm (INTERVAL_OF_NUM `&.3`) = ([],
1411 `interval (&3) (float (&:3) (&:0)) (float (&:0) (&:0))`));;
1413 (* term of the form `--. (&.n)`. Assume format checking already done. *)
1414 let INTERVAL_OF_NEG:conv =
1416 let (sign,u) = dest_comb tm in
1417 let _ = assert(sign = `--.`) in
1418 let (amp,tm1) = (dest_comb u) in
1419 let _ = assert(amp = `&.`) in
1420 let th1 = (ARITH_REWRITE_CONV[] tm1) in
1421 ONCE_REWRITE_RULE[FLOAT_NEG] (
1422 ONCE_REWRITE_RULE[INTERVAL_NEG] (
1423 ONCE_REWRITE_RULE[AP_TERM `&.` (GSYM th1)] (
1424 (SPEC (rhs (concl th1)) INTERVAL_NUM))));;
1426 add_test("INTERVAL_OF_NEG",
1427 dest_thm (INTERVAL_OF_NEG `--.(&. (3+4))`) =
1428 ([],`interval( --.(&.(3 + 4)) )
1429 (float (--: (&:7)) (&:0)) (float (&:0) (&:0))`));;
1431 (* ------------------------------------------------------------------ *)
1433 let INTERVAL_TO_LESS_CONV = fun thm1 thm2 ->
1434 let (a,f,ex) = dest_interval (concl thm1) in
1435 let (b,g,ey) = dest_interval (concl thm2) in
1436 let rthm = ASSUME `!f g ex ey. (&.0 <. (g -. (ey +. ex +. f)))` in
1437 let rspec = concl (SPECL [f;g;ex;ey] rthm) in
1438 let rspec_simp = FLOAT_CONV (snd (dest_binop `(<.)` rspec)) in
1439 let rthm2 = prove (rspec,REWRITE_TAC[rspec_simp;FLOAT_POS;INT_POS';
1440 INT_POS_NEG] THEN ARITH_TAC) in
1441 let fthm = CONJ thm1 (CONJ thm2 rthm2) in
1442 MATCH_MP INTERVAL_TO_LESS fthm;;
1444 add_test("INTERVAL_TO_LESS_CONV",
1446 `interval (#0.1) (float (&:1) (--: (&:1))) (float (&:1) (--: (&:2)))` in
1447 let thm2 = ASSUME `interval (#7) (float (&:4) (&:1)) (float (&:1) (&:0))` in
1448 let thm3 = INTERVAL_TO_LESS_CONV thm1 thm2 in
1449 concl thm3 = `#0.1 <. (#7)`);;
1451 add_test("INTERVAL_TO_LESS_CONV2",
1452 let (h,c) = dest_thm (INTERVAL_TO_LESS_CONV
1453 (INTERVAL_OF_NUM `&.3`) (INTERVAL_OF_NUM `&.8`)) in
1454 (h=[]) && (c = `&.3 <. (&.8)`));;
1456 (* ------------------------------------------------------------------ *)
1458 (* conversion for DEC <= posfloat and posfloat <= DEC *)
1461 `!n m p. ((&.p/(&.m)) <= (&.n)) <=> ((&.p/(&.m)) <= (&.n)/(&.1))`,
1462 MESON_TAC[REAL_DIV_1]);;
1465 `!n m p. ((&.p) <= ((&.n)/(&.m))) <=> ((&.p/(&.1)) <= (&.n)/(&.m))`,
1466 MESON_TAC[REAL_DIV_1]);;
1468 let lemma3 = prove(`!a b c d. (
1469 ((0<b) /\ (0<d) /\ (a*d <=| c*b))
1470 ==> (&.a/(&.b) <=. ((&.c)/(&.d))))`,
1471 EVERY[REPEAT GEN_TAC;
1473 ASM_SIMP_TAC[RAT_LEMMA4;REAL_LT;REAL_OF_NUM_MUL;REAL_LE]]);;
1475 let DEC_FLOAT = EQT_ELIM o
1476 ARITH_SIMP_CONV[DECIMAL;float;TWOPOW_POS;TWOPOW_NEG;GSYM real_div;
1477 REAL_OF_NUM_POW;INT_NUM_REAL;REAL_OF_NUM_MUL;
1478 lemma1;lemma2;lemma3];;
1480 add_test("DEC_FLOAT",
1482 dest_thm (c x) = ([],x) in
1483 ((f DEC_FLOAT `#10.0 <= (float (&:3) (&:2))`) &&
1484 (f DEC_FLOAT `#10 <= (float (&:3) (&:2))`) &&
1485 (f DEC_FLOAT `#0.1 <= (float (&:1) (--: (&:2)))`) &&
1486 (f DEC_FLOAT `float (&:3) (&:2) <= (#13.0)`) &&
1487 (f DEC_FLOAT `float (&:3) (&:2) <= (#13)`) &&
1488 (f DEC_FLOAT `float (&:1) (--: (&:2)) <= (#0.3)`)));;
1489 (* ------------------------------------------------------------------ *)
1490 (* conversion for float inequalities *)
1492 let FLOAT_INEQ_CONV t =
1493 let thm1= (ONCE_REWRITE_CONV[GSYM REAL_SUB_LT;GSYM REAL_SUB_LE] t) in
1494 let rhsx= rhs (concl thm1) in
1495 let thm2= prove(rhsx,REWRITE_TAC[FLOAT_CONV (snd (dest_comb rhsx))] THEN
1496 REWRITE_TAC[FLOAT_NN;FLOAT_POS;INT_NN;INT_NN_NEG;
1497 INT_POS';INT_POS_NEG] THEN ARITH_TAC) in
1498 REWRITE_RULE[GSYM thm1] thm2;;
1500 let t1 = `(float (&:3) (&:0)) +. (float (&:4) (&:0)) <. (float (&:8) (&:1))`;;
1503 add_test("FLOAT_INEQ_CONV",
1505 dest_thm (c x) = ([],x) in
1507 `(float (&:3) (&:0)) +. (float (&:4) (&:0)) <. (float (&:8) (&:1))` in
1508 ((f FLOAT_INEQ_CONV t1)));;
1513 (* ------------------------------------------------------------------ *)
1515 (* converts a DECIMAL TO A THEOREM *)
1517 let INTERVAL_MINMAX = prove(`!x f ex.
1518 ((f -. ex) <= x) /\ (x <=. (f +. ex)) ==> (interval x f ex)`,
1519 EVERY[REPEAT GEN_TAC;
1520 REWRITE_TAC[interval;ABS_BOUNDS];
1524 let INTERVAL_OF_DECIMAL bprec dec =
1525 let a_num = dest_decimal dec in
1526 let f_num = round_rat bprec a_num in
1527 let ex_num = round_rat bprec (Num.abs_num (f_num -/ a_num)) in
1528 let _ = assert (ex_num <=/ f_num) in
1529 let f = mk_float f_num in
1530 let ex= mk_float ex_num in
1531 let fplus_ex = FLOAT_CONV (mk_binop `(+.)` f ex) in
1532 let fminus_ex= FLOAT_CONV (mk_binop `(-.)` f ex) in
1533 let fplus_term = rhs (concl fplus_ex) in
1534 let fminus_term = rhs (concl fminus_ex) in
1535 let th1 = DEC_FLOAT (mk_binop `(<=.)` fminus_term dec) in
1536 let th2 = DEC_FLOAT (mk_binop `(<=.)` dec fplus_term) in
1537 let intv = mk_interval dec f ex in
1538 EQT_ELIM (SIMP_CONV[INTERVAL_MINMAX;fplus_ex;fminus_ex;th1;th2] intv);;
1540 add_test("INTERVAL_OF_DECIMAL",
1541 let (h,c) = dest_thm (INTERVAL_OF_DECIMAL 4 `#36.1`) in
1542 let (x,f,ex) = dest_interval c in
1543 (h=[]) && (x = `#36.1`));;
1545 add_test("INTERVAL_OF_DECIMAL2",
1546 can (fun() -> INTERVAL_TO_LESS_CONV (INTERVAL_OF_DECIMAL 4 `#33.33`)
1547 (INTERVAL_OF_DECIMAL 4 `#36.1`)) ());;
1549 (*--------------------------------------------------------------------*)
1550 (* functions to check format. *)
1551 (* There are various implicit rules: *)
1552 (* NUMERAL is followed by bits and no other kind of num, etc. *)
1553 (* FLOAT a b, both a and b are &:NUMERAL or --:&:NUMERAL, etc. *)
1554 (*--------------------------------------------------------------------*)
1557 (* converts exceptions to false *)
1558 let falsify_ex f x = try (f x) with _ -> false;;
1560 let is_bits_format =
1562 if (x = `_0`) then true
1563 else let (h,t) = dest_comb x in
1564 (((h = `BIT1`) or (h = `BIT0`)) && (format t))
1565 in falsify_ex format;;
1567 let is_numeral_format =
1569 let (h,t) = dest_comb x in
1570 ((h = `NUMERAL`) && (is_bits_format t)) in
1573 let is_decimal_format =
1575 let (t1,t2) = dest_binop `DECIMAL` x in
1576 ((is_numeral_format t1) && (is_numeral_format t2)) in
1579 let is_pos_int_format =
1581 let (h,t) = dest_comb x in
1582 (h = `&:`) && (is_numeral_format t) in
1585 let is_neg_int_format =
1587 let (h,t) = dest_comb x in
1588 (h = `--:`) && (is_pos_int_format t) in
1591 let is_int_format x =
1592 (is_neg_int_format x) or (is_pos_int_format x);;
1594 let is_float_format =
1596 let (t1,t2) = dest_binop `float` x in
1597 (is_int_format t1) && (is_int_format t2) in
1600 let is_interval_format =
1602 let (a,b,c) = dest_interval x in
1603 (is_float_format b) && (is_float_format c) in
1608 let (h,t) = dest_comb x in
1612 let is_real_num_format =
1614 let (h,t) = dest_comb x in
1615 (h=`&.`) && (is_numeral_format t) in
1618 let is_comb_of t u =
1620 t = (fst (dest_comb u)) in
1621 try (fn t u) with failure -> false;;
1623 (* ------------------------------------------------------------------ *)
1624 (* Heron's formula for the square root of A
1625 Return a value x that is always at most the actual square root
1626 and such that abs (x - A/x ) < epsilon *)
1628 let rec heron_sqrt depth A x eps =
1629 let half = (Int 1)//(Int 2) in
1630 if (depth <= 0) then raise (Failure "sqrt recursion depth exceeded") else
1631 if (Num.abs_num (x -/ (A//x) ) </ eps) & (x*/ x >=/ A) then (A//x) else
1632 let x' = half */ (x +/ (A//x)) in
1633 heron_sqrt (depth -1) A x' eps;;
1635 let INTERVAL_OF_TWOPOW = prove(
1636 `!n. interval (twopow n) (float (&:1) n) (float (&:0) (&:0))`,
1637 REWRITE_TAC[interval;float;int_of_num_th] THEN
1641 (* ------------------------------------------------------------------ *)
1643 let rec INTERVAL_OF_TERM bprec tm =
1644 (* treat cached values first *)
1645 if (can get_real_constant tm) then
1648 let int_thm = get_real_constant tm in
1649 if (can dest_interval (concl int_thm)) then int_thm
1651 let absthm = get_real_constant tm in
1652 let (abst,k) = dest_binop `(<=.)` (concl absthm) in
1653 let (absh,cmu) = dest_comb abst in
1654 let (c,u) = dest_binop `(-.)` cmu in
1655 let intk = INTERVAL_OF_TERM bprec k in
1656 let intu = INTERVAL_OF_TERM bprec u in
1657 let thm1 = MATCH_MP ABS_TO_INTERVAL absthm in
1658 let thm2 = MATCH_MP thm1 (CONJ intu intk) in
1659 let (_,f,ex)= dest_interval (concl thm2) in
1660 let fthm = FLOAT_CONV f in
1661 let exthm = FLOAT_CONV ex in
1662 let thm3 = REWRITE_RULE[fthm;exthm] thm2 in
1663 (add_real_constant thm3; thm3)
1665 with _ -> failwith "INTERVAL_OF_TERM : CONSTANT"
1667 else if (is_real_num_format tm) then (INTERVAL_OF_NUM tm)
1668 else if (is_decimal_format tm) then (INTERVAL_OF_DECIMAL bprec tm)
1669 (* treat negative terms *)
1670 else if (is_neg_real tm) then
1673 let (_,t) = dest_comb tm in
1674 let int1 = INTERVAL_OF_TERM bprec t in
1675 let (_,b,_) = dest_interval (concl int1) in
1676 let thm1 = FLOAT_CONV (mk_comb (`--.`, b)) in
1677 REWRITE_RULE[thm1] (ONCE_REWRITE_RULE[INTERVAL_NEG] int1))
1678 with _ -> failwith "INTERVAL_OF_TERM : NEG"
1680 (* treat abs value *)
1681 else if (is_comb_of `||.` tm) then
1684 let (_,b) = dest_comb tm in
1685 let b_int = MATCH_MP INTERVAL_ABSV (INTERVAL_OF_TERM bprec b) in
1686 let (_,f,_) = dest_interval (concl b_int) in
1687 let thm1 = FLOAT_CONV f in
1688 REWRITE_RULE[thm1] b_int)
1689 with _ -> failwith "INTERVAL_OF_TERM : ABS"
1692 else if (is_comb_of `twopow` tm) then
1695 let (_,b) = dest_comb tm in
1696 SPEC b INTERVAL_OF_TWOPOW
1698 with _ -> failwith "INTERVAL_OF_TERM : TWOPOW"
1700 (* treat addition *)
1701 else if (can (dest_binop `(+.)`) tm) then
1704 let (a,b) = dest_binop `(+.)` tm in
1705 let a_int = INTERVAL_OF_TERM bprec a in
1706 let b_int = INTERVAL_OF_TERM bprec b in
1707 let c_int = MATCH_MP INTERVAL_ADD (CONJ a_int b_int) in
1708 let (_,f,ex) = dest_interval (concl c_int) in
1709 let thm1 = FLOAT_CONV f and thm2 = FLOAT_CONV ex in
1710 REWRITE_RULE[thm1;thm2] c_int)
1711 with _ -> failwith "INTERVAL_OF_TERM : ADD"
1713 (* treat subtraction *)
1714 else if (can (dest_binop `(-.)`) tm) then
1717 let (a,b) = dest_binop `(-.)` tm in
1718 let a_int = INTERVAL_OF_TERM bprec a in
1719 let b_int = INTERVAL_OF_TERM bprec b in
1720 let c_int = MATCH_MP INTERVAL_SUB (CONJ a_int b_int) in
1721 let (_,f,ex) = dest_interval (concl c_int) in
1722 let thm1 = FLOAT_CONV f and thm2 = FLOAT_CONV ex in
1723 REWRITE_RULE[thm1;thm2] c_int)
1724 with _ -> failwith "INTERVAL_OF_TERM : SUB"
1726 (* treat multiplication *)
1727 else if (can (dest_binop `( *. )`) tm) then
1730 let (a,b) = dest_binop `( *. )` tm in
1731 let a_int = INTERVAL_OF_TERM bprec a in
1732 let b_int = INTERVAL_OF_TERM bprec b in
1733 let c_int = MATCH_MP INTERVAL_MUL (CONJ a_int b_int) in
1734 let (_,f,ex) = dest_interval (concl c_int) in
1735 let thm1 = FLOAT_CONV f and thm2 = FLOAT_CONV ex in
1736 REWRITE_RULE[thm1;thm2] c_int)
1737 with _ -> failwith "INTERVAL_OF_TERM : MUL"
1739 (* treat division : instantiate INTERVAL_DIV *)
1740 else if (can (dest_binop `( / )`) tm) then
1743 let (a,b) = dest_binop `( / )` tm in
1744 let a_int = INTERVAL_OF_TERM bprec a in
1745 let b_int = INTERVAL_OF_TERM bprec b in
1746 let (_,f,ex) = dest_interval (concl a_int) in
1747 let (_,g,ey) = dest_interval (concl b_int) in
1748 let f_num = dest_float f in
1749 let ex_num = dest_float ex in
1750 let g_num = dest_float g in
1751 let ey_num = dest_float ey in
1752 let h_num = round_rat bprec (f_num//g_num) in
1753 let h = mk_float h_num in
1754 let ez_rat = (ex_num +/ abs_num (f_num -/ (h_num*/ g_num))
1755 +/ (abs_num h_num */ ey_num))//((abs_num g_num) -/ (ey_num)) in
1756 let ez_num = round_rat bprec (ez_rat) in
1757 let _ = assert((ez_num >=/ (Int 0))) in
1758 let ez = mk_float ez_num in
1761 let hyp3 = FLOAT_INEQ_CONV (mk_binop `(<.)` ey (mk_comb (`||.`,g))) in
1762 let thm = SPECL [a;f;ex;b;g;ey;h;ez] INTERVAL_DIV in
1763 let conj2 x = snd (dest_conj x) in
1764 let hyp4t = (conj2 (conj2 (conj2 (fst(dest_imp (concl thm)))))) in
1765 let hyp4 = FLOAT_INEQ_CONV hyp4t in
1766 let hyp_all = end_itlist CONJ [hyp1;hyp2;hyp3;hyp4] in
1767 MATCH_MP thm hyp_all)
1768 with _ -> failwith "INTERVAL_OF_TERM :DIV"
1770 (* treat sqrt : instantiate INTERVAL_SSQRT *)
1771 else if (can (dest_unary `ssqrt`) tm) then
1774 let x = dest_unary `ssqrt` tm in
1775 let x_int = INTERVAL_OF_TERM bprec x in
1776 let (_,f,ex) = dest_interval (concl x_int) in
1777 let f_num = dest_float f in
1778 let ex_num = dest_float ex in
1779 let fd_num = f_num -/ ex_num in
1780 let fe_f = Num.float_of_num fd_num in
1781 let apprx_sqrt = Pervasives.sqrt fe_f in
1782 (* put in heron's formula *)
1783 let v_num1 = round_inward_float 25 (apprx_sqrt) in
1784 let v_num = round_inward_rat bprec
1785 (heron_sqrt 10 fd_num v_num1 ((Int 2) **/ (Int (-bprec-4)))) in
1786 let u_num1 = round_inward_float 25
1787 (Pervasives.sqrt (float_of_num f_num)) in
1788 let u_num = round_inward_rat bprec
1789 (heron_sqrt 10 f_num u_num1 ((Int 2) **/ (Int (-bprec-4)))) in
1790 let ey_num = round_rat bprec (abs_num (f_num -/ (u_num */ u_num))) in
1791 let ez_num = round_rat bprec ((ex_num +/ ey_num)//(u_num +/ v_num)) in
1792 let (v,u) = (mk_float v_num,mk_float u_num) in
1793 let (ey,ez) = (mk_float ey_num,mk_float ez_num) in
1794 let thm = SPECL [x;f;ex;u;ey;ez;v] INTERVAL_SSQRT in
1795 let conjhyp = fst (dest_imp (concl thm)) in
1796 let [hyp6;hyp5;hyp4;hyp3;hyp2;hyp1] =
1797 let rec break_conj c acc =
1798 if (not(is_conj c)) then (c::acc) else
1799 let (u,v) = dest_conj c in break_conj v (u::acc) in
1800 (break_conj conjhyp []) in
1801 let thm2 = prove(hyp2,REWRITE_TAC[interval] THEN
1802 (CONV_TAC FLOAT_INEQ_CONV)) in
1803 let thm3 = FLOAT_INEQ_CONV hyp3 in
1804 let thm4 = FLOAT_INEQ_CONV hyp4 in
1805 let float_tac = REWRITE_TAC[FLOAT_NN;FLOAT_POS;INT_NN;INT_NN_NEG;
1806 INT_POS';INT_POS_NEG] THEN ARITH_TAC in
1807 let thm5 = prove( hyp5,float_tac) in
1808 let thm6 = prove( hyp6,float_tac) in
1809 let ant = end_itlist CONJ[x_int;thm2;thm3;thm4;thm5;thm6] in
1812 with _ -> failwith "INTERVAL_OF_TERM : SSQRT"
1814 else failwith "INTERVAL_OF_TERM : case not installed";;
1817 let real_ineq bprec tm =
1818 let (t1,t2) = dest_binop `(<.)` tm in
1819 let int1 = INTERVAL_OF_TERM bprec t1 in
1820 let int2 = INTERVAL_OF_TERM bprec t2 in
1821 INTERVAL_TO_LESS_CONV int1 int2;;