src/HOL/Library/Float.thy
author bulwahn
Tue Apr 05 09:38:28 2011 +0200 (2011-04-05)
changeset 42231 bc1891226d00
parent 41528 276078f01ada
child 42676 8724f20bf69c
permissions -rw-r--r--
removing bounded_forall code equation for characters when loading Code_Char
wenzelm@30122
     1
(*  Title:      HOL/Library/Float.thy
wenzelm@30122
     2
    Author:     Steven Obua 2008
wenzelm@30122
     3
    Author:     Johannes Hoelzl, TU Muenchen <hoelzl@in.tum.de> 2008 / 2009
wenzelm@30122
     4
*)
huffman@29988
     5
huffman@29988
     6
header {* Floating-Point Numbers *}
huffman@29988
     7
haftmann@20485
     8
theory Float
haftmann@35032
     9
imports Complex_Main Lattice_Algebras
haftmann@20485
    10
begin
obua@16782
    11
wenzelm@19765
    12
definition
wenzelm@21404
    13
  pow2 :: "int \<Rightarrow> real" where
hoelzl@29804
    14
  [simp]: "pow2 a = (if (0 <= a) then (2^(nat a)) else (inverse (2^(nat (-a)))))"
hoelzl@29804
    15
hoelzl@29804
    16
datatype float = Float int int
hoelzl@29804
    17
hoelzl@31098
    18
primrec of_float :: "float \<Rightarrow> real" where
hoelzl@31098
    19
  "of_float (Float a b) = real a * pow2 b"
hoelzl@31098
    20
hoelzl@31098
    21
defs (overloaded)
haftmann@31998
    22
  real_of_float_def [code_unfold]: "real == of_float"
hoelzl@31098
    23
hoelzl@41024
    24
declare [[coercion "% x . Float x 0"]]
hoelzl@41024
    25
declare [[coercion "real::float\<Rightarrow>real"]]
hoelzl@41024
    26
hoelzl@31098
    27
primrec mantissa :: "float \<Rightarrow> int" where
hoelzl@31098
    28
  "mantissa (Float a b) = a"
hoelzl@31098
    29
hoelzl@31098
    30
primrec scale :: "float \<Rightarrow> int" where
hoelzl@31098
    31
  "scale (Float a b) = b"
wenzelm@21404
    32
hoelzl@29804
    33
instantiation float :: zero begin
hoelzl@31467
    34
definition zero_float where "0 = Float 0 0"
hoelzl@29804
    35
instance ..
hoelzl@29804
    36
end
hoelzl@29804
    37
hoelzl@29804
    38
instantiation float :: one begin
hoelzl@29804
    39
definition one_float where "1 = Float 1 0"
hoelzl@29804
    40
instance ..
hoelzl@29804
    41
end
hoelzl@29804
    42
hoelzl@29804
    43
instantiation float :: number begin
hoelzl@29804
    44
definition number_of_float where "number_of n = Float n 0"
hoelzl@29804
    45
instance ..
hoelzl@29804
    46
end
obua@16782
    47
haftmann@32069
    48
lemma number_of_float_Float [code_unfold_post]:
hoelzl@31467
    49
  "number_of k = Float (number_of k) 0"
hoelzl@31467
    50
  by (simp add: number_of_float_def number_of_is_id)
hoelzl@31467
    51
hoelzl@31098
    52
lemma real_of_float_simp[simp]: "real (Float a b) = real a * pow2 b"
hoelzl@31098
    53
  unfolding real_of_float_def using of_float.simps .
hoelzl@29804
    54
hoelzl@31098
    55
lemma real_of_float_neg_exp: "e < 0 \<Longrightarrow> real (Float m e) = real m * inverse (2^nat (-e))" by auto
hoelzl@31098
    56
lemma real_of_float_nge0_exp: "\<not> 0 \<le> e \<Longrightarrow> real (Float m e) = real m * inverse (2^nat (-e))" by auto
hoelzl@31098
    57
lemma real_of_float_ge0_exp: "0 \<le> e \<Longrightarrow> real (Float m e) = real m * (2^nat e)" by auto
obua@16782
    58
hoelzl@29804
    59
lemma Float_num[simp]: shows
hoelzl@31467
    60
   "real (Float 1 0) = 1" and "real (Float 1 1) = 2" and "real (Float 1 2) = 4" and
hoelzl@31098
    61
   "real (Float 1 -1) = 1/2" and "real (Float 1 -2) = 1/4" and "real (Float 1 -3) = 1/8" and
hoelzl@31098
    62
   "real (Float -1 0) = -1" and "real (Float (number_of n) 0) = number_of n"
hoelzl@29804
    63
  by auto
obua@16782
    64
hoelzl@31863
    65
lemma float_number_of[simp]: "real (number_of x :: float) = number_of x"
hoelzl@31863
    66
  by (simp only:number_of_float_def Float_num[unfolded number_of_is_id])
hoelzl@31863
    67
hoelzl@31863
    68
lemma float_number_of_int[simp]: "real (Float n 0) = real n"
wenzelm@41528
    69
  by simp
hoelzl@31863
    70
hoelzl@29804
    71
lemma pow2_0[simp]: "pow2 0 = 1" by simp
hoelzl@29804
    72
lemma pow2_1[simp]: "pow2 1 = 2" by simp
hoelzl@29804
    73
lemma pow2_neg: "pow2 x = inverse (pow2 (-x))" by simp
hoelzl@29804
    74
hoelzl@29804
    75
declare pow2_def[simp del]
obua@16782
    76
wenzelm@19765
    77
lemma pow2_add1: "pow2 (1 + a) = 2 * (pow2 a)"
obua@16782
    78
proof -
obua@16782
    79
  have h: "! n. nat (2 + int n) - Suc 0 = nat (1 + int n)" by arith
obua@16782
    80
  have g: "! a b. a - -1 = a + (1::int)" by arith
obua@16782
    81
  have pos: "! n. pow2 (int n + 1) = 2 * pow2 (int n)"
obua@16782
    82
    apply (auto, induct_tac n)
obua@16782
    83
    apply (simp_all add: pow2_def)
obua@16782
    84
    apply (rule_tac m1="2" and n1="nat (2 + int na)" in ssubst[OF realpow_num_eq_if])
huffman@23431
    85
    by (auto simp add: h)
obua@16782
    86
  show ?thesis
obua@16782
    87
  proof (induct a)
obua@16782
    88
    case (1 n)
nipkow@29667
    89
    from pos show ?case by (simp add: algebra_simps)
obua@16782
    90
  next
obua@16782
    91
    case (2 n)
obua@16782
    92
    show ?case
obua@16782
    93
      apply (auto)
obua@16782
    94
      apply (subst pow2_neg[of "- int n"])
huffman@23431
    95
      apply (subst pow2_neg[of "-1 - int n"])
obua@16782
    96
      apply (auto simp add: g pos)
obua@16782
    97
      done
wenzelm@19765
    98
  qed
obua@16782
    99
qed
wenzelm@19765
   100
obua@16782
   101
lemma pow2_add: "pow2 (a+b) = (pow2 a) * (pow2 b)"
obua@16782
   102
proof (induct b)
wenzelm@19765
   103
  case (1 n)
obua@16782
   104
  show ?case
obua@16782
   105
  proof (induct n)
obua@16782
   106
    case 0
obua@16782
   107
    show ?case by simp
obua@16782
   108
  next
obua@16782
   109
    case (Suc m)
wenzelm@41528
   110
    then show ?case by (auto simp add: algebra_simps pow2_add1)
obua@16782
   111
  qed
obua@16782
   112
next
obua@16782
   113
  case (2 n)
wenzelm@19765
   114
  show ?case
obua@16782
   115
  proof (induct n)
obua@16782
   116
    case 0
wenzelm@19765
   117
    show ?case
obua@16782
   118
      apply (auto)
obua@16782
   119
      apply (subst pow2_neg[of "a + -1"])
obua@16782
   120
      apply (subst pow2_neg[of "-1"])
obua@16782
   121
      apply (simp)
obua@16782
   122
      apply (insert pow2_add1[of "-a"])
nipkow@29667
   123
      apply (simp add: algebra_simps)
obua@16782
   124
      apply (subst pow2_neg[of "-a"])
obua@16782
   125
      apply (simp)
obua@16782
   126
      done
wenzelm@41528
   127
  next
obua@16782
   128
    case (Suc m)
wenzelm@19765
   129
    have a: "int m - (a + -2) =  1 + (int m - a + 1)" by arith
obua@16782
   130
    have b: "int m - -2 = 1 + (int m + 1)" by arith
obua@16782
   131
    show ?case
obua@16782
   132
      apply (auto)
obua@16782
   133
      apply (subst pow2_neg[of "a + (-2 - int m)"])
obua@16782
   134
      apply (subst pow2_neg[of "-2 - int m"])
nipkow@29667
   135
      apply (auto simp add: algebra_simps)
obua@16782
   136
      apply (subst a)
obua@16782
   137
      apply (subst b)
obua@16782
   138
      apply (simp only: pow2_add1)
obua@16782
   139
      apply (subst pow2_neg[of "int m - a + 1"])
obua@16782
   140
      apply (subst pow2_neg[of "int m + 1"])
obua@16782
   141
      apply auto
wenzelm@41528
   142
      apply (insert Suc)
nipkow@29667
   143
      apply (auto simp add: algebra_simps)
obua@16782
   144
      done
obua@16782
   145
  qed
obua@16782
   146
qed
obua@16782
   147
wenzelm@41528
   148
lemma float_components[simp]: "Float (mantissa f) (scale f) = f" by (cases f) auto
hoelzl@29804
   149
wenzelm@41528
   150
lemma float_split: "\<exists> a b. x = Float a b" by (cases x) auto
obua@16782
   151
hoelzl@29804
   152
lemma float_split2: "(\<forall> a b. x \<noteq> Float a b) = False" by (auto simp add: float_split)
hoelzl@29804
   153
hoelzl@31098
   154
lemma float_zero[simp]: "real (Float 0 e) = 0" by simp
hoelzl@29804
   155
hoelzl@29804
   156
lemma abs_div_2_less: "a \<noteq> 0 \<Longrightarrow> a \<noteq> -1 \<Longrightarrow> abs((a::int) div 2) < abs a"
hoelzl@29804
   157
by arith
wenzelm@21404
   158
hoelzl@29804
   159
function normfloat :: "float \<Rightarrow> float" where
wenzelm@41528
   160
  "normfloat (Float a b) =
wenzelm@41528
   161
    (if a \<noteq> 0 \<and> even a then normfloat (Float (a div 2) (b+1))
wenzelm@41528
   162
     else if a=0 then Float 0 0 else Float a b)"
hoelzl@29804
   163
by pat_completeness auto
hoelzl@29804
   164
termination by (relation "measure (nat o abs o mantissa)") (auto intro: abs_div_2_less)
hoelzl@29804
   165
declare normfloat.simps[simp del]
obua@16782
   166
hoelzl@31098
   167
theorem normfloat[symmetric, simp]: "real f = real (normfloat f)"
hoelzl@29804
   168
proof (induct f rule: normfloat.induct)
hoelzl@29804
   169
  case (1 a b)
hoelzl@29804
   170
  have real2: "2 = real (2::int)"
hoelzl@29804
   171
    by auto
hoelzl@29804
   172
  show ?case
hoelzl@29804
   173
    apply (subst normfloat.simps)
wenzelm@41528
   174
    apply auto
hoelzl@29804
   175
    apply (subst 1[symmetric])
hoelzl@29804
   176
    apply (auto simp add: pow2_add even_def)
hoelzl@29804
   177
    done
hoelzl@29804
   178
qed
obua@16782
   179
hoelzl@29804
   180
lemma pow2_neq_zero[simp]: "pow2 x \<noteq> 0"
hoelzl@29804
   181
  by (auto simp add: pow2_def)
obua@16782
   182
wenzelm@26313
   183
lemma pow2_int: "pow2 (int c) = 2^c"
obua@16782
   184
by (simp add: pow2_def)
obua@16782
   185
hoelzl@29804
   186
lemma zero_less_pow2[simp]:
obua@16782
   187
  "0 < pow2 x"
obua@16782
   188
proof -
obua@16782
   189
  {
obua@16782
   190
    fix y
wenzelm@19765
   191
    have "0 <= y \<Longrightarrow> 0 < pow2 y"
wenzelm@41528
   192
      apply (induct y)
wenzelm@41528
   193
      apply (induct_tac n)
wenzelm@41528
   194
      apply (simp_all add: pow2_add)
wenzelm@41528
   195
      done
obua@16782
   196
  }
obua@16782
   197
  note helper=this
obua@16782
   198
  show ?thesis
obua@16782
   199
    apply (case_tac "0 <= x")
obua@16782
   200
    apply (simp add: helper)
obua@16782
   201
    apply (subst pow2_neg)
obua@16782
   202
    apply (simp add: helper)
obua@16782
   203
    done
obua@16782
   204
qed
obua@16782
   205
hoelzl@29804
   206
lemma normfloat_imp_odd_or_zero: "normfloat f = Float a b \<Longrightarrow> odd a \<or> (a = 0 \<and> b = 0)"
hoelzl@29804
   207
proof (induct f rule: normfloat.induct)
hoelzl@29804
   208
  case (1 u v)
hoelzl@29804
   209
  from 1 have ab: "normfloat (Float u v) = Float a b" by auto
hoelzl@29804
   210
  {
hoelzl@29804
   211
    assume eu: "even u"
hoelzl@29804
   212
    assume z: "u \<noteq> 0"
hoelzl@29804
   213
    have "normfloat (Float u v) = normfloat (Float (u div 2) (v + 1))"
hoelzl@29804
   214
      apply (subst normfloat.simps)
hoelzl@29804
   215
      by (simp add: eu z)
hoelzl@29804
   216
    with ab have "normfloat (Float (u div 2) (v + 1)) = Float a b" by simp
hoelzl@29804
   217
    with 1 eu z have ?case by auto
hoelzl@29804
   218
  }
hoelzl@29804
   219
  note case1 = this
hoelzl@29804
   220
  {
hoelzl@29804
   221
    assume "odd u \<or> u = 0"
hoelzl@29804
   222
    then have ou: "\<not> (u \<noteq> 0 \<and> even u)" by auto
hoelzl@29804
   223
    have "normfloat (Float u v) = (if u = 0 then Float 0 0 else Float u v)"
hoelzl@29804
   224
      apply (subst normfloat.simps)
hoelzl@29804
   225
      apply (simp add: ou)
hoelzl@29804
   226
      done
hoelzl@29804
   227
    with ab have "Float a b = (if u = 0 then Float 0 0 else Float u v)" by auto
hoelzl@29804
   228
    then have ?case
hoelzl@29804
   229
      apply (case_tac "u=0")
hoelzl@29804
   230
      apply (auto)
hoelzl@29804
   231
      by (insert ou, auto)
hoelzl@29804
   232
  }
hoelzl@29804
   233
  note case2 = this
hoelzl@29804
   234
  show ?case
hoelzl@29804
   235
    apply (case_tac "odd u \<or> u = 0")
hoelzl@29804
   236
    apply (rule case2)
hoelzl@29804
   237
    apply simp
hoelzl@29804
   238
    apply (rule case1)
hoelzl@29804
   239
    apply auto
hoelzl@29804
   240
    done
hoelzl@29804
   241
qed
hoelzl@29804
   242
hoelzl@29804
   243
lemma float_eq_odd_helper: 
hoelzl@29804
   244
  assumes odd: "odd a'"
hoelzl@31098
   245
  and floateq: "real (Float a b) = real (Float a' b')"
hoelzl@29804
   246
  shows "b \<le> b'"
hoelzl@29804
   247
proof - 
hoelzl@29804
   248
  {
hoelzl@29804
   249
    assume bcmp: "b > b'"
hoelzl@29804
   250
    from floateq have eq: "real a * pow2 b = real a' * pow2 b'" by simp
hoelzl@29804
   251
    {
hoelzl@29804
   252
      fix x y z :: real
hoelzl@29804
   253
      assume "y \<noteq> 0"
hoelzl@29804
   254
      then have "(x * inverse y = z) = (x = z * y)"
wenzelm@32960
   255
        by auto
hoelzl@29804
   256
    }
hoelzl@29804
   257
    note inverse = this
hoelzl@29804
   258
    have eq': "real a * (pow2 (b - b')) = real a'"
hoelzl@29804
   259
      apply (subst diff_int_def)
hoelzl@29804
   260
      apply (subst pow2_add)
hoelzl@29804
   261
      apply (subst pow2_neg[where x = "-b'"])
hoelzl@29804
   262
      apply simp
hoelzl@29804
   263
      apply (subst mult_assoc[symmetric])
hoelzl@29804
   264
      apply (subst inverse)
hoelzl@29804
   265
      apply (simp_all add: eq)
hoelzl@29804
   266
      done
hoelzl@29804
   267
    have "\<exists> z > 0. pow2 (b-b') = 2^z"
hoelzl@29804
   268
      apply (rule exI[where x="nat (b - b')"])
hoelzl@29804
   269
      apply (auto)
hoelzl@29804
   270
      apply (insert bcmp)
hoelzl@29804
   271
      apply simp
hoelzl@29804
   272
      apply (subst pow2_int[symmetric])
hoelzl@29804
   273
      apply auto
hoelzl@29804
   274
      done
hoelzl@29804
   275
    then obtain z where z: "z > 0 \<and> pow2 (b-b') = 2^z" by auto
hoelzl@29804
   276
    with eq' have "real a * 2^z = real a'"
hoelzl@29804
   277
      by auto
hoelzl@29804
   278
    then have "real a * real ((2::int)^z) = real a'"
hoelzl@29804
   279
      by auto
hoelzl@29804
   280
    then have "real (a * 2^z) = real a'"
hoelzl@29804
   281
      apply (subst real_of_int_mult)
hoelzl@29804
   282
      apply simp
hoelzl@29804
   283
      done
hoelzl@29804
   284
    then have a'_rep: "a * 2^z = a'" by arith
hoelzl@29804
   285
    then have "a' = a*2^z" by simp
hoelzl@29804
   286
    with z have "even a'" by simp
hoelzl@29804
   287
    with odd have False by auto
hoelzl@29804
   288
  }
hoelzl@29804
   289
  then show ?thesis by arith
hoelzl@29804
   290
qed
hoelzl@29804
   291
hoelzl@29804
   292
lemma float_eq_odd: 
hoelzl@29804
   293
  assumes odd1: "odd a"
hoelzl@29804
   294
  and odd2: "odd a'"
hoelzl@31098
   295
  and floateq: "real (Float a b) = real (Float a' b')"
hoelzl@29804
   296
  shows "a = a' \<and> b = b'"
hoelzl@29804
   297
proof -
hoelzl@29804
   298
  from 
hoelzl@29804
   299
     float_eq_odd_helper[OF odd2 floateq] 
hoelzl@29804
   300
     float_eq_odd_helper[OF odd1 floateq[symmetric]]
wenzelm@41528
   301
  have beq: "b = b'" by arith
hoelzl@29804
   302
  with floateq show ?thesis by auto
hoelzl@29804
   303
qed
hoelzl@29804
   304
hoelzl@29804
   305
theorem normfloat_unique:
hoelzl@31098
   306
  assumes real_of_float_eq: "real f = real g"
hoelzl@29804
   307
  shows "normfloat f = normfloat g"
hoelzl@29804
   308
proof - 
hoelzl@29804
   309
  from float_split[of "normfloat f"] obtain a b where normf:"normfloat f = Float a b" by auto
hoelzl@29804
   310
  from float_split[of "normfloat g"] obtain a' b' where normg:"normfloat g = Float a' b'" by auto
hoelzl@31098
   311
  have "real (normfloat f) = real (normfloat g)"
hoelzl@31098
   312
    by (simp add: real_of_float_eq)
hoelzl@31098
   313
  then have float_eq: "real (Float a b) = real (Float a' b')"
hoelzl@29804
   314
    by (simp add: normf normg)
hoelzl@29804
   315
  have ab: "odd a \<or> (a = 0 \<and> b = 0)" by (rule normfloat_imp_odd_or_zero[OF normf])
hoelzl@29804
   316
  have ab': "odd a' \<or> (a' = 0 \<and> b' = 0)" by (rule normfloat_imp_odd_or_zero[OF normg])
hoelzl@29804
   317
  {
hoelzl@29804
   318
    assume odd: "odd a"
hoelzl@29804
   319
    then have "a \<noteq> 0" by (simp add: even_def, arith)
hoelzl@29804
   320
    with float_eq have "a' \<noteq> 0" by auto
hoelzl@29804
   321
    with ab' have "odd a'" by simp
hoelzl@29804
   322
    from odd this float_eq have "a = a' \<and> b = b'" by (rule float_eq_odd)
hoelzl@29804
   323
  }
hoelzl@29804
   324
  note odd_case = this
hoelzl@29804
   325
  {
hoelzl@29804
   326
    assume even: "even a"
hoelzl@29804
   327
    with ab have a0: "a = 0" by simp
hoelzl@29804
   328
    with float_eq have a0': "a' = 0" by auto 
hoelzl@29804
   329
    from a0 a0' ab ab' have "a = a' \<and> b = b'" by auto
hoelzl@29804
   330
  }
hoelzl@29804
   331
  note even_case = this
hoelzl@29804
   332
  from odd_case even_case show ?thesis
hoelzl@29804
   333
    apply (simp add: normf normg)
hoelzl@29804
   334
    apply (case_tac "even a")
hoelzl@29804
   335
    apply auto
hoelzl@29804
   336
    done
hoelzl@29804
   337
qed
hoelzl@29804
   338
hoelzl@29804
   339
instantiation float :: plus begin
hoelzl@29804
   340
fun plus_float where
hoelzl@29804
   341
[simp del]: "(Float a_m a_e) + (Float b_m b_e) = 
hoelzl@29804
   342
     (if a_e \<le> b_e then Float (a_m + b_m * 2^(nat(b_e - a_e))) a_e 
hoelzl@29804
   343
                   else Float (a_m * 2^(nat (a_e - b_e)) + b_m) b_e)"
hoelzl@29804
   344
instance ..
hoelzl@29804
   345
end
hoelzl@29804
   346
hoelzl@29804
   347
instantiation float :: uminus begin
haftmann@30960
   348
primrec uminus_float where [simp del]: "uminus_float (Float m e) = Float (-m) e"
hoelzl@29804
   349
instance ..
hoelzl@29804
   350
end
hoelzl@29804
   351
hoelzl@29804
   352
instantiation float :: minus begin
haftmann@30960
   353
definition minus_float where [simp del]: "(z::float) - w = z + (- w)"
hoelzl@29804
   354
instance ..
hoelzl@29804
   355
end
hoelzl@29804
   356
hoelzl@29804
   357
instantiation float :: times begin
hoelzl@29804
   358
fun times_float where [simp del]: "(Float a_m a_e) * (Float b_m b_e) = Float (a_m * b_m) (a_e + b_e)"
hoelzl@29804
   359
instance ..
hoelzl@29804
   360
end
hoelzl@29804
   361
haftmann@30960
   362
primrec float_pprt :: "float \<Rightarrow> float" where
haftmann@30960
   363
  "float_pprt (Float a e) = (if 0 <= a then (Float a e) else 0)"
hoelzl@29804
   364
haftmann@30960
   365
primrec float_nprt :: "float \<Rightarrow> float" where
haftmann@30960
   366
  "float_nprt (Float a e) = (if 0 <= a then 0 else (Float a e))" 
hoelzl@29804
   367
hoelzl@29804
   368
instantiation float :: ord begin
hoelzl@31098
   369
definition le_float_def: "z \<le> (w :: float) \<equiv> real z \<le> real w"
hoelzl@31098
   370
definition less_float_def: "z < (w :: float) \<equiv> real z < real w"
hoelzl@29804
   371
instance ..
hoelzl@29804
   372
end
hoelzl@29804
   373
hoelzl@31098
   374
lemma real_of_float_add[simp]: "real (a + b) = real a + real (b :: float)"
wenzelm@41528
   375
  by (cases a, cases b) (simp add: algebra_simps plus_float.simps, 
hoelzl@29804
   376
      auto simp add: pow2_int[symmetric] pow2_add[symmetric])
hoelzl@29804
   377
hoelzl@31098
   378
lemma real_of_float_minus[simp]: "real (- a) = - real (a :: float)"
wenzelm@41528
   379
  by (cases a) (simp add: uminus_float.simps)
hoelzl@29804
   380
hoelzl@31098
   381
lemma real_of_float_sub[simp]: "real (a - b) = real a - real (b :: float)"
wenzelm@41528
   382
  by (cases a, cases b) (simp add: minus_float_def)
hoelzl@29804
   383
hoelzl@31098
   384
lemma real_of_float_mult[simp]: "real (a*b) = real a * real (b :: float)"
wenzelm@41528
   385
  by (cases a, cases b) (simp add: times_float.simps pow2_add)
hoelzl@29804
   386
hoelzl@31098
   387
lemma real_of_float_0[simp]: "real (0 :: float) = 0"
hoelzl@29804
   388
  by (auto simp add: zero_float_def float_zero)
hoelzl@29804
   389
hoelzl@31098
   390
lemma real_of_float_1[simp]: "real (1 :: float) = 1"
hoelzl@29804
   391
  by (auto simp add: one_float_def)
hoelzl@29804
   392
obua@16782
   393
lemma zero_le_float:
hoelzl@31098
   394
  "(0 <= real (Float a b)) = (0 <= a)"
hoelzl@29804
   395
  apply auto
hoelzl@29804
   396
  apply (auto simp add: zero_le_mult_iff)
obua@16782
   397
  apply (insert zero_less_pow2[of b])
obua@16782
   398
  apply (simp_all)
obua@16782
   399
  done
obua@16782
   400
obua@16782
   401
lemma float_le_zero:
hoelzl@31098
   402
  "(real (Float a b) <= 0) = (a <= 0)"
hoelzl@29804
   403
  apply auto
obua@16782
   404
  apply (auto simp add: mult_le_0_iff)
obua@16782
   405
  apply (insert zero_less_pow2[of b])
obua@16782
   406
  apply auto
obua@16782
   407
  done
obua@16782
   408
hoelzl@39161
   409
lemma zero_less_float:
hoelzl@39161
   410
  "(0 < real (Float a b)) = (0 < a)"
hoelzl@39161
   411
  apply auto
hoelzl@39161
   412
  apply (auto simp add: zero_less_mult_iff)
hoelzl@39161
   413
  apply (insert zero_less_pow2[of b])
hoelzl@39161
   414
  apply (simp_all)
hoelzl@39161
   415
  done
hoelzl@39161
   416
hoelzl@39161
   417
lemma float_less_zero:
hoelzl@39161
   418
  "(real (Float a b) < 0) = (a < 0)"
hoelzl@39161
   419
  apply auto
hoelzl@39161
   420
  apply (auto simp add: mult_less_0_iff)
hoelzl@39161
   421
  apply (insert zero_less_pow2[of b])
hoelzl@39161
   422
  apply (simp_all)
hoelzl@39161
   423
  done
hoelzl@39161
   424
hoelzl@31098
   425
declare real_of_float_simp[simp del]
hoelzl@29804
   426
hoelzl@31098
   427
lemma real_of_float_pprt[simp]: "real (float_pprt a) = pprt (real a)"
wenzelm@41528
   428
  by (cases a) (auto simp add: zero_le_float float_le_zero)
hoelzl@29804
   429
hoelzl@31098
   430
lemma real_of_float_nprt[simp]: "real (float_nprt a) = nprt (real a)"
wenzelm@41528
   431
  by (cases a) (auto simp add: zero_le_float float_le_zero)
hoelzl@29804
   432
hoelzl@29804
   433
instance float :: ab_semigroup_add
hoelzl@29804
   434
proof (intro_classes)
hoelzl@29804
   435
  fix a b c :: float
hoelzl@29804
   436
  show "a + b + c = a + (b + c)"
wenzelm@41528
   437
    by (cases a, cases b, cases c)
wenzelm@41528
   438
      (auto simp add: algebra_simps power_add[symmetric] plus_float.simps)
hoelzl@29804
   439
next
hoelzl@29804
   440
  fix a b :: float
hoelzl@29804
   441
  show "a + b = b + a"
wenzelm@41528
   442
    by (cases a, cases b) (simp add: plus_float.simps)
hoelzl@29804
   443
qed
hoelzl@29804
   444
hoelzl@29804
   445
instance float :: comm_monoid_mult
hoelzl@29804
   446
proof (intro_classes)
hoelzl@29804
   447
  fix a b c :: float
hoelzl@29804
   448
  show "a * b * c = a * (b * c)"
wenzelm@41528
   449
    by (cases a, cases b, cases c) (simp add: times_float.simps)
hoelzl@29804
   450
next
hoelzl@29804
   451
  fix a b :: float
hoelzl@29804
   452
  show "a * b = b * a"
wenzelm@41528
   453
    by (cases a, cases b) (simp add: times_float.simps)
hoelzl@29804
   454
next
hoelzl@29804
   455
  fix a :: float
hoelzl@29804
   456
  show "1 * a = a"
wenzelm@41528
   457
    by (cases a) (simp add: times_float.simps one_float_def)
hoelzl@29804
   458
qed
hoelzl@29804
   459
hoelzl@29804
   460
(* Floats do NOT form a cancel_semigroup_add: *)
hoelzl@29804
   461
lemma "0 + Float 0 1 = 0 + Float 0 2"
hoelzl@29804
   462
  by (simp add: plus_float.simps zero_float_def)
hoelzl@29804
   463
hoelzl@29804
   464
instance float :: comm_semiring
hoelzl@29804
   465
proof (intro_classes)
hoelzl@29804
   466
  fix a b c :: float
hoelzl@29804
   467
  show "(a + b) * c = a * c + b * c"
wenzelm@41528
   468
    by (cases a, cases b, cases c) (simp add: plus_float.simps times_float.simps algebra_simps)
hoelzl@29804
   469
qed
hoelzl@29804
   470
hoelzl@29804
   471
(* Floats do NOT form an order, because "(x < y) = (x <= y & x <> y)" does NOT hold *)
hoelzl@29804
   472
hoelzl@29804
   473
instance float :: zero_neq_one
hoelzl@29804
   474
proof (intro_classes)
hoelzl@29804
   475
  show "(0::float) \<noteq> 1"
hoelzl@29804
   476
    by (simp add: zero_float_def one_float_def)
hoelzl@29804
   477
qed
hoelzl@29804
   478
hoelzl@29804
   479
lemma float_le_simp: "((x::float) \<le> y) = (0 \<le> y - x)"
hoelzl@29804
   480
  by (auto simp add: le_float_def)
hoelzl@29804
   481
hoelzl@29804
   482
lemma float_less_simp: "((x::float) < y) = (0 < y - x)"
hoelzl@29804
   483
  by (auto simp add: less_float_def)
hoelzl@29804
   484
hoelzl@31098
   485
lemma real_of_float_min: "real (min x y :: float) = min (real x) (real y)" unfolding min_def le_float_def by auto
hoelzl@31098
   486
lemma real_of_float_max: "real (max a b :: float) = max (real a) (real b)" unfolding max_def le_float_def by auto
hoelzl@29804
   487
hoelzl@31098
   488
lemma float_power: "real (x ^ n :: float) = real x ^ n"
haftmann@30960
   489
  by (induct n) simp_all
hoelzl@29804
   490
hoelzl@29804
   491
lemma zero_le_pow2[simp]: "0 \<le> pow2 s"
hoelzl@29804
   492
  apply (subgoal_tac "0 < pow2 s")
hoelzl@29804
   493
  apply (auto simp only:)
hoelzl@29804
   494
  apply auto
obua@16782
   495
  done
obua@16782
   496
hoelzl@29804
   497
lemma pow2_less_0_eq_False[simp]: "(pow2 s < 0) = False"
hoelzl@29804
   498
  apply auto
hoelzl@29804
   499
  apply (subgoal_tac "0 \<le> pow2 s")
hoelzl@29804
   500
  apply simp
hoelzl@29804
   501
  apply simp
obua@24301
   502
  done
obua@24301
   503
hoelzl@29804
   504
lemma pow2_le_0_eq_False[simp]: "(pow2 s \<le> 0) = False"
hoelzl@29804
   505
  apply auto
hoelzl@29804
   506
  apply (subgoal_tac "0 < pow2 s")
hoelzl@29804
   507
  apply simp
hoelzl@29804
   508
  apply simp
obua@24301
   509
  done
obua@24301
   510
hoelzl@29804
   511
lemma float_pos_m_pos: "0 < Float m e \<Longrightarrow> 0 < m"
hoelzl@31098
   512
  unfolding less_float_def real_of_float_simp real_of_float_0 zero_less_mult_iff
obua@16782
   513
  by auto
wenzelm@19765
   514
hoelzl@29804
   515
lemma float_pos_less1_e_neg: assumes "0 < Float m e" and "Float m e < 1" shows "e < 0"
hoelzl@29804
   516
proof -
hoelzl@29804
   517
  have "0 < m" using float_pos_m_pos `0 < Float m e` by auto
hoelzl@29804
   518
  hence "0 \<le> real m" and "1 \<le> real m" by auto
hoelzl@29804
   519
  
hoelzl@29804
   520
  show "e < 0"
hoelzl@29804
   521
  proof (rule ccontr)
hoelzl@29804
   522
    assume "\<not> e < 0" hence "0 \<le> e" by auto
hoelzl@29804
   523
    hence "1 \<le> pow2 e" unfolding pow2_def by auto
hoelzl@29804
   524
    from mult_mono[OF `1 \<le> real m` this `0 \<le> real m`]
hoelzl@31098
   525
    have "1 \<le> Float m e" by (simp add: le_float_def real_of_float_simp)
hoelzl@29804
   526
    thus False using `Float m e < 1` unfolding less_float_def le_float_def by auto
hoelzl@29804
   527
  qed
hoelzl@29804
   528
qed
hoelzl@29804
   529
hoelzl@29804
   530
lemma float_less1_mantissa_bound: assumes "0 < Float m e" "Float m e < 1" shows "m < 2^(nat (-e))"
hoelzl@29804
   531
proof -
hoelzl@29804
   532
  have "e < 0" using float_pos_less1_e_neg assms by auto
hoelzl@29804
   533
  have "\<And>x. (0::real) < 2^x" by auto
hoelzl@29804
   534
  have "real m < 2^(nat (-e))" using `Float m e < 1`
hoelzl@31098
   535
    unfolding less_float_def real_of_float_neg_exp[OF `e < 0`] real_of_float_1
hoelzl@29804
   536
          real_mult_less_iff1[of _ _ 1, OF `0 < 2^(nat (-e))`, symmetric] 
huffman@36778
   537
          mult_assoc by auto
hoelzl@29804
   538
  thus ?thesis unfolding real_of_int_less_iff[symmetric] by auto
hoelzl@29804
   539
qed
hoelzl@29804
   540
hoelzl@29804
   541
function bitlen :: "int \<Rightarrow> int" where
hoelzl@29804
   542
"bitlen 0 = 0" | 
hoelzl@29804
   543
"bitlen -1 = 1" | 
hoelzl@29804
   544
"0 < x \<Longrightarrow> bitlen x = 1 + (bitlen (x div 2))" | 
hoelzl@29804
   545
"x < -1 \<Longrightarrow> bitlen x = 1 + (bitlen (x div 2))"
hoelzl@29804
   546
  apply (case_tac "x = 0 \<or> x = -1 \<or> x < -1 \<or> x > 0")
hoelzl@29804
   547
  apply auto
hoelzl@29804
   548
  done
hoelzl@29804
   549
termination by (relation "measure (nat o abs)", auto)
hoelzl@29804
   550
hoelzl@29804
   551
lemma bitlen_ge0: "0 \<le> bitlen x" by (induct x rule: bitlen.induct, auto)
hoelzl@29804
   552
lemma bitlen_ge1: "x \<noteq> 0 \<Longrightarrow> 1 \<le> bitlen x" by (induct x rule: bitlen.induct, auto simp add: bitlen_ge0)
hoelzl@29804
   553
hoelzl@29804
   554
lemma bitlen_bounds': assumes "0 < x" shows "2^nat (bitlen x - 1) \<le> x \<and> x + 1 \<le> 2^nat (bitlen x)" (is "?P x")
hoelzl@29804
   555
  using `0 < x`
hoelzl@29804
   556
proof (induct x rule: bitlen.induct)
hoelzl@29804
   557
  fix x
hoelzl@29804
   558
  assume "0 < x" and hyp: "0 < x div 2 \<Longrightarrow> ?P (x div 2)" hence "0 \<le> x" and "x \<noteq> 0" by auto
hoelzl@29804
   559
  { fix x have "0 \<le> 1 + bitlen x" using bitlen_ge0[of x] by auto } note gt0_pls1 = this
hoelzl@29804
   560
hoelzl@29804
   561
  have "0 < (2::int)" by auto
obua@16782
   562
hoelzl@29804
   563
  show "?P x"
hoelzl@29804
   564
  proof (cases "x = 1")
hoelzl@29804
   565
    case True show "?P x" unfolding True by auto
hoelzl@29804
   566
  next
hoelzl@29804
   567
    case False hence "2 \<le> x" using `0 < x` `x \<noteq> 1` by auto
hoelzl@29804
   568
    hence "2 div 2 \<le> x div 2" by (rule zdiv_mono1, auto)
hoelzl@29804
   569
    hence "0 < x div 2" and "x div 2 \<noteq> 0" by auto
hoelzl@29804
   570
    hence bitlen_s1_ge0: "0 \<le> bitlen (x div 2) - 1" using bitlen_ge1[OF `x div 2 \<noteq> 0`] by auto
obua@16782
   571
hoelzl@29804
   572
    { from hyp[OF `0 < x div 2`]
hoelzl@29804
   573
      have "2 ^ nat (bitlen (x div 2) - 1) \<le> x div 2" by auto
hoelzl@29804
   574
      hence "2 ^ nat (bitlen (x div 2) - 1) * 2 \<le> x div 2 * 2" by (rule mult_right_mono, auto)
hoelzl@29804
   575
      also have "\<dots> \<le> x" using `0 < x` by auto
hoelzl@29804
   576
      finally have "2^nat (1 + bitlen (x div 2) - 1) \<le> x" unfolding power_Suc2[symmetric] Suc_nat_eq_nat_zadd1[OF bitlen_s1_ge0] by auto
hoelzl@29804
   577
    } moreover
hoelzl@29804
   578
    { have "x + 1 \<le> x - x mod 2 + 2"
hoelzl@29804
   579
      proof -
wenzelm@32960
   580
        have "x mod 2 < 2" using `0 < x` by auto
wenzelm@32960
   581
        hence "x < x - x mod 2 +  2" unfolding algebra_simps by auto
wenzelm@32960
   582
        thus ?thesis by auto
hoelzl@29804
   583
      qed
hoelzl@29804
   584
      also have "x - x mod 2 + 2 = (x div 2 + 1) * 2" unfolding algebra_simps using `0 < x` zdiv_zmod_equality2[of x 2 0] by auto
hoelzl@29804
   585
      also have "\<dots> \<le> 2^nat (bitlen (x div 2)) * 2" using hyp[OF `0 < x div 2`, THEN conjunct2] by (rule mult_right_mono, auto)
hoelzl@29804
   586
      also have "\<dots> = 2^(1 + nat (bitlen (x div 2)))" unfolding power_Suc2[symmetric] by auto
hoelzl@29804
   587
      finally have "x + 1 \<le> 2^(1 + nat (bitlen (x div 2)))" .
hoelzl@29804
   588
    }
hoelzl@29804
   589
    ultimately show ?thesis
hoelzl@29804
   590
      unfolding bitlen.simps(3)[OF `0 < x`] nat_add_distrib[OF zero_le_one bitlen_ge0]
hoelzl@29804
   591
      unfolding add_commute nat_add_distrib[OF zero_le_one gt0_pls1]
hoelzl@29804
   592
      by auto
hoelzl@29804
   593
  qed
hoelzl@29804
   594
next
hoelzl@29804
   595
  fix x :: int assume "x < -1" and "0 < x" hence False by auto
hoelzl@29804
   596
  thus "?P x" by auto
hoelzl@29804
   597
qed auto
hoelzl@29804
   598
hoelzl@29804
   599
lemma bitlen_bounds: assumes "0 < x" shows "2^nat (bitlen x - 1) \<le> x \<and> x < 2^nat (bitlen x)"
hoelzl@29804
   600
  using bitlen_bounds'[OF `0<x`] by auto
hoelzl@29804
   601
hoelzl@29804
   602
lemma bitlen_div: assumes "0 < m" shows "1 \<le> real m / 2^nat (bitlen m - 1)" and "real m / 2^nat (bitlen m - 1) < 2"
hoelzl@29804
   603
proof -
hoelzl@29804
   604
  let ?B = "2^nat(bitlen m - 1)"
hoelzl@29804
   605
hoelzl@29804
   606
  have "?B \<le> m" using bitlen_bounds[OF `0 <m`] ..
hoelzl@29804
   607
  hence "1 * ?B \<le> real m" unfolding real_of_int_le_iff[symmetric] by auto
hoelzl@29804
   608
  thus "1 \<le> real m / ?B" by auto
hoelzl@29804
   609
hoelzl@29804
   610
  have "m \<noteq> 0" using assms by auto
hoelzl@29804
   611
  have "0 \<le> bitlen m - 1" using bitlen_ge1[OF `m \<noteq> 0`] by auto
obua@16782
   612
hoelzl@29804
   613
  have "m < 2^nat(bitlen m)" using bitlen_bounds[OF `0 <m`] ..
hoelzl@29804
   614
  also have "\<dots> = 2^nat(bitlen m - 1 + 1)" using bitlen_ge1[OF `m \<noteq> 0`] by auto
hoelzl@29804
   615
  also have "\<dots> = ?B * 2" unfolding nat_add_distrib[OF `0 \<le> bitlen m - 1` zero_le_one] by auto
hoelzl@29804
   616
  finally have "real m < 2 * ?B" unfolding real_of_int_less_iff[symmetric] by auto
hoelzl@29804
   617
  hence "real m / ?B < 2 * ?B / ?B" by (rule divide_strict_right_mono, auto)
hoelzl@29804
   618
  thus "real m / ?B < 2" by auto
hoelzl@29804
   619
qed
hoelzl@29804
   620
hoelzl@29804
   621
lemma float_gt1_scale: assumes "1 \<le> Float m e"
hoelzl@29804
   622
  shows "0 \<le> e + (bitlen m - 1)"
hoelzl@29804
   623
proof (cases "0 \<le> e")
hoelzl@29804
   624
  have "0 < Float m e" using assms unfolding less_float_def le_float_def by auto
hoelzl@29804
   625
  hence "0 < m" using float_pos_m_pos by auto
hoelzl@29804
   626
  hence "m \<noteq> 0" by auto
hoelzl@29804
   627
  case True with bitlen_ge1[OF `m \<noteq> 0`] show ?thesis by auto
hoelzl@29804
   628
next
hoelzl@29804
   629
  have "0 < Float m e" using assms unfolding less_float_def le_float_def by auto
hoelzl@29804
   630
  hence "0 < m" using float_pos_m_pos by auto
hoelzl@29804
   631
  hence "m \<noteq> 0" and "1 < (2::int)" by auto
hoelzl@29804
   632
  case False let ?S = "2^(nat (-e))"
hoelzl@31098
   633
  have "1 \<le> real m * inverse ?S" using assms unfolding le_float_def real_of_float_nge0_exp[OF False] by auto
hoelzl@29804
   634
  hence "1 * ?S \<le> real m * inverse ?S * ?S" by (rule mult_right_mono, auto)
hoelzl@29804
   635
  hence "?S \<le> real m" unfolding mult_assoc by auto
hoelzl@29804
   636
  hence "?S \<le> m" unfolding real_of_int_le_iff[symmetric] by auto
hoelzl@29804
   637
  from this bitlen_bounds[OF `0 < m`, THEN conjunct2]
hoelzl@29804
   638
  have "nat (-e) < (nat (bitlen m))" unfolding power_strict_increasing_iff[OF `1 < 2`, symmetric] by (rule order_le_less_trans)
hoelzl@29804
   639
  hence "-e < bitlen m" using False bitlen_ge0 by auto
hoelzl@29804
   640
  thus ?thesis by auto
hoelzl@29804
   641
qed
hoelzl@29804
   642
hoelzl@31098
   643
lemma normalized_float: assumes "m \<noteq> 0" shows "real (Float m (- (bitlen m - 1))) = real m / 2^nat (bitlen m - 1)"
hoelzl@29804
   644
proof (cases "- (bitlen m - 1) = 0")
hoelzl@31098
   645
  case True show ?thesis unfolding real_of_float_simp pow2_def using True by auto
hoelzl@29804
   646
next
hoelzl@29804
   647
  case False hence P: "\<not> 0 \<le> - (bitlen m - 1)" using bitlen_ge1[OF `m \<noteq> 0`] by auto
huffman@36778
   648
  show ?thesis unfolding real_of_float_nge0_exp[OF P] divide_inverse by auto
hoelzl@29804
   649
qed
hoelzl@29804
   650
hoelzl@29804
   651
lemma bitlen_Pls: "bitlen (Int.Pls) = Int.Pls" by (subst Pls_def, subst Pls_def, simp)
hoelzl@29804
   652
hoelzl@29804
   653
lemma bitlen_Min: "bitlen (Int.Min) = Int.Bit1 Int.Pls" by (subst Min_def, simp add: Bit1_def) 
hoelzl@29804
   654
hoelzl@29804
   655
lemma bitlen_B0: "bitlen (Int.Bit0 b) = (if iszero b then Int.Pls else Int.succ (bitlen b))"
hoelzl@29804
   656
  apply (auto simp add: iszero_def succ_def)
hoelzl@29804
   657
  apply (simp add: Bit0_def Pls_def)
hoelzl@29804
   658
  apply (subst Bit0_def)
hoelzl@29804
   659
  apply simp
hoelzl@29804
   660
  apply (subgoal_tac "0 < 2 * b \<or> 2 * b < -1")
hoelzl@29804
   661
  apply auto
hoelzl@29804
   662
  done
obua@16782
   663
hoelzl@29804
   664
lemma bitlen_B1: "bitlen (Int.Bit1 b) = (if iszero (Int.succ b) then Int.Bit1 Int.Pls else Int.succ (bitlen b))"
hoelzl@29804
   665
proof -
hoelzl@29804
   666
  have h: "! x. (2*x + 1) div 2 = (x::int)"
hoelzl@29804
   667
    by arith    
hoelzl@29804
   668
  show ?thesis
hoelzl@29804
   669
    apply (auto simp add: iszero_def succ_def)
hoelzl@29804
   670
    apply (subst Bit1_def)+
hoelzl@29804
   671
    apply simp
hoelzl@29804
   672
    apply (subgoal_tac "2 * b + 1 = -1")
hoelzl@29804
   673
    apply (simp only:)
hoelzl@29804
   674
    apply simp_all
hoelzl@29804
   675
    apply (subst Bit1_def)
hoelzl@29804
   676
    apply simp
hoelzl@29804
   677
    apply (subgoal_tac "0 < 2 * b + 1 \<or> 2 * b + 1 < -1")
hoelzl@29804
   678
    apply (auto simp add: h)
hoelzl@29804
   679
    done
hoelzl@29804
   680
qed
hoelzl@29804
   681
hoelzl@29804
   682
lemma bitlen_number_of: "bitlen (number_of w) = number_of (bitlen w)"
hoelzl@29804
   683
  by (simp add: number_of_is_id)
obua@16782
   684
hoelzl@29804
   685
lemma [code]: "bitlen x = 
hoelzl@29804
   686
     (if x = 0  then 0 
hoelzl@29804
   687
 else if x = -1 then 1 
hoelzl@29804
   688
                else (1 + (bitlen (x div 2))))"
hoelzl@29804
   689
  by (cases "x = 0 \<or> x = -1 \<or> 0 < x") auto
hoelzl@29804
   690
hoelzl@29804
   691
definition lapprox_posrat :: "nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> float"
hoelzl@29804
   692
where
hoelzl@29804
   693
  "lapprox_posrat prec x y = 
hoelzl@29804
   694
   (let 
hoelzl@29804
   695
       l = nat (int prec + bitlen y - bitlen x) ;
hoelzl@29804
   696
       d = (x * 2^l) div y
hoelzl@29804
   697
    in normfloat (Float d (- (int l))))"
hoelzl@29804
   698
hoelzl@29804
   699
lemma pow2_minus: "pow2 (-x) = inverse (pow2 x)"
hoelzl@29804
   700
  unfolding pow2_neg[of "-x"] by auto
hoelzl@29804
   701
hoelzl@29804
   702
lemma lapprox_posrat: 
hoelzl@29804
   703
  assumes x: "0 \<le> x"
hoelzl@29804
   704
  and y: "0 < y"
hoelzl@31098
   705
  shows "real (lapprox_posrat prec x y) \<le> real x / real y"
hoelzl@29804
   706
proof -
hoelzl@29804
   707
  let ?l = "nat (int prec + bitlen y - bitlen x)"
hoelzl@29804
   708
  
hoelzl@29804
   709
  have "real (x * 2^?l div y) * inverse (2^?l) \<le> (real (x * 2^?l) / real y) * inverse (2^?l)" 
hoelzl@29804
   710
    by (rule mult_right_mono, fact real_of_int_div4, simp)
hoelzl@29804
   711
  also have "\<dots> \<le> (real x / real y) * 2^?l * inverse (2^?l)" by auto
huffman@36778
   712
  finally have "real (x * 2^?l div y) * inverse (2^?l) \<le> real x / real y" unfolding mult_assoc by auto
hoelzl@31098
   713
  thus ?thesis unfolding lapprox_posrat_def Let_def normfloat real_of_float_simp
hoelzl@29804
   714
    unfolding pow2_minus pow2_int minus_minus .
hoelzl@29804
   715
qed
obua@16782
   716
hoelzl@29804
   717
lemma real_of_int_div_mult: 
hoelzl@29804
   718
  fixes x y c :: int assumes "0 < y" and "0 < c"
hoelzl@29804
   719
  shows "real (x div y) \<le> real (x * c div y) * inverse (real c)"
hoelzl@29804
   720
proof -
hoelzl@29804
   721
  have "c * (x div y) + 0 \<le> c * x div y" unfolding zdiv_zmult1_eq[of c x y]
hoelzl@29804
   722
    by (rule zadd_left_mono, 
hoelzl@29804
   723
        auto intro!: mult_nonneg_nonneg 
hoelzl@29804
   724
             simp add: pos_imp_zdiv_nonneg_iff[OF `0 < y`] `0 < c`[THEN less_imp_le] pos_mod_sign[OF `0 < y`])
hoelzl@29804
   725
  hence "real (x div y) * real c \<le> real (x * c div y)" 
hoelzl@29804
   726
    unfolding real_of_int_mult[symmetric] real_of_int_le_iff zmult_commute by auto
hoelzl@29804
   727
  hence "real (x div y) * real c * inverse (real c) \<le> real (x * c div y) * inverse (real c)"
hoelzl@29804
   728
    using `0 < c` by auto
huffman@36778
   729
  thus ?thesis unfolding mult_assoc using `0 < c` by auto
hoelzl@29804
   730
qed
hoelzl@29804
   731
hoelzl@29804
   732
lemma lapprox_posrat_bottom: assumes "0 < y"
hoelzl@31098
   733
  shows "real (x div y) \<le> real (lapprox_posrat n x y)" 
hoelzl@29804
   734
proof -
hoelzl@29804
   735
  have pow: "\<And>x. (0::int) < 2^x" by auto
hoelzl@29804
   736
  show ?thesis
hoelzl@31098
   737
    unfolding lapprox_posrat_def Let_def real_of_float_add normfloat real_of_float_simp pow2_minus pow2_int
hoelzl@29804
   738
    using real_of_int_div_mult[OF `0 < y` pow] by auto
hoelzl@29804
   739
qed
hoelzl@29804
   740
hoelzl@29804
   741
lemma lapprox_posrat_nonneg: assumes "0 \<le> x" and "0 < y"
hoelzl@31098
   742
  shows "0 \<le> real (lapprox_posrat n x y)" 
hoelzl@29804
   743
proof -
hoelzl@29804
   744
  show ?thesis
hoelzl@31098
   745
    unfolding lapprox_posrat_def Let_def real_of_float_add normfloat real_of_float_simp pow2_minus pow2_int
hoelzl@29804
   746
    using pos_imp_zdiv_nonneg_iff[OF `0 < y`] assms by (auto intro!: mult_nonneg_nonneg)
hoelzl@29804
   747
qed
hoelzl@29804
   748
hoelzl@29804
   749
definition rapprox_posrat :: "nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> float"
hoelzl@29804
   750
where
hoelzl@29804
   751
  "rapprox_posrat prec x y = (let
hoelzl@29804
   752
     l = nat (int prec + bitlen y - bitlen x) ;
hoelzl@29804
   753
     X = x * 2^l ;
hoelzl@29804
   754
     d = X div y ;
hoelzl@29804
   755
     m = X mod y
hoelzl@29804
   756
   in normfloat (Float (d + (if m = 0 then 0 else 1)) (- (int l))))"
obua@16782
   757
hoelzl@29804
   758
lemma rapprox_posrat:
hoelzl@29804
   759
  assumes x: "0 \<le> x"
hoelzl@29804
   760
  and y: "0 < y"
hoelzl@31098
   761
  shows "real x / real y \<le> real (rapprox_posrat prec x y)"
hoelzl@29804
   762
proof -
hoelzl@29804
   763
  let ?l = "nat (int prec + bitlen y - bitlen x)" let ?X = "x * 2^?l"
hoelzl@29804
   764
  show ?thesis 
hoelzl@29804
   765
  proof (cases "?X mod y = 0")
hoelzl@29804
   766
    case True hence "y \<noteq> 0" and "y dvd ?X" using `0 < y` by auto
hoelzl@29804
   767
    from real_of_int_div[OF this]
hoelzl@29804
   768
    have "real (?X div y) * inverse (2 ^ ?l) = real ?X / real y * inverse (2 ^ ?l)" by auto
hoelzl@29804
   769
    also have "\<dots> = real x / real y * (2^?l * inverse (2^?l))" by auto
hoelzl@29804
   770
    finally have "real (?X div y) * inverse (2^?l) = real x / real y" by auto
hoelzl@29804
   771
    thus ?thesis unfolding rapprox_posrat_def Let_def normfloat if_P[OF True] 
hoelzl@31098
   772
      unfolding real_of_float_simp pow2_minus pow2_int minus_minus by auto
hoelzl@29804
   773
  next
hoelzl@29804
   774
    case False
hoelzl@29804
   775
    have "0 \<le> real y" and "real y \<noteq> 0" using `0 < y` by auto
hoelzl@29804
   776
    have "0 \<le> real y * 2^?l" by (rule mult_nonneg_nonneg, rule `0 \<le> real y`, auto)
obua@16782
   777
hoelzl@29804
   778
    have "?X = y * (?X div y) + ?X mod y" by auto
hoelzl@29804
   779
    also have "\<dots> \<le> y * (?X div y) + y" by (rule add_mono, auto simp add: pos_mod_bound[OF `0 < y`, THEN less_imp_le])
hoelzl@29804
   780
    also have "\<dots> = y * (?X div y + 1)" unfolding zadd_zmult_distrib2 by auto
hoelzl@29804
   781
    finally have "real ?X \<le> real y * real (?X div y + 1)" unfolding real_of_int_le_iff real_of_int_mult[symmetric] .
hoelzl@29804
   782
    hence "real ?X / (real y * 2^?l) \<le> real y * real (?X div y + 1) / (real y * 2^?l)" 
hoelzl@29804
   783
      by (rule divide_right_mono, simp only: `0 \<le> real y * 2^?l`)
hoelzl@29804
   784
    also have "\<dots> = real y * real (?X div y + 1) / real y / 2^?l" by auto
hoelzl@29804
   785
    also have "\<dots> = real (?X div y + 1) * inverse (2^?l)" unfolding nonzero_mult_divide_cancel_left[OF `real y \<noteq> 0`] 
huffman@36778
   786
      unfolding divide_inverse ..
hoelzl@31098
   787
    finally show ?thesis unfolding rapprox_posrat_def Let_def normfloat real_of_float_simp if_not_P[OF False]
hoelzl@29804
   788
      unfolding pow2_minus pow2_int minus_minus by auto
hoelzl@29804
   789
  qed
hoelzl@29804
   790
qed
hoelzl@29804
   791
hoelzl@29804
   792
lemma rapprox_posrat_le1: assumes "0 \<le> x" and "0 < y" and "x \<le> y"
hoelzl@31098
   793
  shows "real (rapprox_posrat n x y) \<le> 1"
hoelzl@29804
   794
proof -
hoelzl@29804
   795
  let ?l = "nat (int n + bitlen y - bitlen x)" let ?X = "x * 2^?l"
hoelzl@29804
   796
  show ?thesis
hoelzl@29804
   797
  proof (cases "?X mod y = 0")
hoelzl@29804
   798
    case True hence "y \<noteq> 0" and "y dvd ?X" using `0 < y` by auto
hoelzl@29804
   799
    from real_of_int_div[OF this]
hoelzl@29804
   800
    have "real (?X div y) * inverse (2 ^ ?l) = real ?X / real y * inverse (2 ^ ?l)" by auto
hoelzl@29804
   801
    also have "\<dots> = real x / real y * (2^?l * inverse (2^?l))" by auto
hoelzl@29804
   802
    finally have "real (?X div y) * inverse (2^?l) = real x / real y" by auto
hoelzl@29804
   803
    also have "real x / real y \<le> 1" using `0 \<le> x` and `0 < y` and `x \<le> y` by auto
hoelzl@29804
   804
    finally show ?thesis unfolding rapprox_posrat_def Let_def normfloat if_P[OF True]
hoelzl@31098
   805
      unfolding real_of_float_simp pow2_minus pow2_int minus_minus by auto
hoelzl@29804
   806
  next
hoelzl@29804
   807
    case False
hoelzl@29804
   808
    have "x \<noteq> y"
hoelzl@29804
   809
    proof (rule ccontr)
hoelzl@29804
   810
      assume "\<not> x \<noteq> y" hence "x = y" by auto
nipkow@30034
   811
      have "?X mod y = 0" unfolding `x = y` using mod_mult_self1_is_0 by auto
hoelzl@29804
   812
      thus False using False by auto
hoelzl@29804
   813
    qed
hoelzl@29804
   814
    hence "x < y" using `x \<le> y` by auto
hoelzl@29804
   815
    hence "real x / real y < 1" using `0 < y` and `0 \<le> x` by auto
obua@16782
   816
hoelzl@29804
   817
    from real_of_int_div4[of "?X" y]
huffman@35344
   818
    have "real (?X div y) \<le> (real x / real y) * 2^?l" unfolding real_of_int_mult times_divide_eq_left real_of_int_power real_number_of .
hoelzl@29804
   819
    also have "\<dots> < 1 * 2^?l" using `real x / real y < 1` by (rule mult_strict_right_mono, auto)
hoelzl@29804
   820
    finally have "?X div y < 2^?l" unfolding real_of_int_less_iff[of _ "2^?l", symmetric] by auto
hoelzl@29804
   821
    hence "?X div y + 1 \<le> 2^?l" by auto
hoelzl@29804
   822
    hence "real (?X div y + 1) * inverse (2^?l) \<le> 2^?l * inverse (2^?l)"
huffman@35344
   823
      unfolding real_of_int_le_iff[of _ "2^?l", symmetric] real_of_int_power real_number_of
hoelzl@29804
   824
      by (rule mult_right_mono, auto)
hoelzl@29804
   825
    hence "real (?X div y + 1) * inverse (2^?l) \<le> 1" by auto
hoelzl@31098
   826
    thus ?thesis unfolding rapprox_posrat_def Let_def normfloat real_of_float_simp if_not_P[OF False]
hoelzl@29804
   827
      unfolding pow2_minus pow2_int minus_minus by auto
hoelzl@29804
   828
  qed
hoelzl@29804
   829
qed
obua@16782
   830
hoelzl@29804
   831
lemma zdiv_greater_zero: fixes a b :: int assumes "0 < a" and "a \<le> b"
hoelzl@29804
   832
  shows "0 < b div a"
hoelzl@29804
   833
proof (rule ccontr)
hoelzl@29804
   834
  have "0 \<le> b" using assms by auto
hoelzl@29804
   835
  assume "\<not> 0 < b div a" hence "b div a = 0" using `0 \<le> b`[unfolded pos_imp_zdiv_nonneg_iff[OF `0<a`, of b, symmetric]] by auto
hoelzl@29804
   836
  have "b = a * (b div a) + b mod a" by auto
hoelzl@29804
   837
  hence "b = b mod a" unfolding `b div a = 0` by auto
hoelzl@29804
   838
  hence "b < a" using `0 < a`[THEN pos_mod_bound, of b] by auto
hoelzl@29804
   839
  thus False using `a \<le> b` by auto
hoelzl@29804
   840
qed
hoelzl@29804
   841
hoelzl@29804
   842
lemma rapprox_posrat_less1: assumes "0 \<le> x" and "0 < y" and "2 * x < y" and "0 < n"
hoelzl@31098
   843
  shows "real (rapprox_posrat n x y) < 1"
hoelzl@29804
   844
proof (cases "x = 0")
hoelzl@31098
   845
  case True thus ?thesis unfolding rapprox_posrat_def True Let_def normfloat real_of_float_simp by auto
hoelzl@29804
   846
next
hoelzl@29804
   847
  case False hence "0 < x" using `0 \<le> x` by auto
hoelzl@29804
   848
  hence "x < y" using assms by auto
hoelzl@29804
   849
  
hoelzl@29804
   850
  let ?l = "nat (int n + bitlen y - bitlen x)" let ?X = "x * 2^?l"
hoelzl@29804
   851
  show ?thesis
hoelzl@29804
   852
  proof (cases "?X mod y = 0")
hoelzl@29804
   853
    case True hence "y \<noteq> 0" and "y dvd ?X" using `0 < y` by auto
hoelzl@29804
   854
    from real_of_int_div[OF this]
hoelzl@29804
   855
    have "real (?X div y) * inverse (2 ^ ?l) = real ?X / real y * inverse (2 ^ ?l)" by auto
hoelzl@29804
   856
    also have "\<dots> = real x / real y * (2^?l * inverse (2^?l))" by auto
hoelzl@29804
   857
    finally have "real (?X div y) * inverse (2^?l) = real x / real y" by auto
hoelzl@29804
   858
    also have "real x / real y < 1" using `0 \<le> x` and `0 < y` and `x < y` by auto
hoelzl@31098
   859
    finally show ?thesis unfolding rapprox_posrat_def Let_def normfloat real_of_float_simp if_P[OF True]
hoelzl@29804
   860
      unfolding pow2_minus pow2_int minus_minus by auto
hoelzl@29804
   861
  next
hoelzl@29804
   862
    case False
hoelzl@29804
   863
    hence "(real x / real y) < 1 / 2" using `0 < y` and `0 \<le> x` `2 * x < y` by auto
obua@16782
   864
hoelzl@29804
   865
    have "0 < ?X div y"
hoelzl@29804
   866
    proof -
hoelzl@29804
   867
      have "2^nat (bitlen x - 1) \<le> y" and "y < 2^nat (bitlen y)"
wenzelm@32960
   868
        using bitlen_bounds[OF `0 < x`, THEN conjunct1] bitlen_bounds[OF `0 < y`, THEN conjunct2] `x < y` by auto
hoelzl@29804
   869
      hence "(2::int)^nat (bitlen x - 1) < 2^nat (bitlen y)" by (rule order_le_less_trans)
hoelzl@29804
   870
      hence "bitlen x \<le> bitlen y" by auto
hoelzl@29804
   871
      hence len_less: "nat (bitlen x - 1) \<le> nat (int (n - 1) + bitlen y)" by auto
hoelzl@29804
   872
hoelzl@29804
   873
      have "x \<noteq> 0" and "y \<noteq> 0" using `0 < x` `0 < y` by auto
hoelzl@29804
   874
hoelzl@29804
   875
      have exp_eq: "nat (int (n - 1) + bitlen y) - nat (bitlen x - 1) = ?l"
wenzelm@32960
   876
        using `bitlen x \<le> bitlen y` bitlen_ge1[OF `x \<noteq> 0`] bitlen_ge1[OF `y \<noteq> 0`] `0 < n` by auto
hoelzl@29804
   877
hoelzl@29804
   878
      have "y * 2^nat (bitlen x - 1) \<le> y * x" 
wenzelm@32960
   879
        using bitlen_bounds[OF `0 < x`, THEN conjunct1] `0 < y`[THEN less_imp_le] by (rule mult_left_mono)
hoelzl@29804
   880
      also have "\<dots> \<le> 2^nat (bitlen y) * x" using bitlen_bounds[OF `0 < y`, THEN conjunct2, THEN less_imp_le] `0 \<le> x` by (rule mult_right_mono)
hoelzl@29804
   881
      also have "\<dots> \<le> x * 2^nat (int (n - 1) + bitlen y)" unfolding mult_commute[of x] by (rule mult_right_mono, auto simp add: `0 \<le> x`)
hoelzl@29804
   882
      finally have "real y * 2^nat (bitlen x - 1) * inverse (2^nat (bitlen x - 1)) \<le> real x * 2^nat (int (n - 1) + bitlen y) * inverse (2^nat (bitlen x - 1))"
wenzelm@32960
   883
        unfolding real_of_int_le_iff[symmetric] by auto
hoelzl@29804
   884
      hence "real y \<le> real x * (2^nat (int (n - 1) + bitlen y) / (2^nat (bitlen x - 1)))" 
huffman@36778
   885
        unfolding mult_assoc divide_inverse by auto
hoelzl@29804
   886
      also have "\<dots> = real x * (2^(nat (int (n - 1) + bitlen y) - nat (bitlen x - 1)))" using power_diff[of "2::real", OF _ len_less] by auto
hoelzl@29804
   887
      finally have "y \<le> x * 2^?l" unfolding exp_eq unfolding real_of_int_le_iff[symmetric] by auto
hoelzl@29804
   888
      thus ?thesis using zdiv_greater_zero[OF `0 < y`] by auto
hoelzl@29804
   889
    qed
hoelzl@29804
   890
hoelzl@29804
   891
    from real_of_int_div4[of "?X" y]
huffman@35344
   892
    have "real (?X div y) \<le> (real x / real y) * 2^?l" unfolding real_of_int_mult times_divide_eq_left real_of_int_power real_number_of .
hoelzl@29804
   893
    also have "\<dots> < 1/2 * 2^?l" using `real x / real y < 1/2` by (rule mult_strict_right_mono, auto)
hoelzl@29804
   894
    finally have "?X div y * 2 < 2^?l" unfolding real_of_int_less_iff[of _ "2^?l", symmetric] by auto
hoelzl@29804
   895
    hence "?X div y + 1 < 2^?l" using `0 < ?X div y` by auto
hoelzl@29804
   896
    hence "real (?X div y + 1) * inverse (2^?l) < 2^?l * inverse (2^?l)"
huffman@35344
   897
      unfolding real_of_int_less_iff[of _ "2^?l", symmetric] real_of_int_power real_number_of
hoelzl@29804
   898
      by (rule mult_strict_right_mono, auto)
hoelzl@29804
   899
    hence "real (?X div y + 1) * inverse (2^?l) < 1" by auto
hoelzl@31098
   900
    thus ?thesis unfolding rapprox_posrat_def Let_def normfloat real_of_float_simp if_not_P[OF False]
hoelzl@29804
   901
      unfolding pow2_minus pow2_int minus_minus by auto
hoelzl@29804
   902
  qed
hoelzl@29804
   903
qed
hoelzl@29804
   904
hoelzl@29804
   905
lemma approx_rat_pattern: fixes P and ps :: "nat * int * int"
hoelzl@29804
   906
  assumes Y: "\<And>y prec x. \<lbrakk>y = 0; ps = (prec, x, 0)\<rbrakk> \<Longrightarrow> P" 
hoelzl@29804
   907
  and A: "\<And>x y prec. \<lbrakk>0 \<le> x; 0 < y; ps = (prec, x, y)\<rbrakk> \<Longrightarrow> P"
hoelzl@29804
   908
  and B: "\<And>x y prec. \<lbrakk>x < 0; 0 < y; ps = (prec, x, y)\<rbrakk> \<Longrightarrow> P"
hoelzl@29804
   909
  and C: "\<And>x y prec. \<lbrakk>x < 0; y < 0; ps = (prec, x, y)\<rbrakk> \<Longrightarrow> P"
hoelzl@29804
   910
  and D: "\<And>x y prec. \<lbrakk>0 \<le> x; y < 0; ps = (prec, x, y)\<rbrakk> \<Longrightarrow> P"
hoelzl@29804
   911
  shows P
obua@16782
   912
proof -
wenzelm@41528
   913
  obtain prec x y where [simp]: "ps = (prec, x, y)" by (cases ps) auto
hoelzl@29804
   914
  from Y have "y = 0 \<Longrightarrow> P" by auto
wenzelm@41528
   915
  moreover {
wenzelm@41528
   916
    assume "0 < y"
wenzelm@41528
   917
    have P
wenzelm@41528
   918
    proof (cases "0 \<le> x")
wenzelm@41528
   919
      case True
wenzelm@41528
   920
      with A and `0 < y` show P by auto
wenzelm@41528
   921
    next
wenzelm@41528
   922
      case False
wenzelm@41528
   923
      with B and `0 < y` show P by auto
wenzelm@41528
   924
    qed
wenzelm@41528
   925
  } 
wenzelm@41528
   926
  moreover {
wenzelm@41528
   927
    assume "y < 0"
wenzelm@41528
   928
    have P
wenzelm@41528
   929
    proof (cases "0 \<le> x")
wenzelm@41528
   930
      case True
wenzelm@41528
   931
      with D and `y < 0` show P by auto
wenzelm@41528
   932
    next
wenzelm@41528
   933
      case False
wenzelm@41528
   934
      with C and `y < 0` show P by auto
wenzelm@41528
   935
    qed
wenzelm@41528
   936
  }
wenzelm@41528
   937
  ultimately show P by (cases "y = 0 \<or> 0 < y \<or> y < 0") auto
obua@16782
   938
qed
obua@16782
   939
hoelzl@29804
   940
function lapprox_rat :: "nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> float"
hoelzl@29804
   941
where
hoelzl@29804
   942
  "y = 0 \<Longrightarrow> lapprox_rat prec x y = 0"
hoelzl@29804
   943
| "0 \<le> x \<Longrightarrow> 0 < y \<Longrightarrow> lapprox_rat prec x y = lapprox_posrat prec x y"
hoelzl@29804
   944
| "x < 0 \<Longrightarrow> 0 < y \<Longrightarrow> lapprox_rat prec x y = - (rapprox_posrat prec (-x) y)"
hoelzl@29804
   945
| "x < 0 \<Longrightarrow> y < 0 \<Longrightarrow> lapprox_rat prec x y = lapprox_posrat prec (-x) (-y)"
hoelzl@29804
   946
| "0 \<le> x \<Longrightarrow> y < 0 \<Longrightarrow> lapprox_rat prec x y = - (rapprox_posrat prec x (-y))"
hoelzl@29804
   947
apply simp_all by (rule approx_rat_pattern)
hoelzl@29804
   948
termination by lexicographic_order
obua@16782
   949
hoelzl@29804
   950
lemma compute_lapprox_rat[code]:
hoelzl@29804
   951
      "lapprox_rat prec x y = (if y = 0 then 0 else if 0 \<le> x then (if 0 < y then lapprox_posrat prec x y else - (rapprox_posrat prec x (-y))) 
hoelzl@29804
   952
                                                             else (if 0 < y then - (rapprox_posrat prec (-x) y) else lapprox_posrat prec (-x) (-y)))"
hoelzl@29804
   953
  by auto
hoelzl@29804
   954
            
hoelzl@31098
   955
lemma lapprox_rat: "real (lapprox_rat prec x y) \<le> real x / real y"
hoelzl@29804
   956
proof -      
hoelzl@29804
   957
  have h[rule_format]: "! a b b'. b' \<le> b \<longrightarrow> a \<le> b' \<longrightarrow> a \<le> (b::real)" by auto
hoelzl@29804
   958
  show ?thesis
hoelzl@29804
   959
    apply (case_tac "y = 0")
hoelzl@29804
   960
    apply simp
hoelzl@29804
   961
    apply (case_tac "0 \<le> x \<and> 0 < y")
hoelzl@29804
   962
    apply (simp add: lapprox_posrat)
hoelzl@29804
   963
    apply (case_tac "x < 0 \<and> 0 < y")
hoelzl@29804
   964
    apply simp
hoelzl@29804
   965
    apply (subst minus_le_iff)   
hoelzl@29804
   966
    apply (rule h[OF rapprox_posrat])
hoelzl@29804
   967
    apply (simp_all)
hoelzl@29804
   968
    apply (case_tac "x < 0 \<and> y < 0")
hoelzl@29804
   969
    apply simp
hoelzl@29804
   970
    apply (rule h[OF _ lapprox_posrat])
hoelzl@29804
   971
    apply (simp_all)
hoelzl@29804
   972
    apply (case_tac "0 \<le> x \<and> y < 0")
hoelzl@29804
   973
    apply (simp)
hoelzl@29804
   974
    apply (subst minus_le_iff)   
hoelzl@29804
   975
    apply (rule h[OF rapprox_posrat])
hoelzl@29804
   976
    apply simp_all
hoelzl@29804
   977
    apply arith
hoelzl@29804
   978
    done
hoelzl@29804
   979
qed
obua@16782
   980
hoelzl@29804
   981
lemma lapprox_rat_bottom: assumes "0 \<le> x" and "0 < y"
hoelzl@31098
   982
  shows "real (x div y) \<le> real (lapprox_rat n x y)" 
hoelzl@29804
   983
  unfolding lapprox_rat.simps(2)[OF assms]  using lapprox_posrat_bottom[OF `0<y`] .
hoelzl@29804
   984
hoelzl@29804
   985
function rapprox_rat :: "nat \<Rightarrow> int \<Rightarrow> int \<Rightarrow> float"
hoelzl@29804
   986
where
hoelzl@29804
   987
  "y = 0 \<Longrightarrow> rapprox_rat prec x y = 0"
hoelzl@29804
   988
| "0 \<le> x \<Longrightarrow> 0 < y \<Longrightarrow> rapprox_rat prec x y = rapprox_posrat prec x y"
hoelzl@29804
   989
| "x < 0 \<Longrightarrow> 0 < y \<Longrightarrow> rapprox_rat prec x y = - (lapprox_posrat prec (-x) y)"
hoelzl@29804
   990
| "x < 0 \<Longrightarrow> y < 0 \<Longrightarrow> rapprox_rat prec x y = rapprox_posrat prec (-x) (-y)"
hoelzl@29804
   991
| "0 \<le> x \<Longrightarrow> y < 0 \<Longrightarrow> rapprox_rat prec x y = - (lapprox_posrat prec x (-y))"
hoelzl@29804
   992
apply simp_all by (rule approx_rat_pattern)
hoelzl@29804
   993
termination by lexicographic_order
obua@16782
   994
hoelzl@29804
   995
lemma compute_rapprox_rat[code]:
hoelzl@29804
   996
      "rapprox_rat prec x y = (if y = 0 then 0 else if 0 \<le> x then (if 0 < y then rapprox_posrat prec x y else - (lapprox_posrat prec x (-y))) else 
hoelzl@29804
   997
                                                                  (if 0 < y then - (lapprox_posrat prec (-x) y) else rapprox_posrat prec (-x) (-y)))"
hoelzl@29804
   998
  by auto
obua@16782
   999
hoelzl@31098
  1000
lemma rapprox_rat: "real x / real y \<le> real (rapprox_rat prec x y)"
hoelzl@29804
  1001
proof -      
hoelzl@29804
  1002
  have h[rule_format]: "! a b b'. b' \<le> b \<longrightarrow> a \<le> b' \<longrightarrow> a \<le> (b::real)" by auto
hoelzl@29804
  1003
  show ?thesis
hoelzl@29804
  1004
    apply (case_tac "y = 0")
hoelzl@29804
  1005
    apply simp
hoelzl@29804
  1006
    apply (case_tac "0 \<le> x \<and> 0 < y")
hoelzl@29804
  1007
    apply (simp add: rapprox_posrat)
hoelzl@29804
  1008
    apply (case_tac "x < 0 \<and> 0 < y")
hoelzl@29804
  1009
    apply simp
hoelzl@29804
  1010
    apply (subst le_minus_iff)   
hoelzl@29804
  1011
    apply (rule h[OF _ lapprox_posrat])
hoelzl@29804
  1012
    apply (simp_all)
hoelzl@29804
  1013
    apply (case_tac "x < 0 \<and> y < 0")
hoelzl@29804
  1014
    apply simp
hoelzl@29804
  1015
    apply (rule h[OF rapprox_posrat])
hoelzl@29804
  1016
    apply (simp_all)
hoelzl@29804
  1017
    apply (case_tac "0 \<le> x \<and> y < 0")
hoelzl@29804
  1018
    apply (simp)
hoelzl@29804
  1019
    apply (subst le_minus_iff)   
hoelzl@29804
  1020
    apply (rule h[OF _ lapprox_posrat])
hoelzl@29804
  1021
    apply simp_all
hoelzl@29804
  1022
    apply arith
hoelzl@29804
  1023
    done
hoelzl@29804
  1024
qed
obua@16782
  1025
hoelzl@29804
  1026
lemma rapprox_rat_le1: assumes "0 \<le> x" and "0 < y" and "x \<le> y"
hoelzl@31098
  1027
  shows "real (rapprox_rat n x y) \<le> 1"
hoelzl@29804
  1028
  unfolding rapprox_rat.simps(2)[OF `0 \<le> x` `0 < y`] using rapprox_posrat_le1[OF assms] .
hoelzl@29804
  1029
hoelzl@29804
  1030
lemma rapprox_rat_neg: assumes "x < 0" and "0 < y"
hoelzl@31098
  1031
  shows "real (rapprox_rat n x y) \<le> 0"
hoelzl@29804
  1032
  unfolding rapprox_rat.simps(3)[OF assms] using lapprox_posrat_nonneg[of "-x" y n] assms by auto
hoelzl@29804
  1033
hoelzl@29804
  1034
lemma rapprox_rat_nonneg_neg: assumes "0 \<le> x" and "y < 0"
hoelzl@31098
  1035
  shows "real (rapprox_rat n x y) \<le> 0"
hoelzl@29804
  1036
  unfolding rapprox_rat.simps(5)[OF assms] using lapprox_posrat_nonneg[of x "-y" n] assms by auto
obua@16782
  1037
hoelzl@29804
  1038
lemma rapprox_rat_nonpos_pos: assumes "x \<le> 0" and "0 < y"
hoelzl@31098
  1039
  shows "real (rapprox_rat n x y) \<le> 0"
hoelzl@29804
  1040
proof (cases "x = 0") 
wenzelm@41528
  1041
  case True
wenzelm@41528
  1042
  hence "0 \<le> x" by auto show ?thesis
wenzelm@41528
  1043
    unfolding rapprox_rat.simps(2)[OF `0 \<le> x` `0 < y`]
wenzelm@41528
  1044
    unfolding True rapprox_posrat_def Let_def
wenzelm@41528
  1045
    by auto
hoelzl@29804
  1046
next
wenzelm@41528
  1047
  case False
wenzelm@41528
  1048
  hence "x < 0" using assms by auto
hoelzl@29804
  1049
  show ?thesis using rapprox_rat_neg[OF `x < 0` `0 < y`] .
hoelzl@29804
  1050
qed
hoelzl@29804
  1051
hoelzl@29804
  1052
fun float_divl :: "nat \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float"
hoelzl@29804
  1053
where
hoelzl@29804
  1054
  "float_divl prec (Float m1 s1) (Float m2 s2) = 
hoelzl@29804
  1055
    (let
hoelzl@29804
  1056
       l = lapprox_rat prec m1 m2;
hoelzl@29804
  1057
       f = Float 1 (s1 - s2)
hoelzl@29804
  1058
     in
hoelzl@29804
  1059
       f * l)"     
obua@16782
  1060
hoelzl@31098
  1061
lemma float_divl: "real (float_divl prec x y) \<le> real x / real y"
hoelzl@29804
  1062
proof - 
hoelzl@29804
  1063
  from float_split[of x] obtain mx sx where x: "x = Float mx sx" by auto
hoelzl@29804
  1064
  from float_split[of y] obtain my sy where y: "y = Float my sy" by auto
hoelzl@29804
  1065
  have "real mx / real my \<le> (real mx * pow2 sx / (real my * pow2 sy)) / (pow2 (sx - sy))"
hoelzl@29804
  1066
    apply (case_tac "my = 0")
hoelzl@29804
  1067
    apply simp
hoelzl@29804
  1068
    apply (case_tac "my > 0")       
hoelzl@29804
  1069
    apply (subst pos_le_divide_eq)
hoelzl@29804
  1070
    apply simp
hoelzl@29804
  1071
    apply (subst pos_le_divide_eq)
hoelzl@29804
  1072
    apply (simp add: mult_pos_pos)
hoelzl@29804
  1073
    apply simp
hoelzl@29804
  1074
    apply (subst pow2_add[symmetric])
hoelzl@29804
  1075
    apply simp
hoelzl@29804
  1076
    apply (subgoal_tac "my < 0")
hoelzl@29804
  1077
    apply auto
hoelzl@29804
  1078
    apply (simp add: field_simps)
hoelzl@29804
  1079
    apply (subst pow2_add[symmetric])
hoelzl@29804
  1080
    apply (simp add: field_simps)
hoelzl@29804
  1081
    done
hoelzl@31098
  1082
  then have "real (lapprox_rat prec mx my) \<le> (real mx * pow2 sx / (real my * pow2 sy)) / (pow2 (sx - sy))"
hoelzl@29804
  1083
    by (rule order_trans[OF lapprox_rat])
hoelzl@31098
  1084
  then have "real (lapprox_rat prec mx my) * pow2 (sx - sy) \<le> real mx * pow2 sx / (real my * pow2 sy)"
hoelzl@29804
  1085
    apply (subst pos_le_divide_eq[symmetric])
hoelzl@29804
  1086
    apply simp_all
hoelzl@29804
  1087
    done
hoelzl@31098
  1088
  then have "pow2 (sx - sy) * real (lapprox_rat prec mx my) \<le> real mx * pow2 sx / (real my * pow2 sy)"
hoelzl@29804
  1089
    by (simp add: algebra_simps)
hoelzl@29804
  1090
  then show ?thesis
hoelzl@31098
  1091
    by (simp add: x y Let_def real_of_float_simp)
hoelzl@29804
  1092
qed
obua@16782
  1093
hoelzl@29804
  1094
lemma float_divl_lower_bound: assumes "0 \<le> x" and "0 < y" shows "0 \<le> float_divl prec x y"
hoelzl@29804
  1095
proof (cases x, cases y)
hoelzl@29804
  1096
  fix xm xe ym ye :: int
hoelzl@29804
  1097
  assume x_eq: "x = Float xm xe" and y_eq: "y = Float ym ye"
wenzelm@41528
  1098
  have "0 \<le> xm"
wenzelm@41528
  1099
    using `0 \<le> x`[unfolded x_eq le_float_def real_of_float_simp real_of_float_0 zero_le_mult_iff]
wenzelm@41528
  1100
    by auto
wenzelm@41528
  1101
  have "0 < ym"
wenzelm@41528
  1102
    using `0 < y`[unfolded y_eq less_float_def real_of_float_simp real_of_float_0 zero_less_mult_iff]
wenzelm@41528
  1103
    by auto
obua@16782
  1104
wenzelm@41528
  1105
  have "\<And>n. 0 \<le> real (Float 1 n)"
wenzelm@41528
  1106
    unfolding real_of_float_simp using zero_le_pow2 by auto
wenzelm@41528
  1107
  moreover have "0 \<le> real (lapprox_rat prec xm ym)"
wenzelm@41528
  1108
    apply (rule order_trans[OF _ lapprox_rat_bottom[OF `0 \<le> xm` `0 < ym`]])
wenzelm@41528
  1109
    apply (auto simp add: `0 \<le> xm` pos_imp_zdiv_nonneg_iff[OF `0 < ym`])
wenzelm@41528
  1110
    done
hoelzl@29804
  1111
  ultimately show "0 \<le> float_divl prec x y"
wenzelm@41528
  1112
    unfolding x_eq y_eq float_divl.simps Let_def le_float_def real_of_float_0
wenzelm@41528
  1113
    by (auto intro!: mult_nonneg_nonneg)
hoelzl@29804
  1114
qed
hoelzl@29804
  1115
wenzelm@41528
  1116
lemma float_divl_pos_less1_bound:
wenzelm@41528
  1117
  assumes "0 < x" and "x < 1" and "0 < prec"
wenzelm@41528
  1118
  shows "1 \<le> float_divl prec 1 x"
hoelzl@29804
  1119
proof (cases x)
hoelzl@29804
  1120
  case (Float m e)
wenzelm@41528
  1121
  from `0 < x` `x < 1` have "0 < m" "e < 0"
wenzelm@41528
  1122
    using float_pos_m_pos float_pos_less1_e_neg unfolding Float by auto
hoelzl@29804
  1123
  let ?b = "nat (bitlen m)" and ?e = "nat (-e)"
hoelzl@29804
  1124
  have "1 \<le> m" and "m \<noteq> 0" using `0 < m` by auto
hoelzl@29804
  1125
  with bitlen_bounds[OF `0 < m`] have "m < 2^?b" and "(2::int) \<le> 2^?b" by auto
hoelzl@29804
  1126
  hence "1 \<le> bitlen m" using power_le_imp_le_exp[of "2::int" 1 ?b] by auto
hoelzl@29804
  1127
  hence pow_split: "nat (int prec + bitlen m - 1) = (prec - 1) + ?b" using `0 < prec` by auto
hoelzl@29804
  1128
  
hoelzl@29804
  1129
  have pow_not0: "\<And>x. (2::real)^x \<noteq> 0" by auto
obua@16782
  1130
hoelzl@29804
  1131
  from float_less1_mantissa_bound `0 < x` `x < 1` Float 
hoelzl@29804
  1132
  have "m < 2^?e" by auto
wenzelm@41528
  1133
  with bitlen_bounds[OF `0 < m`, THEN conjunct1] have "(2::int)^nat (bitlen m - 1) < 2^?e"
wenzelm@41528
  1134
    by (rule order_le_less_trans)
hoelzl@29804
  1135
  from power_less_imp_less_exp[OF _ this]
hoelzl@29804
  1136
  have "bitlen m \<le> - e" by auto
hoelzl@29804
  1137
  hence "(2::real)^?b \<le> 2^?e" by auto
wenzelm@41528
  1138
  hence "(2::real)^?b * inverse (2^?b) \<le> 2^?e * inverse (2^?b)"
wenzelm@41528
  1139
    by (rule mult_right_mono) auto
hoelzl@29804
  1140
  hence "(1::real) \<le> 2^?e * inverse (2^?b)" by auto
hoelzl@29804
  1141
  also
hoelzl@29804
  1142
  let ?d = "real (2 ^ nat (int prec + bitlen m - 1) div m) * inverse (2 ^ nat (int prec + bitlen m - 1))"
wenzelm@41528
  1143
  {
wenzelm@41528
  1144
    have "2^(prec - 1) * m \<le> 2^(prec - 1) * 2^?b"
wenzelm@41528
  1145
      using `m < 2^?b`[THEN less_imp_le] by (rule mult_left_mono) auto
wenzelm@41528
  1146
    also have "\<dots> = 2 ^ nat (int prec + bitlen m - 1)"
wenzelm@41528
  1147
      unfolding pow_split zpower_zadd_distrib by auto
wenzelm@41528
  1148
    finally have "2^(prec - 1) * m div m \<le> 2 ^ nat (int prec + bitlen m - 1) div m"
wenzelm@41528
  1149
      using `0 < m` by (rule zdiv_mono1)
wenzelm@41528
  1150
    hence "2^(prec - 1) \<le> 2 ^ nat (int prec + bitlen m - 1) div m"
wenzelm@41528
  1151
      unfolding div_mult_self2_is_id[OF `m \<noteq> 0`] .
hoelzl@29804
  1152
    hence "2^(prec - 1) * inverse (2 ^ nat (int prec + bitlen m - 1)) \<le> ?d"
wenzelm@41528
  1153
      unfolding real_of_int_le_iff[of "2^(prec - 1)", symmetric] by auto
wenzelm@41528
  1154
  }
wenzelm@41528
  1155
  from mult_left_mono[OF this [unfolded pow_split power_add inverse_mult_distrib mult_assoc[symmetric] right_inverse[OF pow_not0] mult_1_left], of "2^?e"]
hoelzl@29804
  1156
  have "2^?e * inverse (2^?b) \<le> 2^?e * ?d" unfolding pow_split power_add by auto
hoelzl@29804
  1157
  finally have "1 \<le> 2^?e * ?d" .
hoelzl@29804
  1158
  
hoelzl@29804
  1159
  have e_nat: "0 - e = int (nat (-e))" using `e < 0` by auto
hoelzl@29804
  1160
  have "bitlen 1 = 1" using bitlen.simps by auto
hoelzl@29804
  1161
  
hoelzl@29804
  1162
  show ?thesis 
wenzelm@41528
  1163
    unfolding one_float_def Float float_divl.simps Let_def
wenzelm@41528
  1164
      lapprox_rat.simps(2)[OF zero_le_one `0 < m`]
wenzelm@41528
  1165
      lapprox_posrat_def `bitlen 1 = 1`
wenzelm@41528
  1166
    unfolding le_float_def real_of_float_mult normfloat real_of_float_simp
wenzelm@41528
  1167
      pow2_minus pow2_int e_nat
hoelzl@29804
  1168
    using `1 \<le> 2^?e * ?d` by (auto simp add: pow2_def)
hoelzl@29804
  1169
qed
obua@16782
  1170
hoelzl@29804
  1171
fun float_divr :: "nat \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float"
hoelzl@29804
  1172
where
hoelzl@29804
  1173
  "float_divr prec (Float m1 s1) (Float m2 s2) = 
hoelzl@29804
  1174
    (let
hoelzl@29804
  1175
       r = rapprox_rat prec m1 m2;
hoelzl@29804
  1176
       f = Float 1 (s1 - s2)
hoelzl@29804
  1177
     in
hoelzl@29804
  1178
       f * r)"  
obua@16782
  1179
hoelzl@31098
  1180
lemma float_divr: "real x / real y \<le> real (float_divr prec x y)"
hoelzl@29804
  1181
proof - 
hoelzl@29804
  1182
  from float_split[of x] obtain mx sx where x: "x = Float mx sx" by auto
hoelzl@29804
  1183
  from float_split[of y] obtain my sy where y: "y = Float my sy" by auto
hoelzl@29804
  1184
  have "real mx / real my \<ge> (real mx * pow2 sx / (real my * pow2 sy)) / (pow2 (sx - sy))"
hoelzl@29804
  1185
    apply (case_tac "my = 0")
hoelzl@29804
  1186
    apply simp
hoelzl@29804
  1187
    apply (case_tac "my > 0")
hoelzl@29804
  1188
    apply auto
hoelzl@29804
  1189
    apply (subst pos_divide_le_eq)
hoelzl@29804
  1190
    apply (rule mult_pos_pos)+
hoelzl@29804
  1191
    apply simp_all
hoelzl@29804
  1192
    apply (subst pow2_add[symmetric])
hoelzl@29804
  1193
    apply simp
hoelzl@29804
  1194
    apply (subgoal_tac "my < 0")
hoelzl@29804
  1195
    apply auto
hoelzl@29804
  1196
    apply (simp add: field_simps)
hoelzl@29804
  1197
    apply (subst pow2_add[symmetric])
hoelzl@29804
  1198
    apply (simp add: field_simps)
hoelzl@29804
  1199
    done
hoelzl@31098
  1200
  then have "real (rapprox_rat prec mx my) \<ge> (real mx * pow2 sx / (real my * pow2 sy)) / (pow2 (sx - sy))"
hoelzl@29804
  1201
    by (rule order_trans[OF _ rapprox_rat])
hoelzl@31098
  1202
  then have "real (rapprox_rat prec mx my) * pow2 (sx - sy) \<ge> real mx * pow2 sx / (real my * pow2 sy)"
hoelzl@29804
  1203
    apply (subst pos_divide_le_eq[symmetric])
hoelzl@29804
  1204
    apply simp_all
hoelzl@29804
  1205
    done
hoelzl@29804
  1206
  then show ?thesis
hoelzl@31098
  1207
    by (simp add: x y Let_def algebra_simps real_of_float_simp)
hoelzl@29804
  1208
qed
obua@16782
  1209
hoelzl@29804
  1210
lemma float_divr_pos_less1_lower_bound: assumes "0 < x" and "x < 1" shows "1 \<le> float_divr prec 1 x"
hoelzl@29804
  1211
proof -
hoelzl@31098
  1212
  have "1 \<le> 1 / real x" using `0 < x` and `x < 1` unfolding less_float_def by auto
hoelzl@31098
  1213
  also have "\<dots> \<le> real (float_divr prec 1 x)" using float_divr[where x=1 and y=x] by auto
hoelzl@29804
  1214
  finally show ?thesis unfolding le_float_def by auto
hoelzl@29804
  1215
qed
hoelzl@29804
  1216
hoelzl@29804
  1217
lemma float_divr_nonpos_pos_upper_bound: assumes "x \<le> 0" and "0 < y" shows "float_divr prec x y \<le> 0"
hoelzl@29804
  1218
proof (cases x, cases y)
hoelzl@29804
  1219
  fix xm xe ym ye :: int
hoelzl@29804
  1220
  assume x_eq: "x = Float xm xe" and y_eq: "y = Float ym ye"
hoelzl@31098
  1221
  have "xm \<le> 0" using `x \<le> 0`[unfolded x_eq le_float_def real_of_float_simp real_of_float_0 mult_le_0_iff] by auto
hoelzl@31098
  1222
  have "0 < ym" using `0 < y`[unfolded y_eq less_float_def real_of_float_simp real_of_float_0 zero_less_mult_iff] by auto
hoelzl@29804
  1223
hoelzl@31098
  1224
  have "\<And>n. 0 \<le> real (Float 1 n)" unfolding real_of_float_simp using zero_le_pow2 by auto
hoelzl@31098
  1225
  moreover have "real (rapprox_rat prec xm ym) \<le> 0" using rapprox_rat_nonpos_pos[OF `xm \<le> 0` `0 < ym`] .
hoelzl@29804
  1226
  ultimately show "float_divr prec x y \<le> 0"
hoelzl@31098
  1227
    unfolding x_eq y_eq float_divr.simps Let_def le_float_def real_of_float_0 real_of_float_mult by (auto intro!: mult_nonneg_nonpos)
hoelzl@29804
  1228
qed
obua@16782
  1229
hoelzl@29804
  1230
lemma float_divr_nonneg_neg_upper_bound: assumes "0 \<le> x" and "y < 0" shows "float_divr prec x y \<le> 0"
hoelzl@29804
  1231
proof (cases x, cases y)
hoelzl@29804
  1232
  fix xm xe ym ye :: int
hoelzl@29804
  1233
  assume x_eq: "x = Float xm xe" and y_eq: "y = Float ym ye"
hoelzl@31098
  1234
  have "0 \<le> xm" using `0 \<le> x`[unfolded x_eq le_float_def real_of_float_simp real_of_float_0 zero_le_mult_iff] by auto
hoelzl@31098
  1235
  have "ym < 0" using `y < 0`[unfolded y_eq less_float_def real_of_float_simp real_of_float_0 mult_less_0_iff] by auto
hoelzl@29804
  1236
  hence "0 < - ym" by auto
hoelzl@29804
  1237
hoelzl@31098
  1238
  have "\<And>n. 0 \<le> real (Float 1 n)" unfolding real_of_float_simp using zero_le_pow2 by auto
hoelzl@31098
  1239
  moreover have "real (rapprox_rat prec xm ym) \<le> 0" using rapprox_rat_nonneg_neg[OF `0 \<le> xm` `ym < 0`] .
hoelzl@29804
  1240
  ultimately show "float_divr prec x y \<le> 0"
hoelzl@31098
  1241
    unfolding x_eq y_eq float_divr.simps Let_def le_float_def real_of_float_0 real_of_float_mult by (auto intro!: mult_nonneg_nonpos)
hoelzl@29804
  1242
qed
hoelzl@29804
  1243
haftmann@30960
  1244
primrec round_down :: "nat \<Rightarrow> float \<Rightarrow> float" where
hoelzl@29804
  1245
"round_down prec (Float m e) = (let d = bitlen m - int prec in
hoelzl@29804
  1246
     if 0 < d then let P = 2^nat d ; n = m div P in Float n (e + d)
hoelzl@29804
  1247
              else Float m e)"
hoelzl@29804
  1248
haftmann@30960
  1249
primrec round_up :: "nat \<Rightarrow> float \<Rightarrow> float" where
hoelzl@29804
  1250
"round_up prec (Float m e) = (let d = bitlen m - int prec in
hoelzl@29804
  1251
  if 0 < d then let P = 2^nat d ; n = m div P ; r = m mod P in Float (n + (if r = 0 then 0 else 1)) (e + d) 
hoelzl@29804
  1252
           else Float m e)"
obua@16782
  1253
hoelzl@31098
  1254
lemma round_up: "real x \<le> real (round_up prec x)"
hoelzl@29804
  1255
proof (cases x)
hoelzl@29804
  1256
  case (Float m e)
hoelzl@29804
  1257
  let ?d = "bitlen m - int prec"
hoelzl@29804
  1258
  let ?p = "(2::int)^nat ?d"
hoelzl@29804
  1259
  have "0 < ?p" by auto
hoelzl@29804
  1260
  show "?thesis"
hoelzl@29804
  1261
  proof (cases "0 < ?d")
hoelzl@29804
  1262
    case True
huffman@35344
  1263
    hence pow_d: "pow2 ?d = real ?p" using pow2_int[symmetric] by simp
hoelzl@29804
  1264
    show ?thesis
hoelzl@29804
  1265
    proof (cases "m mod ?p = 0")
hoelzl@29804
  1266
      case True
hoelzl@29804
  1267
      have m: "m = m div ?p * ?p + 0" unfolding True[symmetric] using zdiv_zmod_equality2[where k=0, unfolded monoid_add_class.add_0_right, symmetric] .
hoelzl@31098
  1268
      have "real (Float m e) = real (Float (m div ?p) (e + ?d))" unfolding real_of_float_simp arg_cong[OF m, of real]
wenzelm@32960
  1269
        by (auto simp add: pow2_add `0 < ?d` pow_d)
hoelzl@29804
  1270
      thus ?thesis
wenzelm@32960
  1271
        unfolding Float round_up.simps Let_def if_P[OF `m mod ?p = 0`] if_P[OF `0 < ?d`]
wenzelm@32960
  1272
        by auto
hoelzl@29804
  1273
    next
hoelzl@29804
  1274
      case False
hoelzl@29804
  1275
      have "m = m div ?p * ?p + m mod ?p" unfolding zdiv_zmod_equality2[where k=0, unfolded monoid_add_class.add_0_right] ..
hoelzl@29804
  1276
      also have "\<dots> \<le> (m div ?p + 1) * ?p" unfolding left_distrib zmult_1 by (rule add_left_mono, rule pos_mod_bound[OF `0 < ?p`, THEN less_imp_le])
hoelzl@31098
  1277
      finally have "real (Float m e) \<le> real (Float (m div ?p + 1) (e + ?d))" unfolding real_of_float_simp add_commute[of e]
wenzelm@32960
  1278
        unfolding pow2_add mult_assoc[symmetric] real_of_int_le_iff[of m, symmetric]
wenzelm@32960
  1279
        by (auto intro!: mult_mono simp add: pow2_add `0 < ?d` pow_d)
hoelzl@29804
  1280
      thus ?thesis
wenzelm@32960
  1281
        unfolding Float round_up.simps Let_def if_not_P[OF `\<not> m mod ?p = 0`] if_P[OF `0 < ?d`] .
hoelzl@29804
  1282
    qed
hoelzl@29804
  1283
  next
hoelzl@29804
  1284
    case False
hoelzl@29804
  1285
    show ?thesis
hoelzl@29804
  1286
      unfolding Float round_up.simps Let_def if_not_P[OF False] .. 
hoelzl@29804
  1287
  qed
hoelzl@29804
  1288
qed
obua@16782
  1289
hoelzl@31098
  1290
lemma round_down: "real (round_down prec x) \<le> real x"
hoelzl@29804
  1291
proof (cases x)
hoelzl@29804
  1292
  case (Float m e)
hoelzl@29804
  1293
  let ?d = "bitlen m - int prec"
hoelzl@29804
  1294
  let ?p = "(2::int)^nat ?d"
hoelzl@29804
  1295
  have "0 < ?p" by auto
hoelzl@29804
  1296
  show "?thesis"
hoelzl@29804
  1297
  proof (cases "0 < ?d")
hoelzl@29804
  1298
    case True
huffman@35344
  1299
    hence pow_d: "pow2 ?d = real ?p" using pow2_int[symmetric] by simp
hoelzl@29804
  1300
    have "m div ?p * ?p \<le> m div ?p * ?p + m mod ?p" by (auto simp add: pos_mod_bound[OF `0 < ?p`, THEN less_imp_le])
hoelzl@29804
  1301
    also have "\<dots> \<le> m" unfolding zdiv_zmod_equality2[where k=0, unfolded monoid_add_class.add_0_right] ..
hoelzl@31098
  1302
    finally have "real (Float (m div ?p) (e + ?d)) \<le> real (Float m e)" unfolding real_of_float_simp add_commute[of e]
hoelzl@29804
  1303
      unfolding pow2_add mult_assoc[symmetric] real_of_int_le_iff[of _ m, symmetric]
hoelzl@29804
  1304
      by (auto intro!: mult_mono simp add: pow2_add `0 < ?d` pow_d)
hoelzl@29804
  1305
    thus ?thesis
hoelzl@29804
  1306
      unfolding Float round_down.simps Let_def if_P[OF `0 < ?d`] .
hoelzl@29804
  1307
  next
hoelzl@29804
  1308
    case False
hoelzl@29804
  1309
    show ?thesis
hoelzl@29804
  1310
      unfolding Float round_down.simps Let_def if_not_P[OF False] .. 
hoelzl@29804
  1311
  qed
hoelzl@29804
  1312
qed
hoelzl@29804
  1313
hoelzl@29804
  1314
definition lb_mult :: "nat \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float" where
hoelzl@29804
  1315
"lb_mult prec x y = (case normfloat (x * y) of Float m e \<Rightarrow> let
hoelzl@29804
  1316
    l = bitlen m - int prec
hoelzl@29804
  1317
  in if l > 0 then Float (m div (2^nat l)) (e + l)
hoelzl@29804
  1318
              else Float m e)"
obua@16782
  1319
hoelzl@29804
  1320
definition ub_mult :: "nat \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float" where
hoelzl@29804
  1321
"ub_mult prec x y = (case normfloat (x * y) of Float m e \<Rightarrow> let
hoelzl@29804
  1322
    l = bitlen m - int prec
hoelzl@29804
  1323
  in if l > 0 then Float (m div (2^nat l) + 1) (e + l)
hoelzl@29804
  1324
              else Float m e)"
obua@16782
  1325
hoelzl@31098
  1326
lemma lb_mult: "real (lb_mult prec x y) \<le> real (x * y)"
hoelzl@29804
  1327
proof (cases "normfloat (x * y)")
hoelzl@29804
  1328
  case (Float m e)
hoelzl@29804
  1329
  hence "odd m \<or> (m = 0 \<and> e = 0)" by (rule normfloat_imp_odd_or_zero)
hoelzl@29804
  1330
  let ?l = "bitlen m - int prec"
hoelzl@31098
  1331
  have "real (lb_mult prec x y) \<le> real (normfloat (x * y))"
hoelzl@29804
  1332
  proof (cases "?l > 0")
hoelzl@29804
  1333
    case False thus ?thesis unfolding lb_mult_def Float Let_def float.cases by auto
hoelzl@29804
  1334
  next
hoelzl@29804
  1335
    case True
hoelzl@29804
  1336
    have "real (m div 2^(nat ?l)) * pow2 ?l \<le> real m"
hoelzl@29804
  1337
    proof -
huffman@35344
  1338
      have "real (m div 2^(nat ?l)) * pow2 ?l = real (2^(nat ?l) * (m div 2^(nat ?l)))" unfolding real_of_int_mult real_of_int_power real_number_of unfolding pow2_int[symmetric] 
wenzelm@32960
  1339
        using `?l > 0` by auto
hoelzl@29804
  1340
      also have "\<dots> \<le> real (2^(nat ?l) * (m div 2^(nat ?l)) + m mod 2^(nat ?l))" unfolding real_of_int_add by auto
hoelzl@29804
  1341
      also have "\<dots> = real m" unfolding zmod_zdiv_equality[symmetric] ..
hoelzl@29804
  1342
      finally show ?thesis by auto
hoelzl@29804
  1343
    qed
huffman@36778
  1344
    thus ?thesis unfolding lb_mult_def Float Let_def float.cases if_P[OF True] real_of_float_simp pow2_add mult_commute mult_assoc by auto
hoelzl@29804
  1345
  qed
hoelzl@31098
  1346
  also have "\<dots> = real (x * y)" unfolding normfloat ..
hoelzl@29804
  1347
  finally show ?thesis .
hoelzl@29804
  1348
qed
obua@16782
  1349
hoelzl@31098
  1350
lemma ub_mult: "real (x * y) \<le> real (ub_mult prec x y)"
hoelzl@29804
  1351
proof (cases "normfloat (x * y)")
hoelzl@29804
  1352
  case (Float m e)
hoelzl@29804
  1353
  hence "odd m \<or> (m = 0 \<and> e = 0)" by (rule normfloat_imp_odd_or_zero)
hoelzl@29804
  1354
  let ?l = "bitlen m - int prec"
hoelzl@31098
  1355
  have "real (x * y) = real (normfloat (x * y))" unfolding normfloat ..
hoelzl@31098
  1356
  also have "\<dots> \<le> real (ub_mult prec x y)"
hoelzl@29804
  1357
  proof (cases "?l > 0")
hoelzl@29804
  1358
    case False thus ?thesis unfolding ub_mult_def Float Let_def float.cases by auto
hoelzl@29804
  1359
  next
hoelzl@29804
  1360
    case True
hoelzl@29804
  1361
    have "real m \<le> real (m div 2^(nat ?l) + 1) * pow2 ?l"
hoelzl@29804
  1362
    proof -
hoelzl@29804
  1363
      have "m mod 2^(nat ?l) < 2^(nat ?l)" by (rule pos_mod_bound) auto
hoelzl@29804
  1364
      hence mod_uneq: "real (m mod 2^(nat ?l)) \<le> 1 * 2^(nat ?l)" unfolding zmult_1 real_of_int_less_iff[symmetric] by auto
hoelzl@29804
  1365
      
hoelzl@29804
  1366
      have "real m = real (2^(nat ?l) * (m div 2^(nat ?l)) + m mod 2^(nat ?l))" unfolding zmod_zdiv_equality[symmetric] ..
hoelzl@29804
  1367
      also have "\<dots> = real (m div 2^(nat ?l)) * 2^(nat ?l) + real (m mod 2^(nat ?l))" unfolding real_of_int_add by auto
huffman@36778
  1368
      also have "\<dots> \<le> (real (m div 2^(nat ?l)) + 1) * 2^(nat ?l)" unfolding left_distrib using mod_uneq by auto
hoelzl@29804
  1369
      finally show ?thesis unfolding pow2_int[symmetric] using True by auto
hoelzl@29804
  1370
    qed
huffman@36778
  1371
    thus ?thesis unfolding ub_mult_def Float Let_def float.cases if_P[OF True] real_of_float_simp pow2_add mult_commute mult_assoc by auto
hoelzl@29804
  1372
  qed
hoelzl@29804
  1373
  finally show ?thesis .
hoelzl@29804
  1374
qed
hoelzl@29804
  1375
haftmann@30960
  1376
primrec float_abs :: "float \<Rightarrow> float" where
haftmann@30960
  1377
  "float_abs (Float m e) = Float \<bar>m\<bar> e"
hoelzl@29804
  1378
hoelzl@29804
  1379
instantiation float :: abs begin
hoelzl@29804
  1380
definition abs_float_def: "\<bar>x\<bar> = float_abs x"
hoelzl@29804
  1381
instance ..
hoelzl@29804
  1382
end
obua@16782
  1383
hoelzl@31098
  1384
lemma real_of_float_abs: "real \<bar>x :: float\<bar> = \<bar>real x\<bar>" 
hoelzl@29804
  1385
proof (cases x)
hoelzl@29804
  1386
  case (Float m e)
hoelzl@29804
  1387
  have "\<bar>real m\<bar> * pow2 e = \<bar>real m * pow2 e\<bar>" unfolding abs_mult by auto
hoelzl@31098
  1388
  thus ?thesis unfolding Float abs_float_def float_abs.simps real_of_float_simp by auto
hoelzl@29804
  1389
qed
hoelzl@29804
  1390
haftmann@30960
  1391
primrec floor_fl :: "float \<Rightarrow> float" where
haftmann@30960
  1392
  "floor_fl (Float m e) = (if 0 \<le> e then Float m e
hoelzl@29804
  1393
                                  else Float (m div (2 ^ (nat (-e)))) 0)"
obua@16782
  1394
hoelzl@31098
  1395
lemma floor_fl: "real (floor_fl x) \<le> real x"
hoelzl@29804
  1396
proof (cases x)
hoelzl@29804
  1397
  case (Float m e)
hoelzl@29804
  1398
  show ?thesis
hoelzl@29804
  1399
  proof (cases "0 \<le> e")
hoelzl@29804
  1400
    case False
hoelzl@29804
  1401
    hence me_eq: "pow2 (-e) = pow2 (int (nat (-e)))" by auto
hoelzl@31098
  1402
    have "real (Float (m div (2 ^ (nat (-e)))) 0) = real (m div 2 ^ (nat (-e)))" unfolding real_of_float_simp by auto
hoelzl@29804
  1403
    also have "\<dots> \<le> real m / real ((2::int) ^ (nat (-e)))" using real_of_int_div4 .
huffman@36778
  1404
    also have "\<dots> = real m * inverse (2 ^ (nat (-e)))" unfolding real_of_int_power real_number_of divide_inverse ..
hoelzl@31098
  1405
    also have "\<dots> = real (Float m e)" unfolding real_of_float_simp me_eq pow2_int pow2_neg[of e] ..
hoelzl@29804
  1406
    finally show ?thesis unfolding Float floor_fl.simps if_not_P[OF `\<not> 0 \<le> e`] .
hoelzl@29804
  1407
  next
hoelzl@29804
  1408
    case True thus ?thesis unfolding Float by auto
hoelzl@29804
  1409
  qed
hoelzl@29804
  1410
qed
obua@16782
  1411
hoelzl@29804
  1412
lemma floor_pos_exp: assumes floor: "Float m e = floor_fl x" shows "0 \<le> e"
hoelzl@29804
  1413
proof (cases x)
hoelzl@29804
  1414
  case (Float mx me)
hoelzl@29804
  1415
  from floor[unfolded Float floor_fl.simps] show ?thesis by (cases "0 \<le> me", auto)
hoelzl@29804
  1416
qed
hoelzl@29804
  1417
hoelzl@29804
  1418
declare floor_fl.simps[simp del]
obua@16782
  1419
haftmann@30960
  1420
primrec ceiling_fl :: "float \<Rightarrow> float" where
haftmann@30960
  1421
  "ceiling_fl (Float m e) = (if 0 \<le> e then Float m e
hoelzl@29804
  1422
                                    else Float (m div (2 ^ (nat (-e))) + 1) 0)"
obua@16782
  1423
hoelzl@31098
  1424
lemma ceiling_fl: "real x \<le> real (ceiling_fl x)"
hoelzl@29804
  1425
proof (cases x)
hoelzl@29804
  1426
  case (Float m e)
hoelzl@29804
  1427
  show ?thesis
hoelzl@29804
  1428
  proof (cases "0 \<le> e")
hoelzl@29804
  1429
    case False
hoelzl@29804
  1430
    hence me_eq: "pow2 (-e) = pow2 (int (nat (-e)))" by auto
hoelzl@31098
  1431
    have "real (Float m e) = real m * inverse (2 ^ (nat (-e)))" unfolding real_of_float_simp me_eq pow2_int pow2_neg[of e] ..
huffman@36778
  1432
    also have "\<dots> = real m / real ((2::int) ^ (nat (-e)))" unfolding real_of_int_power real_number_of divide_inverse ..
hoelzl@29804
  1433
    also have "\<dots> \<le> 1 + real (m div 2 ^ (nat (-e)))" using real_of_int_div3[unfolded diff_le_eq] .
hoelzl@31098
  1434
    also have "\<dots> = real (Float (m div (2 ^ (nat (-e))) + 1) 0)" unfolding real_of_float_simp by auto
hoelzl@29804
  1435
    finally show ?thesis unfolding Float ceiling_fl.simps if_not_P[OF `\<not> 0 \<le> e`] .
hoelzl@29804
  1436
  next
hoelzl@29804
  1437
    case True thus ?thesis unfolding Float by auto
hoelzl@29804
  1438
  qed
hoelzl@29804
  1439
qed
hoelzl@29804
  1440
hoelzl@29804
  1441
declare ceiling_fl.simps[simp del]
hoelzl@29804
  1442
hoelzl@29804
  1443
definition lb_mod :: "nat \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float" where
hoelzl@29804
  1444
"lb_mod prec x ub lb = x - ceiling_fl (float_divr prec x lb) * ub"
hoelzl@29804
  1445
hoelzl@29804
  1446
definition ub_mod :: "nat \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float \<Rightarrow> float" where
hoelzl@29804
  1447
"ub_mod prec x ub lb = x - floor_fl (float_divl prec x ub) * lb"
obua@16782
  1448
hoelzl@31098
  1449
lemma lb_mod: fixes k :: int assumes "0 \<le> real x" and "real k * y \<le> real x" (is "?k * y \<le> ?x")
hoelzl@31098
  1450
  assumes "0 < real lb" "real lb \<le> y" (is "?lb \<le> y") "y \<le> real ub" (is "y \<le> ?ub")
hoelzl@31098
  1451
  shows "real (lb_mod prec x ub lb) \<le> ?x - ?k * y"
hoelzl@29804
  1452
proof -
wenzelm@33555
  1453
  have "?lb \<le> ?ub" using assms by auto
wenzelm@33555
  1454
  have "0 \<le> ?lb" and "?lb \<noteq> 0" using assms by auto
hoelzl@29804
  1455
  have "?k * y \<le> ?x" using assms by auto
hoelzl@29804
  1456
  also have "\<dots> \<le> ?x / ?lb * ?ub" by (metis mult_left_mono[OF `?lb \<le> ?ub` `0 \<le> ?x`] divide_right_mono[OF _ `0 \<le> ?lb` ] times_divide_eq_left nonzero_mult_divide_cancel_right[OF `?lb \<noteq> 0`])
hoelzl@31098
  1457
  also have "\<dots> \<le> real (ceiling_fl (float_divr prec x lb)) * ?ub" by (metis mult_right_mono order_trans `0 \<le> ?lb` `?lb \<le> ?ub` float_divr ceiling_fl)
hoelzl@31098
  1458
  finally show ?thesis unfolding lb_mod_def real_of_float_sub real_of_float_mult by auto
hoelzl@29804
  1459
qed
obua@16782
  1460
hoelzl@31098
  1461
lemma ub_mod: fixes k :: int and x :: float assumes "0 \<le> real x" and "real x \<le> real k * y" (is "?x \<le> ?k * y")
hoelzl@31098
  1462
  assumes "0 < real lb" "real lb \<le> y" (is "?lb \<le> y") "y \<le> real ub" (is "y \<le> ?ub")
hoelzl@31098
  1463
  shows "?x - ?k * y \<le> real (ub_mod prec x ub lb)"
hoelzl@29804
  1464
proof -
wenzelm@33555
  1465
  have "?lb \<le> ?ub" using assms by auto
wenzelm@33555
  1466
  hence "0 \<le> ?lb" and "0 \<le> ?ub" and "?ub \<noteq> 0" using assms by auto
hoelzl@31098
  1467
  have "real (floor_fl (float_divl prec x ub)) * ?lb \<le> ?x / ?ub * ?lb" by (metis mult_right_mono order_trans `0 \<le> ?lb` `?lb \<le> ?ub` float_divl floor_fl)
hoelzl@29804
  1468
  also have "\<dots> \<le> ?x" by (metis mult_left_mono[OF `?lb \<le> ?ub` `0 \<le> ?x`] divide_right_mono[OF _ `0 \<le> ?ub` ] times_divide_eq_left nonzero_mult_divide_cancel_right[OF `?ub \<noteq> 0`])
hoelzl@29804
  1469
  also have "\<dots> \<le> ?k * y" using assms by auto
hoelzl@31098
  1470
  finally show ?thesis unfolding ub_mod_def real_of_float_sub real_of_float_mult by auto
hoelzl@29804
  1471
qed
obua@16782
  1472
hoelzl@39161
  1473
lemma le_float_def'[code]: "f \<le> g = (case f - g of Float a b \<Rightarrow> a \<le> 0)"
hoelzl@29804
  1474
proof -
hoelzl@31098
  1475
  have le_transfer: "(f \<le> g) = (real (f - g) \<le> 0)" by (auto simp add: le_float_def)
hoelzl@29804
  1476
  from float_split[of "f - g"] obtain a b where f_diff_g: "f - g = Float a b" by auto
hoelzl@31098
  1477
  with le_transfer have le_transfer': "f \<le> g = (real (Float a b) \<le> 0)" by simp
hoelzl@29804
  1478
  show ?thesis by (simp add: le_transfer' f_diff_g float_le_zero)
hoelzl@29804
  1479
qed
hoelzl@29804
  1480
hoelzl@39161
  1481
lemma less_float_def'[code]: "f < g = (case f - g of Float a b \<Rightarrow> a < 0)"
hoelzl@29804
  1482
proof -
hoelzl@31098
  1483
  have less_transfer: "(f < g) = (real (f - g) < 0)" by (auto simp add: less_float_def)
hoelzl@29804
  1484
  from float_split[of "f - g"] obtain a b where f_diff_g: "f - g = Float a b" by auto
hoelzl@31098
  1485
  with less_transfer have less_transfer': "f < g = (real (Float a b) < 0)" by simp
hoelzl@29804
  1486
  show ?thesis by (simp add: less_transfer' f_diff_g float_less_zero)
hoelzl@29804
  1487
qed
wenzelm@20771
  1488
obua@16782
  1489
end