(*****************************)
(* Floating point arithmetic *)
(*****************************)
(* Dependencies *)
needs "../formal_lp/arith/nat.hl";;
needs "../formal_lp/arith/num_exp_theory.hl";;
needs "../formal_lp/arith/float_theory.hl";;
needs "../formal_lp/arith/interval_arith.hl";;
prioritize_real();;
module type Arith_float_sig =
sig
val mk_num_exp : term -> term -> term
val dest_num_exp : term -> (term * term)
val dest_float : term -> (string * term * term)
val float_lt0 : term -> thm
val float_gt0 : term -> thm
val float_lt : term -> term -> thm
val float_le0 : term -> thm
val float_ge0 : term -> thm
val float_le : term -> term -> thm
val float_min : term -> term -> thm
val float_max : term -> term -> thm
val float_min_max : term -> term -> (thm * thm)
val float_mul_eq : term -> term -> thm
val float_mul_lo : int -> term -> term -> thm
val float_mul_hi : int -> term -> term -> thm
val float_div_lo : int -> term -> term -> thm
val float_div_hi : int -> term -> term -> thm
val float_add_lo : int -> term -> term -> thm
val float_add_hi : int -> term -> term -> thm
val float_sub_lo : int -> term -> term -> thm
val float_sub_hi : int -> term -> term -> thm
val float_sqrt_lo : int -> term -> thm
val float_sqrt_hi : int -> term -> thm
val reset_stat : unit -> unit
val reset_cache : unit -> unit
val print_stat : unit -> unit
(*
val mul_lo_list : (int * term * term) list ref
val mul_hi_list : (int * term * term) list ref
val div_lo_list : (int * term * term) list ref
val div_hi_list : (int * term * term) list ref
val add_lo_list : (int * term * term) list ref
val add_hi_list : (int * term * term) list ref
val sub_lo_list : (int * term * term) list ref
val sub_hi_list : (int * term * term) list ref
*)
val dest_float_interval : term -> term * term * term
val mk_float_interval_small_num : int -> thm
val mk_float_interval_num : num -> thm
val float_lo : int -> term -> thm
val float_hi : int -> term -> thm
val float_interval_round : int -> thm -> thm
val float_interval_neg : thm -> thm
val float_interval_mul : int -> thm -> thm -> thm
val float_interval_div : int -> thm -> thm -> thm
val float_interval_add : int -> thm -> thm -> thm
val float_interval_sub : int -> thm -> thm -> thm
val float_interval_sqrt : int -> thm -> thm
val float_abs : term -> thm
val FLOAT_TO_NUM_CONV : term -> thm
end;;
module Arith_float : Arith_float_sig = struct
open Big_int;;
open Arith_options;;
open Arith_misc;;
open Arith_nat;;
open Num_exp_theory;;
open Float_theory;;
open Interval_arith;;
(* interval *)
let APPROX_INTERVAL' = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP]) APPROX_INTERVAL;;
let zero_const = `_0` and
t_const = `T` and
f_const = `F`;;
let n_var_num = `n:num` and
m_var_num = `m:num` and
k_var_num = `k:num` and
e_var_num = `e:num` and
e1_var_num = `e1:num` and
e2_var_num = `e2:num` and
r_var_num = `r:num` and
r1_var_num = `r1:num` and
r2_var_num = `r2:num` and
n1_var_num = `n1:num` and
n2_var_num = `n2:num` and
m1_var_num = `m1:num` and
m2_var_num = `m2:num` and
x_var_num = `x:num` and
y_var_num = `y:num`;;
let le_op_num = `(<=):num->num->bool` and
lt_op_num = `(<):num->num->bool` and
mul_op_num = `( * ):num->num->num` and
plus_op_num = `(+):num->num->num` and
minus_op_num = `(-):num->num->num` and
div_op_real = `(/):real->real->real` and
div_op_num = `DIV` and
mul_op_real = `( * ):real->real->real` and
plus_op_real = `(+):real->real->real` and
minus_op_real = `(-):real->real->real` and
neg_op_real = `(--):real->real` and
le_op_real = `(<=):real->real->bool`;;
let amp_op_real = `(&):num->real` and
interval_const = `interval_arith` and
num_exp_const = `num_exp`;;
let x_var_real = `x:real` and
y_var_real = `y:real` and
z_var_real = `z:real` and
a_var_real = `a:real` and
b_var_real = `b:real` and
lo_var_real = `lo:real` and
hi_var_real = `hi:real` and
f1_var_real = `f1:real` and
f2_var_real = `f2:real`;;
let b0_const = (fst o dest_comb o lhand o concl) (Arith_hash.def_array.(0));;
let b0_name = (fst o dest_const) b0_const;;
let base_const = mk_small_numeral base;;
let NUM_REMOVE = prove(mk_eq(mk_comb(Arith_hash.num_const, n_var_num), n_var_num),
REWRITE_TAC[Arith_hash.num_def; NUMERAL]);;
(* B0 n = base * n *)
let b0_thm = prove(mk_eq(mk_comb(b0_const, n_var_num),
mk_binop mul_op_num base_const n_var_num),
REWRITE_TAC[Arith_hash.def_array.(0)] THEN
TRY ARITH_TAC THEN
GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [BIT0] THEN
ARITH_TAC);;
let dest_num_exp tm =
let ltm, e_tm = dest_comb tm in
rand ltm, e_tm;;
let num_exp_const = `num_exp`;;
let mk_num_exp n_tm e_tm = mk_binop num_exp_const n_tm e_tm;;
(* float s n e -> "s", n, e *)
let dest_float tm =
let ltm, e_tm = dest_comb tm in
let ltm, n_tm = dest_comb ltm in
let float_tm, s_tm = dest_comb ltm in
if (fst o dest_const) float_tm <> "float" then
failwith "dest_float: not float"
else
(fst o dest_const) s_tm, n_tm, e_tm;;
(************************************)
let NUM_EXP_EXP' = SPEC_ALL NUM_EXP_EXP;;
let NUM_EXP_0' = (SPEC_ALL o REWRITE_RULE[NUMERAL]) NUM_EXP_0;;
let NUM_EXP_LE' = (UNDISCH_ALL o SPEC_ALL) NUM_EXP_LE;;
let NUM_EXP_LT' = (UNDISCH_ALL o SPEC_ALL) NUM_EXP_LT;;
(* NUM_EXP_DIV *)
let NUM_EXP_DIV1 = prove(`~(n2 = 0) /\ e2 <= e1 ==>
num_exp n1 e1 DIV
num_exp n2 e2 =
num_exp n1 (e1 - e2) DIV n2`,
STRIP_TAC THEN
(*`num_exp n1 e1 = 16 EXP e2 * num_exp n1 (e1 - e2)` MP_TAC THENL*)
SUBGOAL_THEN (mk_eq(`
num_exp n1 e1`, mk_binop mul_op_num (mk_binop `
EXP` base_const `e2:num`) `
num_exp n1 (e1 - e2)`)) MP_TAC THENL
[
REWRITE_TAC[
num_exp] THEN
ONCE_REWRITE_TAC[ARITH_RULE `a * b * c = b * (a * c:num)`] THEN
REWRITE_TAC[GSYM
EXP_ADD] THEN
ASM_SIMP_TAC[ARITH_RULE `e2 <= e1 ==> e2 + e1 - e2 = e1:num`];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
SUBGOAL_THEN (mk_eq(`
num_exp n2 e2`, mk_binop mul_op_num (mk_binop `
EXP` base_const `e2:num`) `n2:num`)) MP_TAC THENL
[
REWRITE_TAC[
num_exp;
MULT_AC];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
MATCH_MP_TAC
DIV_MULT2 THEN
ASM_REWRITE_TAC[
MULT_EQ_0; DE_MORGAN_THM;
EXP_EQ_0] THEN
ARITH_TAC);;
let NUM_EXP_DIV2 = prove(`~(n2 = 0) /\ e1 <= e2 ==>
num_exp n1 e1 DIV
num_exp n2 e2 = n1 DIV
num_exp n2 (e2 - e1)`,
STRIP_TAC THEN
(*`num_exp n2 e2 = 16 EXP e1 * num_exp n2 (e2 - e1)` MP_TAC THENL*)
SUBGOAL_THEN (mk_eq(`
num_exp n2 e2`, mk_binop mul_op_num (mk_binop `
EXP` base_const `e1:num`) `
num_exp n2 (e2 - e1)`)) MP_TAC THENL
[
REWRITE_TAC[
num_exp] THEN
ONCE_REWRITE_TAC[ARITH_RULE `a * b * c = b * (a * c:num)`] THEN
REWRITE_TAC[GSYM
EXP_ADD] THEN
ASM_SIMP_TAC[ARITH_RULE `e1 <= e2 ==> e1 + e2 - e1 = e2:num`];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
SUBGOAL_THEN (mk_eq(`
num_exp n1 e1`, mk_binop mul_op_num (mk_binop `
EXP` base_const `e1:num`) `n1:num`)) MP_TAC THENL
[
REWRITE_TAC[
num_exp;
MULT_AC];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
MATCH_MP_TAC
DIV_MULT2 THEN
ASM_REWRITE_TAC[
num_exp;
MULT_EQ_0; DE_MORGAN_THM;
EXP_EQ_0] THEN
ARITH_TAC);;
(* B0 n = num_exp n bits *)
let normal_lemma1 = prove(mk_eq(mk_comb(b0_const, n_var_num), `num_exp n 1`),
REWRITE_TAC[Arith_hash.def_array.(0); num_exp] THEN
TRY ARITH_TAC THEN
GEN_REWRITE_TAC (LAND_CONV o DEPTH_CONV) [BIT0] THEN
ARITH_TAC);;
let NORMAL_LEMMA1 = NUMERALS_TO_NUM normal_lemma1;;
let rec normalize tm =
if (is_comb tm) then
let ltm, rtm = dest_comb tm in
let lname = (fst o dest_const) ltm in
if (lname = b0_name) then
let lth = INST[rtm, n_var_num] NORMAL_LEMMA1 in
let rth, flag = normalize rtm in
if flag then
let ltm, lexp = (dest_comb o snd o dest_eq o concl) lth in
let ltm, rtm = dest_comb ltm in
let rn, rexp = (dest_comb o snd o dest_eq o concl) rth in
let rn = rand rn in
let th1 = AP_THM (AP_TERM ltm rth) lexp in
let th2 = INST[rexp, e1_var_num; lexp, e2_var_num; rn, n_var_num] NUM_EXP_EXP' in
let th3 = TRANS lth (TRANS th1 th2) in
let ltm, rtm = (dest_comb o snd o dest_eq o concl) th3 in
let add_th = raw_add_conv_hash rtm in
let th4 = AP_TERM ltm add_th in
(TRANS th3 th4, true)
else
(lth, true)
else
(REFL tm, false)
else
(REFL tm, false);;
(* Converts a raw numeral to a num_exp expression *)
let to_num_exp tm =
let x, flag = normalize tm in
if flag then x
else
INST[tm, n_var_num] NUM_EXP_0';;
(*
let tm = `B0 (B0 (B0 (B1 (B2 (B3 _0)))))`;;
(* 8: 0.568 *)
test 10000 normalize tm;; (* 0.568 *)
(* 8: 0.012 *)
test 10000 normalize `B2 (B3 (B4 _0))`;;
*)
(************************************)
let SYM_NUM_EXP_0' = SYM NUM_EXP_0';;
let NUM_EXP_n0' = (REWRITE_RULE[NUMERAL] o SPEC_ALL) NUM_EXP_n0;;
let NUM_EXP_DENORM = (UNDISCH_ALL o prove)
(mk_imp(`e = _0 <=> F`, mk_eq(`num_exp n e`, mk_comb (b0_const, `num_exp n (PRE e)`))),
REWRITE_TAC[] THEN ONCE_REWRITE_TAC[SYM (REWRITE_CONV[NUMERAL] `0`)] THEN
REWRITE_TAC[num_exp; b0_thm] THEN
REWRITE_TAC[ARITH_RULE (mk_eq(mk_binop mul_op_num base_const `n * a:num`,
mk_binop mul_op_num `n:num` (mk_binop mul_op_num base_const `a:num`)))] THEN
REWRITE_TAC[GSYM EXP] THEN
SIMP_TAC[ARITH_RULE `~(e = 0) ==> SUC (PRE e) = e`]);;
(* Converts num_exp n e to a numeral by adding e B0's *)
let rec denormalize tm =
let ltm, etm = dest_comb tm in
let ntm = rand ltm in
if (etm = zero_const) then
INST[ntm, n_var_num] SYM_NUM_EXP_0'
else
if ntm = zero_const then
INST[etm, e_var_num] NUM_EXP_n0'
else
let e_th = raw_eq0_hash_conv etm in
let th0' = INST[etm, e_var_num; ntm, n_var_num] NUM_EXP_DENORM in
let th0 = MY_PROVE_HYP e_th th0' in
let b0_tm, rtm = dest_comb(rand(concl th0)) in
let ltm, pre_tm = dest_comb rtm in
let pre_th = raw_pre_hash_conv pre_tm in
let th1 = AP_TERM ltm pre_th in
let th2 = denormalize (rand(concl th1)) in
TRANS th0 (AP_TERM b0_tm (TRANS th1 th2));;
(*
let tm = `num_exp (B1 (B3 (B5 _0))) (B15 _0)`;;
denormalize tm;;
(* 4: 0.264 *)
test 1000 denormalize tm;;
*)
(***************************************)
let rec comb_number tm n =
if (is_comb tm) then comb_number ((snd o dest_comb) tm) (n + 1) else n;;
let make_lo_thm i =
let th_concl = mk_binop `(<=):num->num->bool`
(mk_comb (Arith_hash.const_array.(0), n_var_num))
(mk_comb (Arith_hash.const_array.(i), n_var_num)) in
prove(th_concl,
REWRITE_TAC[Arith_hash.def_array.(i); Arith_hash.def_array.(0)] THEN
REWRITE_TAC[ARITH_LE; LE_REFL] THEN
ARITH_TAC);;
let lo_thm_array = Array.init base make_lo_thm;;
let lo_thm_table = Hashtbl.create base;;
for i = 0 to base - 1 do
Hashtbl.add lo_thm_table Arith_hash.const_array.(i) lo_thm_array.(i);
done;;
let make_lo_thm2 i =
let th_concl = mk_imp (`n <= m:num`,
mk_binop `(<=):num->num->bool`
(mk_comb (Arith_hash.const_array.(0), n_var_num))
(mk_comb (Arith_hash.const_array.(i), m_var_num))) in
(UNDISCH_ALL o prove) (th_concl,
REWRITE_TAC[Arith_hash.def_array.(i); Arith_hash.def_array.(0); ARITH_LE] THEN
ARITH_TAC);;
let lo_thm2_array = Array.init base make_lo_thm2;;
let lo_thm2_table = Hashtbl.create base;;
for i = 0 to base - 1 do
Hashtbl.add lo_thm2_table Arith_hash.const_array.(i) lo_thm2_array.(i);
done;;
let make_hi_thm i =
let th_concl = mk_imp (`n < m:num`,
mk_binop `(<):num->num->bool`
(mk_comb (Arith_hash.const_array.(i), n_var_num))
(mk_comb (Arith_hash.const_array.(0), m_var_num))) in
(UNDISCH_ALL o prove) (th_concl,
REWRITE_TAC[Arith_hash.def_array.(i); Arith_hash.def_array.(0); ARITH_LT] THEN
ARITH_TAC);;
let hi_thm_array = Array.init base make_hi_thm;;
let hi_thm_table = Hashtbl.create base;;
for i = 0 to base - 1 do
Hashtbl.add hi_thm_table Arith_hash.const_array.(i) hi_thm_array.(i);
done;;
(***************************************)
let LE_REFL' = SPEC_ALL LE_REFL;;
let LE_TRANS' = (UNDISCH_ALL o SPEC_ALL o REWRITE_RULE[GSYM IMP_IMP]) LE_TRANS;;
let lo_num_conv p tm =
let n = comb_number tm 0 in
if (n <= p) then
INST[tm, n_var_num] LE_REFL'
else
let rec lo_bound n tm =
let btm, rtm = dest_comb tm in
let th0 = INST[rtm, n_var_num] (Hashtbl.find lo_thm_table btm) in
if n > 1 then
let rth = lo_bound (n - 1) rtm in
let xtm = rand (rator (concl rth)) in
let th1' = INST[xtm, n_var_num; rtm, m_var_num] (Hashtbl.find lo_thm2_table btm) in
let th1 = MY_PROVE_HYP rth th1' in
th1
else
th0 in
lo_bound (n - p) tm;;
let LT_IMP_LE' = (UNDISCH_ALL o SPEC_ALL) LT_IMP_LE;;
let LT_LE_TRANS = (UNDISCH_ALL o ARITH_RULE) `n < e ==> e <= m ==> n < m:num`;;
(* Generates a theorem |- n <= m such that m contains at most p non-zero digits *)
let hi_num_conv p tm =
let n = comb_number tm 0 in
if (n <= p) then
INST[tm, n_var_num] LE_REFL'
else
let k = n - p in
let rec check_b0s n tm =
let btm, rtm = dest_comb tm in
if ((fst o dest_const) btm = b0_name) then
if n > 1 then check_b0s (n - 1) rtm else true
else
false in
if (check_b0s k tm) then
INST[tm, n_var_num] LE_REFL'
else
let rec hi_bound n tm =
if n > 0 then
let btm, rtm = dest_comb tm in
let r_th = hi_bound (n - 1) rtm in
let xtm = rand (concl r_th) in
let th0 = INST[rtm, n_var_num; xtm, m_var_num] (Hashtbl.find hi_thm_table btm) in
MY_PROVE_HYP r_th th0
else
let th0 = INST[tm, n_var_num] N_LT_SUC in
let ltm, suc_tm = dest_comb (concl th0) in
let suc_th = raw_suc_conv_hash suc_tm in
EQ_MP (AP_TERM ltm suc_th) th0 in
let th = hi_bound k tm in
let m_tm, l_tm = dest_comb (concl th) in
MY_PROVE_HYP th (INST[rand m_tm, m_var_num; l_tm, n_var_num] LT_IMP_LE');;
(*
let tm = `B10 (B12 (B11 (B1 (B14 (B15 _0)))))`;;
hi_num_conv 4 tm;;
let tm = `B0 (B0 (B1 (B2 _0)))`;;
hi_num_conv 2 tm;;
*)
(* Generates a theorem |- n < m such that m contains at most p non-zero digits *)
let hi_lt_num_conv p tm =
let n = comb_number tm 0 in
if (n <= p) then
let th0 = INST[tm, n_var_num] N_LT_SUC in
let ltm, rtm = dest_comb(concl th0) in
let suc_th = raw_suc_conv_hash rtm in
EQ_MP (AP_TERM ltm suc_th) th0
else
let k = n - p in
let rec check_b0s n tm =
let btm, rtm = dest_comb tm in
if ((fst o dest_const) btm = b0_name) then
if n > 1 then check_b0s (n - 1) rtm else true
else
false in
if (check_b0s k tm) then
let th0 = INST[tm, n_var_num] N_LT_SUC in
let ltm, rtm = dest_comb (concl th0) in
let suc_th = raw_suc_conv_hash rtm in
let suc_tm = rand(concl suc_th) in
let th1 = hi_num_conv p suc_tm in
let th2 = EQ_MP (AP_TERM ltm suc_th) th0 in
let th = INST[tm, n_var_num; suc_tm, e_var_num; rand(concl th1), m_var_num] LT_LE_TRANS in
MY_PROVE_HYP th1 (MY_PROVE_HYP th2 th)
else
let rec hi_bound n tm =
if n > 0 then
let btm, rtm = dest_comb tm in
let r_th = hi_bound (n - 1) rtm in
let xtm = rand (concl r_th) in
let th0 = INST[rtm, n_var_num; xtm, m_var_num] (Hashtbl.find hi_thm_table btm) in
MY_PROVE_HYP r_th th0
else
let th0 = INST[tm, n_var_num] N_LT_SUC in
let ltm, suc_tm = dest_comb (concl th0) in
let suc_th = raw_suc_conv_hash suc_tm in
EQ_MP (AP_TERM ltm suc_th) th0 in
hi_bound k tm;;
(*
let tm = `B10 (B12 (B11 (B1 (B14 (B15 _0)))))`;;
hi_num_conv 4 tm;;
hi_lt_num_conv 4 tm;;
let tm = `B0 (B0 (B1 (B2 _0)))`;;
hi_num_conv 3 tm;;
hi_lt_num_conv 3 tm;;
*)
(*****************************************)
let num_exp_lo p tm =
let ltm, e_tm = dest_comb tm in
let n_tm = rand ltm in
let n_th = lo_num_conv p n_tm in
let m_tm = rand (rator (concl n_th)) in
let m_norm, flag = normalize m_tm in
let th0' = INST[m_tm, m_var_num; n_tm, n_var_num; e_tm, e_var_num] NUM_EXP_LE' in
let th0 = MY_PROVE_HYP n_th th0' in
if flag then
let th1 = AP_THM (AP_TERM (rator ltm) m_norm) e_tm in
let m_tm, me_tm = (dest_comb o rand o concl) m_norm in
let th2 = INST[me_tm, e1_var_num; e_tm, e2_var_num; rand m_tm, n_var_num] NUM_EXP_EXP' in
let th3 = TRANS th1 th2 in
let ltm, rtm = (dest_comb o rand o concl) th3 in
let th_add = raw_add_conv_hash rtm in
let th4 = TRANS th3 (AP_TERM ltm th_add) in
EQ_MP (AP_THM (AP_TERM le_op_num th4) tm) th0
else
th0;;
let num_exp_hi p tm =
let ltm, e_tm = dest_comb tm in
let n_tm = rand ltm in
let n_th = hi_num_conv p n_tm in
let m_tm = rand (concl n_th) in
let m_norm, flag = normalize m_tm in
let th0' = INST[m_tm, n_var_num; n_tm, m_var_num; e_tm, e_var_num] NUM_EXP_LE' in
let th0 = MY_PROVE_HYP n_th th0' in
if flag then
let th1 = AP_THM (AP_TERM (rator ltm) m_norm) e_tm in
let m_tm, me_tm = (dest_comb o rand o concl) m_norm in
let th2 = INST[me_tm, e1_var_num; e_tm, e2_var_num; rand m_tm, n_var_num] NUM_EXP_EXP' in
let th3 = TRANS th1 th2 in
let ltm, rtm = (dest_comb o rand o concl) th3 in
let th_add = raw_add_conv_hash rtm in
let th4 = TRANS th3 (AP_TERM ltm th_add) in
EQ_MP (AP_TERM (rator (concl th0)) th4) th0
else
th0;;
let num_exp_hi_lt p tm =
let ltm, e_tm = dest_comb tm in
let n_tm = rand ltm in
let n_th = hi_lt_num_conv p n_tm in
let m_tm = rand (concl n_th) in
let m_norm, flag = normalize m_tm in
let th0' = INST[m_tm, n_var_num; n_tm, m_var_num; e_tm, e_var_num] NUM_EXP_LT' in
let th0 = MY_PROVE_HYP n_th th0' in
if flag then
let th1 = AP_THM (AP_TERM (rator ltm) m_norm) e_tm in
let m_tm, me_tm = (dest_comb o rand o concl) m_norm in
let th2 = INST[me_tm, e1_var_num; e_tm, e2_var_num; rand m_tm, n_var_num] NUM_EXP_EXP' in
let th3 = TRANS th1 th2 in
let ltm, rtm = (dest_comb o rand o concl) th3 in
let th_add = raw_add_conv_hash rtm in
let th4 = TRANS th3 (AP_TERM ltm th_add) in
EQ_MP (AP_TERM (rator (concl th0)) th4) th0
else
th0;;
(*
let tm = `num_exp (B5 (B1 (B2 (B3 _0)))) (B3 _0)`;;
num_exp_lo 2 tm;;
num_exp_hi 2 tm;;
num_exp_hi_lt 2 tm;;
num_exp_hi_lt 2 `num_exp (B0 (B0 (B1 _0))) (B4 _0)`;;
(* 4: 0.848 *)
test 10000 (num_exp_lo 2) tm;;
(* 4: 0.448 *)
test 10000 (num_exp_lo 3) tm;;
(* 4: 0.116 *)
test 10000 (num_exp_lo 5) tm;;
*)
(***************************************)
(* num_exp_lt, num_exp_le *)
let transform = UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL;;
let NUM_EXP_LT1_EQ' = transform NUM_EXP_LT1_EQ and
NUM_EXP_LT2_EQ' = transform NUM_EXP_LT2_EQ;;
let NUM_EXP_LE1_EQ' = transform NUM_EXP_LE1_EQ and
NUM_EXP_LE2_EQ' = transform NUM_EXP_LE2_EQ;;
let num_exp_lt tm1 tm2 =
let n1_tm, e1_tm = dest_num_exp tm1 in
let n2_tm, e2_tm = dest_num_exp tm2 in
let sub_th, le_th = raw_sub_and_le_hash_conv e1_tm e2_tm in
let r_tm = rand(concl sub_th) in
if (rand(concl le_th) = e1_tm) then
let x_expr = mk_num_exp n1_tm r_tm in
let x_th = denormalize x_expr in
let x_tm = rand(concl x_th) in
let th0 = INST[e2_tm, e2_var_num; e1_tm, e1_var_num;
r_tm, r_var_num; x_tm, x_var_num;
n1_tm, n1_var_num; n2_tm, n2_var_num] NUM_EXP_LT1_EQ' in
let th1 = MY_PROVE_HYP x_th (MY_PROVE_HYP sub_th (MY_PROVE_HYP le_th th0)) in
let lt_th = raw_lt_hash_conv (rand(concl th1)) in
TRANS th1 lt_th
else
let x_expr = mk_num_exp n2_tm r_tm in
let x_th = denormalize x_expr in
let x_tm = rand(concl x_th) in
let th0 = INST[e2_tm, e2_var_num; e1_tm, e1_var_num;
r_tm, r_var_num; x_tm, x_var_num;
n1_tm, n1_var_num; n2_tm, n2_var_num] NUM_EXP_LT2_EQ' in
let th1 = MY_PROVE_HYP x_th (MY_PROVE_HYP sub_th (MY_PROVE_HYP le_th th0)) in
let lt_th = raw_lt_hash_conv (rand(concl th1)) in
TRANS th1 lt_th;;
let num_exp_le tm1 tm2 =
let n1_tm, e1_tm = dest_num_exp tm1 in
let n2_tm, e2_tm = dest_num_exp tm2 in
let sub_th, le_th = raw_sub_and_le_hash_conv e1_tm e2_tm in
let r_tm = rand(concl sub_th) in
if (rand(concl le_th) = e1_tm) then
let x_expr = mk_num_exp n1_tm r_tm in
let x_th = denormalize x_expr in
let x_tm = rand(concl x_th) in
let th0 = INST[e2_tm, e2_var_num; e1_tm, e1_var_num;
r_tm, r_var_num; x_tm, x_var_num;
n1_tm, n1_var_num; n2_tm, n2_var_num] NUM_EXP_LE1_EQ' in
let th1 = MY_PROVE_HYP x_th (MY_PROVE_HYP sub_th (MY_PROVE_HYP le_th th0)) in
let le_th = raw_le_hash_conv (rand(concl th1)) in
TRANS th1 le_th
else
let x_expr = mk_num_exp n2_tm r_tm in
let x_th = denormalize x_expr in
let x_tm = rand(concl x_th) in
let th0 = INST[e2_tm, e2_var_num; e1_tm, e1_var_num;
r_tm, r_var_num; x_tm, x_var_num;
n1_tm, n1_var_num; n2_tm, n2_var_num] NUM_EXP_LE2_EQ' in
let th1 = MY_PROVE_HYP x_th (MY_PROVE_HYP sub_th (MY_PROVE_HYP le_th th0)) in
let le_th = raw_le_hash_conv (rand(concl th1)) in
TRANS th1 le_th;;
(*
let tm1 = `num_exp (D0 (D4 (D1 _0))) (D2 (D3 _0))`;;
let tm2 = `num_exp (D4 (D6 _0)) (D5 (D3 _0))`;;
num_exp_lt tm1 tm2;;
num_exp_lt tm2 tm1;;
num_exp_le tm1 tm1;;
num_exp_lt tm1 tm1;;
(* 100: 0.164 *)
test 1000 (num_exp_lt tm1) tm2;;
*)
(***************************************)
(* num_exp_mul *)
let NUM_EXP_MUL' = SPEC_ALL NUM_EXP_MUL;;
let num_exp_mul tm1 tm2 =
let n1_tm, e1_tm = dest_comb tm1 in
let n1_tm = rand n1_tm in
let n2_tm, e2_tm = dest_comb tm2 in
let n2_tm = rand n2_tm in
let th0 = INST[n1_tm, n1_var_num; e1_tm, e1_var_num;
n2_tm, n2_var_num; e2_tm, e2_var_num] NUM_EXP_MUL' in
let ltm, tm_add = dest_comb (rand (concl th0)) in
let tm_mul = rand ltm in
let th_mul = raw_mul_conv_hash tm_mul in
let th_add = raw_add_conv_hash tm_add in
TRANS th0 (MK_COMB (AP_TERM (rator ltm) th_mul, th_add));;
(**********************************)
(* num_exp_add *)
let NUM_EXP_ADD' = (UNDISCH_ALL o SPEC_ALL) NUM_EXP_ADD;;
let num_exp_add tm1 tm2 =
let n1_tm, e1_tm = dest_comb tm1 in
let n1_tm = rand n1_tm in
let n2_tm, e2_tm = dest_comb tm2 in
let n2_tm = rand n2_tm in
let e_sub, e_le = raw_sub_and_le_hash_conv e1_tm e2_tm in
let flag = (rand(concl e_le) = e2_tm) in
let th0' =
if flag then
INST[n1_tm, n1_var_num; e1_tm, e1_var_num;
n2_tm, n2_var_num; e2_tm, e2_var_num] NUM_EXP_ADD'
else
INST[n2_tm, n1_var_num; e2_tm, e1_var_num;
n1_tm, n2_var_num; e1_tm, e2_var_num] NUM_EXP_ADD' in
let th0 = MY_PROVE_HYP e_le th0' in
let ltm, e0_tm = dest_comb(rand(concl th0)) in
let exp_tm, add_tm = dest_comb ltm in
let ltm, d_tm = dest_comb add_tm in
let th1 = AP_TERM (rator d_tm) e_sub in
let th2 = denormalize (rand(concl th1)) in
let th3 = AP_TERM ltm (TRANS th1 th2) in
let th4 = raw_add_conv_hash (rand(concl th3)) in
let th5 = AP_THM (AP_TERM exp_tm (TRANS th3 th4)) e0_tm in
let th = TRANS th0 th5 in
if flag then th else
TRANS (INST[tm1, m_var_num; tm2, n_var_num] ADD_COMM) th;;
(*
let tm1 = `num_exp (B0 (B4 (B1 _0))) (B1 (B3 _0))`;;
let tm2 = `num_exp (B4 (B6 _0)) (B1 (B2 _0))`;;
num_exp_add tm1 tm2;;
num_exp_add tm2 tm1;;
num_exp_mul tm1 tm2;;
(* 4: 0.836 *)
test 10000 (num_exp_mul tm1) tm2;;
(* 4: 4.112 *)
test 10000 (num_exp_add tm1) tm2;;
*)
(****************************************)
(* num_exp_sub *)
let NUM_EXP_SUB1' = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL) NUM_EXP_SUB1 and
NUM_EXP_SUB2' = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL) NUM_EXP_SUB2 and
NUM_EXP_LE1' = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL) NUM_EXP_LE1 and
NUM_EXP_LE2' = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o SPEC_ALL) NUM_EXP_LE2;;
(* Returns two theorems: |- tm1 - tm2 = tm, |- tm2 <= tm1 or
|- tm2 - tm1 = tm, |- tm1 <= tm2 *)
let num_exp_sub tm1 tm2 =
let n1_tm, e1_tm = dest_num_exp tm1 in
let n2_tm, e2_tm = dest_num_exp tm2 in
let e_sub, e_le = raw_sub_and_le_hash_conv e1_tm e2_tm in
if rand(concl e_le) = e1_tm then
(* e2 <= e1 *)
let e1_sub_e2 = rand(concl e_sub) in
let a0 = mk_num_exp n1_tm e1_sub_e2 in
let b = n2_tm in
let a_th = denormalize a0 in
let a = rand(concl a_th) in
let th_sub, th_le = raw_sub_and_le_hash_conv a b in
if rand(concl th_le) = a then
(* b <= a *)
let a_sub_b = TRANS (AP_THM (AP_TERM minus_op_num a_th) b) th_sub in
let b_le_a = EQ_MP (SYM (AP_TERM (rator(concl th_le)) a_th)) th_le in
let th0 = AP_THM (AP_TERM num_exp_const a_sub_b) e2_tm in
let inst = INST[n1_tm, n1_var_num; e1_tm, e1_var_num;
n2_tm, n2_var_num; e2_tm, e2_var_num; e1_sub_e2, r_var_num] in
let th1_sub = inst NUM_EXP_SUB1' in
let th1_le = inst NUM_EXP_LE1' in
let th2_sub = MY_PROVE_HYP e_sub (MY_PROVE_HYP e_le th1_sub) in
let th2_le = MY_PROVE_HYP e_sub (MY_PROVE_HYP b_le_a (MY_PROVE_HYP e_le th1_le)) in
TRANS th2_sub th0, th2_le
else
(* a <= b *)
let b_sub_a = TRANS (AP_TERM (rator(lhand(concl th_sub))) a_th) th_sub in
let a_le_b = EQ_MP (SYM (AP_THM (AP_TERM le_op_num a_th) b)) th_le in
let th0 = AP_THM (AP_TERM num_exp_const b_sub_a) e2_tm in
let inst = INST[n2_tm, n1_var_num; e2_tm, e1_var_num;
n1_tm, n2_var_num; e1_tm, e2_var_num; e1_sub_e2, r_var_num] in
let th1_sub = inst NUM_EXP_SUB2' in
let th1_le = inst NUM_EXP_LE2' in
let th2_sub = MY_PROVE_HYP e_sub (MY_PROVE_HYP e_le th1_sub) in
let th2_le = MY_PROVE_HYP e_sub (MY_PROVE_HYP a_le_b (MY_PROVE_HYP e_le th1_le)) in
TRANS th2_sub th0, th2_le
else
(* e1 <= e2 *)
let e2_sub_e1 = rand(concl e_sub) in
let b0 = mk_num_exp n2_tm e2_sub_e1 in
let a = n1_tm in
let b_th = denormalize b0 in
let b = rand(concl b_th) in
let th_sub, th_le = raw_sub_and_le_hash_conv a b in
if rand(concl th_le) = a then
(* b <= a *)
let a_sub_b = TRANS (AP_TERM (rator(lhand(concl th_sub))) b_th) th_sub in
let b_le_a = EQ_MP (SYM (AP_THM (AP_TERM le_op_num b_th) a)) th_le in
let th0 = AP_THM (AP_TERM num_exp_const a_sub_b) e1_tm in
let inst = INST[n1_tm, n1_var_num; e1_tm, e1_var_num;
n2_tm, n2_var_num; e2_tm, e2_var_num; e2_sub_e1, r_var_num] in
let th1_sub = inst NUM_EXP_SUB2' in
let th1_le = inst NUM_EXP_LE2' in
let th2_sub = MY_PROVE_HYP e_sub (MY_PROVE_HYP e_le th1_sub) in
let th2_le = MY_PROVE_HYP e_sub (MY_PROVE_HYP b_le_a (MY_PROVE_HYP e_le th1_le)) in
TRANS th2_sub th0, th2_le
else
(* a <= b *)
let b_sub_a = TRANS (AP_THM (AP_TERM minus_op_num b_th) a) th_sub in
let a_le_b = EQ_MP (SYM (AP_TERM (rator(concl th_le)) b_th)) th_le in
let th0 = AP_THM (AP_TERM num_exp_const b_sub_a) e1_tm in
let inst = INST[n2_tm, n1_var_num; e2_tm, e1_var_num;
n1_tm, n2_var_num; e1_tm, e2_var_num; e2_sub_e1, r_var_num] in
let th1_sub = inst NUM_EXP_SUB1' in
let th1_le = inst NUM_EXP_LE1' in
let th2_sub = MY_PROVE_HYP e_sub (MY_PROVE_HYP e_le th1_sub) in
let th2_le = MY_PROVE_HYP e_sub (MY_PROVE_HYP a_le_b (MY_PROVE_HYP e_le th1_le)) in
TRANS th2_sub th0, th2_le;;
(*
let tm1 = `num_exp (D3 (D4 (D1 _0))) (D2 _0)`;;
let tm2 = `num_exp (D1 (D2 (D1 _0))) (D3 _0)`;;
num_exp_sub tm1 tm2;;
(* 10: 0.252 *)
test 1000 (num_exp_sub tm1) tm2;;
*)
(*************************************)
(* division *)
let NUM_EXP_DIV1' = (UNDISCH_ALL o PURE_REWRITE_RULE[NUMERAL] o
PURE_ONCE_REWRITE_RULE[ARITH_RULE `~(x = 0) <=> (x = 0 <=> F)`] o
REWRITE_RULE[GSYM IMP_IMP]) NUM_EXP_DIV1;;
let NUM_EXP_DIV2' = (UNDISCH_ALL o PURE_REWRITE_RULE[NUMERAL] o
PURE_ONCE_REWRITE_RULE[ARITH_RULE `~(x = 0) <=> (x = 0 <=> F)`] o
REWRITE_RULE[GSYM IMP_IMP]) NUM_EXP_DIV2;;
let num_exp_div tm1 tm2 =
let n1_tm, e1_tm = dest_comb tm1 in
let n1_tm = rand n1_tm in
let n2_tm, e2_tm = dest_comb tm2 in
let n2_tm = rand n2_tm in
let e_sub, e_le = raw_sub_and_le_hash_conv e1_tm e2_tm in
let inst = INST[n1_tm, n1_var_num; e1_tm, e1_var_num;
n2_tm, n2_var_num; e2_tm, e2_var_num] in
let n2_not_0 = raw_eq0_hash_conv n2_tm in
if ((fst o dest_const o rand o concl) n2_not_0 = "T") then
failwith "num_exp_div: n2 = 0"
else
if (rand(concl e_le) = e1_tm) then
let th0' = inst NUM_EXP_DIV1' in
let th0 = MY_PROVE_HYP n2_not_0 (MY_PROVE_HYP e_le th0') in
let ltm, rtm = dest_comb(rand(concl th0)) in
let div_tm, rtm2 = dest_comb ltm in
let num_exp_tm = rator rtm2 in
let th1 = AP_THM (AP_TERM div_tm (AP_TERM num_exp_tm e_sub)) rtm in
let ltm, rtm = dest_comb(rand(concl th1)) in
let tm1 = rand ltm in
let th2 = AP_THM (AP_TERM div_tm (denormalize tm1)) rtm in
let th3 = raw_div_hash_conv (rand(concl th2)) in
let th = TRANS th0 (TRANS th1 (TRANS th2 th3)) in
TRANS th (INST[rand(concl th), n_var_num] NUM_EXP_0')
else
let th0' = inst NUM_EXP_DIV2' in
let th0 = MY_PROVE_HYP n2_not_0 (MY_PROVE_HYP e_le th0') in
let ltm, rtm = dest_comb(rand(concl th0)) in
let num_exp_tm = rator rtm in
let th1 = AP_TERM ltm (AP_TERM num_exp_tm e_sub) in
let ltm, rtm = dest_comb(rand(concl th1)) in
let th2 = AP_TERM ltm (denormalize rtm) in
let th3 = raw_div_hash_conv (rand(concl th2)) in
let th = TRANS th0 (TRANS th1 (TRANS th2 th3)) in
TRANS th (INST[rand(concl th), n_var_num] NUM_EXP_0');;
(*
let tm1 = `num_exp (B0 (B4 (B1 _0))) (B1 (B3 _0))`;;
let tm2 = `num_exp (B4 (B6 _0)) (B1 (B2 _0))`;;
num_exp_div tm1 tm2;;
num_exp_div tm2 tm1;;
(* 4: 1.768 *)
test 1000 (num_exp_div tm1) tm2;;
(* 4: 0.656 *)
test 1000 (num_exp_div tm2) tm1;;
*)
(*****************************)
(* Computes the lower bound for (op tm1 tm2) *)
let num_exp_op_lo p op tm1 tm2 =
let op_th = op tm1 tm2 in
let rtm = rand (concl op_th) in
let lo_th = num_exp_lo p rtm in
let ltm = rator (concl lo_th) in
let th0 = AP_TERM ltm op_th in
EQ_MP (SYM th0) lo_th;;
let num_exp_op_hi p op tm1 tm2 =
let op_th = op tm1 tm2 in
let rtm = rand (concl op_th) in
let hi_th = num_exp_hi p rtm in
let tm = rand (concl hi_th) in
let th0 = AP_THM (AP_TERM le_op_num op_th) tm in
EQ_MP (SYM th0) hi_th;;
let num_exp_op_hi_lt p op tm1 tm2 =
let op_th = op tm1 tm2 in
let rtm = rand (concl op_th) in
let hi_lt_th = num_exp_hi_lt p rtm in
let tm = rand (concl hi_lt_th) in
let th0 = AP_THM (AP_TERM lt_op_num op_th) tm in
EQ_MP (SYM th0) hi_lt_th;;
(*
num_exp_op_lo 1 num_exp_add tm1 tm2;;
num_exp_op_hi 1 num_exp_div tm1 tm2;;
num_exp_op_hi_lt 1 num_exp_div tm1 tm2;;
*)
(******************************************)
(* float *)
let NUM_EXP_SUB_lemma = prove(`!n e1 e2. e2 <= e1 ==> &(
num_exp n (e1 - e2)) =
&(
num_exp n e1) * inv(&(
num_exp 1 e2))`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[
num_exp] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
MP_TAC (SPECL [base_const; `e1:num`; `e2:num`]
EXP_INV_lemma) THEN
ANTS_TAC THENL
[
ASM_REWRITE_TAC[] THEN ARITH_TAC;
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
REAL_ARITH_TAC);;
(********************)
(* Float operations *)
(********************)
module Float_ops = struct
(**********************************)
(* FLOAT_LT *)
let FLOAT_LT_TF_00 = (PURE_REWRITE_RULE[NUMERAL] o prove)
(`float T 0 e1 < float F 0 e2 <=> F`,
MP_TAC (SPECL [`T`; `0`; `e1:num`] FLOAT_EQ_0) THEN
MP_TAC (SPECL [`F`; `0`; `e2:num`] FLOAT_EQ_0) THEN
REWRITE_TAC[] THEN
REPLICATE_TAC 2 (DISCH_THEN (fun th -> REWRITE_TAC[th])) THEN
REAL_ARITH_TAC);;
let FLOAT_LT_TF_1 = (UNDISCH_ALL o PURE_REWRITE_RULE[NUMERAL] o prove)
(`(n1 = 0 <=> F) ==> (float T n1 e1 < float F n2 e2 <=> T)`,
DISCH_TAC THEN
MATCH_MP_TAC (REAL_ARITH `a < &0 /\ &0 <= b ==> (a < b <=> T)`) THEN
REWRITE_TAC[FLOAT_F_POS] THEN
MATCH_MP_TAC (REAL_ARITH `~(a = &0) /\ a <= &0 ==> a < &0`) THEN
ASM_REWRITE_TAC[FLOAT_T_NEG; FLOAT_EQ_0]);;
let FLOAT_LT_TF_2 = (UNDISCH_ALL o PURE_REWRITE_RULE[NUMERAL] o prove)
(`(n2 = 0 <=> F) ==> (float T n1 e1 < float F n2 e2 <=> T)`,
DISCH_TAC THEN
MATCH_MP_TAC (REAL_ARITH `a <= &0 /\ &0 < b ==> (a < b <=> T)`) THEN
REWRITE_TAC[FLOAT_T_NEG] THEN
MATCH_MP_TAC (REAL_ARITH `~(a = &0) /\ &0 <= a ==> &0 < a`) THEN
ASM_REWRITE_TAC[FLOAT_F_POS; FLOAT_EQ_0]);;
let FLOAT_T_LT_0 = (CONV_RULE (RAND_CONV (REWRITE_CONV[NUMERAL])) o prove)
(`float T n e < &0 <=> (0 < n)`,
REWRITE_TAC[REAL_ARITH `a < &0 <=> a <= &0 /\ ~(a = &0)`] THEN
REWRITE_TAC[FLOAT_T_NEG; FLOAT_EQ_0] THEN
ARITH_TAC);;
let FLOAT_F_GT_0 = (CONV_RULE (RAND_CONV (REWRITE_CONV[NUMERAL])) o prove)
(`&0 < float F n e <=> 0 < n`,
REWRITE_TAC[REAL_ARITH `&0 < a <=> &0 <= a /\ ~(a = &0)`] THEN
REWRITE_TAC[FLOAT_F_POS; FLOAT_EQ_0] THEN
ARITH_TAC);;
(* float_lt0, float_gt0 *)
let float_lt0 f1 =
let s, n_tm, e_tm = dest_float f1 in
let inst = INST[n_tm, n_var_num; e_tm, e_var_num] in
if s = "F" then
inst FLOAT_F_LT_0
else
let gt_th = raw_gt0_hash_conv n_tm in
TRANS (inst FLOAT_T_LT_0) gt_th;;
let float_gt0 f1 =
let s, n_tm, e_tm = dest_float f1 in
let inst = INST[n_tm, n_var_num; e_tm, e_var_num] in
if s = "F" then
let gt_th = raw_gt0_hash_conv n_tm in
TRANS (inst FLOAT_F_GT_0) gt_th
else
inst FLOAT_T_GT_0;;
(* float_lt *)
let float_lt f1 f2 =
let s1, n1, e1 = dest_float f1 in
let s2, n2, e2 = dest_float f2 in
let inst = INST[n1, n1_var_num; e1, e1_var_num;
n2, n2_var_num; e2, e2_var_num] in
if s1 = "F" then
if s2 = "F" then
(* FF *)
let th0 = inst FLOAT_LT_FF in
let ltm, tm2 = dest_comb (rand (concl th0)) in
let lt_th = num_exp_lt (rand ltm) tm2 in
TRANS th0 lt_th
else
(* FT *)
inst FLOAT_LT_FT
else
if s2 = "F" then
(* TF *)
if (is_const n1 && is_const n2) then
(* n1 = _0 and n2 = _0 *)
inst FLOAT_LT_TF_00
else
let n1_0 = raw_eq0_hash_conv n1 in
if (fst o dest_const o rand o concl) n1_0 = "F" then
(* n1 <> _0 *)
MY_PROVE_HYP n1_0 (inst FLOAT_LT_TF_1)
else
let n2_0 = raw_eq0_hash_conv n2 in
if (fst o dest_const o rand o concl) n2_0 = "F" then
(* n2 <> _0 *)
MY_PROVE_HYP n2_0 (inst FLOAT_LT_TF_2)
else
failwith "float_lt: D0 _0 exception"
else
(* TT *)
let th0 = inst FLOAT_LT_TT in
let ltm, tm2 = dest_comb (rand (concl th0)) in
let lt_th = num_exp_lt (rand ltm) tm2 in
TRANS th0 lt_th;;
(*
let f1 = `float T (_0) (D5 _0)`;;
let f2 = `float F (D1 _0) (D3 _0)`;;
float_lt f1 f2;;
*)
(**********************************)
(* FLOAT_LE *)
let FLOAT_LE_FT_00 = (PURE_REWRITE_RULE[NUMERAL] o prove)
(`float F 0 e1 <= float T 0 e2 <=> T`, REWRITE_TAC[FLOAT_LE_FT]);;
let FLOAT_LE_FT_1 = (UNDISCH_ALL o PURE_REWRITE_RULE[NUMERAL] o prove)
(`(n1 = 0 <=> F) ==> (float F n1 e1 <= float T n2 e2 <=> F)`,
DISCH_TAC THEN ASM_REWRITE_TAC[FLOAT_LE_FT]);;
let FLOAT_LE_FT_2 = (UNDISCH_ALL o PURE_REWRITE_RULE[NUMERAL] o prove)
(`(n2 = 0 <=> F) ==> (float F n1 e1 <= float T n2 e2 <=> F)`,
DISCH_TAC THEN ASM_REWRITE_TAC[FLOAT_LE_FT]);;
let FLOAT_F_LE_0 = (CONV_RULE (RAND_CONV (REWRITE_CONV[NUMERAL])) o prove)
(`float F n e <= &0 <=> n = 0`,
REWRITE_TAC[GSYM (SPEC `F` FLOAT_EQ_0)] THEN
MP_TAC (SPEC_ALL FLOAT_F_POS) THEN
REAL_ARITH_TAC);;
let FLOAT_T_GE_0 = (CONV_RULE (RAND_CONV (REWRITE_CONV[NUMERAL])) o prove)
(`&0 <= float T n e <=> n = 0`,
REWRITE_TAC[GSYM (SPEC `T` FLOAT_EQ_0)] THEN
MP_TAC (SPEC_ALL FLOAT_T_NEG) THEN
REAL_ARITH_TAC);;
(* float_le0, float_ge0 *)
let float_le0 f1 =
let s, n_tm, e_tm = dest_float f1 in
let inst = INST[n_tm, n_var_num; e_tm, e_var_num] in
if s = "T" then
inst FLOAT_T_LE_0
else
let eq_th = raw_eq0_hash_conv n_tm in
TRANS (inst FLOAT_F_LE_0) eq_th;;
let float_ge0 f1 =
let s, n_tm, e_tm = dest_float f1 in
let inst = INST[n_tm, n_var_num; e_tm, e_var_num] in
if s = "T" then
let eq_th = raw_eq0_hash_conv n_tm in
TRANS (inst FLOAT_T_GE_0) eq_th
else
inst FLOAT_F_GE_0;;
(* float_le *)
let float_le f1 f2 =
let s1, n1, e1 = dest_float f1 in
let s2, n2, e2 = dest_float f2 in
let inst = INST[n1, n1_var_num; e1, e1_var_num;
n2, n2_var_num; e2, e2_var_num] in
if s2 = "F" then
if s1 = "F" then
(* FF *)
let th0 = inst FLOAT_LE_FF in
let ltm, tm2 = dest_comb (rand (concl th0)) in
let le_th = num_exp_le (rand ltm) tm2 in
TRANS th0 le_th
else
(* TF *)
inst FLOAT_LE_TF
else
if s1 = "F" then
(* FT *)
if (is_const n1 && is_const n2) then
(* n1 = _0 and n2 = _0 *)
inst FLOAT_LE_FT_00
else
let n1_0 = raw_eq0_hash_conv n1 in
if (fst o dest_const o rand o concl) n1_0 = "F" then
(* n1 <> _0 *)
MY_PROVE_HYP n1_0 (inst FLOAT_LE_FT_1)
else
let n2_0 = raw_eq0_hash_conv n2 in
if (fst o dest_const o rand o concl) n2_0 = "F" then
(* n2 <> _0 *)
MY_PROVE_HYP n2_0 (inst FLOAT_LE_FT_2)
else
failwith "float_lt: D0 _0 exception"
else
(* TT *)
let th0 = inst FLOAT_LE_TT in
let ltm, tm2 = dest_comb (rand (concl th0)) in
let le_th = num_exp_le (rand ltm) tm2 in
TRANS th0 le_th;;
(*
let f1 = `float F (D1 _0) (D5 _0)`;;
let f2 = `float T (D2 _0) (D3 _0)`;;
float_le f1 f2;;
*)
(*************************************)
(* float_max, float_min *)
let FLOAT_MIN_1 = (UNDISCH_ALL o prove)(`(f1 <= f2 <=> T) ==> min f1 f2 = f1`, REAL_ARITH_TAC);;
let FLOAT_MIN_2 = (UNDISCH_ALL o prove)(`(f1 <= f2 <=> F) ==> min f1 f2 = f2`, REAL_ARITH_TAC);;
let FLOAT_MAX_1 = (UNDISCH_ALL o prove)(`(f1 <= f2 <=> T) ==> max f1 f2 = f2`, REAL_ARITH_TAC);;
let FLOAT_MAX_2 = (UNDISCH_ALL o prove)(`(f1 <= f2 <=> F) ==> max f1 f2 = f1`, REAL_ARITH_TAC);;
let float_min f1 f2 =
let inst = INST[f1, f1_var_real; f2, f2_var_real] in
let le_th = float_le f1 f2 in
let th0 =
if (fst o dest_const o rand o concl) le_th = "T" then
inst FLOAT_MIN_1
else
inst FLOAT_MIN_2 in
MY_PROVE_HYP le_th th0;;
let float_max f1 f2 =
let inst = INST[f1, f1_var_real; f2, f2_var_real] in
let le_th = float_le f1 f2 in
let th0 =
if (fst o dest_const o rand o concl) le_th = "T" then
inst FLOAT_MAX_1
else
inst FLOAT_MAX_2 in
MY_PROVE_HYP le_th th0;;
let float_min_max f1 f2 =
let inst = INST[f1, f1_var_real; f2, f2_var_real] in
let le_th = float_le f1 f2 in
let th_min, th_max =
if (fst o dest_const o rand o concl) le_th = "T" then
inst FLOAT_MIN_1, inst FLOAT_MAX_1
else
inst FLOAT_MIN_2, inst FLOAT_MAX_2 in
MY_PROVE_HYP le_th th_min, MY_PROVE_HYP le_th th_max;;
(*
let f1 = `float F (D1 _0) (D5 _0)`;;
let f2 = `float T (D2 _0) (D3 _0)`;;
float_min f1 f2;;
float_max f1 f2;;
float_min_max f1 f2;;
*)
(*************************************)
(* FLOAT_MUL *)
let FLOAT_MUL = prove(`!s1 s2. min_exp <= e /\
num_exp n1 e1 *
num_exp n2 e2 =
num_exp n e
==>
float s1 n1 e1 *
float s2 n2 e2 =
float (
mod_plus s1 s2) n (e - min_exp)`,
REPEAT STRIP_TAC THEN
REWRITE_TAC[
float] THEN
ONCE_REWRITE_TAC[REAL_ARITH `(a * b / c) * (d * e / f) = (a * d) * (b * e) / c / f`] THEN
SUBGOAL_THEN `(if s1 then -- &1 else &1) * (if s2 then -- &1 else &1) = if
mod_plus s1 s2 then -- &1 else &1` MP_TAC THENL
[
REWRITE_TAC[
mod_plus] THEN
COND_CASES_TAC THEN COND_CASES_TAC THEN
REWRITE_TAC[REAL_ARITH `-- &1 * -- &1 = &1`; REAL_MUL_LID;
REAL_MUL_RID];
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
REWRITE_TAC[
real_div] THEN
REWRITE_TAC[GSYM REAL_MUL_ASSOC] THEN
REWRITE_TAC[
REAL_EQ_MUL_LCANCEL] THEN
DISJ2_TAC THEN
MP_TAC (SPECL[`n:num`; `e:num`; `min_exp`]
NUM_EXP_SUB_lemma) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
ASM_REWRITE_TAC[REAL_OF_NUM_MUL]);;
let FLOAT_MUL_FF_hi, FLOAT_MUL_FF_lo =
let ff_hi = `min_exp <= e /\ e - min_exp = r /\ num_exp n1 e1 * num_exp n2 e2 <= num_exp n e
==> float F n1 e1 * float F n2 e2 <= float F n r` in
let ff_lo = `min_exp <= e /\ e - min_exp = r /\ num_exp n e <= num_exp n1 e1 * num_exp n2 e2
==> float F n r <= float F n1 e1 * float F n2 e2` in
let proof =
REPEAT STRIP_TAC THEN
POP_ASSUM MP_TAC THEN
POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN
REWRITE_TAC[GSYM REAL_OF_NUM_LE; GSYM REAL_OF_NUM_MUL] THEN
DISCH_TAC THEN
MAP_EVERY ABBREV_TAC [`z = &(num_exp n e)`; `x = &(num_exp n1 e1)`; `y = &(num_exp n2 e2)`] THEN
ASM_REWRITE_TAC[float; REAL_MUL_LID] THEN
REWRITE_TAC[REAL_ARITH `a / b * c / d = (a * c) / b / d`] THEN
REWRITE_TAC[real_div] THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC REAL_LE_RMUL THEN
REWRITE_TAC[REAL_LE_INV_EQ; REAL_POS] THEN
MP_TAC (SPECL [`n:num`; `e:num`; `min_exp`] NUM_EXP_SUB_lemma) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun th -> REWRITE_TAC[th]) THEN
MATCH_MP_TAC REAL_LE_RMUL THEN
ASM_REWRITE_TAC[REAL_LE_INV_EQ; REAL_POS] in
prove(ff_hi, proof), prove(ff_lo, proof);;
let FLOAT_MUL_TT_hi, FLOAT_MUL_TT_lo =
let tt_hi = `min_exp <= e /\ e - min_exp = r /\ num_exp n1 e1 * num_exp n2 e2 <= num_exp n e
==> float T n1 e1 * float T n2 e2 <= float F n r` in
let tt_lo = `min_exp <= e /\ e - min_exp = r /\ num_exp n e <= num_exp n1 e1 * num_exp n2 e2
==> float F n r <= float T n1 e1 * float T n2 e2` in
let proof =
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[REAL_ARITH `--a * --b = a * b`] THEN
REWRITE_TAC[FLOAT_MUL_FF_hi; FLOAT_MUL_FF_lo] in
prove(tt_hi, proof), prove(tt_lo, proof);;
let FLOAT_MUL_FT_hi, FLOAT_MUL_FT_lo =
let ft_hi = `min_exp <= e /\ e - min_exp = r /\ num_exp n e <= num_exp n1 e1 * num_exp n2 e2
==> float F n1 e1 * float T n2 e2 <= float T n r` in
let ft_lo = `min_exp <= e /\ e - min_exp = r /\ num_exp n1 e1 * num_exp n2 e2 <= num_exp n e
==> float T n r <= float F n1 e1 * float T n2 e2` in
let proof =
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[REAL_ARITH `a * --b <= --c <=> c <= a * b`] THEN
REWRITE_TAC[REAL_ARITH `--c <= a * --b <=> a * b <= c`] THEN
REWRITE_TAC[FLOAT_MUL_FF_hi; FLOAT_MUL_FF_lo] in
prove(ft_hi, proof), prove(ft_lo, proof);;
let FLOAT_MUL_TF_hi, FLOAT_MUL_TF_lo =
let ft_hi = `min_exp <= e /\ e - min_exp = r /\ num_exp n e <= num_exp n1 e1 * num_exp n2 e2
==> float T n1 e1 * float F n2 e2 <= float T n r` in
let ft_lo = `min_exp <= e /\ e - min_exp = r /\ num_exp n1 e1 * num_exp n2 e2 <= num_exp n e
==> float T n r <= float T n1 e1 * float F n2 e2` in
let proof =
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[REAL_ARITH `--a * b <= --c <=> c <= a * b`] THEN
REWRITE_TAC[REAL_ARITH `--c <= --a * b <=> a * b <= c`] THEN
REWRITE_TAC[FLOAT_MUL_FF_hi; FLOAT_MUL_FF_lo] in
prove(ft_hi, proof), prove(ft_lo, proof);;
(*********************************************)
(* float_mul_lo, float_mul_hi *)
let transform = UNDISCH_ALL o NUMERALS_TO_NUM o REWRITE_RULE[min_exp_def; GSYM IMP_IMP];;
let FLOAT_MUL_FF_hi' = transform FLOAT_MUL_FF_hi and
FLOAT_MUL_FF_lo' = transform FLOAT_MUL_FF_lo and
FLOAT_MUL_TT_hi' = transform FLOAT_MUL_TT_hi and
FLOAT_MUL_TT_lo' = transform FLOAT_MUL_TT_lo and
FLOAT_MUL_FT_hi' = transform FLOAT_MUL_FT_hi and
FLOAT_MUL_FT_lo' = transform FLOAT_MUL_FT_lo and
FLOAT_MUL_TF_hi' = transform FLOAT_MUL_TF_hi and
FLOAT_MUL_TF_lo' = transform FLOAT_MUL_TF_lo;;
let FLOAT_MUL_FF' = transform FLOAT_MUL_FF and
FLOAT_MUL_TT' = transform FLOAT_MUL_TT and
FLOAT_MUL_FT' = transform FLOAT_MUL_FT and
FLOAT_MUL_TF' = transform FLOAT_MUL_TF;;
let float_mul_eq f1 f2 =
let s1, n1, e1 = dest_float f1 and
s2, n2, e2 = dest_float f2 in
let flag = s1 = s2 in
let num_exp1 = mk_num_exp n1 e1 and
num_exp2 = mk_num_exp n2 e2 in
let mul_th = num_exp_mul num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand (concl mul_th)) in
let sub_th, le_th = raw_sub_and_le_hash_conv e_tm min_exp_num_const in
if (rand(concl le_th) <> e_tm) then
failwith "float_mul_lo: underflow"
else
let r_tm = rand(concl sub_th) in
let inst = INST[e_tm, e_var_num; r_tm, r_var_num; n_tm, n_var_num;
n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] in
let th0 = inst
(if flag then
if s1 = "F" then FLOAT_MUL_FF' else FLOAT_MUL_TT'
else
if s1 = "F" then FLOAT_MUL_FT' else FLOAT_MUL_TF') in
MY_PROVE_HYP sub_th (MY_PROVE_HYP mul_th (MY_PROVE_HYP le_th th0));;
let float_mul_lo pp f1 f2 =
let s1, n1, e1 = dest_float f1 and
s2, n2, e2 = dest_float f2 in
let flag = s1 = s2 in
let num_exp1 = mk_num_exp n1 e1 and
num_exp2 = mk_num_exp n2 e2 in
let mul_th, n_tm, e_tm =
if flag then
let th = num_exp_op_lo pp num_exp_mul num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (lhand (concl th)) in
th, n_tm, e_tm
else
let th = num_exp_op_hi pp num_exp_mul num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand (concl th)) in
th, n_tm, e_tm in
let sub_th, le_th = raw_sub_and_le_hash_conv e_tm min_exp_num_const in
if (rand(concl le_th) <> e_tm) then
failwith "float_mul_lo: underflow"
else
let r_tm = rand(concl sub_th) in
let inst = INST[e_tm, e_var_num; r_tm, r_var_num; n_tm, n_var_num;
n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] in
let th0 = inst
(if flag then
if s1 = "F" then FLOAT_MUL_FF_lo' else FLOAT_MUL_TT_lo'
else
if s1 = "F" then FLOAT_MUL_FT_lo' else FLOAT_MUL_TF_lo') in
MY_PROVE_HYP sub_th (MY_PROVE_HYP mul_th (MY_PROVE_HYP le_th th0));;
let float_mul_hi pp f1 f2 =
let s1, n1, e1 = dest_float f1 and
s2, n2, e2 = dest_float f2 in
let flag = s1 = s2 in
let num_exp1 = mk_num_exp n1 e1 and
num_exp2 = mk_num_exp n2 e2 in
let mul_th, n_tm, e_tm =
if flag then
let th = num_exp_op_hi pp num_exp_mul num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand (concl th)) in
th, n_tm, e_tm
else
let th = num_exp_op_lo pp num_exp_mul num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (lhand (concl th)) in
th, n_tm, e_tm in
let sub_th, le_th = raw_sub_and_le_hash_conv e_tm min_exp_num_const in
if (rand(concl le_th) <> e_tm) then
failwith "float_mul_hi: underflow"
else
let r_tm = rand(concl sub_th) in
let inst = INST[e_tm, e_var_num; r_tm, r_var_num; n_tm, n_var_num;
n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] in
let th0 = inst
(if flag then
if s1 = "F" then FLOAT_MUL_FF_hi' else FLOAT_MUL_TT_hi'
else
if s1 = "F" then FLOAT_MUL_FT_hi' else FLOAT_MUL_TF_hi') in
MY_PROVE_HYP sub_th (MY_PROVE_HYP mul_th (MY_PROVE_HYP le_th th0));;
(*********************************************)
(* FLOAT_DIV *)
let DIV_lemma = prove(`!x y. ~(y = 0) ==> &(x DIV y) <= &x / &y /\ &x / &y <= &(x DIV y + 1)`,
REPEAT GEN_TAC THEN DISCH_TAC THEN
MP_TAC (SPECL [`y:num`; `x:num`]
FLOOR_DIV_DIV) THEN
ASM_REWRITE_TAC[GSYM REAL_OF_NUM_ADD] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
SIMP_TAC[
FLOOR;
REAL_LT_IMP_LE]);;
let FLOAT_DIV_FF_lo = prove(`e2 + k = r1 /\ min_exp + e + e1 = r2 /\ r2 - r1 = r /\
r1 <= r2 /\ ~(n2 = 0) /\
num_exp n e <=
num_exp n1 k DIV
num_exp n2 0
==>
float F n r <=
float F n1 e1 /
float F n2 e2`,
MAP_EVERY ABBREV_TAC [`z =
num_exp n e`; `x =
num_exp n1 k`; `y =
num_exp n2 0`] THEN
REPEAT STRIP_TAC THEN
REPLICATE_TAC 3 (POP_ASSUM MP_TAC) THEN
REPLICATE_TAC 3 (POP_ASSUM (fun
th -> REWRITE_TAC[SYM
th])) THEN
REPEAT STRIP_TAC THEN
REWRITE_TAC[
float; REAL_MUL_LID] THEN
REWRITE_TAC[
real_div;
REAL_INV_MUL;
REAL_INV_INV] THEN
REWRITE_TAC[REAL_ARITH `(a * b) * c * d = (b * d) * (a * c)`] THEN
SUBGOAL_THEN `~(&(
num_exp 1 min_exp) = &0)` ASSUME_TAC THENL
[
REWRITE_TAC[
num_exp; REAL_OF_NUM_EQ;
MULT_CLAUSES;
EXP_EQ_0] THEN
ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[REAL_MUL_LINV; REAL_MUL_LID] THEN
ASM_SIMP_TAC[
NUM_EXP_SUB_lemma] THEN
SUBGOAL_THEN `&(
num_exp n1 e1) * inv(&(
num_exp n2 e2)) = (&x / &y) * &(
num_exp 1 e1) * inv(&(
num_exp 1 (e2 + k)))` MP_TAC THENL
[
EXPAND_TAC "x" THEN EXPAND_TAC "y" THEN
REWRITE_TAC[
real_div] THEN
REWRITE_TAC[
num_exp; GSYM REAL_OF_NUM_MUL; GSYM
REAL_OF_NUM_POW] THEN
REWRITE_TAC[REAL_MUL_LID;
REAL_INV_MUL;
REAL_INV_1;
real_pow;
REAL_MUL_RID] THEN
REWRITE_TAC[
REAL_POW_ADD;
REAL_INV_MUL] THEN
REWRITE_TAC[REAL_ARITH `((a * b) * c) * d * e * f = (b * f) * (a * c * d * e)`] THEN
SUBGOAL_THEN
(mk_comb(`(~)`, mk_eq(mk_binop `pow` (mk_comb (`&`, base_const)) `k:num`, `&0`))) ASSUME_TAC THENL
[
REWRITE_TAC[
REAL_POW_EQ_0] THEN
REAL_ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[
REAL_MUL_RINV; REAL_MUL_LID] THEN
REAL_ARITH_TAC;
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
ONCE_REWRITE_TAC[REAL_ARITH `(a * b) * c = (a * c) * b`] THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
REWRITE_TAC[
REAL_LE_INV_EQ;
REAL_POS] THEN
ONCE_REWRITE_TAC[
NUM_EXP_SUM1] THEN
REWRITE_TAC[
NUM_EXP_SUM] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
ASM_REWRITE_TAC[REAL_ARITH `(a * b * c) * d = (d * a) * b * c`] THEN
ASM_SIMP_TAC[REAL_MUL_LINV; REAL_MUL_LID] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
REWRITE_TAC[
REAL_LE_INV_EQ;
REAL_POS] THEN
MP_TAC (SPEC_ALL
DIV_lemma) THEN
ANTS_TAC THENL
[
EXPAND_TAC "y" THEN
REWRITE_TAC[
num_exp;
MULT_EQ_0; DE_MORGAN_THM] THEN
ASM_REWRITE_TAC[
EXP] THEN
ARITH_TAC;
ALL_TAC
] THEN
STRIP_TAC THEN
MATCH_MP_TAC
REAL_LE_TRANS THEN
EXISTS_TAC `&(x DIV y)` THEN
ASM_REWRITE_TAC[REAL_OF_NUM_LE]);;
let FLOAT_DIV_FF_hi = prove(`e2 + k = r1 /\ min_exp + e + e1 = r2 /\ r2 - r1 = r /\
r1 <= r2 /\ ~(n2 = 0) /\
num_exp n1 k DIV
num_exp n2 0 <
num_exp n e
==>
float F n1 e1 /
float F n2 e2 <=
float F n r`,
MAP_EVERY ABBREV_TAC [`z =
num_exp n e`; `x =
num_exp n1 k`; `y =
num_exp n2 0`] THEN
REPEAT STRIP_TAC THEN
REPLICATE_TAC 3 (POP_ASSUM MP_TAC) THEN
REPLICATE_TAC 3 (POP_ASSUM (fun
th -> REWRITE_TAC[SYM
th])) THEN
REPEAT STRIP_TAC THEN
REWRITE_TAC[
float; REAL_MUL_LID] THEN
REWRITE_TAC[
real_div;
REAL_INV_MUL;
REAL_INV_INV] THEN
REWRITE_TAC[REAL_ARITH `(a * b) * c * d = (b * d) * (a * c)`] THEN
SUBGOAL_THEN `~(&(
num_exp 1 min_exp) = &0)` ASSUME_TAC THENL
[
REWRITE_TAC[
num_exp; REAL_OF_NUM_EQ;
MULT_CLAUSES;
EXP_EQ_0] THEN
ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[REAL_MUL_LINV; REAL_MUL_LID] THEN
ASM_SIMP_TAC[
NUM_EXP_SUB_lemma] THEN
SUBGOAL_THEN `&(
num_exp n1 e1) * inv(&(
num_exp n2 e2)) = (&x / &y) * &(
num_exp 1 e1) * inv(&(
num_exp 1 (e2 + k)))` MP_TAC THENL
[
EXPAND_TAC "x" THEN EXPAND_TAC "y" THEN
REWRITE_TAC[
real_div] THEN
REWRITE_TAC[
num_exp; GSYM REAL_OF_NUM_MUL; GSYM
REAL_OF_NUM_POW] THEN
REWRITE_TAC[REAL_MUL_LID;
REAL_INV_MUL;
REAL_INV_1;
real_pow;
REAL_MUL_RID] THEN
REWRITE_TAC[
REAL_POW_ADD;
REAL_INV_MUL] THEN
REWRITE_TAC[REAL_ARITH `((a * b) * c) * d * e * f = (b * f) * (a * c * d * e)`] THEN
SUBGOAL_THEN
(mk_comb(`(~)`, mk_eq(mk_binop `pow` (mk_comb (`&`, base_const)) `k:num`, `&0`))) ASSUME_TAC THENL
[
REWRITE_TAC[
REAL_POW_EQ_0] THEN
REAL_ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[
REAL_MUL_RINV; REAL_MUL_LID] THEN
REAL_ARITH_TAC;
ALL_TAC
] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[
th]) THEN
ONCE_REWRITE_TAC[REAL_ARITH `(a * b) * c = (a * c) * b`] THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
REWRITE_TAC[
REAL_LE_INV_EQ;
REAL_POS] THEN
ONCE_REWRITE_TAC[
NUM_EXP_SUM1] THEN
REWRITE_TAC[
NUM_EXP_SUM] THEN
REWRITE_TAC[GSYM REAL_OF_NUM_MUL] THEN
ASM_REWRITE_TAC[REAL_ARITH `(a * b * c) * d = (d * a) * b * c`] THEN
ASM_SIMP_TAC[REAL_MUL_LINV; REAL_MUL_LID] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
REWRITE_TAC[
REAL_LE_INV_EQ;
REAL_POS] THEN
MP_TAC (SPEC_ALL
DIV_lemma) THEN
ANTS_TAC THENL
[
EXPAND_TAC "y" THEN
REWRITE_TAC[
num_exp;
MULT_EQ_0; DE_MORGAN_THM] THEN
ASM_REWRITE_TAC[
EXP] THEN
ARITH_TAC;
ALL_TAC
] THEN
STRIP_TAC THEN
MATCH_MP_TAC
REAL_LE_TRANS THEN
EXISTS_TAC `&(x DIV y + 1)` THEN
ASM_REWRITE_TAC[REAL_OF_NUM_LE] THEN
UNDISCH_TAC `x DIV y < z` THEN
ARITH_TAC);;
(******************************************)
(* float_div_lo, float_div_hi *)
let transform = UNDISCH_ALL o PURE_REWRITE_RULE[TAUT `~P <=> (P <=> F)`] o
NUMERALS_TO_NUM o REWRITE_RULE[GSYM IMP_IMP; min_exp_def];;
let FLOAT_DIV_FF_hi' = transform FLOAT_DIV_FF_hi and
FLOAT_DIV_FF_lo' = transform FLOAT_DIV_FF_lo and
FLOAT_DIV_TT_hi' = transform FLOAT_DIV_TT_hi and
FLOAT_DIV_TT_lo' = transform FLOAT_DIV_TT_lo and
FLOAT_DIV_FT_hi' = transform FLOAT_DIV_FT_hi and
FLOAT_DIV_FT_lo' = transform FLOAT_DIV_FT_lo and
FLOAT_DIV_TF_hi' = transform FLOAT_DIV_TF_hi and
FLOAT_DIV_TF_lo' = transform FLOAT_DIV_TF_lo;;
let float_div_lo pp f1 f2 =
let s1, n1, e1 = dest_float f1 and
s2, n2, e2 = dest_float f2 in
let flag = s1 = s2 in
let k_tm = rand (mk_small_numeral_array (2 * pp)) in
let num_exp1 = mk_num_exp n1 k_tm and
num_exp2 = mk_num_exp n2 zero_const in
let div_th, n_tm, e_tm =
if flag then
let th = num_exp_op_lo pp num_exp_div num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (lhand(concl th)) in
th, n_tm, e_tm
else
let th = num_exp_op_hi_lt pp num_exp_div num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand(concl th)) in
th, n_tm, e_tm in
let r1_th = raw_add_conv_hash (mk_binop plus_op_num e2 k_tm) in
let r1_tm = rand(concl r1_th) in
let e_plus_e1 = raw_add_conv_hash (mk_binop plus_op_num e_tm e1) in
let ltm, rtm = dest_comb(concl e_plus_e1) in
let r2_th' = raw_add_conv_hash (mk_binop plus_op_num min_exp_num_const rtm) in
let r2_th = TRANS (AP_TERM (mk_comb (plus_op_num, min_exp_num_const)) e_plus_e1) r2_th' in
let r2_tm = rand(concl r2_th) in
let sub_th, le_th = raw_sub_and_le_hash_conv r2_tm r1_tm in
if rand(concl le_th) <> r2_tm then
failwith "float_div_lo: underflow"
else
let r_tm = rand(concl sub_th) in
let n2_not_zero = raw_eq0_hash_conv n2 in
let inst = INST[r1_tm, r1_var_num; r2_tm, r2_var_num;
n1, n1_var_num; e1, e1_var_num;
e_tm, e_var_num; k_tm, k_var_num;
n2, n2_var_num; e2, e2_var_num;
n_tm, n_var_num; r_tm, r_var_num] in
let th0 = inst
(if flag then
if s1 = "F" then FLOAT_DIV_FF_lo' else FLOAT_DIV_TT_lo'
else
if s1 = "F" then FLOAT_DIV_FT_lo' else FLOAT_DIV_TF_lo') in
let th1 = MY_PROVE_HYP n2_not_zero (MY_PROVE_HYP div_th (MY_PROVE_HYP le_th th0)) in
MY_PROVE_HYP sub_th (MY_PROVE_HYP r2_th (MY_PROVE_HYP r1_th th1));;
let float_div_hi pp f1 f2 =
let s1, n1, e1 = dest_float f1 and
s2, n2, e2 = dest_float f2 in
let flag = s1 = s2 in
let k_tm = rand (mk_small_numeral_array (2 * pp)) in
let num_exp1 = mk_num_exp n1 k_tm and
num_exp2 = mk_num_exp n2 zero_const in
let div_th, n_tm, e_tm =
if flag then
let th = num_exp_op_hi_lt pp num_exp_div num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand(concl th)) in
th, n_tm, e_tm
else
let th = num_exp_op_lo pp num_exp_div num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (lhand(concl th)) in
th, n_tm, e_tm in
let r1_th = raw_add_conv_hash (mk_binop plus_op_num e2 k_tm) in
let r1_tm = rand(concl r1_th) in
let e_plus_e1 = raw_add_conv_hash (mk_binop plus_op_num e_tm e1) in
let ltm, rtm = dest_comb(concl e_plus_e1) in
let r2_th' = raw_add_conv_hash (mk_binop plus_op_num min_exp_num_const rtm) in
let r2_th = TRANS (AP_TERM (mk_comb (plus_op_num, min_exp_num_const)) e_plus_e1) r2_th' in
let r2_tm = rand(concl r2_th) in
let sub_th, le_th = raw_sub_and_le_hash_conv r2_tm r1_tm in
if rand(concl le_th) <> r2_tm then
failwith "float_div_hi: underflow"
else
let r_tm = rand(concl sub_th) in
let n2_not_zero = raw_eq0_hash_conv n2 in
let inst = INST[r1_tm, r1_var_num; r2_tm, r2_var_num;
n1, n1_var_num; e1, e1_var_num;
e_tm, e_var_num; k_tm, k_var_num;
n2, n2_var_num; e2, e2_var_num;
n_tm, n_var_num; r_tm, r_var_num] in
let th0 = inst
(if flag then
if s1 = "F" then FLOAT_DIV_FF_hi' else FLOAT_DIV_TT_hi'
else
if s1 = "F" then FLOAT_DIV_FT_hi' else FLOAT_DIV_TF_hi') in
let th1 = MY_PROVE_HYP n2_not_zero (MY_PROVE_HYP div_th (MY_PROVE_HYP le_th th0)) in
MY_PROVE_HYP sub_th (MY_PROVE_HYP r2_th (MY_PROVE_HYP r1_th th1));;
(*
float_div_lo 1 `float F (B1 _0) (B10 _0)` `float F (B3 _0) (B10 _0)`;;
float_div_hi 1 `float F (B1 _0) (B10 _0)` `float F (B3 _0) (B10 _0)`;;
float_div_hi 5 f1 f2;;
*)
(***********************************)
(* FLOAT_ADD *)
(******************************************)
(* float_add_lo, float_add_hi *)
let m_var_real = `m:real` and
n_var_real = `n:real`;;
let REAL_ADD_COMM = CONJUNCT1 REAL_ADD_AC;;
let transform = UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o NUMERALS_TO_NUM;;
let FLOAT_ADD_FF_hi' = transform FLOAT_ADD_FF_hi and
FLOAT_ADD_FF_lo' = transform FLOAT_ADD_FF_lo and
FLOAT_ADD_TT_hi' = transform FLOAT_ADD_TT_hi and
FLOAT_ADD_TT_lo' = transform FLOAT_ADD_TT_lo and
FLOAT_ADD_FT_F_lo' = transform FLOAT_ADD_FT_F_lo and
FLOAT_ADD_FT_T_lo' = transform FLOAT_ADD_FT_T_lo and
FLOAT_ADD_FT_F_hi' = transform FLOAT_ADD_FT_F_hi and
FLOAT_ADD_FT_T_hi' = transform FLOAT_ADD_FT_T_hi;;
let float_add_lo pp f1 f2 =
let s1, n1, e1 = dest_float f1 in
let s2, n2, e2 = dest_float f2 in
if s1 = s2 then
let num_exp1 = mk_num_exp n1 e1 in
let num_exp2 = mk_num_exp n2 e2 in
if s1 = "F" then
(* F + F *)
let add_th = num_exp_op_lo pp num_exp_add num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (lhand(concl add_th)) in
let th0 = INST[e_tm, e_var_num; n_tm, n_var_num; n1, n1_var_num;
e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] FLOAT_ADD_FF_lo' in
MY_PROVE_HYP add_th th0
else
(* T + T *)
let add_th = num_exp_op_hi pp num_exp_add num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand(concl add_th)) in
let th0 = INST[e_tm, e_var_num; n_tm, n_var_num; n1, n1_var_num;
e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] FLOAT_ADD_TT_lo' in
MY_PROVE_HYP add_th th0
else
(* F + T or T + F *)
let th0, n1, e1, n2, e2 =
if s1 = "T" then
INST[f2, m_var_real; f1, n_var_real] REAL_ADD_COMM, n2, e2, n1, e1
else
REFL(mk_binop plus_op_real f1 f2), n1, e1, n2, e2 in
let num_exp1 = mk_num_exp n1 e1 in
let num_exp2 = mk_num_exp n2 e2 in
let sub_th, le_th = num_exp_sub num_exp1 num_exp2 in
let sub_tm = rand(concl sub_th) in
if rand(concl le_th) = num_exp1 then
let lo_th = num_exp_lo pp sub_tm in
let n_tm, e_tm = dest_num_exp (lhand(concl lo_th)) in
let lo_sub_th = EQ_MP (AP_TERM (rator(concl lo_th)) (SYM sub_th)) lo_th in
let th1 = INST[n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num;
n_tm, n_var_num; e_tm, e_var_num] FLOAT_ADD_FT_F_lo' in
let th2 = MY_PROVE_HYP lo_sub_th (MY_PROVE_HYP le_th th1) in
EQ_MP (AP_TERM (rator(concl th2)) th0) th2
else
let hi_th = num_exp_hi pp sub_tm in
let n_tm, e_tm = dest_num_exp(rand(concl hi_th)) in
let hi_sub_th = EQ_MP (SYM (AP_THM (AP_TERM le_op_num sub_th) (rand(concl hi_th)))) hi_th in
let th1 = INST[n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num;
n_tm, n_var_num; e_tm, e_var_num] FLOAT_ADD_FT_T_lo' in
let th2 = MY_PROVE_HYP hi_sub_th (MY_PROVE_HYP le_th th1) in
EQ_MP (AP_TERM (rator(concl th2)) th0) th2;;
let float_add_hi pp f1 f2 =
let s1, n1, e1 = dest_float f1 in
let s2, n2, e2 = dest_float f2 in
if s1 = s2 then
let num_exp1 = mk_num_exp n1 e1 in
let num_exp2 = mk_num_exp n2 e2 in
if s1 = "F" then
(* F + F *)
let add_th = num_exp_op_hi pp num_exp_add num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (rand(concl add_th)) in
let th0 = INST[e_tm, e_var_num; n_tm, n_var_num; n1, n1_var_num;
e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] FLOAT_ADD_FF_hi' in
MY_PROVE_HYP add_th th0
else
(* T + T *)
let add_th = num_exp_op_lo pp num_exp_add num_exp1 num_exp2 in
let n_tm, e_tm = dest_num_exp (lhand(concl add_th)) in
let th0 = INST[e_tm, e_var_num; n_tm, n_var_num; n1, n1_var_num;
e1, e1_var_num; n2, n2_var_num; e2, e2_var_num] FLOAT_ADD_TT_hi' in
MY_PROVE_HYP add_th th0
else
(* F + T or T + F *)
let th0, n1, e1, n2, e2 =
if s1 = "T" then
INST[f2, m_var_real; f1, n_var_real] REAL_ADD_COMM, n2, e2, n1, e1
else
REFL(mk_binop plus_op_real f1 f2), n1, e1, n2, e2 in
let num_exp1 = mk_num_exp n1 e1 in
let num_exp2 = mk_num_exp n2 e2 in
let sub_th, le_th = num_exp_sub num_exp1 num_exp2 in
let sub_tm = rand(concl sub_th) in
if rand(concl le_th) = num_exp1 then
let hi_th = num_exp_hi pp sub_tm in
let n_tm, e_tm = dest_num_exp (rand(concl hi_th)) in
let hi_sub_th = EQ_MP (SYM (AP_THM (AP_TERM le_op_num sub_th) (rand(concl hi_th)))) hi_th in
let th1 = INST[n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num;
n_tm, n_var_num; e_tm, e_var_num] FLOAT_ADD_FT_F_hi' in
let th2 = MY_PROVE_HYP hi_sub_th (MY_PROVE_HYP le_th th1) in
EQ_MP (AP_THM (AP_TERM le_op_real th0) (rand(concl th2))) th2
else
let lo_th = num_exp_lo pp sub_tm in
let n_tm, e_tm = dest_num_exp(lhand(concl lo_th)) in
let lo_sub_th = EQ_MP (AP_TERM (rator(concl lo_th)) (SYM sub_th)) lo_th in
let th1 = INST[n1, n1_var_num; e1, e1_var_num; n2, n2_var_num; e2, e2_var_num;
n_tm, n_var_num; e_tm, e_var_num] FLOAT_ADD_FT_T_hi' in
let th2 = MY_PROVE_HYP lo_sub_th (MY_PROVE_HYP le_th th1) in
EQ_MP (AP_THM (AP_TERM le_op_real th0) (rand(concl th2))) th2;;
(*
float_add_lo 1 f1 f2;;
float_add_hi 1 f1 f2;;
*)
(******************************************)
(* float_sub_lo, float_sub_hi *)
let s1_var_bool = `s1:bool` and
f1_var_real = `f1:real` and
f2_var_real = `f2:real`;;
let FLOAT_SUB_F_EQ_ADD = (SYM o prove)(`f1 - float F n2 e2 = f1 + float T n2 e2`,
REWRITE_TAC[FLOAT_NEG_T] THEN REAL_ARITH_TAC);;
let FLOAT_SUB_T_EQ_ADD = (SYM o prove)(`f1 - float T n2 e2 = f1 + float F n2 e2`,
REWRITE_TAC[FLOAT_NEG_T] THEN REAL_ARITH_TAC);;
let float_sub_lo pp f1 f2 =
let s2, n2, e2 = dest_float f2 in
let th0 =
INST[f1, f1_var_real; n2, n2_var_num; e2, e2_var_num]
(if s2 = "F" then FLOAT_SUB_F_EQ_ADD else FLOAT_SUB_T_EQ_ADD) in
let ltm,f2_tm = dest_comb(lhand(concl th0)) in
let f1_tm = rand ltm in
let lo_th = float_add_lo pp f1_tm f2_tm in
EQ_MP (AP_TERM (rator(concl lo_th)) th0) lo_th;;
let float_sub_hi pp f1 f2 =
let s2, n2, e2 = dest_float f2 in
let th0 =
INST[f1, f1_var_real; n2, n2_var_num; e2, e2_var_num]
(if s2 = "F" then FLOAT_SUB_F_EQ_ADD else FLOAT_SUB_T_EQ_ADD) in
let ltm, f2_tm = dest_comb(lhand(concl th0)) in
let f1_tm = rand ltm in
let hi_th = float_add_hi pp f1_tm f2_tm in
EQ_MP (AP_THM (AP_TERM le_op_real th0) (rand(concl hi_th))) hi_th;;
(*
let f1 = `float F (D5 (D2 _0)) (D0 (D1 _0))`;;
let f2 = `float F (D3 (D2 _0)) (D9 _0)`;;
float_sub_hi 1 f2 f1;;
*)
(*******************************************)
(* FLOAT_SQRT *)
(* float F m e = float F (B0 m) (PRE e) *)
let FLOAT_PRE_EXP = prove(mk_imp(`~(e = 0) /\ PRE e = e1`,
mk_eq(`float F m e`,
mk_comb(mk_comb(`float F`, mk_comb(b0_const, m_var_num)), `e1:num`))),
STRIP_TAC THEN POP_ASSUM (fun th -> REWRITE_TAC[SYM th]) THEN
REWRITE_TAC[float; REAL_MUL_LID; real_div; REAL_EQ_MUL_RCANCEL] THEN
DISJ1_TAC THEN
REWRITE_TAC[num_exp; b0_thm; REAL_OF_NUM_EQ] THEN
SUBGOAL_THEN `e = SUC (PRE e)` MP_TAC THENL
[
POP_ASSUM MP_TAC THEN ARITH_TAC;
ALL_TAC
] THEN
DISCH_THEN (fun th -> CONV_TAC (LAND_CONV (ONCE_REWRITE_CONV[th]))) THEN
REWRITE_TAC[EXP] THEN
ARITH_TAC);;
let DIV2_EVEN_lemma = prove(`!n.
EVEN n ==> 2 * (n DIV 2) = n`,
GEN_TAC THEN
REWRITE_TAC[
EVEN_EXISTS] THEN
STRIP_TAC THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC (ARITH_RULE `x = y ==> 2 * x = 2 * y`) THEN
MATCH_MP_TAC DIV_MULT THEN
ARITH_TAC);;
let FLOAT_SQRT_EVEN_lo = prove(`f1 * f1 = f2 /\ f2 <= x /\
num_exp m (2 * p) = x /\ f1 =
num_exp n1 e1
/\
EVEN e /\ e DIV 2 = e2 /\
e1 + e2 + (min_exp DIV 2) = r /\
p <= r /\ r - p = r2
==>
float F n1 r2 <=
sqrt (
float F m e)`,
STRIP_TAC THEN
UNDISCH_TAC `f2 <= x:num` THEN
UNDISCH_TAC `
num_exp m (2 * p) = x` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
UNDISCH_TAC `f1 * f1 = f2:num` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
UNDISCH_TAC `e1 + e2 + min_exp DIV 2 = r` THEN
UNDISCH_TAC `e DIV 2 = e2` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
REPEAT (POP_ASSUM MP_TAC) THEN
REWRITE_TAC[
num_exp;
float; REAL_MUL_LID; GSYM REAL_OF_NUM_MUL] THEN
REPEAT STRIP_TAC THEN
UNDISCH_TAC `r - p = r2:num` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
MATCH_MP_TAC
REAL_LE_RSQRT THEN
REWRITE_TAC[GSYM
REAL_OF_NUM_POW;
REAL_POW_DIV] THEN
REWRITE_TAC[REAL_POW_2;
real_div;
REAL_INV_MUL] THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
CONJ_TAC THENL
[
REWRITE_TAC[REAL_ARITH `(((a * b) * a) * b) * c = (a * a) * (b * b) * c:real`] THEN
REWRITE_TAC[GSYM
REAL_POW_ADD] THEN
REWRITE_TAC[ARITH_RULE `r - p + r - p = 2 * r - 2 * p`] THEN
MP_TAC (SPECL[mk_comb(amp_op_real, base_const); `2 * r`; `2 * p`]
REAL_DIV_POW2) THEN
ANTS_TAC THENL [ REAL_ARITH_TAC; ALL_TAC ] THEN
ASM_SIMP_TAC[ARITH_RULE `p <= r ==> 2 * p <= 2 * r`] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th;
real_div]) THEN
SUBGOAL_THEN `2 * r = (e1 + e1) + min_exp + e` (fun
th -> REWRITE_TAC[
th]) THENL
[
EXPAND_TAC "r" THEN
REWRITE_TAC[ARITH_RULE `2 * (e1 + b + c) = (e1 + e1) + 2 * c + 2 * b`] THEN
MATCH_MP_TAC (ARITH_RULE `b1 = b2 /\
c1 = c2 ==> a + b1 +
c1 = a + b2 + c2:num`) THEN
SUBGOAL_THEN `
EVEN min_exp` ASSUME_TAC THENL
[
REWRITE_TAC[
min_exp_def] THEN ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[
DIV2_EVEN_lemma];
ALL_TAC
] THEN
REWRITE_TAC[
REAL_POW_ADD] THEN
REWRITE_TAC[REAL_ARITH `(n * n) * (((e * e) * x * y) * z) * u = (n * e) * (n * e) * (x * u) * z * y:real`] THEN
SUBGOAL_THEN `~(&(
num_exp 1 min_exp) = &0)` MP_TAC THENL
[
REWRITE_TAC[REAL_OF_NUM_EQ;
NUM_EXP_EQ_0] THEN ARITH_TAC;
ALL_TAC
] THEN
REWRITE_TAC[
num_exp; REAL_MUL_LID; GSYM
REAL_OF_NUM_POW; GSYM REAL_OF_NUM_MUL] THEN
DISCH_THEN (fun
th -> SIMP_TAC[
th;
REAL_MUL_RINV; REAL_MUL_LID]) THEN
FIRST_X_ASSUM (MP_TAC o check(fun
th -> (fst o dest_var o lhand o concl)
th = "f1")) THEN
REWRITE_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_MUL; GSYM
REAL_OF_NUM_POW] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
CONJ_TAC THENL
[
SUBGOAL_THEN `!x y z. &0 < x /\ y <= z * x ==> y * inv x <= z` MP_TAC THENL
[
REPEAT STRIP_TAC THEN
MP_TAC (SPECL [`y * inv x`; `z:real`; `x:real`]
REAL_LE_RMUL_EQ) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th; GSYM REAL_MUL_ASSOC]) THEN
ASM_SIMP_TAC[REAL_ARITH `&0 < x ==> ~(x = &0)`; REAL_MUL_LINV;
REAL_MUL_RID];
ALL_TAC
] THEN
DISCH_THEN (MP_TAC o SPECL[`&(
num_exp 1 (2 * p))`; `&(f1 * f1)`; `&m`]) THEN
REWRITE_TAC[
num_exp; GSYM REAL_OF_NUM_MUL; GSYM
REAL_OF_NUM_POW; REAL_MUL_LID] THEN
DISCH_THEN MATCH_MP_TAC THEN
ASM_REWRITE_TAC[REAL_OF_NUM_MUL;
REAL_OF_NUM_POW; REAL_OF_NUM_LE] THEN
REWRITE_TAC[
REAL_OF_NUM_LT;
EXP_LT_0] THEN
ARITH_TAC;
ALL_TAC
] THEN
MATCH_MP_TAC
REAL_POW_LE THEN
ARITH_TAC;
ALL_TAC
] THEN
MATCH_MP_TAC
REAL_LE_INV THEN
MATCH_MP_TAC
REAL_POW_LE THEN
ARITH_TAC);;
let FLOAT_SQRT_EVEN_hi = prove(`f1 * f1 = f2 /\ x <= f2 /\
num_exp m (2 * p) = x /\ f1 =
num_exp n1 e1
/\
EVEN e /\ e DIV 2 = e2 /\
e1 + e2 + (min_exp DIV 2) = r /\
p <= r /\ r - p = r2
==>
sqrt (
float F m e) <=
float F n1 r2`,
STRIP_TAC THEN
UNDISCH_TAC `x <= f2:num` THEN
UNDISCH_TAC `
num_exp m (2 * p) = x` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
UNDISCH_TAC `f1 * f1 = f2:num` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
UNDISCH_TAC `e1 + e2 + min_exp DIV 2 = r` THEN
UNDISCH_TAC `e DIV 2 = e2` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
REPEAT (POP_ASSUM MP_TAC) THEN
REWRITE_TAC[
num_exp;
float; REAL_MUL_LID; GSYM REAL_OF_NUM_MUL] THEN
REPEAT STRIP_TAC THEN
UNDISCH_TAC `r - p = r2:num` THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
MATCH_MP_TAC
REAL_LE_LSQRT THEN
REPEAT CONJ_TAC THENL
[
REWRITE_TAC[REAL_OF_NUM_MUL;
real_div] THEN
MATCH_MP_TAC
REAL_LE_MUL THEN
REWRITE_TAC[
REAL_POS] THEN
MATCH_MP_TAC
REAL_LE_INV THEN
REWRITE_TAC[
REAL_POS];
REWRITE_TAC[REAL_OF_NUM_MUL;
real_div] THEN
MATCH_MP_TAC
REAL_LE_MUL THEN
REWRITE_TAC[
REAL_POS] THEN
MATCH_MP_TAC
REAL_LE_INV THEN
REWRITE_TAC[
REAL_POS];
ALL_TAC
] THEN
REWRITE_TAC[GSYM
REAL_OF_NUM_POW;
REAL_POW_DIV] THEN
REWRITE_TAC[REAL_POW_2;
real_div;
REAL_INV_MUL] THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
CONJ_TAC THENL
[
REWRITE_TAC[REAL_ARITH `(((a * b) * a) * b) * c = (a * a) * (b * b) * c:real`] THEN
REWRITE_TAC[GSYM
REAL_POW_ADD] THEN
REWRITE_TAC[ARITH_RULE `r - p + r - p = 2 * r - 2 * p`] THEN
MP_TAC (SPECL[mk_comb(amp_op_real, base_const); `2 * r`; `2 * p`]
REAL_DIV_POW2) THEN
ANTS_TAC THENL [ REAL_ARITH_TAC; ALL_TAC ] THEN
ASM_SIMP_TAC[ARITH_RULE `p <= r ==> 2 * p <= 2 * r`] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th;
real_div]) THEN
SUBGOAL_THEN `2 * r = (e1 + e1) + min_exp + e` (fun
th -> REWRITE_TAC[
th]) THENL
[
EXPAND_TAC "r" THEN
REWRITE_TAC[ARITH_RULE `2 * (e1 + b + c) = (e1 + e1) + 2 * c + 2 * b`] THEN
MATCH_MP_TAC (ARITH_RULE `b1 = b2 /\
c1 = c2 ==> a + b1 +
c1 = a + b2 + c2:num`) THEN
SUBGOAL_THEN `
EVEN min_exp` ASSUME_TAC THENL
[
REWRITE_TAC[
min_exp_def] THEN ARITH_TAC;
ALL_TAC
] THEN
ASM_SIMP_TAC[
DIV2_EVEN_lemma];
ALL_TAC
] THEN
REWRITE_TAC[
REAL_POW_ADD] THEN
REWRITE_TAC[REAL_ARITH `(n * n) * (((e * e) * x * y) * z) * u = (n * e) * (n * e) * (x * u) * z * y:real`] THEN
SUBGOAL_THEN `~(&(
num_exp 1 min_exp) = &0)` MP_TAC THENL
[
REWRITE_TAC[REAL_OF_NUM_EQ;
NUM_EXP_EQ_0] THEN ARITH_TAC;
ALL_TAC
] THEN
REWRITE_TAC[
num_exp; REAL_MUL_LID; GSYM
REAL_OF_NUM_POW; GSYM REAL_OF_NUM_MUL] THEN
DISCH_THEN (fun
th -> SIMP_TAC[
th;
REAL_MUL_RINV; REAL_MUL_LID]) THEN
FIRST_X_ASSUM (MP_TAC o check(fun
th -> (fst o dest_var o lhand o concl)
th = "f1")) THEN
REWRITE_TAC[GSYM REAL_OF_NUM_EQ; GSYM REAL_OF_NUM_MUL; GSYM
REAL_OF_NUM_POW] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th]) THEN
REWRITE_TAC[REAL_MUL_ASSOC] THEN
MATCH_MP_TAC
REAL_LE_RMUL THEN
CONJ_TAC THENL
[
SUBGOAL_THEN `!x y z. &0 < x /\ z * x <= y ==> z <= y * inv x` MP_TAC THENL
[
REPEAT STRIP_TAC THEN
MP_TAC (SPECL [`z:real`; `y * inv x`; `x:real`]
REAL_LE_RMUL_EQ) THEN
ASM_REWRITE_TAC[] THEN
DISCH_THEN (fun
th -> REWRITE_TAC[SYM
th; GSYM REAL_MUL_ASSOC]) THEN
ASM_SIMP_TAC[REAL_ARITH `&0 < x ==> ~(x = &0)`; REAL_MUL_LINV;
REAL_MUL_RID];
ALL_TAC
] THEN
DISCH_THEN (MP_TAC o SPECL[`&(
num_exp 1 (2 * p))`; `&(f1 * f1)`; `&m`]) THEN
REWRITE_TAC[
num_exp; GSYM REAL_OF_NUM_MUL; GSYM
REAL_OF_NUM_POW; REAL_MUL_LID] THEN
DISCH_THEN MATCH_MP_TAC THEN
ASM_REWRITE_TAC[REAL_OF_NUM_MUL;
REAL_OF_NUM_POW; REAL_OF_NUM_LE] THEN
REWRITE_TAC[
REAL_OF_NUM_LT;
EXP_LT_0] THEN
ARITH_TAC;
ALL_TAC
] THEN
MATCH_MP_TAC
REAL_POW_LE THEN
ARITH_TAC;
ALL_TAC
] THEN
MATCH_MP_TAC
REAL_LE_INV THEN
MATCH_MP_TAC
REAL_POW_LE THEN
ARITH_TAC);;
let transform = UNDISCH_ALL o
PURE_ONCE_REWRITE_RULE[TAUT `EVEN e <=> (EVEN e <=> T)`] o
NUMERALS_TO_NUM o
CONV_RULE (DEPTH_CONV NUM_DIV_CONV) o
REWRITE_RULE[GSYM IMP_IMP; min_exp_def];;
let FLOAT_SQRT_EVEN_lo' = transform FLOAT_SQRT_EVEN_lo and
FLOAT_SQRT_EVEN_hi' = transform FLOAT_SQRT_EVEN_hi and
FLOAT_PRE_EXP' = (UNDISCH_ALL o
PURE_ONCE_REWRITE_RULE[TAUT `~(e = _0) <=> ((e = _0) <=> F)`] o
REWRITE_RULE[GSYM IMP_IMP; NUMERAL]) FLOAT_PRE_EXP;;
let even_const = `EVEN` and
pre_const = `PRE` and
two_num = rand(mk_small_numeral_array 2) and
min_exp_div2 = rand(mk_small_numeral_array (min_exp / 2)) and
f2_var_num = `f2:num` and
f1_var_num = `f1:num` and
p_var_num = `p:num`;;
(* Returns the list of digits of the given Big_int n in the base b *)
let rec get_big_int_digits b n =
let bb = big_int_of_int b in
if le_big_int n zero_big_int then []
else
let q, r = quomod_big_int n bb in
r :: get_big_int_digits b q;;
(* [1;2;3] -> 123 (base = 10) *)
let rec big_int_from_list b list =
let rec proc acc list =
match list with
[] -> acc
| h::t -> proc (add_big_int h (mult_int_big_int b acc)) t in
proc zero_big_int list;;
(* Returns n first elements of the list *)
let rec take n list =
match list with
x :: xs -> if n > 0 then x :: take (n - 1) xs else []
| [] -> [];;
(* Returns an integer number that contains at most pp "significant" digits
in the given base b *)
let big_int_round_lo base pp n =
let digits = rev (get_big_int_digits base n) in
let n_digits = length digits in
if n_digits <= pp then
n
else
let m = big_int_from_list base (take pp digits) in
mult_big_int (power_int_positive_int base (n_digits - pp)) m;;
let big_int_round_hi base pp n =
let digits = rev (get_big_int_digits base n) in
let n_digits = length digits in
if n_digits <= pp then n
else
let l1, l2 = chop_list pp digits in
if forall (eq_big_int zero_big_int) l2 then n
else
let m = succ_big_int (big_int_from_list base l1) in
mult_big_int (power_int_positive_int base (n_digits - pp)) m;;
(******************)
let rec float_sqrt_lo pp tm =
let s, m_tm, e_tm = dest_float tm in
let p_tm = rand (mk_small_numeral_array pp) in
if s <> "F" then
failwith "float_sqrt_lo: negative argument"
else
let even_th = raw_even_hash_conv (mk_comb (even_const, e_tm)) in
if (fst o dest_const o rand o concl) even_th <> "T" then
(* ODD e *)
let pre_e = raw_pre_hash_conv (mk_comb (pre_const, e_tm)) in
let e_neq_0 = raw_eq0_hash_conv e_tm in
let e1_tm = rand (concl pre_e) in
let th0 = INST[e1_tm, e1_var_num; e_tm, e_var_num; m_tm, m_var_num] FLOAT_PRE_EXP' in
let th1 = MY_PROVE_HYP pre_e (MY_PROVE_HYP e_neq_0 th0) in
let th2 = float_sqrt_lo pp (rand(concl th1)) in
let ltm, rtm = dest_comb (concl th2) in
EQ_MP (SYM (AP_TERM ltm (AP_TERM (rator rtm) th1))) th2
else
(* EVEN e *)
let p2_tm = mk_binop mul_op_num two_num p_tm in
let p2_th = raw_mul_conv_hash p2_tm in
let f1_1 = AP_TERM (mk_comb(num_exp_const, m_tm)) p2_th in
let f1_2 = TRANS f1_1 (denormalize (rand (concl f1_1))) in
let x_tm = rand(concl f1_2) in
let x = raw_dest_hash x_tm in
let f1' = Big_int.sqrt_big_int (big_int_of_num x) in
let f1 = num_of_big_int (big_int_round_lo base pp f1') in
let f1_tm = rand(mk_numeral_array f1) in
let f1_num_exp = to_num_exp f1_tm in
let n1_tm, e1_tm = dest_num_exp (rand (concl f1_num_exp)) in
let f1f1_eq_f2 = raw_mul_conv_hash (mk_binop mul_op_num f1_tm f1_tm) in
let f2_tm = rand(concl f1f1_eq_f2) in
let f2_le_x = EQT_ELIM (raw_le_hash_conv (mk_binop le_op_num f2_tm x_tm)) in
let e_div2_eq_e2 = raw_div_hash_conv (mk_binop div_op_num e_tm two_num) in
let e2_tm = rand(concl e_div2_eq_e2) in
let r_th1 = raw_add_conv_hash (mk_binop plus_op_num e2_tm min_exp_div2) in
let r_th2 = AP_TERM (mk_comb(plus_op_num, e1_tm)) r_th1 in
let r_th = TRANS r_th2 (raw_add_conv_hash (rand (concl r_th2))) in
let r_tm = rand(concl r_th) in
let r_sub_p, p_le_r = raw_sub_and_le_hash_conv p_tm r_tm in
let r2_tm = rand(concl r_sub_p) in
if (rand(concl p_le_r) <> r_tm) then
failwith "float_sqrt_lo: underflow"
else
let th0 = INST[f2_tm, f2_var_num; x_tm, x_var_num; p_tm, p_var_num; r_tm, r_var_num;
f1_tm, f1_var_num; n1_tm, n1_var_num; e1_tm, e1_var_num; e2_tm, e2_var_num;
e_tm, e_var_num; m_tm, m_var_num; r2_tm, r2_var_num]
FLOAT_SQRT_EVEN_lo' in
MY_PROVE_HYP f1_2 (
MY_PROVE_HYP e_div2_eq_e2 (
MY_PROVE_HYP r_sub_p (
MY_PROVE_HYP r_th (
MY_PROVE_HYP f1f1_eq_f2 (
MY_PROVE_HYP f1_num_exp (
MY_PROVE_HYP even_th (
MY_PROVE_HYP f2_le_x (
MY_PROVE_HYP p_le_r th0
))))))));;
let rec float_sqrt_hi pp tm =
let s, m_tm, e_tm = dest_float tm in
let p_tm = rand (mk_small_numeral_array pp) in
if s <> "F" then
failwith "float_sqrt_lo: negative argument"
else
let even_th = raw_even_hash_conv (mk_comb (even_const, e_tm)) in
if (fst o dest_const o rand o concl) even_th <> "T" then
(* ODD e *)
let pre_e = raw_pre_hash_conv (mk_comb (pre_const, e_tm)) in
let e_neq_0 = raw_eq0_hash_conv e_tm in
let e1_tm = rand (concl pre_e) in
let th0 = INST[e1_tm, e1_var_num; e_tm, e_var_num; m_tm, m_var_num] FLOAT_PRE_EXP' in
let th1 = MY_PROVE_HYP pre_e (MY_PROVE_HYP e_neq_0 th0) in
let th2 = float_sqrt_hi pp (rand(concl th1)) in
let ltm, rtm = dest_comb (concl th2) in
let ltm2, rtm2 = dest_comb ltm in
let th3 = AP_THM (AP_TERM ltm2 (AP_TERM (rator rtm2) th1)) rtm in
EQ_MP (SYM th3) th2
else
(* EVEN e *)
let p2_tm = mk_binop mul_op_num two_num p_tm in
let p2_th = raw_mul_conv_hash p2_tm in
let f1_1 = AP_TERM (mk_comb(num_exp_const, m_tm)) p2_th in
let f1_2 = TRANS f1_1 (denormalize (rand (concl f1_1))) in
let x_tm = rand(concl f1_2) in
let x = raw_dest_hash x_tm in
let x' = big_int_of_num x in
let f1' = sqrt_big_int x' in
let f1 = (num_of_big_int o big_int_round_hi base pp)
(if eq_big_int (mult_big_int f1' f1') x' then f1' else succ_big_int f1') in
let f1_tm = rand(mk_numeral_array f1) in
let f1_num_exp = to_num_exp f1_tm in
let n1_tm, e1_tm = dest_num_exp (rand (concl f1_num_exp)) in
let f1f1_eq_f2 = raw_mul_conv_hash (mk_binop mul_op_num f1_tm f1_tm) in
let f2_tm = rand(concl f1f1_eq_f2) in
let x_le_f2 = EQT_ELIM (raw_le_hash_conv (mk_binop le_op_num x_tm f2_tm)) in
let e_div2_eq_e2 = raw_div_hash_conv (mk_binop div_op_num e_tm two_num) in
let e2_tm = rand(concl e_div2_eq_e2) in
let r_th1 = raw_add_conv_hash (mk_binop plus_op_num e2_tm min_exp_div2) in
let r_th2 = AP_TERM (mk_comb(plus_op_num, e1_tm)) r_th1 in
let r_th = TRANS r_th2 (raw_add_conv_hash (rand (concl r_th2))) in
let r_tm = rand(concl r_th) in
let r_sub_p, p_le_r = raw_sub_and_le_hash_conv p_tm r_tm in
let r2_tm = rand(concl r_sub_p) in
if (rand(concl p_le_r) <> r_tm) then
failwith "float_sqrt_lo: underflow"
else
let th0 = INST[f2_tm, f2_var_num; x_tm, x_var_num; p_tm, p_var_num; r_tm, r_var_num;
f1_tm, f1_var_num; n1_tm, n1_var_num; e1_tm, e1_var_num; e2_tm, e2_var_num;
e_tm, e_var_num; m_tm, m_var_num; r2_tm, r2_var_num]
FLOAT_SQRT_EVEN_hi' in
MY_PROVE_HYP f1_2 (
MY_PROVE_HYP e_div2_eq_e2 (
MY_PROVE_HYP r_sub_p (
MY_PROVE_HYP r_th (
MY_PROVE_HYP f1f1_eq_f2 (
MY_PROVE_HYP f1_num_exp (
MY_PROVE_HYP even_th (
MY_PROVE_HYP x_le_f2 (
MY_PROVE_HYP p_le_r th0
))))))));;
(*
float_sqrt_lo 3 `float F (D2 _0) (D0 (D2 _0))`;;
float_sqrt_hi 3 `float F (D2 _0) (D0 (D2 _0))`;;
let tm = `float F (D2 _0) (D0 (D2 _0))`;;
(* 10: 1.092 *)
test 1000 (float_sqrt_lo 5) tm;;
(* 10: 1.128 *)
test 1000 (float_sqrt_hi 5) tm;;
*)
end;; (* Float_ops module *)
(************************************)
(* Cached floating point operations *)
(************************************)
(* Counters for collecting stats *)
let lt0_c = ref 0 and
gt0_c = ref 0 and
lt_c = ref 0 and
le0_c = ref 0 and
ge0_c = ref 0 and
le_c = ref 0 and
min_c = ref 0 and
max_c = ref 0 and
min_max_c = ref 0 and
mul_lo_c = ref 0 and
mul_hi_c = ref 0 and
div_lo_c = ref 0 and
div_hi_c = ref 0 and
add_lo_c = ref 0 and
add_hi_c = ref 0 and
sub_lo_c = ref 0 and
sub_hi_c = ref 0 and
sqrt_lo_c = ref 0 and
sqrt_hi_c = ref 0;;
(*
let mul_lo_list = ref [] and
mul_hi_list = ref [] and
div_lo_list = ref [] and
div_hi_list = ref [] and
add_lo_list = ref [] and
add_hi_list = ref [] and
sub_lo_list = ref [] and
sub_hi_list = ref [];;
*)
(* Hash tables *)
let cache_size = if Arith_options.cached then 10000 else 1;;
let max_cache_size = cache_size * 2;;
let my_add h key v =
if Hashtbl.length h >= max_cache_size then
let _ = Hashtbl.clear h in
print_string "Clearing a float hash table"
else
();
Hashtbl.add h key v;;
let mul_table = Hashtbl.create cache_size and
div_table = Hashtbl.create cache_size and
add_table = Hashtbl.create cache_size and
sub_table = Hashtbl.create cache_size and
sqrt_table = Hashtbl.create cache_size and
le_table = Hashtbl.create cache_size and
max_table = Hashtbl.create cache_size;;
let reset_cache () =
Hashtbl.clear mul_table;
Hashtbl.clear div_table;
Hashtbl.clear add_table;
Hashtbl.clear sub_table;
Hashtbl.clear sqrt_table;
Hashtbl.clear le_table;
Hashtbl.clear max_table;;
let reset_stat () =
lt0_c := 0;
gt0_c := 0;
lt_c := 0;
le0_c := 0;
ge0_c := 0;
le_c := 0;
min_c := 0;
max_c := 0;
min_max_c := 0;
mul_lo_c := 0;
mul_hi_c := 0;
div_lo_c := 0;
div_hi_c := 0;
add_lo_c := 0;
add_hi_c := 0;
sub_lo_c := 0;
sub_hi_c := 0;
sqrt_lo_c := 0;
sqrt_hi_c := 0;;
let print_stat () =
let len = Hashtbl.length in
let cmp_str1 = sprintf "lt0 = %d\ngt0 = %d\nlt = %d\n" !lt0_c !gt0_c !lt_c and
cmp_str2 = sprintf "le0 = %d\nge0 = %d\n" !le0_c !ge0_c and
cmp_str3 = sprintf "min = %d\nmin_max = %d\n" !min_c !min_max_c and
le_str = sprintf "le = %d (le_hash = %d)\n" !le_c (len le_table) and
max_str = sprintf "max = %d (max_hash = %d)\n" !max_c (len max_table) and
mul_str = sprintf "mul_lo = %d, mul_hi = %d (mul_hash = %d)\n" !mul_lo_c !mul_hi_c (len mul_table) and
div_str = sprintf "div_lo = %d, div_hi = %d (div_hash = %d)\n" !div_lo_c !div_hi_c (len div_table) and
add_str = sprintf "add_lo = %d, add_hi = %d (add_hash = %d)\n" !add_lo_c !add_hi_c (len add_table) and
sub_str = sprintf "sub_lo = %d, sub_hi = %d (sub_hash = %d)\n" !sub_lo_c !sub_hi_c (len sub_table) and
sqrt_str = sprintf "sqrt_lo = %d, sqrt_hi = %d (sqrt_hash = %d)\n" !sqrt_lo_c !sqrt_hi_c (len sqrt_table) in
print_string (cmp_str1 ^ cmp_str2 ^ cmp_str3 ^
le_str ^ max_str ^ mul_str ^ div_str ^ add_str ^ sub_str ^ sqrt_str);;
(* lt0 *)
let float_lt0 =
if float_cached then
fun tm ->
let _ = lt0_c := !lt0_c + 1 in
Float_ops.float_lt0 tm
else
Float_ops.float_lt0;;
(* gt0 *)
let float_gt0 =
if float_cached then
fun tm ->
let _ = gt0_c := !gt0_c + 1 in
Float_ops.float_gt0 tm
else
Float_ops.float_gt0;;
(* lt *)
let float_lt =
if float_cached then
fun tm1 tm2 ->
let _ = lt_c := !lt_c + 1 in
Float_ops.float_lt tm1 tm2
else
Float_ops.float_lt;;
(* le0 *)
let float_le0 =
if float_cached then
fun tm ->
let _ = le0_c := !le0_c + 1 in
Float_ops.float_le0 tm
else
Float_ops.float_le0;;
(* ge0 *)
let float_ge0 =
if float_cached then
fun tm ->
let _ = ge0_c := !ge0_c + 1 in
Float_ops.float_ge0 tm
else
Float_ops.float_ge0;;
(* min *)
let float_min =
if float_cached then
fun tm1 tm2 ->
let _ = min_c := !min_c + 1 in
Float_ops.float_min tm1 tm2
else
Float_ops.float_min;;
(* min_max *)
let float_min_max =
if float_cached then
fun tm1 tm2 ->
let _ = min_max_c := !min_max_c + 1 in
Float_ops.float_min_max tm1 tm2
else
Float_ops.float_min_max;;
(***************)
let float_hash tm =
let s, n_tm, e_tm = dest_float tm in
s ^ (Arith_cache.num_tm_hash n_tm) ^ "e" ^ (Arith_cache.num_tm_hash e_tm);;
let float_op_hash pp tm1 tm2 =
string_of_int pp ^ float_hash tm1 ^ "x" ^ float_hash tm2;;
let float_op_hash1 pp tm =
string_of_int pp ^ float_hash tm;;
(* le *)
let float_le =
if float_cached then
fun tm1 tm2 ->
let _ = le_c := !le_c + 1 in
let hash = float_op_hash 0 tm1 tm2 in
try
Hashtbl.find le_table hash
with Not_found ->
let result = Float_ops.float_le tm1 tm2 in
let _ = my_add le_table hash result in
result
else
Float_ops.float_le;;
(* max *)
let float_max =
if float_cached then
fun tm1 tm2 ->
let _ = max_c := !max_c + 1 in
let hash = float_op_hash 0 tm1 tm2 in
try
Hashtbl.find max_table hash
with Not_found ->
let result = Float_ops.float_max tm1 tm2 in
let _ = my_add max_table hash result in
result
else
Float_ops.float_max;;
(* mul_eq *)
let float_mul_eq = Float_ops.float_mul_eq;;
(* mul_lo *)
let float_mul_lo =
if float_cached then
fun pp tm1 tm2 ->
let _ = mul_lo_c := !mul_lo_c + 1 in
(* let _ = mul_lo_list := (pp,tm1,tm2) :: !mul_lo_list in *)
let hash = "lo" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find mul_table hash
with Not_found ->
let result = Float_ops.float_mul_lo pp tm1 tm2 in
let _ = my_add mul_table hash result in
result
else
Float_ops.float_mul_lo;;
(* mul_hi *)
let float_mul_hi =
if float_cached then
fun pp tm1 tm2 ->
let _ = mul_hi_c := !mul_hi_c + 1 in
(* let _ = mul_hi_list := (pp,tm1,tm2) :: !mul_hi_list in *)
let hash = "hi" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find mul_table hash
with Not_found ->
let result = Float_ops.float_mul_hi pp tm1 tm2 in
let _ = my_add mul_table hash result in
result
else
Float_ops.float_mul_hi;;
(* div_lo *)
let float_div_lo =
if float_cached then
fun pp tm1 tm2 ->
let _ = div_lo_c := !div_lo_c + 1 in
(* let _ = div_lo_list := (pp,tm1,tm2) :: !div_lo_list in *)
let hash = "lo" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find div_table hash
with Not_found ->
let result = Float_ops.float_div_lo pp tm1 tm2 in
let _ = my_add div_table hash result in
result
else
Float_ops.float_div_lo;;
(* div_hi *)
let float_div_hi =
if float_cached then
fun pp tm1 tm2 ->
let _ = div_hi_c := !div_hi_c + 1 in
(* let _ = div_hi_list := (pp,tm1,tm2) :: !div_hi_list in *)
let hash = "hi" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find div_table hash
with Not_found ->
let result = Float_ops.float_div_hi pp tm1 tm2 in
let _ = my_add div_table hash result in
result
else
Float_ops.float_div_hi;;
(* add_lo *)
let float_add_lo =
if float_cached then
fun pp tm1 tm2 ->
let _ = add_lo_c := !add_lo_c + 1 in
(* let _ = add_lo_list := (pp,tm1,tm2) :: !add_lo_list in *)
let hash = "lo" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find add_table hash
with Not_found ->
let result = Float_ops.float_add_lo pp tm1 tm2 in
let _ = my_add add_table hash result in
result
else
Float_ops.float_add_lo;;
(* add_hi *)
let float_add_hi =
if float_cached then
fun pp tm1 tm2 ->
let _ = add_hi_c := !add_hi_c + 1 in
(* let _ = add_hi_list := (pp,tm1,tm2) :: !add_hi_list in *)
let hash = "hi" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find add_table hash
with Not_found ->
let result = Float_ops.float_add_hi pp tm1 tm2 in
let _ = my_add add_table hash result in
result
else
Float_ops.float_add_hi;;
(* sub_lo *)
let float_sub_lo =
if float_cached then
fun pp tm1 tm2 ->
let _ = sub_lo_c := !sub_lo_c + 1 in
(* let _ = sub_lo_list := (pp,tm1,tm2) :: !sub_lo_list in *)
let hash = "lo" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find sub_table hash
with Not_found ->
let result = Float_ops.float_sub_lo pp tm1 tm2 in
let _ = my_add sub_table hash result in
result
else
Float_ops.float_sub_lo;;
(* sub_hi *)
let float_sub_hi =
if float_cached then
fun pp tm1 tm2 ->
let _ = sub_hi_c := !sub_hi_c + 1 in
(* let _ = sub_hi_list := (pp,tm1,tm2) :: !sub_hi_list in *)
let hash = "hi" ^ float_op_hash pp tm1 tm2 in
try
Hashtbl.find sub_table hash
with Not_found ->
let result = Float_ops.float_sub_hi pp tm1 tm2 in
let _ = my_add sub_table hash result in
result
else
Float_ops.float_sub_hi;;
(* sqrt_lo *)
let float_sqrt_lo =
if float_cached then
fun pp tm ->
let _ = sqrt_lo_c := !sqrt_lo_c + 1 in
let hash = "lo" ^ float_op_hash1 pp tm in
try
Hashtbl.find sqrt_table hash
with Not_found ->
let result = Float_ops.float_sqrt_lo pp tm in
let _ = my_add sqrt_table hash result in
result
else
Float_ops.float_sqrt_lo;;
(* sqrt_hi *)
let float_sqrt_hi =
if float_cached then
fun pp tm ->
let _ = sqrt_hi_c := !sqrt_hi_c + 1 in
let hash = "hi" ^ float_op_hash1 pp tm in
try
Hashtbl.find sqrt_table hash
with Not_found ->
let result = Float_ops.float_sqrt_hi pp tm in
let _ = my_add sqrt_table hash result in
result
else
Float_ops.float_sqrt_hi;;
(******************************************)
(* float intervals *)
let FLOAT_OF_NUM' = (SPEC_ALL o REWRITE_RULE[min_exp_def]) FLOAT_OF_NUM;;
let FLOAT_INTERVAL_OF_NUM = (NUMERALS_TO_NUM o REWRITE_RULE[min_exp_def] o prove)(`interval_arith (&n) (float F n min_exp, float F n min_exp)`,
REWRITE_TAC[FLOAT_OF_NUM; CONST_INTERVAL]);;
let FLOAT_F_bound' = (UNDISCH_ALL o SPEC_ALL) FLOAT_F_bound;;
let FLOAT_T_bound' = (UNDISCH_ALL o SPEC_ALL) FLOAT_T_bound;;
(* interval_arith x (float s1 n1 e1, float s2 n2 e2) -> x, float s1 n1 e1, float s2 n2 e2 *)
let dest_float_interval tm =
let ltm, rtm = dest_comb tm in
let f1, f2 = dest_pair rtm in
rand ltm, f1, f2;;
let mk_float_interval_small_num n =
let n_tm0 = mk_small_numeral n in
let n_th = NUMERAL_TO_NUM_CONV n_tm0 in
let n_tm = rand(rand(concl n_th)) in
let n_th1 = TRANS n_th (INST[n_tm, n_var_num] NUM_REMOVE) in
let th1 = AP_TERM amp_op_real n_th1 in
let int_th = INST[n_tm, n_var_num] FLOAT_INTERVAL_OF_NUM in
let rtm = rand(concl int_th) in
EQ_MP (SYM (AP_THM (AP_TERM interval_const th1) rtm)) int_th;;
let mk_float_interval_num n =
let n_tm0 = mk_numeral n in
let n_th = NUMERAL_TO_NUM_CONV n_tm0 in
let n_tm = rand(rand(concl n_th)) in
let n_th1 = TRANS n_th (INST[n_tm, n_var_num] NUM_REMOVE) in
let th1 = AP_TERM amp_op_real n_th1 in
let int_th = INST[n_tm, n_var_num] FLOAT_INTERVAL_OF_NUM in
let rtm = rand(concl int_th) in
EQ_MP (SYM (AP_THM (AP_TERM interval_const th1) rtm)) int_th;;
(* Returns the lower bound for the given float *)
let float_lo p tm =
let s, n_tm, e_tm = dest_float tm in
if s = "F" then
let num_exp_tm = mk_num_exp n_tm e_tm in
let th0 = num_exp_lo p num_exp_tm in
let ltm, e1_tm = dest_comb(lhand(concl th0)) in
let n1_tm = rand ltm in
let th1 = INST[n1_tm, n1_var_num; e1_tm, e1_var_num; n_tm, n2_var_num; e_tm, e2_var_num] FLOAT_F_bound' in
MY_PROVE_HYP th0 th1
else
let num_exp_tm = mk_num_exp n_tm e_tm in
let th0 = num_exp_hi p num_exp_tm in
let ltm, e1_tm = dest_comb(rand(concl th0)) in
let n1_tm = rand ltm in
let th1 = INST[n_tm, n1_var_num; e_tm, e1_var_num; n1_tm, n2_var_num; e1_tm, e2_var_num] FLOAT_T_bound' in
MY_PROVE_HYP th0 th1;;
(* Returns the upper bound for the given float *)
let float_hi p tm =
let s, n_tm, e_tm = dest_float tm in
if s = "F" then
let num_exp_tm = mk_num_exp n_tm e_tm in
let th0 = num_exp_hi p num_exp_tm in
let ltm, e2_tm = dest_comb(rand(concl th0)) in
let n2_tm = rand ltm in
let th1 = INST[n_tm, n1_var_num; e_tm, e1_var_num; n2_tm, n2_var_num; e2_tm, e2_var_num] FLOAT_F_bound' in
MY_PROVE_HYP th0 th1
else
let num_exp_tm = mk_num_exp n_tm e_tm in
let th0 = num_exp_lo p num_exp_tm in
let ltm, e1_tm = dest_comb(lhand(concl th0)) in
let n1_tm = rand ltm in
let th1 = INST[n1_tm, n1_var_num; e1_tm, e1_var_num; n_tm, n2_var_num; e_tm, e2_var_num] FLOAT_T_bound' in
MY_PROVE_HYP th0 th1;;
(* Approximates the given interval with p-digit float numbers *)
let float_interval_round p th =
let x_tm, f1, f2 = dest_float_interval (concl th) in
let lo_th = float_lo p f1 in
let hi_th = float_hi p f2 in
let lo_tm = lhand(concl lo_th) in
let hi_tm = rand(concl hi_th) in
let th0 = INST[x_tm, x_var_real; f1, lo_var_real; f2, hi_var_real; lo_tm, a_var_real; hi_tm, b_var_real] APPROX_INTERVAL' in
MY_PROVE_HYP lo_th (MY_PROVE_HYP hi_th (MY_PROVE_HYP th th0));;
(*
let th = mk_float_interval_num 124235353;;
float_interval_round 5 th;;
(* 4: 0.240 *)
test 1000 (float_interval_round 5) th;;
*)
(****************************************)
(* float_interval_lt *)
(****************************************)
(* float_interval_neg *)
let FLOAT_INTERVAL_NEG_FF = (UNDISCH_ALL o REWRITE_RULE[] o SPECL[`F`; `F`]) FLOAT_INTERVAL_NEG;;
let FLOAT_INTERVAL_NEG_FT = (UNDISCH_ALL o REWRITE_RULE[] o SPECL[`F`; `T`]) FLOAT_INTERVAL_NEG;;
let FLOAT_INTERVAL_NEG_TF = (UNDISCH_ALL o REWRITE_RULE[] o SPECL[`T`; `F`]) FLOAT_INTERVAL_NEG;;
let FLOAT_INTERVAL_NEG_TT = (UNDISCH_ALL o REWRITE_RULE[] o SPECL[`T`; `T`]) FLOAT_INTERVAL_NEG;;
(* |- interval x (float s1 n1 e1, float s2 n2 e2) ->
|- interval (--x) (float ~s2 n2 e2, float ~s1 n1 e1 *)
let float_interval_neg th =
let x_tm, f1, f2 = dest_float_interval (concl th) in
let s1, n1_tm, e1_tm = dest_float f1 in
let s2, n2_tm, e2_tm = dest_float f2 in
let inst = INST[x_tm, x_var_real; n1_tm, n1_var_num; e1_tm, e1_var_num;
n2_tm, n2_var_num; e2_tm, e2_var_num] in
let th0 =
if s1 = "F" then
if s2 = "F" then
inst FLOAT_INTERVAL_NEG_FF
else
inst FLOAT_INTERVAL_NEG_FT
else
if s2 = "F" then
inst FLOAT_INTERVAL_NEG_TF
else
inst FLOAT_INTERVAL_NEG_TT in
MY_PROVE_HYP th th0;;
(***********************************************)
(* float_interval_mul *)
let f1_var_real = `f1:real` and
f2_var_real = `f2:real` and
f1_1_var = `f1_1:real` and
f1_2_var = `f1_2:real` and
f2_1_var = `f2_1:real` and
f2_2_var = `f2_2:real`;;
(* FF_FF *)
let FLOAT_INTERVAL_MUL_FF_FF = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float F n1 e1, float F n2 e2) /\
interval_arith y (float F m1 r1, float F m2 r2) /\
f1 <= float F n1 e1 * float F m1 r1 /\
float F n2 e2 * float F m2 r2 <= f2
==> interval_arith (x * y) (f1, f2)`,
MAP_EVERY ABBREV_TAC [`a = float F n1 e1`; `b = float F n2 e2`; `c = float F m1 r1`; `d = float F m2 r2`] THEN
SUBGOAL_THEN `&0 <= a /\ &0 <= b /\ &0 <= c /\ &0 <= d` MP_TAC THENL
[
MAP_EVERY EXPAND_TAC ["a"; "b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
REPEAT (POP_ASSUM (fun th -> ALL_TAC)) THEN
REWRITE_TAC[interval_arith] THEN
REPEAT STRIP_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `a * c:real` THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ASM_REWRITE_TAC[];
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `b * d:real` THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ASM_REWRITE_TAC[] THEN
CONJ_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THENL
[
EXISTS_TAC `a:real` THEN ASM_REWRITE_TAC[];
EXISTS_TAC `c:real` THEN ASM_REWRITE_TAC[]
]
]);;
(* TT_TT *)
let FLOAT_INTERVAL_MUL_TT_TT = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float T n1 e1, float T n2 e2) /\
interval_arith y (float T m1 r1, float T m2 r2) /\
f1 <= float T n2 e2 * float T m2 r2 /\
float T n1 e1 * float T m1 r1 <= f2
==> interval_arith (x * y) (f1, f2)`,
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[interval_arith] THEN
MAP_EVERY ABBREV_TAC [`a = float F n1 e1`; `b = float F n2 e2`; `c = float F m1 r1`; `d = float F m2 r2`] THEN
SUBGOAL_THEN `&0 <= a /\ &0 <= b /\ &0 <= c /\ &0 <= d` MP_TAC THENL
[
MAP_EVERY EXPAND_TAC ["a"; "b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
REWRITE_TAC[REAL_NEG_MUL2] THEN
REPEAT STRIP_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `b * d:real` THEN
ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[REAL_ARITH `a <= x * y <=> a <= --x * --y`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ONCE_REWRITE_TAC[REAL_ARITH `b <= --x <=> x <= --b`] THEN
ASM_REWRITE_TAC[];
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `a * c:real` THEN
ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[REAL_ARITH `x * y <= a <=> --x * --y <= a`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ONCE_REWRITE_TAC[REAL_ARITH `--x <= c <=> --c <= x`] THEN
ASM_REWRITE_TAC[] THEN
ASSUME_TAC (REAL_ARITH `!b x. &0 <= b /\ x <= --b ==> &0 <= --x`) THEN
CONJ_TAC THEN FIRST_X_ASSUM MATCH_MP_TAC THENL
[
EXISTS_TAC `b:real` THEN ASM_REWRITE_TAC[];
EXISTS_TAC `d:real` THEN ASM_REWRITE_TAC[]
]
]);;
(* FF_TT *)
let FLOAT_INTERVAL_MUL_FF_TT = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float F n1 e1, float F n2 e2) /\
interval_arith y (float T m1 r1, float T m2 r2) /\
f1 <= float F n2 e2 * float T m1 r1 /\
float F n1 e1 * float T m2 r2 <= f2
==> interval_arith (x * y) (f1, f2)`,
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[interval_arith] THEN
MAP_EVERY ABBREV_TAC [`a = float F n1 e1`; `b = float F n2 e2`; `c = float F m1 r1`; `d = float F m2 r2`] THEN
SUBGOAL_THEN `&0 <= a /\ &0 <= b /\ &0 <= c /\ &0 <= d` MP_TAC THENL
[
MAP_EVERY EXPAND_TAC ["a"; "b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
REPEAT STRIP_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `b * --c` THEN
ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[REAL_ARITH `b * --c <= x * y <=> x * --y <= b * c`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ONCE_REWRITE_TAC[REAL_ARITH `--y <= c <=> --c <= y`] THEN
ASM_REWRITE_TAC[] THEN
CONJ_TAC THEN MATCH_MP_TAC REAL_LE_TRANS THENL
[
EXISTS_TAC `a:real` THEN ASM_REWRITE_TAC[];
EXISTS_TAC `d:real` THEN
ONCE_REWRITE_TAC[REAL_ARITH `d <= --y <=> y <= --d`] THEN
ASM_REWRITE_TAC[]
];
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `a * --d` THEN
ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[REAL_ARITH `x * y <= a * --d <=> a * d <= x * --y`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ONCE_REWRITE_TAC[REAL_ARITH `d <= --y <=> y <= --d`] THEN
ASM_REWRITE_TAC[]
]);;
(* TT_FF *)
let FLOAT_INTERVAL_MUL_TT_FF = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float T n1 e1, float T n2 e2) /\
interval_arith y (float F m1 r1, float F m2 r2) /\
f1 <= float T n1 e1 * float F m2 r2 /\
float T n2 e2 * float F m1 r1 <= f2
==> interval_arith (x * y) (f1, f2)`,
STRIP_TAC THEN
MP_TAC ((GEN_ALL o DISCH_ALL) FLOAT_INTERVAL_MUL_FF_TT) THEN
DISCH_THEN (MP_TAC o SPECL[`n1:num`; `e1:num`; `n2:num`; `e2:num`; `m1:num`; `r1:num`; `m2:num`; `r2:num`]) THEN
DISCH_THEN (MP_TAC o SPECL[`y:real`; `x:real`; `f1:real`; `f2:real`]) THEN
REPEAT (POP_ASSUM MP_TAC) THEN
SIMP_TAC[REAL_MUL_AC]);;
(* TF_FF *)
let FLOAT_INTERVAL_MUL_TF_FF = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float T n1 e1, float F n2 e2) /\
interval_arith y (float F m1 r1, float F m2 r2) /\
f1 <= float T n1 e1 * float F m2 r2 /\
float F n2 e2 * float F m2 r2 <= f2
==> interval_arith (x * y) (f1, f2)`,
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[interval_arith] THEN
MAP_EVERY ABBREV_TAC [`a = float F n1 e1`; `b = float F n2 e2`; `c = float F m1 r1`; `d = float F m2 r2`] THEN
STRIP_TAC THEN
SUBGOAL_THEN `&0 <= a /\ &0 <= b /\ &0 <= c /\ &0 <= d` ASSUME_TAC THENL
[
MAP_EVERY EXPAND_TAC ["a"; "b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
SUBGOAL_THEN `&0 <= y` ASSUME_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `c:real` THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
CONJ_TAC THENL
[
DISJ_CASES_TAC (REAL_ARITH `&0 <= x \/ &0 <= --x`) THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * d` THEN
ASM_REWRITE_TAC[REAL_ARITH `--a * d <= &0 <=> &0 <= a * d`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[]
];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * d` THEN ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[REAL_ARITH `--a * d <= x * y <=> --x * y <= a * d`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ONCE_REWRITE_TAC[REAL_ARITH `--x <= a <=> --a <= x`] THEN ASM_REWRITE_TAC[];
DISJ_CASES_TAC (REAL_ARITH `&0 <= --x \/ &0 <= x`) THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
REWRITE_TAC[REAL_ARITH `x * y <= &0 <=> &0 <= --x * y`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * d` THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[]
];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * d` THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_REWRITE_TAC[]
]);;
(* TF_TT *)
let FLOAT_INTERVAL_MUL_TF_TT = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float T n1 e1, float F n2 e2) /\
interval_arith y (float T m1 r1, float T m2 r2) /\
f1 <= float F n2 e2 * float T m1 r1 /\
float T n1 e1 * float T m1 r1 <= f2
==> interval_arith (x * y) (f1, f2)`,
REWRITE_TAC[FLOAT_NEG_T] THEN
REWRITE_TAC[interval_arith] THEN
MAP_EVERY ABBREV_TAC [`a = float F n1 e1`; `b = float F n2 e2`; `c = float F m1 r1`; `d = float F m2 r2`] THEN
STRIP_TAC THEN
SUBGOAL_THEN `&0 <= a /\ &0 <= b /\ &0 <= c /\ &0 <= d` ASSUME_TAC THENL
[
MAP_EVERY EXPAND_TAC ["a"; "b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
SUBGOAL_THEN `&0 <= --y` ASSUME_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `d:real` THEN
ONCE_REWRITE_TAC[REAL_ARITH `d <= --y <=> y <= --d`] THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
CONJ_TAC THENL
[
DISJ_CASES_TAC (REAL_ARITH `&0 <= --x \/ &0 <= x`) THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * --c` THEN
ASM_REWRITE_TAC[REAL_ARITH `b * --c <= &0 <=> &0 <= b * c`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ONCE_REWRITE_TAC[REAL_ARITH `x * y = --x * --y`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[]
];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * --c` THEN ASM_REWRITE_TAC[] THEN
ONCE_REWRITE_TAC[REAL_ARITH `b * --c <= x * y <=> x * --y <= b * c`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN ONCE_REWRITE_TAC[REAL_ARITH `--y <= c <=> --c <= y`] THEN
ASM_REWRITE_TAC[];
DISJ_CASES_TAC (REAL_ARITH `&0 <= x \/ &0 <= --x`) THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
REWRITE_TAC[REAL_ARITH `x * y <= &0 <=> &0 <= x * --y`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * --c` THEN ASM_REWRITE_TAC[REAL_NEG_MUL2] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[]
];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * --c` THEN ASM_REWRITE_TAC[REAL_NEG_MUL2] THEN
ONCE_REWRITE_TAC[REAL_ARITH `x * y <= a * c <=> --x * --y <= a * c`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN ONCE_REWRITE_TAC[REAL_ARITH `--x <= a <=> --a <= x`] THEN
ASM_REWRITE_TAC[]
]);;
(* FF_TF *)
let FLOAT_INTERVAL_MUL_FF_TF = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float F n1 e1, float F n2 e2) /\
interval_arith y (float T m1 r1, float F m2 r2) /\
f1 <= float F n2 e2 * float T m1 r1 /\
float F n2 e2 * float F m2 r2 <= f2
==> interval_arith (x * y) (f1, f2)`,
STRIP_TAC THEN
MP_TAC ((SPECL [`n1:num`; `e1:num`; `n2:num`; `e2:num`; `m1:num`; `r1:num`; `m2:num`; `r2:num`; `y:real`; `x:real`; `f1:real`; `f2:real`] o GEN_ALL o DISCH_ALL) FLOAT_INTERVAL_MUL_TF_FF) THEN
ASM_REWRITE_TAC[REAL_MUL_SYM] THEN DISCH_THEN MATCH_MP_TAC THEN
POP_ASSUM MP_TAC THEN REAL_ARITH_TAC);;
(* TT_TF *)
let FLOAT_INTERVAL_MUL_TT_TF = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float T n1 e1, float T n2 e2) /\
interval_arith y (float T m1 r1, float F m2 r2) /\
f1 <= float T n1 e1 * float F m2 r2 /\
float T n1 e1 * float T m1 r1 <= f2
==> interval_arith (x * y) (f1, f2)`,
STRIP_TAC THEN
MP_TAC ((SPECL [`n1:num`; `e1:num`; `n2:num`; `e2:num`; `m1:num`; `r1:num`; `m2:num`; `r2:num`; `y:real`; `x:real`; `f1:real`; `f2:real`] o GEN_ALL o DISCH_ALL) FLOAT_INTERVAL_MUL_TF_TT) THEN
ASM_REWRITE_TAC[REAL_MUL_SYM] THEN POP_ASSUM MP_TAC THEN POP_ASSUM MP_TAC THEN
SIMP_TAC[REAL_MUL_SYM]);;
(* TF_TF *)
let FLOAT_INTERVAL_MUL_TF_TF = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (float T n1 e1, float F n2 e2) /\
interval_arith y (float T m1 r1, float F m2 r2) /\
f1_1 <= float T n1 e1 * float F m2 r2 /\
f1_2 <= float F n2 e2 * float T m1 r1 /\
min f1_1 f1_2 = f1 /\
float T n1 e1 * float T m1 r1 <= f2_1 /\
float F n2 e2 * float F m2 r2 <= f2_2 /\
max f2_1 f2_2 = f2
==> interval_arith (x * y) (f1, f2)`,
REWRITE_TAC[EQ_SYM_EQ; FLOAT_NEG_T] THEN
REWRITE_TAC[interval_arith] THEN
MAP_EVERY ABBREV_TAC [`a = float F n1 e1`; `b = float F n2 e2`; `c = float F m1 r1`; `d = float F m2 r2`] THEN
STRIP_TAC THEN
SUBGOAL_THEN `&0 <= a /\ &0 <= b /\ &0 <= c /\ &0 <= d` ASSUME_TAC THENL
[
MAP_EVERY EXPAND_TAC ["a"; "b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
DISJ_CASES_TAC (REAL_ARITH `&0 <= x \/ &0 <= --x`) THENL
[
DISJ_CASES_TAC (REAL_ARITH `&0 <= y \/ &0 <= --y`) THENL
[
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f1_1:real` THEN
ASM_REWRITE_TAC[REAL_MIN_MIN] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * d` THEN
ASM_REWRITE_TAC[REAL_ARITH `--a * d <= &0 <=> &0 <= a * d`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * d` THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_MUL2 THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f2_2:real` THEN
ASM_REWRITE_TAC[REAL_MAX_MAX];
ALL_TAC
] THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f1_2:real` THEN
ASM_REWRITE_TAC[REAL_MIN_MIN] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * --c` THEN
ONCE_REWRITE_TAC[REAL_ARITH `b * --c <= x * y <=> x * --y <= b * c`] THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN ONCE_REWRITE_TAC[REAL_ARITH `--y <= c <=> --c <= y`] THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
REWRITE_TAC[REAL_ARITH `x * y <= &0 <=> &0 <= x * --y`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f2_2:real` THEN
ASM_REWRITE_TAC[REAL_MAX_MAX] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * d` THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
DISJ_CASES_TAC (REAL_ARITH `&0 <= y \/ &0 <= --y`) THENL
[
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f1_1:real` THEN
ASM_REWRITE_TAC[REAL_MIN_MIN] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * d` THEN
ASM_REWRITE_TAC[] THEN ONCE_REWRITE_TAC[REAL_ARITH `--a * d <= x * y <=> --x * y <= a * d`] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN ONCE_REWRITE_TAC[REAL_ARITH `--x <= a <=> --a <= x`] THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
REWRITE_TAC[REAL_ARITH `x * y <= &0 <=> &0 <= --x * y`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f2_2:real` THEN
ASM_REWRITE_TAC[REAL_MAX_MAX] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b * d` THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f1_1:real` THEN
ASM_REWRITE_TAC[REAL_MIN_MIN] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * d` THEN
ASM_REWRITE_TAC[REAL_ARITH `--a * d <= &0 <=> &0 <= a * d`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
ONCE_REWRITE_TAC[GSYM REAL_NEG_MUL2] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a * --c` THEN
CONJ_TAC THENL
[
ONCE_REWRITE_TAC[GSYM REAL_NEG_MUL2] THEN REWRITE_TAC[REAL_NEG_NEG] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN ONCE_REWRITE_TAC[REAL_ARITH `--x <= a <=> --a <= x`] THEN
ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `f2_1:real` THEN
ASM_REWRITE_TAC[REAL_MAX_MAX]);;
(****************************)
let float_interval_mul pp th1 th2 =
let x, l_lo, l_hi = dest_float_interval (concl th1) and
y, r_lo, r_hi = dest_float_interval (concl th2) in
let s1, n1, e1 = dest_float l_lo and
s2, n2, e2 = dest_float l_hi and
s3, m1, r1 = dest_float r_lo and
s4, m2, r2 = dest_float r_hi in
(* Special case *)
if s1 <> s2 && s3 <> s4 then
if s1 = "F" or s3 = "F" then
failwith ("float_interval_mul: FT interval: "^
(string_of_term (concl th1))^"; "^(string_of_term (concl th2)))
else
let lo1, lo2 = float_mul_lo pp l_lo r_hi, float_mul_lo pp l_hi r_lo and
hi1, hi2 = float_mul_hi pp l_lo r_lo, float_mul_hi pp l_hi r_hi in
let f1_1 = (lhand o concl) lo1 and
f1_2 = (lhand o concl) lo2 and
f2_1 = (rand o concl) hi1 and
f2_2 = (rand o concl) hi2 in
let min_th = float_min f1_1 f1_2 and
max_th = float_max f2_1 f2_2 in
let f1_tm = (rand o concl) min_th and
f2_tm = (rand o concl) max_th in
let th0 = INST[x, x_var_real; n1, n1_var_num; e1, e1_var_num;
y, y_var_real; n2, n2_var_num; e2, e2_var_num;
m1, m1_var_num; r1, r1_var_num;
m2, m2_var_num; r2, r2_var_num;
f1_tm, f1_var_real; f2_tm, f2_var_real;
f1_1, f1_1_var; f1_2, f1_2_var;
f2_1, f2_1_var; f2_2, f2_2_var] FLOAT_INTERVAL_MUL_TF_TF in
(MY_PROVE_HYP min_th o MY_PROVE_HYP max_th o MY_PROVE_HYP lo1 o MY_PROVE_HYP lo2 o
MY_PROVE_HYP hi1 o MY_PROVE_HYP hi2 o MY_PROVE_HYP th1 o MY_PROVE_HYP th2) th0
else
let lo_th, hi_th, th0 =
if s1 <> s2 then
if s1 = "F" then
failwith ("float_interval_mul: FT interval: "^
(string_of_term (concl th1))^"; "^(string_of_term (concl th2)))
else
if s3 = "F" then
float_mul_lo pp l_lo r_hi, float_mul_hi pp l_hi r_hi, FLOAT_INTERVAL_MUL_TF_FF
else
float_mul_lo pp l_hi r_lo, float_mul_hi pp l_lo r_lo, FLOAT_INTERVAL_MUL_TF_TT
else
if s3 <> s4 then
if s3 = "F" then
failwith ("float_interval_mul: FT interval: "^
(string_of_term (concl th1))^"; "^(string_of_term (concl th2)))
else
if s1 = "F" then
float_mul_lo pp l_hi r_lo, float_mul_hi pp l_hi r_hi, FLOAT_INTERVAL_MUL_FF_TF
else
float_mul_lo pp l_lo r_hi, float_mul_hi pp l_lo r_lo, FLOAT_INTERVAL_MUL_TT_TF
else
if s1 = "F" then
if s3 = "F" then
float_mul_lo pp l_lo r_lo, float_mul_hi pp l_hi r_hi, FLOAT_INTERVAL_MUL_FF_FF
else
float_mul_lo pp l_hi r_lo, float_mul_hi pp l_lo r_hi, FLOAT_INTERVAL_MUL_FF_TT
else
if s3 = "F" then
float_mul_lo pp l_lo r_hi, float_mul_hi pp l_hi r_lo, FLOAT_INTERVAL_MUL_TT_FF
else
float_mul_lo pp l_hi r_hi, float_mul_hi pp l_lo r_lo, FLOAT_INTERVAL_MUL_TT_TT in
let f1_tm = lhand(concl lo_th) and
f2_tm = rand(concl hi_th) in
let th = INST[x, x_var_real; n1, n1_var_num; e1, e1_var_num;
y, y_var_real; n2, n2_var_num; e2, e2_var_num;
m1, m1_var_num; r1, r1_var_num;
m2, m2_var_num; r2, r2_var_num;
f1_tm, f1_var_real; f2_tm, f2_var_real] th0 in
MY_PROVE_HYP lo_th (MY_PROVE_HYP hi_th (MY_PROVE_HYP th1 (MY_PROVE_HYP th2 th)));;
let float_interval_mul_old pp th1 th2 =
let x, l_lo, l_hi = dest_float_interval (concl th1) and
y, r_lo, r_hi = dest_float_interval (concl th2) in
let s1, n1, e1 = dest_float l_lo and
s2, n2, e2 = dest_float l_hi and
s3, m1, r1 = dest_float r_lo and
s4, m2, r2 = dest_float r_hi in
(* Special case *)
if s1 <> s2 or s3 <> s4 then
failwith "float_interval_mul: not implemented"
else
let lo_th, hi_th, th0 =
if s1 = "F" then
if s3 = "F" then
float_mul_lo pp l_lo r_lo, float_mul_hi pp l_hi r_hi, FLOAT_INTERVAL_MUL_FF_FF
else
float_mul_lo pp l_hi r_lo, float_mul_hi pp l_lo r_hi, FLOAT_INTERVAL_MUL_FF_TT
else
if s3 = "F" then
float_mul_lo pp l_lo r_hi, float_mul_hi pp l_hi r_lo, FLOAT_INTERVAL_MUL_TT_FF
else
float_mul_lo pp l_hi r_hi, float_mul_hi pp l_lo r_lo, FLOAT_INTERVAL_MUL_TT_TT in
let f1_tm = lhand(concl lo_th) and
f2_tm = rand(concl hi_th) in
let th = INST[x, x_var_real; n1, n1_var_num; e1, e1_var_num;
y, y_var_real; n2, n2_var_num; e2, e2_var_num;
m1, m1_var_num; r1, r1_var_num;
m2, m2_var_num; r2, r2_var_num;
f1_tm, f1_var_real; f2_tm, f2_var_real] th0 in
MY_PROVE_HYP lo_th (MY_PROVE_HYP hi_th (MY_PROVE_HYP th1 (MY_PROVE_HYP th2 th)));;
(*
let th1 = mk_float_interval_small_num 135;;
let th2 = mk_float_interval_small_num 34;;
let th1' = float_interval_neg th1;;
let th2' = float_interval_neg th2;;
float_interval_mul_old 2 th1 th2;;
float_interval_mul_old 2 th1 th2';;
float_interval_mul_old 2 th1' th2;;
float_interval_mul_old 2 th1' th2';;
float_interval_mul 2 th1 th2;;
float_interval_mul 2 th1 th2';;
float_interval_mul 2 th1' th2;;
float_interval_mul 2 th1' th2';;
let th3 = (NUMERALS_TO_NUM o REWRITE_RULE[FLOAT_OF_NUM; min_exp_def; GSYM FLOAT_NEG_T] o prove)
(`interval_arith (&0) (-- &5, &10)`, REWRITE_TAC[interval_arith] THEN REAL_ARITH_TAC);;
let th4 = (NUMERALS_TO_NUM o REWRITE_RULE[FLOAT_OF_NUM; min_exp_def; GSYM FLOAT_NEG_T] o prove)
(`interval_arith (&0) (-- &10, &5)`, REWRITE_TAC[interval_arith] THEN REAL_ARITH_TAC);;
float_interval_mul_old 2 th3 th1;;
float_interval_mul 2 th3 th1;;
float_interval_mul 2 th1 th3;;
float_interval_mul 2 th3 th1';;
float_interval_mul 2 th1' th3;;
float_interval_mul 2 th3 th3;;
float_interval_mul 2 th3 th4;;
(* 10: 0.708 *)
test 1000 (float_interval_mul_old 2 th1) th2;;
(* 10: 0.712 *)
test 1000 (float_interval_mul 2 th1) th2;;
(* 10: 0.504 *)
test 1000 (float_interval_mul 2 th3) th2;;
(* 10: 1.096 *)
test 1000 (float_interval_mul 2 th3) th4;;
let th1 = mk_float_interval_small_num 123456781;;
let th2 = mk_float_interval_small_num 514553443;;
(* 4: 0.340 *)
test 100 (float_interval_mul_old 5 th1) th2;;
(* 4: 0.368 *)
test 100 (float_interval_mul_old 1 th1) th2;;
let tm1 = mk_small_numeral_array 123456781;;
let tm2 = mk_small_numeral_array 514553443;;
let tm = mk_binop mul_op_num tm1 tm2;;
(* 4: 0.148 *)
test 100 NUM_MULT_HASH_CONV tm;;
let th1' = float_interval_round 5 th1;;
let th2' = float_interval_round 5 th2;;
(* 4: 0.176 *)
test 100 (float_interval_mul_old 5 th1') th2';;
*)
(*************************************)
(* float_interval_div *)
(* FF_FF *)
"b"; "c"; "d"] THEN
REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
SUBGOAL_THEN `~(c = &0)` ASSUME_TAC THENL
[
EXPAND_TAC "c" THEN ASM_REWRITE_TAC[FLOAT_EQ_0];
ALL_TAC
] THEN
STRIP_TAC THEN
SUBGOAL_THEN `~(d = &0)` MP_TAC THENL
[
MATCH_MP_TAC (REAL_ARITH `~(c = &0) /\ &0 <= c /\ c <= d ==> ~(d = &0)`) THEN
ASM_REWRITE_TAC[] THEN
UNDISCH_TAC `interval_arith y (c,d)` THEN
REWRITE_TAC[interval_arith] THEN
REAL_ARITH_TAC;
ALL_TAC
] THEN
REPLICATE_TAC 10 (POP_ASSUM MP_TAC) THEN
REPEAT (POP_ASSUM (fun th -> ALL_TAC)) THEN
REWRITE_TAC[interval_arith] THEN
REPEAT STRIP_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `a * inv d` THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ASM_REWRITE_TAC[REAL_LE_INV_EQ] THEN
MATCH_MP_TAC REAL_LE_INV2 THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LTE_TRANS THEN
EXISTS_TAC `c:real` THEN
ASM_REWRITE_TAC[REAL_ARITH `&0 < c <=> ~(c = &0) /\ &0 <= c`];
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `b * inv c` THEN
ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_MUL2 THEN
ASM_REWRITE_TAC[REAL_LE_INV_EQ] THEN
REPEAT CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `a:real` THEN ASM_REWRITE_TAC[];
MATCH_MP_TAC REAL_LE_TRANS THEN
EXISTS_TAC `c:real` THEN ASM_REWRITE_TAC[];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_INV2 THEN
ASM_REWRITE_TAC[REAL_ARITH `&0 < c <=> ~(c = &0) /\ &0 <= c`]
]);;
(* TT_TT *)
(* FF_TT *)
(* TT_FF *)
(* TF_FF *)
"b"; "c"; "d"] THEN REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
DISJ_CASES_TAC (REAL_ARITH `&0 <= x \/ x <= &0`) THENL
[
SUBGOAL_THEN `interval_arith x (float F 0 0, b)` ASSUME_TAC THENL
[
UNDISCH_TAC `interval_arith x (--a, b)` THEN POP_ASSUM MP_TAC THEN
REWRITE_TAC[interval_arith; FLOAT_0] THEN REAL_ARITH_TAC;
ALL_TAC
] THEN
MP_TAC ((SPEC_ALL o SPECL [`0`; `0`] o GEN_ALL) FLOAT_INTERVAL_DIV_FF_FF) THEN
ASM_REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
REWRITE_TAC[real_div] THEN CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a / c` THEN
ASM_REWRITE_TAC[real_div; ARITH_RULE `--a * b <= &0 <=> &0 <= a * b`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[REAL_LE_INV_EQ];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[REAL_LE_INV_EQ; FLOAT_F_POS];
ALL_TAC
] THEN
SUBGOAL_THEN `interval_arith x (--a, float T 0 0)` ASSUME_TAC THENL
[
UNDISCH_TAC `interval_arith x (--a, b)` THEN POP_ASSUM MP_TAC THEN
REWRITE_TAC[interval_arith; FLOAT_0] THEN REAL_ARITH_TAC;
ALL_TAC
] THEN
MP_TAC ((INST[`0`, `n2:num`; `0`, `e2:num`]) FLOAT_INTERVAL_DIV_TT_FF) THEN
ASM_REWRITE_TAC[FLOAT_NEG_T] THEN DISCH_THEN MATCH_MP_TAC THEN
ASM_REWRITE_TAC[GSYM FLOAT_NEG_T] THEN MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
REWRITE_TAC[real_div] THEN CONJ_TAC THENL
[
REWRITE_TAC[FLOAT_0; REAL_MUL_LZERO; REAL_LE_REFL];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b / c` THEN ASM_REWRITE_TAC[] THEN
MATCH_MP_TAC REAL_LE_DIV THEN ASM_REWRITE_TAC[]);;
(* TF_TT *)
"b"; "c"; "d"] THEN REWRITE_TAC[FLOAT_F_POS];
ALL_TAC
] THEN
DISJ_CASES_TAC (REAL_ARITH `x <= &0 \/ &0 <= x`) THENL
[
SUBGOAL_THEN `interval_arith x (--a, float T 0 0)` ASSUME_TAC THENL
[
UNDISCH_TAC `interval_arith x (--a, b)` THEN POP_ASSUM MP_TAC THEN
REWRITE_TAC[interval_arith; FLOAT_0] THEN REAL_ARITH_TAC;
ALL_TAC
] THEN
MP_TAC ((SPEC_ALL o SPECL [`0`; `0`] o GEN_ALL) FLOAT_INTERVAL_DIV_TT_TT) THEN
ASM_REWRITE_TAC[] THEN DISCH_THEN MATCH_MP_TAC THEN ASM_REWRITE_TAC[FLOAT_NEG_T] THEN
ASM_REWRITE_TAC[GSYM FLOAT_NEG_T] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
REWRITE_TAC[real_div] THEN CONJ_TAC THENL
[
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `b / --d` THEN
ASM_REWRITE_TAC[real_div; REAL_INV_NEG; REAL_ARITH `b * --d <= &0 <=> &0 <= b * d`] THEN
MATCH_MP_TAC REAL_LE_MUL THEN ASM_REWRITE_TAC[REAL_LE_INV_EQ];
ALL_TAC
] THEN
REWRITE_TAC[FLOAT_0; REAL_MUL_LZERO; REAL_LE_REFL];
ALL_TAC
] THEN
SUBGOAL_THEN `interval_arith x (float F 0 0, b)` ASSUME_TAC THENL
[
UNDISCH_TAC `interval_arith x (--a, b)` THEN POP_ASSUM MP_TAC THEN
REWRITE_TAC[interval_arith; FLOAT_0] THEN REAL_ARITH_TAC;
ALL_TAC
] THEN
MP_TAC ((INST[`0`, `n1:num`; `0`, `e1:num`]) FLOAT_INTERVAL_DIV_FF_TT) THEN
ASM_REWRITE_TAC[FLOAT_NEG_T] THEN DISCH_THEN MATCH_MP_TAC THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `&0` THEN
REWRITE_TAC[real_div] THEN CONJ_TAC THENL
[
REWRITE_TAC[FLOAT_0; REAL_MUL_LZERO; REAL_LE_REFL];
ALL_TAC
] THEN
MATCH_MP_TAC REAL_LE_TRANS THEN EXISTS_TAC `--a / --d` THEN ASM_REWRITE_TAC[] THEN
REWRITE_TAC[real_div; REAL_INV_NEG; REAL_NEG_MUL2] THEN MATCH_MP_TAC REAL_LE_MUL THEN
ASM_REWRITE_TAC[REAL_LE_INV_EQ]);;
let transform = UNDISCH_ALL o
PURE_REWRITE_RULE[TAUT `~P <=> (P <=> F)`] o
REWRITE_RULE[GSYM IMP_IMP] o
NUMERALS_TO_NUM;;
let FLOAT_INTERVAL_DIV_FF_FF' = transform FLOAT_INTERVAL_DIV_FF_FF and
FLOAT_INTERVAL_DIV_TT_TT' = transform FLOAT_INTERVAL_DIV_TT_TT and
FLOAT_INTERVAL_DIV_FF_TT' = transform FLOAT_INTERVAL_DIV_FF_TT and
FLOAT_INTERVAL_DIV_TT_FF' = transform FLOAT_INTERVAL_DIV_TT_FF and
FLOAT_INTERVAL_DIV_TF_FF' = transform FLOAT_INTERVAL_DIV_TF_FF and
FLOAT_INTERVAL_DIV_TF_TT' = transform FLOAT_INTERVAL_DIV_TF_TT;;
let float_interval_div pp th1 th2 =
let x, l_lo, l_hi = dest_float_interval (concl th1) and
y, r_lo, r_hi = dest_float_interval (concl th2) in
let s1, n1, e1 = dest_float l_lo and
s2, n2, e2 = dest_float l_hi and
s3, m1, r1 = dest_float r_lo and
s4, m2, r2 = dest_float r_hi in
if s3 <> s4 then
failwith "float_interval_div: division by an interval containing 0"
else
let lo_th, hi_th, th0, zero_th =
if s1 = s2 then
if s1 = "F" then
if s3 = "F" then
float_div_lo pp l_lo r_hi, float_div_hi pp l_hi r_lo,
FLOAT_INTERVAL_DIV_FF_FF', raw_eq0_hash_conv m1
else
float_div_lo pp l_hi r_hi, float_div_hi pp l_lo r_lo,
FLOAT_INTERVAL_DIV_FF_TT', raw_eq0_hash_conv m2
else
if s3 = "F" then
float_div_lo pp l_lo r_lo, float_div_hi pp l_hi r_hi,
FLOAT_INTERVAL_DIV_TT_FF', raw_eq0_hash_conv m1
else
float_div_lo pp l_hi r_lo, float_div_hi pp l_lo r_hi,
FLOAT_INTERVAL_DIV_TT_TT', raw_eq0_hash_conv m2
else
if s1 = "F" then
failwith "float_interval_div: interval (F,T)"
else
if s3 = "F" then
float_div_lo pp l_lo r_lo, float_div_hi pp l_hi r_lo,
FLOAT_INTERVAL_DIV_TF_FF', raw_eq0_hash_conv m1
else
float_div_lo pp l_hi r_hi, float_div_hi pp l_lo r_hi,
FLOAT_INTERVAL_DIV_TF_TT', raw_eq0_hash_conv m2 in
let f1_tm = lhand(concl lo_th) and
f2_tm = rand(concl hi_th) in
let th = INST[x, x_var_real; n1, n1_var_num; e1, e1_var_num;
y, y_var_real; n2, n2_var_num; e2, e2_var_num;
m1, m1_var_num; r1, r1_var_num;
m2, m2_var_num; r2, r2_var_num;
f1_tm, f1_var_real; f2_tm, f2_var_real] th0 in
(MY_PROVE_HYP lo_th o MY_PROVE_HYP hi_th o
MY_PROVE_HYP th1 o MY_PROVE_HYP th2 o MY_PROVE_HYP zero_th) th;;
(*
let th1 = mk_float_interval_small_num 123456781;;
let th2 = mk_float_interval_small_num 514;;
let th1' = float_interval_neg th1;;
let th2' = float_interval_neg th2;;
let th3 = (NUMERALS_TO_NUM o REWRITE_RULE[FLOAT_OF_NUM; min_exp_def; GSYM FLOAT_NEG_T] o prove)
(`interval_arith (&0) (-- &5, &10)`, REWRITE_TAC[interval_arith] THEN REAL_ARITH_TAC);;
let th4 = (NUMERALS_TO_NUM o REWRITE_RULE[FLOAT_OF_NUM; min_exp_def; GSYM FLOAT_NEG_T] o prove)
(`interval_arith (&0) (-- &10, &5)`, REWRITE_TAC[interval_arith] THEN REAL_ARITH_TAC);;
float_interval_div 5 th1 th2;;
float_interval_div 5 th1' th2;;
float_interval_div 5 th1 th2';;
float_interval_div 5 th1' th2';;
float_interval_div 1 th1 th2;;
float_interval_div 5 th3 th1;;
float_interval_div 5 th3 th1';;
float_interval_div 5 th3 th4;;
(* 4: 0.392 *)
test 100 (float_interval_div 5 th1) th2;;
(* 4: 0.224 *)
test 100 (float_interval_div 1 th1) th2;;
let tm1 = mk_small_numeral_array 123456781;;
let tm2 = mk_small_numeral_array 514;;
let tm = mk_binop `DIV` tm1 tm2;;
(* 4: 0.056 *)
test 100 NUM_DIV_HASH_CONV tm;;
NUM_DIV_HASH_CONV tm;;
let th1' = float_interval_round 3 th1;;
let th2' = float_interval_round 3 th2;;
(* 4: 0.256 *)
test 100 (float_interval_div 3 th1') th2';;
let th1 = mk_float_interval_num 1;;
let th2 = mk_float_interval_num 17;;
float_interval_div 5 th1 th2;;
*)
(*****************************************)
(* float_interval_add, float_interval_sub *)
let n1_var_real = `n1:real` and
n2_var_real = `n2:real` and
m1_var_real = `m1:real` and
m2_var_real = `m2:real` and
n_var_real = `n:real` and
m_var_real = `m:real`;;
let INTERVAL_ADD = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (n1, m1) /\
interval_arith y (n2, m2) /\
n <= n1 + n2 /\ m1 + m2 <= m
==> interval_arith (x + y) (n, m)`,
REWRITE_TAC[interval_arith] THEN REAL_ARITH_TAC);;
let INTERVAL_SUB = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP] o prove)(
`interval_arith x (n1, m1) /\
interval_arith y (n2, m2) /\
n <= n1 - m2 /\ m1 - n2 <= m
==> interval_arith (x - y) (n, m)`,
REWRITE_TAC[interval_arith] THEN REAL_ARITH_TAC);;
let float_interval_add pp th1 th2 =
let x, n1, m1 = dest_float_interval (concl th1) in
let y, n2, m2 = dest_float_interval (concl th2) in
let lo_th = float_add_lo pp n1 n2 in
let hi_th = float_add_hi pp m1 m2 in
let n_tm = lhand (concl lo_th) in
let m_tm = rand (concl hi_th) in
let th0 = INST[x, x_var_real; n1, n1_var_real; m1, m1_var_real;
y, y_var_real; n2, n2_var_real; m2, m2_var_real;
n_tm, n_var_real; m_tm, m_var_real] INTERVAL_ADD in
MY_PROVE_HYP lo_th (MY_PROVE_HYP hi_th (MY_PROVE_HYP th2 (MY_PROVE_HYP th1 th0)));;
let float_interval_sub pp th1 th2 =
let x, n1, m1 = dest_float_interval (concl th1) in
let y, n2, m2 = dest_float_interval (concl th2) in
let lo_th = float_sub_lo pp n1 m2 in
let hi_th = float_sub_hi pp m1 n2 in
let n_tm = lhand(concl lo_th) in
let m_tm = rand(concl hi_th) in
let th0 = INST[x, x_var_real; n1, n1_var_real; m1, m1_var_real;
y, y_var_real; n2, n2_var_real; m2, m2_var_real;
n_tm, n_var_real; m_tm, m_var_real] INTERVAL_SUB in
MY_PROVE_HYP lo_th (MY_PROVE_HYP hi_th (MY_PROVE_HYP th2 (MY_PROVE_HYP th1 th0)));;
(*
let th1 = mk_float_interval_num (Num.num_of_int 123456781);;
let th2 = mk_float_interval_num (Num.num_of_int 514);;
let th3 = float_interval_neg th1;;
float_interval_add 5 th1 th2;;
float_interval_sub 5 th2 th1;;
float_interval_add 1 th1 th2;;
float_interval_add 5 th3 th2;;
float_interval_add 1 th3 th2;;
(* 4: 0.424 *)
test 1000 (float_interval_add 5 th1) th2;;
(* 4: 0.648 *)
test 1000 (float_interval_add 1 th1) th2;;
let tm1 = mk_small_numeral_array 123456781;;
let tm2 = mk_small_numeral_array 514;;
let tm = mk_binop plus_op_num tm1 tm2;;
(* 4: 0.036 *)
test 1000 NUM_ADD_HASH_CONV tm;;
NUM_ADD_HASH_CONV tm;;
let th1' = float_interval_round 3 th1;;
let th2' = float_interval_round 3 th2;;
float_interval_add 3 th1' th2';;
(* 4: 0.724 *)
test 1000 (float_interval_add 3 th1') th2';;
*)
(********************************************)
(* FLOAT_ABS *)
let s_var_bool = `s:bool`;;
let float_abs tm =
let ltm, rtm = dest_comb tm in
if ((fst o dest_const) ltm <> "real_abs") then
failwith "float_abs: no abs"
else
let ltm, e_tm = dest_comb rtm in
let ltm, n_tm = dest_comb ltm in
let s_tm = rand ltm in
INST[s_tm, s_var_bool; n_tm, n_var_num; e_tm, e_var_num] FLOAT_ABS;;
(*******************************)
(* float_interval_sqrt *)
let FLOAT_INTERVAL_SQRT' = (UNDISCH_ALL o REWRITE_RULE[GSYM IMP_IMP]) FLOAT_INTERVAL_SQRT;;
let float_interval_sqrt pp th =
let x_tm, lo_tm, hi_tm = dest_float_interval (concl th) in
let s1, n1_tm, e1_tm = dest_float lo_tm in
if s1 <> "F" then
failwith "float_interval_sqrt: negative low bound"
else
let lo_th = float_sqrt_lo pp lo_tm in
let hi_th = float_sqrt_hi pp hi_tm in
let f1_tm = lhand (concl lo_th) in
let f2_tm = rand (concl hi_th) in
let th0 = INST[x_tm, x_var_real; n1_tm, n1_var_num; e1_tm, e1_var_num;
hi_tm, hi_var_real; f1_tm, f1_var_real;
f2_tm, f2_var_real] FLOAT_INTERVAL_SQRT' in
MY_PROVE_HYP lo_th (MY_PROVE_HYP hi_th (MY_PROVE_HYP th th0));;
(******************************************)
(* FLOAT_TO_NUM_CONV *)
let FLOAT_TO_NUM_CONV tm =
let ltm, e_tm = dest_comb tm in
let f_tm, n_tm = dest_comb ltm in
if (fst o dest_const o rator) f_tm <> "float" then
failwith "FLOAT_TO_NUM_CONV"
else
let n_th' = SYM (INST[n_tm, n_var_num] Arith_hash.NUM_THM) in
let e_th' = SYM (INST[e_tm, n_var_num] Arith_hash.NUM_THM) in
let n_th = TRANS n_th' (NUM_TO_NUMERAL_CONV (mk_comb(Arith_hash.num_const, n_tm))) in
let e_th = TRANS e_th' (NUM_TO_NUMERAL_CONV (mk_comb(Arith_hash.num_const, e_tm))) in
let th0 = MK_COMB (AP_TERM f_tm n_th, e_th) in
let tm0 = rand(concl th0) in
let th1 = REWRITE_CONV[float; num_exp; REAL_MUL_LID; GSYM REAL_OF_NUM_MUL; GSYM REAL_OF_NUM_POW; min_exp_def] tm0 in
let th2 = REAL_RAT_REDUCE_CONV (rand(concl th1)) in
TRANS th0 (TRANS th1 th2);;
end;;
(**************************************)
(* Printer for floating-point numbers *)
(**************************************)
let print_float tm=
try
let s, m_tm, e_tm = Arith_float.dest_float tm in
let m = Arith_hash.raw_dest_hash m_tm and
e = Arith_hash.raw_dest_hash e_tm -/ Num.num_of_int Arith_options.min_exp in
let s_str = if s = "T" then "-" else "" in
let m_str = Num.string_of_num m in
let e_str = if e = num_0 then ""
else "*" ^ string_of_int Arith_options.base ^ "^" ^ Num.string_of_num e in
let str = "##" ^ s_str ^ m_str ^ e_str in
print_string str
with _ -> failwith "print_float";;
install_user_printer ("float", print_float);;