1(*=========================================================================== 2== LIBRARY: reduce (part II) == 3== == 4== DESCRIPTION: Conversions to reduce arithmetic constant expressions == 5== == 6== AUTHOR: Michael Norrish == 7== University of Cambridge Computer Laboratory == 8== New Museums Site == 9== Pembroke Street == 10== Cambridge CB2 3QG == 11== England. == 12== == 13== mn200@cl.cam.ac.uk == 14== == 15== DATE: January 1999 == 16== == 17== NOTE: The original functionality in this file was provided by == 18== carefully written CONVs. With the use of proper numerals == 19== (see numeralTheory), this is no longer necessary, and == 20== simple rewriting can be used for most tasks. == 21== It is the (untested) claim that this will be as efficient. == 22============================================================================*) 23 24structure Arithconv :> Arithconv = 25struct 26 27open HolKernel boolTheory boolLib Parse Rsyntax 28 Num_conv numSyntax arithmeticTheory numeralTheory; 29 30val ambient_grammars = Parse.current_grammars(); 31val _ = Parse.temp_set_grammars arithmeticTheory.arithmetic_grammars 32 33val ERR = mk_HOL_ERR "Arithconv" 34fun failwith function = raise (ERR function "") 35 36 37(*--------------------------------------------------------------------------- 38 A "conv-al" that takes a conv and makes it fail if the 39 result is not either true, false or a numeral. 40 ---------------------------------------------------------------------------*) 41 42fun TFN_CONV c t = 43 let val result = c t 44 val result_t = rhs (concl result) 45 in 46 if result_t = T orelse result_t = F orelse Literal.is_numeral result_t 47 then result 48 else failwith "TFN_CONV" 49end 50 51 52(*-----------------------------------------------------------------------*) 53(* NEQ_CONV "[x] = [y]" = |- ([x] = [y]) = [x=y -> T | F] *) 54(*-----------------------------------------------------------------------*) 55 56local 57 val NEQ_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_eq]) 58 val REFL_CLAUSE_num = INST_TYPE [alpha |-> num] REFL_CLAUSE 59in 60fun NEQ_CONV tm = 61 case total boolLib.dest_eq tm 62 of NONE => failwith "NEQ_CONV" 63 | SOME (n1,n2) => 64 if is_numeral n1 andalso is_numeral n2 65 then if n1=n2 then SPEC n1 REFL_CLAUSE_num 66 else with_exn NEQ_RW tm (ERR "NEQ_CONV" "") 67 else failwith "NEQ_CONV" 68end; 69 70(*-----------------------------------------------------------------------*) 71(* LT_CONV "[x] < [y]" = |- ([x] < [y]) = [x<y -> T | F] *) 72(*-----------------------------------------------------------------------*) 73 74local val LT_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_lt]) 75in 76fun LT_CONV tm = 77 if is_less tm then with_exn LT_RW tm (ERR "LT_CONV" "") 78 else failwith "LT_CONV" 79end; 80 81(*-----------------------------------------------------------------------*) 82(* GT_CONV "[x] > [y]" = |- ([x] > [y]) = [x>y -> T | F] *) 83(*-----------------------------------------------------------------------*) 84 85local val GT_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_lt]) 86in 87fun GT_CONV tm = 88 if is_greater tm then with_exn GT_RW tm (ERR "GT_CONV" "") 89 else failwith "GT_CONV" 90end; 91 92(*-----------------------------------------------------------------------*) 93(* LE_CONV "[x] <= [y]" = |- ([x]<=> [y]) = [x<=y -> T | F] *) 94(*-----------------------------------------------------------------------*) 95 96local val LE_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_lte]) 97in 98fun LE_CONV tm = 99 if is_leq tm then with_exn LE_RW tm (ERR "LE_CONV" "") else failwith "LE_CONV" 100end; 101 102(*-----------------------------------------------------------------------*) 103(* GE_CONV "[x] >= [y]" = |- ([x] >= [y]) = [x>=y -> T | F] *) 104(*-----------------------------------------------------------------------*) 105 106local val GE_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_lte]) 107in 108fun GE_CONV tm = 109 if is_geq tm then with_exn GE_RW tm (ERR "GE_CONV" "") 110 else failwith "GE_CONV" 111end; 112 113(*-----------------------------------------------------------------------*) 114(* EVEN_CONV "EVEN [x]" = |- EVEN [x] = [ x divisible by 2 -> T | F ] *) 115(*-----------------------------------------------------------------------*) 116 117local val EC = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_evenodd]) 118in 119fun EVEN_CONV tm = 120 if is_even tm then with_exn EC tm (ERR "EVEN_CONV" "") 121 else failwith "EVEN_CONV" 122end 123 124(*-----------------------------------------------------------------------*) 125(* ODD_CONV "ODD [x]" = |- ODD [x] = [ x divisible by 2 -> F | T ] *) 126(*-----------------------------------------------------------------------*) 127 128local val OC = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_evenodd]) 129in 130fun ODD_CONV tm = 131 if is_odd tm then with_exn OC tm (ERR "ODD_CONV" "") else failwith "ODD_CONV" 132end 133 134(*-----------------------------------------------------------------------*) 135(* SUC_CONV "SUC [x]" = |- SUC [x] = [x+1] *) 136(*-----------------------------------------------------------------------*) 137 138local val SUC_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_suc]) 139in 140fun SUC_CONV tm = 141 if is_suc tm then with_exn SUC_RW tm (ERR "SUC_CONV" "") 142 else failwith "SUC_CONV" 143end; 144 145(*-----------------------------------------------------------------------*) 146(* PRE_CONV "PRE [n]" = |- PRE [n] = [n-1] *) 147(*-----------------------------------------------------------------------*) 148 149local 150 val PRE_RW = TFN_CONV (REWRITE_CONV [numeral_distrib, numeral_pre,NORM_0]) 151in 152fun PRE_CONV tm = 153 if is_pre tm then with_exn PRE_RW tm (ERR "PRE_CONV" "") 154 else failwith "PRE_CONV" 155end; 156 157(*-----------------------------------------------------------------------*) 158(* SBC_CONV "[x] - [y]" = |- ([x] - [y]) = [x - y] *) 159(*-----------------------------------------------------------------------*) 160 161local 162 val SBC_RW = 163 TFN_CONV (REWRITE_CONV 164 [numeral_distrib, numeral_sub,iSUB_THM, 165 iDUB_removal,numeral_pre, numeral_lt]) 166in 167fun SBC_CONV tm = 168 if is_minus tm then with_exn SBC_RW tm (ERR "SBC_CONV" "") 169 else failwith "SBC_CONV" 170end; 171 172(*-----------------------------------------------------------------------*) 173(* ADD_CONV "[x] + [y]" = |- [x] + [y] = [x+y] *) 174(*-----------------------------------------------------------------------*) 175 176local 177 val ADD_RW = 178 TFN_CONV (REWRITE_CONV 179 [numeral_distrib, numeral_add,numeral_suc, numeral_iisuc]) 180in 181fun ADD_CONV tm = 182 if is_plus tm then with_exn ADD_RW tm (ERR "ADD_CONV" "") 183 else failwith "ADD_CONV" 184end; 185 186(*-----------------------------------------------------------------------*) 187(* MUL_CONV "[x] * [y]" = |- [x] * [y] = [x * y] *) 188(*-----------------------------------------------------------------------*) 189 190local 191 val MUL_RW = 192 TFN_CONV (REWRITE_CONV 193 [numeral_distrib, numeral_add, numeral_suc, 194 numeral_iisuc, numeral_mult, iDUB_removal, numeral_pre]) 195in 196fun MUL_CONV tm = 197 if is_mult tm then with_exn MUL_RW tm (ERR "MUL_CONV" "") 198 else failwith "MUL_CONV" 199end; 200 201(*-----------------------------------------------------------------------*) 202(* EXP_CONV "[x] EXP [y]" = |- [x] EXP [y] = [x ** y] *) 203(*-----------------------------------------------------------------------*) 204 205local 206 val RW1 = REWRITE_CONV [numeral_distrib, numeral_exp] 207 val RW2 = REWRITE_CONV [numeral_add, numeral_suc, numeral_iisuc, 208 numeral_mult, iDUB_removal, numeral_pre, iSQR] 209 val EXP_RW = TFN_CONV (RW1 THENC RW2) 210in 211fun EXP_CONV tm = 212 if is_exp tm then with_exn EXP_RW tm (ERR "EXP_CONV" "") 213 else failwith "EXP_CONV" 214end; 215 216(*-----------------------------------------------------------------------*) 217(* DIV_CONV "[x] DIV [y]" = |- [x] DIV [y] = [x div y] *) 218(*-----------------------------------------------------------------------*) 219 220fun provelt x y = EQT_ELIM (LT_CONV (mk_less(mk_numeral x, mk_numeral y))) 221 222val xv = mk_var {Name= "x", Ty=num} 223val yv = mk_var {Name= "y", Ty=num} 224val zv = mk_var {Name= "z", Ty=num} 225val pv = mk_var {Name= "p", Ty=num} 226val qv = mk_var {Name= "q", Ty=num} 227val rv = mk_var {Name= "r", Ty=num}; 228 229local val divt = 230 prove((���(q * y = p) ==> (p + r = x) ==> (r < y) ==> (x DIV y = q)���), 231 REPEAT DISCH_TAC THEN 232 MATCH_MP_TAC (arithmeticTheory.DIV_UNIQUE) THEN 233 EXISTS_TAC (���r:num���) THEN ASM_REWRITE_TAC[]) 234in 235fun DIV_CONV tm = 236 let open Arbnum 237 val (xn,yn) = dest_div tm 238 val x = dest_numeral xn 239 and y = dest_numeral yn 240 val q = x div y 241 val p = q * y 242 val r = x - p 243 val pn = mk_numeral p 244 and qn = mk_numeral q 245 and rn = mk_numeral r 246 val p1 = MUL_CONV (mk_mult(qn,yn)) 247 and p2 = ADD_CONV (mk_plus(pn,rn)) 248 and p3 = provelt r y 249 and chain = INST [xv |-> xn, yv |-> yn, pv |-> pn, 250 qv |-> qn, rv |-> rn] divt 251 in 252 MP (MP (MP chain p1) p2) p3 253 end handle HOL_ERR _ => failwith "DIV_CONV" 254 | Div => raise ERR "DIV_CONV" "attempt to divide by zero" 255end; 256 257(*-----------------------------------------------------------------------*) 258(* MOD_CONV "[x] MOD [y]" = |- [x] MOD [y] = [x mod y] *) 259(*-----------------------------------------------------------------------*) 260 261local val modt = 262 prove(���(q * y = p) ==> (p + r = x) ==> (r < y) ==> (x MOD y = r)���, 263 REPEAT DISCH_TAC THEN 264 MATCH_MP_TAC arithmeticTheory.MOD_UNIQUE THEN 265 EXISTS_TAC ���q:num��� THEN ASM_REWRITE_TAC[]) 266in 267fun MOD_CONV tm = 268 let open Arbnum 269 val (xn,yn) = dest_mod tm 270 val x = dest_numeral xn 271 and y = dest_numeral yn 272 val q = x div y 273 val p = q * y 274 val r = x - p 275 val pn = mk_numeral p 276 and qn = mk_numeral q 277 and rn = mk_numeral r 278 val p1 = MUL_CONV (mk_mult(qn,yn)) 279 and p2 = ADD_CONV (mk_plus(pn,rn)) 280 and p3 = provelt r y 281 and chain = INST [xv |-> xn, yv |-> yn, pv |-> pn, 282 qv |-> qn, rv |-> rn] modt 283 in 284 MP (MP (MP chain p1) p2) p3 285 end handle HOL_ERR _ => failwith "MOD_CONV" 286 | Div => raise ERR "MOD_CONV" "attempt to take mod 0" 287end; 288 289val _ = Parse.temp_set_grammars ambient_grammars 290 291end 292