# HG changeset patch # User immler # Date 1456484025 -3600 # Node ID c7666166c24ee659c9e01399ede426039c7a5aa7 # Parent c7d6f4dded193e980fda05b69f0d51eaffb43693 positive precision for truncate; fixed precision for approximation of rationals; code for truncate diff -r c7d6f4dded19 -r c7666166c24e src/HOL/Library/Float.thy --- a/src/HOL/Library/Float.thy Fri Feb 26 11:53:42 2016 +0100 +++ b/src/HOL/Library/Float.thy Fri Feb 26 11:53:45 2016 +0100 @@ -1074,7 +1074,7 @@ subsection \Truncating Real Numbers\ definition truncate_down::"nat \ real \ real" - where "truncate_down prec x = round_down (prec - \log 2 \x\\ - 1) x" + where "truncate_down prec x = round_down (prec - \log 2 \x\\) x" lemma truncate_down: "truncate_down prec x \ x" using round_down by (simp add: truncate_down_def) @@ -1089,7 +1089,7 @@ by (auto simp: truncate_down_def) definition truncate_up::"nat \ real \ real" - where "truncate_up prec x = round_up (prec - \log 2 \x\\ - 1) x" + where "truncate_up prec x = round_up (prec - \log 2 \x\\) x" lemma truncate_up: "x \ truncate_up prec x" using round_up by (simp add: truncate_up_def) @@ -1111,7 +1111,7 @@ by (simp_all add: powr_add) lemma truncate_down_pos: - assumes "x > 0" "p > 0" + assumes "x > 0" shows "truncate_down p x > 0" proof - have "0 \ log 2 x - real_of_int \log 2 x\" @@ -1126,14 +1126,16 @@ lemma truncate_down_nonneg: "0 \ y \ 0 \ truncate_down prec y" by (auto simp: truncate_down_def round_down_def) -lemma truncate_down_ge1: "1 \ x \ 1 \ p \ 1 \ truncate_down p x" - by (auto simp: truncate_down_def algebra_simps intro!: round_down_ge1 add_mono) +lemma truncate_down_ge1: "1 \ x \ 1 \ truncate_down p x" + apply (auto simp: truncate_down_def algebra_simps intro!: round_down_ge1) + apply linarith + done lemma truncate_up_nonpos: "x \ 0 \ truncate_up prec x \ 0" by (auto simp: truncate_up_def round_up_def intro!: mult_nonpos_nonneg) lemma truncate_up_le1: - assumes "x \ 1" "1 \ p" + assumes "x \ 1" shows "truncate_up p x \ 1" proof - consider "x \ 0" | "x > 0" @@ -1147,13 +1149,27 @@ case 2 then have le: "\log 2 \x\\ \ 0" using assms by (auto simp: log_less_iff) - from assms have "1 \ int p" by simp + from assms have "0 \ int p" by simp from add_mono[OF this le] show ?thesis using assms by (simp add: truncate_up_def round_up_le1 add_mono) qed qed +lemma truncate_down_shift_int: "truncate_down p (x * 2 powr real_of_int k) = truncate_down p x * 2 powr k" + by (cases "x = 0") + (simp_all add: algebra_simps abs_mult log_mult truncate_down_def round_down_shift[of _ _ k, simplified]) + +lemma truncate_down_shift_nat: "truncate_down p (x * 2 powr real k) = truncate_down p x * 2 powr k" + by (metis of_int_of_nat_eq truncate_down_shift_int) + +lemma truncate_up_shift_int: "truncate_up p (x * 2 powr real_of_int k) = truncate_up p x * 2 powr k" + by (cases "x = 0") + (simp_all add: algebra_simps abs_mult log_mult truncate_up_def round_up_shift[of _ _ k, simplified]) + +lemma truncate_up_shift_nat: "truncate_up p (x * 2 powr real k) = truncate_up p x * 2 powr k" + by (metis of_int_of_nat_eq truncate_up_shift_int) + subsection \Truncating Floats\ @@ -1186,12 +1202,13 @@ begin qualified lemma compute_float_round_down[code]: - "float_round_down prec (Float m e) = (let d = bitlen \m\ - int prec in + "float_round_down prec (Float m e) = (let d = bitlen \m\ - int prec - 1 in if 0 < d then Float (div_twopow m (nat d)) (e + d) else Float m e)" - using Float.compute_float_down[of "prec - bitlen \m\ - e" m e, symmetric] - by transfer (simp add: field_simps abs_mult log_mult bitlen_def truncate_down_def - cong del: if_weak_cong) + using Float.compute_float_down[of "Suc prec - bitlen \m\ - e" m e, symmetric] + by transfer + (simp add: field_simps abs_mult log_mult bitlen_def truncate_down_def + cong del: if_weak_cong) qualified lemma compute_float_round_up[code]: "float_round_up prec x = - float_round_down prec (-x)" @@ -1212,10 +1229,46 @@ shows "a div b = real_of_int \a / b\" by (simp add: floor_divide_of_nat_eq [of a b]) -definition "rat_precision prec x y = int prec - (bitlen x - bitlen y)" +definition "rat_precision prec x y = + (let d = bitlen x - bitlen y in int prec - d + + (if Float (abs x) 0 < Float (abs y) d then 1 else 0))" + +lemma floor_log_divide_eq: + assumes "i > 0" "j > 0" "p > 1" + shows "\log p (i / j)\ = floor (log p i) - floor (log p j) - + (if i \ j * p powr (floor (log p i) - floor (log p j)) then 0 else 1)" +proof - + let ?l = "log p" + let ?fl = "\x. floor (?l x)" + have "\?l (i / j)\ = \?l i - ?l j\" using assms + by (auto simp: log_divide) + also have "\ = floor (real_of_int (?fl i - ?fl j) + (?l i - ?fl i - (?l j - ?fl j)))" + (is "_ = floor (_ + ?r)") + by (simp add: algebra_simps) + also note floor_add2 + also note \p > 1\ + note powr = powr_le_cancel_iff[symmetric, OF \1 < p\, THEN iffD2] + note powr_strict = powr_less_cancel_iff[symmetric, OF \1 < p\, THEN iffD2] + have "floor ?r = (if i \ j * p powr (?fl i - ?fl j) then 0 else -1)" (is "_ = ?if") + using assms + by (linarith | + auto + intro!: floor_eq2 + intro: powr_strict powr + simp: powr_divide2[symmetric] powr_add divide_simps algebra_simps bitlen_def)+ + finally + show ?thesis by simp +qed + +lemma truncate_down_rat_precision: + "truncate_down prec (real x / real y) = round_down (rat_precision prec x y) (real x / real y)" + and truncate_up_rat_precision: + "truncate_up prec (real x / real y) = round_up (rat_precision prec x y) (real x / real y)" + unfolding truncate_down_def truncate_up_def rat_precision_def + by (cases x; cases y) (auto simp: floor_log_divide_eq algebra_simps bitlen_def) lift_definition lapprox_posrat :: "nat \ nat \ nat \ float" - is "\prec (x::nat) (y::nat). round_down (rat_precision prec x y) (x / y)" + is "\prec (x::nat) (y::nat). truncate_down prec (x / y)" by simp context @@ -1230,14 +1283,14 @@ in normfloat (Float d (- l)))" unfolding div_mult_twopow_eq by transfer - (simp add: round_down_def powr_int real_div_nat_eq_floor_of_divide field_simps Let_def - del: two_powr_minus_int_float) + (simp add: round_down_def powr_int real_div_nat_eq_floor_of_divide field_simps Let_def + truncate_down_rat_precision del: two_powr_minus_int_float) end lift_definition rapprox_posrat :: "nat \ nat \ nat \ float" - is "\prec (x::nat) (y::nat). round_up (rat_precision prec x y) (x / y)" by - simp + is "\prec (x::nat) (y::nat). truncate_up prec (x / y)" + by simp context begin @@ -1268,7 +1321,7 @@ using ceil_divide_floor_conv[of y x'] powr_realpow[of 2 "nat l"] \0 \ l\ \y \ 0\ l_def[symmetric, THEN meta_eq_to_obj_eq] apply transfer - apply (auto simp add: round_up_def) + apply (auto simp add: round_up_def truncate_up_rat_precision) by (metis floor_divide_of_int_eq of_int_of_nat_eq) next case False @@ -1282,7 +1335,7 @@ using ceil_divide_floor_conv[of y' x] \\ 0 \ l\ \y' \ 0\ \y \ 0\ l_def[symmetric, THEN meta_eq_to_obj_eq] apply transfer - apply (auto simp add: round_up_def ceil_divide_floor_conv) + apply (auto simp add: round_up_def ceil_divide_floor_conv truncate_up_rat_precision) by (metis floor_divide_of_int_eq of_int_of_nat_eq) qed qed @@ -1293,7 +1346,6 @@ assumes "0 \ x" and "0 < y" and "2 * x < y" - and "0 < n" shows "rat_precision n (int x) (int y) > 0" proof - have "0 < x \ log 2 x + 1 = log 2 (2 * x)" @@ -1308,11 +1360,11 @@ qed lemma rapprox_posrat_less1: - "0 \ x \ 0 < y \ 2 * x < y \ 0 < n \ real_of_float (rapprox_posrat n x y) < 1" - by transfer (simp add: rat_precision_pos round_up_less1) + "0 \ x \ 0 < y \ 2 * x < y \ real_of_float (rapprox_posrat n x y) < 1" + by transfer (simp add: rat_precision_pos round_up_less1 truncate_up_rat_precision) lift_definition lapprox_rat :: "nat \ int \ int \ float" is - "\prec (x::int) (y::int). round_down (rat_precision prec \x\ \y\) (x / y)" + "\prec (x::int) (y::int). truncate_down prec (x / y)" by simp context @@ -1327,10 +1379,10 @@ else (if 0 < y then - (rapprox_posrat prec (nat (-x)) (nat y)) else lapprox_posrat prec (nat (-x)) (nat (-y))))" - by transfer (auto simp: round_up_def round_down_def ceiling_def ac_simps) + by transfer (simp add: truncate_up_uminus_eq) lift_definition rapprox_rat :: "nat \ int \ int \ float" is - "\prec (x::int) (y::int). round_up (rat_precision prec \x\ \y\) (x / y)" + "\prec (x::int) (y::int). truncate_up prec (x / y)" by simp lemma "rapprox_rat = rapprox_posrat" @@ -1341,16 +1393,22 @@ qualified lemma compute_rapprox_rat[code]: "rapprox_rat prec x y = - lapprox_rat prec (-x) y" - by transfer (simp add: round_down_uminus_eq) + by transfer (simp add: truncate_down_uminus_eq) + +qualified lemma compute_truncate_down[code]: "truncate_down p (Ratreal r) = (let (a, b) = quotient_of r in lapprox_rat p a b)" + by transfer (auto split: prod.split simp: of_rat_divide dest!: quotient_of_div) + +qualified lemma compute_truncate_up[code]: "truncate_up p (Ratreal r) = (let (a, b) = quotient_of r in rapprox_rat p a b)" + by transfer (auto split: prod.split simp: of_rat_divide dest!: quotient_of_div) end subsection \Division\ -definition "real_divl prec a b = round_down (int prec + \ log 2 \b\ \ - \ log 2 \a\ \) (a / b)" +definition "real_divl prec a b = truncate_down prec (a / b)" -definition "real_divr prec a b = round_up (int prec + \ log 2 \b\ \ - \ log 2 \a\ \) (a / b)" +definition "real_divr prec a b = truncate_up prec (a / b)" lift_definition float_divl :: "nat \ float \ float \ float" is real_divl by (simp add: real_divl_def) @@ -1360,29 +1418,17 @@ qualified lemma compute_float_divl[code]: "float_divl prec (Float m1 s1) (Float m2 s2) = lapprox_rat prec m1 m2 * Float 1 (s1 - s2)" -proof (cases "m1 \ 0 \ m2 \ 0") - case True - let ?f1 = "real_of_int m1 * 2 powr real_of_int s1" and ?f2 = "real_of_int m2 * 2 powr real_of_int s2" - let ?m = "real_of_int m1 / real_of_int m2" and ?s = "2 powr real_of_int (s1 - s2)" - from True have eq2: "(int prec + \log 2 \?f2\\ - \log 2 \?f1\\) = - rat_precision prec \m1\ \m2\ + (s2 - s1)" - by (simp add: abs_mult log_mult rat_precision_def bitlen_def) - have eq1: "real_of_int m1 * 2 powr real_of_int s1 / (real_of_int m2 * 2 powr real_of_int s2) = ?m * ?s" - by (simp add: field_simps powr_divide2[symmetric]) - from True show ?thesis - by (transfer fixing: m1 s1 m2 s2 prec) (unfold eq1 eq2 round_down_shift real_divl_def, - simp add: field_simps) -next - case False - then show ?thesis by transfer (auto simp: real_divl_def) -qed + apply transfer + unfolding real_divl_def of_int_1 mult_1 truncate_down_shift_int[symmetric] + apply (simp add: powr_divide2[symmetric] powr_minus) + done lift_definition float_divr :: "nat \ float \ float \ float" is real_divr by (simp add: real_divr_def) qualified lemma compute_float_divr[code]: "float_divr prec x y = - float_divl prec (-x) y" - by transfer (simp add: real_divr_def real_divl_def round_down_uminus_eq) + by transfer (simp add: real_divr_def real_divl_def truncate_down_uminus_eq) end @@ -1532,7 +1578,7 @@ lemma truncate_down_log2_eqI: assumes "\log 2 \x\\ = \log 2 \y\\" - assumes "\x * 2 powr (p - \log 2 \x\\ - 1)\ = \y * 2 powr (p - \log 2 \x\\ - 1)\" + assumes "\x * 2 powr (p - \log 2 \x\\)\ = \y * 2 powr (p - \log 2 \x\\)\" shows "truncate_down p x = truncate_down p y" using assms by (auto simp: truncate_down_def round_down_def) @@ -1716,7 +1762,7 @@ qualified lemma compute_far_float_plus_down: fixes m1 e1 m2 e2 :: int and p :: nat - defines "k1 \ p - nat (bitlen \m1\)" + defines "k1 \ Suc p - nat (bitlen \m1\)" assumes H: "bitlen \m2\ \ e1 - e2 - k1 - 2" "m1 \ 0" "m2 \ 0" "e1 \ e2" shows "float_plus_down p (Float m1 e1) (Float m2 e2) = float_round_down p (Float (m1 * 2 ^ (Suc (Suc k1)) + sgn m2) (e1 - int k1 - 2))" @@ -1791,7 +1837,7 @@ truncate_down p (Float (?m1*2 + sgn m2) (?e - 1))" unfolding plus_down_def proof (rule truncate_down_log2_eqI) - let ?f = "(int p - \log 2 \real_of_float (Float m1 e1) + real_of_float (Float m2 e2)\\ - 1)" + let ?f = "(int p - \log 2 \real_of_float (Float m1 e1) + real_of_float (Float m2 e2)\\)" let ?ai = "m1 * 2 ^ (Suc k1)" have "\(?a + ?b) * 2 powr real_of_int ?f\ = \(real_of_int (2 * ?ai) + sgn ?b) * 2 powr real_of_int (?f - - ?e - 1)\" proof (rule floor_sum_times_2_powr_sgn_eq) @@ -1811,7 +1857,7 @@ finally have "int p - \log 2 \?a + ?b\\ \ p - (bitlen \m1\) - e1 + 2" by (auto simp: algebra_simps bitlen_def \m1 \ 0\) - also have "\ \ 1 - ?e" + also have "\ \ - ?e" using bitlen_nonneg[of "\m1\"] by (simp add: k1_def) finally show "?f \ - ?e" by simp qed @@ -1838,14 +1884,14 @@ else if m2 = 0 then float_round_down p (Float m1 e1) else (if e1 \ e2 then (let - k1 = p - nat (bitlen \m1\) + k1 = Suc p - nat (bitlen \m1\) in if bitlen \m2\ > e1 - e2 - k1 - 2 then float_round_down p ((Float m1 e1) + (Float m2 e2)) else float_round_down p (Float (m1 * 2 ^ (Suc (Suc k1)) + sgn m2) (e1 - int k1 - 2))) else float_plus_down p (Float m2 e2) (Float m1 e1)))" proof - { - assume "bitlen \m2\ \ e1 - e2 - (p - nat (bitlen \m1\)) - 2" "m1 \ 0" "m2 \ 0" "e1 \ e2" + assume "bitlen \m2\ \ e1 - e2 - (Suc p - nat (bitlen \m1\)) - 2" "m1 \ 0" "m2 \ 0" "e1 \ e2" note compute_far_float_plus_down[OF this] } then show ?thesis @@ -1872,7 +1918,8 @@ "real_of_float (Float 1 (- 2)) = 1/4" "real_of_float (Float 1 (- 3)) = 1/8" "real_of_float (Float (- 1) 0) = -1" - "real_of_float (Float (number_of n) 0) = number_of n" + "real_of_float (Float (numeral n) 0) = numeral n" + "real_of_float (Float (- numeral n) 0) = - numeral n" using two_powr_int_float[of 2] two_powr_int_float[of "-1"] two_powr_int_float[of "-2"] two_powr_int_float[of "-3"] using powr_realpow[of 2 2] powr_realpow[of 2 3] @@ -1889,7 +1936,7 @@ by arith lemma lapprox_rat: "real_of_float (lapprox_rat prec x y) \ real_of_int x / real_of_int y" - using round_down by (simp add: lapprox_rat_def) + by (simp add: lapprox_rat.rep_eq truncate_down) lemma mult_div_le: fixes a b :: int @@ -1911,40 +1958,37 @@ fixes n x y assumes "0 \ x" and "0 \ y" shows "0 \ real_of_float (lapprox_rat n x y)" - using assms by (auto simp: lapprox_rat_def simp: round_down_nonneg) + using assms + by transfer (simp add: truncate_down_nonneg) lemma rapprox_rat: "real_of_int x / real_of_int y \ real_of_float (rapprox_rat prec x y)" - using round_up by (simp add: rapprox_rat_def) + by transfer (simp add: truncate_up) lemma rapprox_rat_le1: fixes n x y assumes xy: "0 \ x" "0 < y" "x \ y" shows "real_of_float (rapprox_rat n x y) \ 1" -proof - - have "bitlen \x\ \ bitlen \y\" - using xy unfolding bitlen_def by (auto intro!: floor_mono) - from this assms show ?thesis - by transfer (auto intro!: round_up_le1 simp: rat_precision_def) -qed + using assms + by transfer (simp add: truncate_up_le1) lemma rapprox_rat_nonneg_nonpos: "0 \ x \ y \ 0 \ real_of_float (rapprox_rat n x y) \ 0" - by transfer (simp add: round_up_le0 divide_nonneg_nonpos) + by transfer (simp add: truncate_up_nonpos divide_nonneg_nonpos) lemma rapprox_rat_nonpos_nonneg: "x \ 0 \ 0 \ y \ real_of_float (rapprox_rat n x y) \ 0" - by transfer (simp add: round_up_le0 divide_nonpos_nonneg) + by transfer (simp add: truncate_up_nonpos divide_nonpos_nonneg) lemma real_divl: "real_divl prec x y \ x / y" - by (simp add: real_divl_def round_down) + by (simp add: real_divl_def truncate_down) lemma real_divr: "x / y \ real_divr prec x y" - using round_up by (simp add: real_divr_def) + by (simp add: real_divr_def truncate_up) lemma float_divl: "real_of_float (float_divl prec x y) \ x / y" by transfer (rule real_divl) lemma real_divl_lower_bound: "0 \ x \ 0 \ y \ 0 \ real_divl prec x y" - by (simp add: real_divl_def round_down_nonneg) + by (simp add: real_divl_def truncate_down_nonneg) lemma float_divl_lower_bound: "0 \ x \ 0 \ y \ 0 \ real_of_float (float_divl prec x y)" @@ -1992,14 +2036,10 @@ qed lemma real_divl_pos_less1_bound: - assumes "0 < x" "x \ 1" "prec \ 1" + assumes "0 < x" "x \ 1" shows "1 \ real_divl prec 1 x" -proof - - have "log 2 x \ real_of_int prec + real_of_int \log 2 x\" - using \prec \ 1\ by arith - from this assms show ?thesis - by (simp add: real_divl_def log_divide round_down_ge1) -qed + using assms + by (auto intro!: truncate_down_ge1 simp: real_divl_def) lemma float_divl_pos_less1_bound: "0 < real_of_float x \ real_of_float x \ 1 \ prec \ 1 \ 1 \ real_of_float (float_divl prec 1 x)" @@ -2025,7 +2065,7 @@ lemma real_divr_nonpos_pos_upper_bound: "x \ 0 \ 0 \ y \ real_divr prec x y \ 0" - by (simp add: real_divr_def round_up_le0 divide_le_0_iff) + by (simp add: real_divr_def truncate_up_nonpos divide_le_0_iff) lemma float_divr_nonpos_pos_upper_bound: "real_of_float x \ 0 \ 0 \ real_of_float y \ real_of_float (float_divr prec x y) \ 0" @@ -2033,7 +2073,7 @@ lemma real_divr_nonneg_neg_upper_bound: "0 \ x \ y \ 0 \ real_divr prec x y \ 0" - by (simp add: real_divr_def round_up_le0 divide_le_0_iff) + by (simp add: real_divr_def truncate_up_nonpos divide_le_0_iff) lemma float_divr_nonneg_neg_upper_bound: "0 \ real_of_float x \ real_of_float y \ 0 \ real_of_float (float_divr prec x y) \ 0" @@ -2059,25 +2099,26 @@ have logless: "log 2 x < log 2 y" and flogless: "\log 2 x\ < \log 2 y\" by (metis floor_less_cancel linorder_cases not_le)+ have "truncate_up prec x = - real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\ - 1)\ * 2 powr - real_of_int (int prec - \log 2 x\ - 1)" + real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\ )\ * 2 powr - real_of_int (int prec - \log 2 x\)" using assms by (simp add: truncate_up_def round_up_def) - also have "\x * 2 powr real_of_int (int prec - \log 2 x\ - 1)\ \ (2 ^ prec)" + also have "\x * 2 powr real_of_int (int prec - \log 2 x\)\ \ (2 ^ (Suc prec))" proof (unfold ceiling_le_iff) - have "x * 2 powr real_of_int (int prec - \log 2 x\ - 1) \ x * (2 powr real prec / (2 powr log 2 x))" + have "x * 2 powr real_of_int (int prec - \log 2 x\) \ x * (2 powr real (Suc prec) / (2 powr log 2 x))" using real_of_int_floor_add_one_ge[of "log 2 x"] assms by (auto simp add: algebra_simps powr_divide2 intro!: mult_left_mono) - then show "x * 2 powr real_of_int (int prec - \log 2 x\ - 1) \ real_of_int ((2::int) ^ prec)" - using \0 < x\ by (simp add: powr_realpow) + then show "x * 2 powr real_of_int (int prec - \log 2 x\) \ real_of_int ((2::int) ^ (Suc prec))" + using \0 < x\ by (simp add: powr_realpow powr_add) qed - then have "real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\ - 1)\ \ 2 powr int prec" - by (auto simp: powr_realpow) + then have "real_of_int \x * 2 powr real_of_int (int prec - \log 2 x\)\ \ 2 powr int (Suc prec)" + apply (auto simp: powr_realpow powr_add) + by (metis power_Suc real_of_int_le_numeral_power_cancel_iff) also - have "2 powr - real_of_int (int prec - \log 2 x\ - 1) \ 2 powr - real_of_int (int prec - \log 2 y\)" + have "2 powr - real_of_int (int prec - \log 2 x\) \ 2 powr - real_of_int (int prec - \log 2 y\ + 1)" using logless flogless by (auto intro!: floor_mono) - also have "2 powr real_of_int (int prec) \ 2 powr (log 2 y + real_of_int (int prec - \log 2 y\))" + also have "2 powr real_of_int (int (Suc prec)) \ 2 powr (log 2 y + real_of_int (int prec - \log 2 y\ + 1))" using assms \0 < x\ by (auto simp: algebra_simps) - finally have "truncate_up prec x \ 2 powr (log 2 y + real_of_int (int prec - \log 2 y\)) * 2 powr - real_of_int (int prec - \log 2 y\)" + finally have "truncate_up prec x \ 2 powr (log 2 y + real_of_int (int prec - \log 2 y\ + 1)) * 2 powr - real_of_int (int prec - \log 2 y\ + 1)" by simp also have "\ = 2 powr (log 2 y + real_of_int (int prec - \log 2 y\) - real_of_int (int prec - \log 2 y\))" by (subst powr_add[symmetric]) simp @@ -2104,34 +2145,6 @@ finally show ?thesis . qed -lemma truncate_down_zeroprec_mono: - assumes "0 < x" "x \ y" - shows "truncate_down 0 x \ truncate_down 0 y" -proof - - have "x * 2 powr (- real_of_int \log 2 x\ - 1) = x * inverse (2 powr ((real_of_int \log 2 x\ + 1)))" - by (simp add: powr_divide2[symmetric] powr_add powr_minus inverse_eq_divide) - also have "\ = 2 powr (log 2 x - (real_of_int \log 2 x\) - 1)" - using \0 < x\ - by (auto simp: field_simps powr_add powr_divide2[symmetric]) - also have "\ < 2 powr 0" - using real_of_int_floor_add_one_gt - unfolding neg_less_iff_less - by (intro powr_less_mono) (auto simp: algebra_simps) - finally have "\x * 2 powr (- real_of_int \log 2 x\ - 1)\ < 1" - unfolding less_ceiling_iff of_int_minus of_int_1 - by simp - moreover have "0 \ \x * 2 powr (- real_of_int \log 2 x\ - 1)\" - using \x > 0\ by auto - ultimately have "\x * 2 powr (- real_of_int \log 2 x\ - 1)\ \ {0 ..< 1}" - by simp - also have "\ \ {0}" - by auto - finally have "\x * 2 powr (- real_of_int \log 2 x\ - 1)\ = 0" - by simp - with assms show ?thesis - by (auto simp: truncate_down_def round_down_def) -qed - lemma truncate_down_switch_sign_mono: assumes "x \ 0" and "0 \ y" @@ -2147,59 +2160,54 @@ assumes "0 \ x" "x \ y" shows "truncate_down prec x \ truncate_down prec y" proof - - consider "0 < x" "prec = 0" | "x \ 0" | "\log 2 \x\\ = \log 2 \y\\" | - "0 < x" "\log 2 \x\\ \ \log 2 \y\\" "prec \ 0" + consider "x \ 0" | "\log 2 \x\\ = \log 2 \y\\" | + "0 < x" "\log 2 \x\\ \ \log 2 \y\\" by arith then show ?thesis proof cases case 1 - with assms show ?thesis - by (simp add: truncate_down_zeroprec_mono) - next - case 2 with assms have "x = 0" "0 \ y" by simp_all then show ?thesis by (auto intro!: truncate_down_nonneg) next - case 3 + case 2 then show ?thesis using assms by (auto simp: truncate_down_def round_down_def intro!: floor_mono) next - case 4 + case 3 from \0 < x\ have "log 2 x \ log 2 y" "0 < y" "0 \ y" using assms by auto with \\log 2 \x\\ \ \log 2 \y\\\ have logless: "log 2 x < log 2 y" and flogless: "\log 2 x\ < \log 2 y\" unfolding atomize_conj abs_of_pos[OF \0 < x\] abs_of_pos[OF \0 < y\] by (metis floor_less_cancel linorder_cases not_le) - from \prec \ 0\ have [simp]: "prec \ Suc 0" - by auto - have "2 powr (prec - 1) \ y * 2 powr real (prec - 1) / (2 powr log 2 y)" + have "2 powr prec \ y * 2 powr real prec / (2 powr log 2 y)" using \0 < y\ by simp - also have "\ \ y * 2 powr real prec / (2 powr (real_of_int \log 2 y\ + 1))" + also have "\ \ y * 2 powr real (Suc prec) / (2 powr (real_of_int \log 2 y\ + 1))" using \0 \ y\ \0 \ x\ assms(2) by (auto intro!: powr_mono divide_left_mono simp: of_nat_diff powr_add powr_divide2[symmetric]) - also have "\ = y * 2 powr real prec / (2 powr real_of_int \log 2 y\ * 2)" + also have "\ = y * 2 powr real (Suc prec) / (2 powr real_of_int \log 2 y\ * 2)" by (auto simp: powr_add) - finally have "(2 ^ (prec - 1)) \ \y * 2 powr real_of_int (int prec - \log 2 \y\\ - 1)\" + finally have "(2 ^ prec) \ \y * 2 powr real_of_int (int (Suc prec) - \log 2 \y\\ - 1)\" using \0 \ y\ - by (auto simp: powr_divide2[symmetric] le_floor_iff powr_realpow) - then have "(2 ^ (prec - 1)) * 2 powr - real_of_int (int prec - \log 2 \y\\ - 1) \ truncate_down prec y" + by (auto simp: powr_divide2[symmetric] le_floor_iff powr_realpow powr_add) + then have "(2 ^ (prec)) * 2 powr - real_of_int (int prec - \log 2 \y\\) \ truncate_down prec y" by (auto simp: truncate_down_def round_down_def) moreover { have "x = 2 powr (log 2 \x\)" using \0 < x\ by simp - also have "\ \ (2 ^ (prec )) * 2 powr - real_of_int (int prec - \log 2 \x\\ - 1)" - using real_of_int_floor_add_one_ge[of "log 2 \x\"] - by (auto simp: powr_realpow[symmetric] powr_add[symmetric] algebra_simps) + also have "\ \ (2 ^ (Suc prec )) * 2 powr - real_of_int (int prec - \log 2 \x\\)" + using real_of_int_floor_add_one_ge[of "log 2 \x\"] \0 < x\ + by (auto simp: powr_realpow[symmetric] powr_add[symmetric] algebra_simps + powr_mult_base le_powr_iff) also - have "2 powr - real_of_int (int prec - \log 2 \x\\ - 1) \ 2 powr - real_of_int (int prec - \log 2 \y\\)" + have "2 powr - real_of_int (int prec - \log 2 \x\\) \ 2 powr - real_of_int (int prec - \log 2 \y\\ + 1)" using logless flogless \x > 0\ \y > 0\ by (auto intro!: floor_mono) - finally have "x \ (2 ^ (prec - 1)) * 2 powr - real_of_int (int prec - \log 2 \y\\ - 1)" + finally have "x \ (2 ^ prec) * 2 powr - real_of_int (int prec - \log 2 \y\\)" by (auto simp: powr_realpow[symmetric] powr_divide2[symmetric] assms of_nat_diff) } ultimately show ?thesis