(* Sqrt *)
(* Direct transcription of an old proof of a fortran program in boyer-moore *)

(* Specifications: *)
Lemma quotient_by_2 a: a - 1 <= (a/2) + (a/2).
Lemma sqrt_main_trick j k: 0 <= j -> 0 <= k ->
(j * k) + j <= ((j + k)/2 + 1)  ^ 2.
Lemma sqrt_main i j: 0 <= i -> 0 < j -> i < ((j + (i/j))/2 + 1) ^ 2.
Lemma sqrt_test_false i j: 0 <= i -> 0 < j -> i/j < j ->  (j + (i/j))/2 < j.
Lemma sqrt_test_true i j: 0 <= i -> 0 < j -> i/j >= j -> j ^ 2 <= i.
Lemma sqrt_step_correct rec i j:
0 < φ i -> 0 < φ j -> φ i < (φ j + 1) ^ 2 ->
2 * φ j < wB ->
(forall j1 : int,
0 < φ j1 < φ j -> φ i < (φ j1 + 1) ^ 2 ->
φ (rec i j1) ^ 2 <= φ i < (φ (rec i j1) + 1) ^ 2) ->
φ (sqrt_step rec i j) ^ 2 <= φ i < (φ (sqrt_step rec i j) + 1) ^ 2.
Lemma iter_sqrt_correct n rec i j: 0 < φ i -> 0 < φ j ->
φ i < (φ j + 1) ^ 2 -> 2 * φ j < wB ->
(forall j1, 0 < φ j1 -> 2^(Z_of_nat n) + φ j1 <= φ j ->
φ i < (φ j1 + 1) ^ 2 -> 2 * φ j1 < wB ->
φ (rec i j1) ^ 2 <= φ i < (φ (rec i j1) + 1) ^ 2) ->
φ (iter_sqrt n rec i j) ^ 2 <= φ i < (φ (iter_sqrt n rec i j) + 1) ^ 2.
Lemma sqrt_init i: 1 < i -> i < (i/2 + 1) ^ 2.
Lemma sqrt_spec : forall x,
φ (sqrt x) ^ 2 <= φ x < (φ (sqrt x) + 1) ^ 2.
(* sqrt2 *)
Lemma sqrt2_step_def rec ih il j:
sqrt2_step rec ih il j =
if (ih <? j)%uint63 then
let quo := fst (diveucl_21 ih il j) in
if (quo <? j)%uint63 then
let m :=
match j +c quo with
| C0 m1 => m1 >> 1
| C1 m1 => (m1 >> 1 + 1 << (digits -1))%uint63
end in
rec ih il m
else j
else j.
Lemma sqrt2_lower_bound ih il j:
Φ (WW ih il) < (φ j + 1) ^ 2 -> φ ih <= φ j.
Lemma diveucl_21_spec_aux : forall a1 a2 b,
wB/2 <= φ b ->
φ a1 < φ b ->
let (q,r) := diveucl_21 a1 a2 b in
φ a1 *wB+ φ a2 = φ q * φ b + φ r /\
0 <= φ r < φ b.
Lemma div2_phi ih il j: (2^62 <= φ j -> φ ih < φ j ->
φ (fst (diveucl_21 ih il j)) = Φ (WW ih il) / φ j)%Z.
Lemma sqrt2_step_correct rec ih il j:
2 ^ (Z_of_nat (size - 2)) <= φ ih ->
0 < φ j -> Φ (WW ih il) < (φ j + 1) ^ 2 ->
(forall j1, 0 < φ j1 < φ j ->  Φ (WW ih il) < (φ j1 + 1) ^ 2 ->
φ (rec ih il j1) ^ 2 <= Φ (WW ih il) < (φ (rec ih il j1) + 1) ^ 2) ->
φ (sqrt2_step rec ih il j) ^ 2 <= Φ (WW ih il)
< (φ (sqrt2_step rec ih il j) + 1) ^  2.
Lemma iter2_sqrt_correct n rec ih il j:
2^(Z_of_nat (size - 2)) <= φ ih ->  0 < φ j -> Φ (WW ih il) < (φ j + 1) ^ 2 ->
(forall j1, 0 < φ j1 -> 2^(Z_of_nat n) + φ j1 <= φ j ->
Φ (WW ih il) < (φ j1 + 1) ^ 2 ->
φ (rec ih il j1) ^ 2 <= Φ (WW ih il) < (φ (rec ih il j1) + 1) ^ 2)  ->
φ (iter2_sqrt n rec ih il j) ^ 2 <= Φ (WW ih il)
< (φ (iter2_sqrt n rec ih il j) + 1) ^ 2.
Lemma sqrt2_spec : forall x y,
wB/ 4 <= φ x ->
let (s,r) := sqrt2 x y in
Φ (WW x y) = φ s ^ 2 + [+|r|] /\
[+|r|] <= 2 * φ s.
(* of_pos *)
Lemma of_pos_rec_spec (k: nat) :
(k <= size)%nat →
∀ p, φ(of_pos_rec k p) = Zpos p mod 2 ^ Z.of_nat k.
Lemma is_int n :
0 <= n < 2 ^ φ digits →
n = φ (of_Z n).
Lemma of_Z_spec n : φ (of_Z n) = n mod wB.
(* General lemmas *)
Lemma Z_oddE a : Z.odd a = (a mod 2 =? 1)%Z.
(* bit *)
Lemma bitE i j : bit i j = Z.testbit φ(i) φ(j).
(* land, lor, lxor *)
Lemma lt_pow_lt_log d k n :
0 < d <= n →
0 <= k < 2 ^ d →
Z.log2 k < n.
Lemma land_spec' x y : φ (x land y) = Z.land φ(x) φ(y).
Lemma lor_spec' x y : φ (x lor y) = Z.lor φ(x) φ(y).
Lemma lxor_spec' x y : φ (x lxor y) = Z.lxor φ(x) φ(y).
Lemma landC i j : i land j = j land i.
Lemma landA i j k : i land (j land k) = i land j land k.
Lemma land0 i : 0 land i = 0%uint63.
Lemma land0_r i : i land 0 = 0%uint63.
Lemma lorA i j k : i lor (j lor k) = i lor j lor k.
Lemma lor0 i : 0 lor i = i.
Lemma lor0_r i : i lor 0 = i.
Lemma lxorA i j k : i lxor (j lxor k) = i lxor j lxor k.
Lemma lxor0 i : 0 lxor i = i.
Lemma lxor0_r i : i lxor 0 = i.
Definition min (i1 i2 : int) :=
if (i1 <=? i2)%uint63 then i1 else i2.