Library util

Require Import EqNat.
Require Import Bool.
Require Import ZArith.
Require Import List.
Require Import Classical.
Require Import Max.

Lemma beq_dif_false : forall n m, n <> m -> beq_nat n m = false.

Lemma beq_nat_false : forall a b, beq_nat a b = false -> a <> b.

Lemma beq_nat_true: forall x y, beq_nat x y = true -> x = y.

Lemma beq_nat_classic : forall a b,
  beq_nat a b = true \/ beq_nat a b =false.

Lemma beq_nat_com: forall n m, beq_nat n m = beq_nat m n.

Lemma negb_false_is_true : forall x, negb x = false -> x = true.

Lemma negb_true_is_false : forall x, negb x = true -> x = false.

Lemma plus_lt_exists: forall l l' L, l' + l <= L -> exists n, L = n + l' + l.

Lemma Zeq_bool_classic : forall x y,
  Zeq_bool x y = true \/ Zeq_bool x y = false.

Lemma Zeq_bool_refl : forall x, Zeq_bool x x = true.

Lemma Zeq_bool_sym : forall x y, Zeq_bool x y = Zeq_bool y x.

Lemma Zeq_bool_true : forall x y, Zeq_bool x y = true -> x = y.

Lemma Zeq_bool_false : forall x y, Zeq_bool x y = false <-> x <> y.

Lemma Zeq_bool_false' : forall x y, Zeq_bool x y = false -> x <> y.

Lemma Zeq_bool_false'' : forall x y, x <> y -> Zeq_bool x y = false.

Lemma Zgt_bool_true : forall a b, Zgt_bool a b = true -> (a > b)%Z.

Lemma Zgt_bool_true' : forall a b, (a > b)%Z -> Zgt_bool a b = true.

Lemma Zgt_bool_false: forall a b, Zgt_bool a b = false -> (a <= b)%Z.

Lemma Zge_bool_true : forall a b, Zge_bool a b = true -> (a >= b)%Z.

Lemma Zge_bool_true' : forall a b, (a >= b)%Z -> Zge_bool a b = true.

Lemma Zlt_bool_true : forall a b, Zlt_bool a b = true -> (a < b)%Z.

Lemma Zlt_bool_Prop : forall a b, (a < b)%Z -> Zlt_bool a b = true.

Lemma Zlt_bool_Prop' : forall a b, (b >= a)%Z -> Zlt_bool b a = false.

Lemma Zle_bool_true : forall a b, Zle_bool a b = true -> (a <= b)%Z.

Lemma Zle_bool_true' : forall a b, (a <= b)%Z -> Zle_bool a b = true.

Lemma Zle_neq_lt : forall n m,
  (n <= m)%Z -> (n <> m)%Z -> (n < m)%Z.

Lemma Z_of_nat_Zpos_P_of_succ_nat : forall n,
  Z_of_nat (n + 1) = Zpos (P_of_succ_nat n).

Lemma nat2pos: forall n,
  n > 0 ->
  exists p, Z_of_nat n = Zpos p /\ nat_of_P p = n.

Lemma Z_of_nat_inj : forall x y,
  Z_of_nat x = Z_of_nat y -> x = y.

Lemma Z_S : forall n,
  Z_of_nat (S n) = (Z_of_nat n + 1)%Z.

Lemma Z_of_nat_inj': (forall x y, x = y -> Z_of_nat x = Z_of_nat y).

Lemma Z_of_nat_le_inj': forall x y, x <= y -> (Z_of_nat x <= Z_of_nat y)%Z.

Lemma Z_of_nat_le_inj: forall x y, (Z_of_nat x <= Z_of_nat y)%Z -> x <= y.

Lemma Z_of_nat_lt_inj': forall x y, x < y -> (Z_of_nat x < Z_of_nat y)%Z.

Lemma Z_of_nat_lt_inj: forall x y, (Z_of_nat x < Z_of_nat y)%Z -> x < y.

Lemma Z_of_nat_ge_inj': forall x y, x >= y -> (Z_of_nat x >= Z_of_nat y)%Z.

Lemma Z_of_nat_ge_inj: forall x y, (Z_of_nat x >= Z_of_nat y)%Z -> x >= y.

Lemma Z_of_nat_gt_inj': forall x y, x > y -> (Z_of_nat x > Z_of_nat y)%Z.

Lemma Z_of_nat_gt_inj: forall x y, (Z_of_nat x > Z_of_nat y)%Z -> x > y.

Lemma nat_of_Z: forall z,
  (z >= 0)%Z ->
  exists n, z = Z_of_nat n.

Lemma length_app : forall (A:Set) (l:list A) l', length (l++l') = plus (length l) (length l').

Lemma tail_length : forall (A:Set) (lst:list A),
  length (tail lst) = (length lst - 1)%nat.

Lemma tail_app : forall (A:Set) (lst lst':list A),
  (0 < length lst)%nat ->
  tail (lst ++ lst') = tail lst ++ lst'.

Lemma incl_nil : forall (A:Set) (h:list A), incl h nil -> h=nil.

Definition inter (A:Set) h1 h2 h := forall (x:A),
  In x h1 /\ In x h2 <-> In x h.
Implicit Arguments inter.

Lemma inter_nil: forall (A:Set) l, @inter A l nil nil.
Implicit Arguments inter_nil.

Lemma inter_weak : forall (A:Set) x L K M,
 @inter A K L M -> ~ In x K -> inter K (x :: L) M.
Implicit Arguments inter_weak.

Lemma inter_sym: forall (A:Set) h h1 h2,
  @inter A h h1 h2 -> inter h1 h h2.
Implicit Arguments inter_sym.

Lemma inter_nil_subset : forall (A:Set) (l:list A) l',
  inter l l' nil ->
  forall l'',
    incl l'' l ->
    inter l'' l' nil.

Lemma inter_app : forall (A:Set) (l k m:list A), inter (l++k) m nil ->
  inter l m nil /\ inter k m nil.

Lemma inter_stren : forall (A:Set) (hd1:A) tl1 l2,
  inter (hd1::tl1) l2 nil -> inter tl1 l2 nil.
Implicit Arguments inter_stren.

Lemma list_split : forall (A:Set) (l:list A) x,
  In x l ->
  exists l1, exists l2, l = l1 ++ (x::nil) ++ l2.

Lemma list_split2 : forall (A:Set) (l:list A) k,
  (k <= length l)%nat ->
  exists l1, exists l2, length l1 = k /\
    l = l1 ++ l2.


Inductive permut (A:Set) : (list A) -> (list A) -> Prop :=
  permut_refl: forall h, permut h h
  | permut_cons: forall a l0 l1, permut l0 l1 -> permut (a::l0) (a::l1)
  | permut_append: forall a l, permut (a::l) (l ++ a::nil)
  | permut_trans: forall l0 l1 l2, permut l0 l1 -> permut l1 l2 -> permut l0 l2.

Lemma permut_sym : forall (A:Set) (h1 h2 : (list A)),
  permut h1 h2 -> permut h2 h1.

Lemma permut_nil' : forall (A:Set) (k k':(list A)),
  permut k k' -> k'=nil -> k=nil.

Lemma permut_nil : forall (A:Set) (k:(list A)),
  permut k nil -> k=nil.

Lemma In_permut : forall (A:Set) (h h':(list A)), permut h' h ->
  forall x, In x h -> In x h'.

Lemma permut_head : forall (A:Set) h (a b:A), permut (a::b::h) (b::a::h).

Lemma rotate_is_permut : forall (A:Set) k (a:A), (permut (a::k) (k++a::nil)).

Lemma permut_inter : forall (A:Set) (k m:(list A)), permut k m ->
  forall n p, inter n m p -> inter n k p.

Ltac Permut n :=
  match goal with
  | |- (permut ?X1 ?X1) => apply permut_refl
  | |- (permut (?X1 :: ?X2) (?X1 :: ?X3)) =>
      let newn := eval compute in (length X2) in
      (apply permut_cons; Permut newn)
  | |- (permut (?X1 :: ?X2) ?X3) =>
      match eval compute in n with
      | 1 => fail
      | _ =>
          let l0' := constr:(X2 ++ X1 :: nil) in
          (apply (@permut_trans _ (X1 :: X2) l0' X3);
            [ apply permut_append | compute; Permut (pred n) ])
      end
  end.

Ltac PermutProve :=
  match goal with
  | |- (permut ?X1 ?X2) =>
      match eval compute in (length X1 = length X2) with
      | (?X1 = ?X1) => Permut X1
      end
  end.

Lemma permut_inv_head : forall (A:Set) (L:list A) (c d:A), permut (c :: d :: L) (d :: c :: L).

Lemma permut_app_com : forall (A:Set) (L K:(list A)), permut (L ++ K) (K ++ L).


Definition length_rev : forall (A:Set) (l:list A), length (rev l) = length l.

Lemma rev_inj : forall (A:Set) (l k:list A),
  rev l = rev k -> l = k.

Lemma list_last : forall (A:Set) (lst:list A), length lst > O ->
  exists lst', exists a,
    lst = lst' ++ a::nil.

Lemma nth_app : forall (A:Set) n (lst:list A) (v:A),
  length lst <= n -> forall lst',
    nth n (lst++lst') v = nth (n-length lst) lst' v.

Definition last (A:Set) (lst:list A) (def:A) :=
  match length lst with
    O => def
    | S n => nth n lst def
  end.
Implicit Arguments last.

Fixpoint del_heads (A:Set) (l: list A) (n: nat) {struct n} : list A :=
  match n with
    0 => l
    | S n' => match l with
                nil => nil
                | hd::tl => del_heads A tl n'
              end
  end.
Implicit Arguments del_heads.

Lemma del_heads_length: forall n (A:Set) (l: list A),
  length (del_heads l n) = length l - n.
Implicit Arguments del_heads_length.

Lemma del_heads_plus : forall (A:Set) a b (lst:list A),
  del_heads lst (a + b) = del_heads (del_heads lst a) b.

Lemma del_heads_app' : forall n (A:Set) (lst lst':list A),
  length lst = n ->
  forall k, k <= n ->
    del_heads (lst ++ lst') k = (del_heads lst k) ++ lst'.

Lemma del_heads_app: forall n (A:Set) (l l':list A),
  length l = n ->
  del_heads (l ++ l') n = l'.
Implicit Arguments del_heads_app.

Lemma del_heads_all : forall n (A:Set) (lst:list A),
  length lst = n ->
  del_heads lst n = nil.

Fixpoint heads (A: Set) (l: list A) (n: nat) {struct n} : list A :=
  match n with
    0 => nil
    | S n' => match l with
                nil => nil
                | hd::tl => hd::heads A tl n'
              end
  end.
Implicit Arguments heads.

Lemma length_heads : forall n (A:Set) (lst:list A) k,
  length lst = n ->
  k <= n ->
  length (heads lst k) = k.

Lemma heads_app : forall n (A:Set) (lst1:list A),
  length lst1 = n ->
  forall lst2,
    heads (lst1 ++ lst2) n = lst1.

Lemma heads_del_heads : forall (A:Set) n (lst:list A),
  length lst = n ->
  forall k, k <= n ->
    lst = heads lst k ++ del_heads lst k.

Lemma mult_minus_distr_r : forall n m p, n >= m -> (n - m) * p = n * p - m * p.

Lemma mult_minus_distr_l : forall n m p, m >= p -> n * (m - p) = n * m - n * p.

Lemma max_lemma1: forall x1 x2 x3,
   x1 >= x2 ->
   max x1 x3 >= max x2 x3.

Lemma max_lemma2: forall x1 x2 x3,
   x1 > max x2 x3 ->
   x1 > x2 /\ x1 > x3.

Lemma max_lemma3: forall x1 x2 x3,
  x1 > x2 /\ x1 > x3 ->
  x1 > max x2 x3.

Lemma max_lemma4: forall x y,
  max x y >= x.

Lemma max_lemma5: forall x y z,
  z >= x ->
  max z y >= x.

Lemma max_lemma6: forall x y z,
  z >= x ->
  max y z >= x.

Fixpoint nat_lt (n m:nat) {struct n}: bool :=
  match n with
    0 => match m with
           0 => false
           | S m' => true
         end
    | S n' => match m with
                0 => false
                | S m' => nat_lt n' m'
              end
  end.

Definition nat_le (n m:nat) : bool := orb (beq_nat n m) (nat_lt n m).

Fixpoint nat_gt (n m:nat) {struct n}: bool :=
  match n with
    0 => false
    | S n' => match m with
                0 => true
                | S m' => nat_gt n' m'
              end
  end.

Definition nat_ge (n m:nat) : bool := orb (beq_nat n m) (nat_gt n m).

Lemma nat_lt_true: forall n m, nat_lt n m = true -> n < m.

Lemma nat_lt_true': forall n m, n < m -> nat_lt n m = true.

Lemma nat_lt_false: forall n m, nat_lt n m = false -> n >= m.

Lemma nat_lt_false': forall n m, n >= m -> nat_lt n m = false.

Lemma nat_lt_assym: forall n m, nat_lt n m = true -> nat_lt m n= false.

Lemma nat_lt_irrefl: forall n , nat_lt n n = false.

Lemma nat_lt_trans: forall n m p, nat_lt n m = true -> nat_lt m p = true -> nat_lt n p = true.

Lemma nat_lt_classic: forall n m, nat_lt n m = true \/ nat_lt n m = false.

Ltac Contrad_lt := intros; Hyp_lt_clean;
  match goal with
    | id: ?a = ?b |- _ => subst a; Contrad_lt
    | id: ?a < ?a |- _ => generalize (lt_irrefl a); tauto
    | id1: ?b < ?a, id': ?a < ?b |- _ => generalize (lt_asym a b); tauto
    | id1: ?b < ?a, id': ?a < ?b' |- _ => generalize (lt_trans b a b' id1 id'); clear id'; intros; Contrad_lt
    | |- _ => tauto
  end
  with Hyp_lt_clean :=
  match goal with
    | id: ?a = ?a |- _ => clear id; Hyp_lt_clean
    | id: ?a < ?b, id': ?a < ?b |- _ => clear id; Hyp_lt_clean
    | |- _ => idtac
  end.

Lemma nth_beyond : forall (A:Set) (lst:list A) k dv,
  k < length lst ->
  forall lst',
    nth k lst dv = nth k (lst++lst') dv.

Lemma list_tail' : forall (A:Set) (lst:list A) def_val,
  length lst > 0 ->
  nth 0 lst def_val :: tail lst = lst.

Lemma list_split' : forall (A:Set) n (lst:list A) (def:A),
  length lst = n ->
  n > 0 ->
  forall j, j < n ->
    exists l1, length l1 = j /\
      exists l2,
        lst = l1 ++ (nth j lst def)::nil ++ l2.

Lemma list_split'' : forall (A:Set) n (lst:list A) (def:A),
  length lst = n ->
  forall j, j < n ->
    exists l1, length l1 = j /\
      exists l2,
        lst = l1 ++ (nth j lst def)::nil ++ l2.

Lemma list_last' : forall (A:Set) n (lst:list A) (def:A),
  length lst = n ->
  n > 0 ->
  exists l1, lst = l1 ++ (nth (n-1) lst def)::nil.

Fixpoint del_nth (A:Set) (n:nat) (lst:list A) { struct lst } : list A :=
  match lst with
    nil => nil
    | hd::tl => match n with
                  O => tl
                  | S n' => hd::del_nth A n' tl
                end
  end.
Implicit Arguments del_nth.

Lemma del_nth_length : forall (A:Set) (lst:list A) (n:nat),
  n < length lst ->
  length (del_nth n lst) = length lst - 1.

Definition del_nth_last (A:Set) (lst:list A) : list A :=
  match lst with
    nil => nil
    | _ => del_nth ((length lst) - 1) lst
  end.
Implicit Arguments del_nth_last.

Lemma del_nth_last_length: forall (n:nat) (A:Set) (lst:list A),
  length lst = n ->
  length (del_nth_last lst) = (n - 1)%nat.

Lemma del_nth_last_exact' : forall (A:Set) (lst:list A) (a:A),
  del_nth (length lst) (lst ++ a::nil) = lst.

Lemma del_nth_last_exact : forall (A:Set) (lst:list A) a,
  del_nth_last (lst ++ a::nil) = lst.

Lemma del_nth_app : forall (A:Set) k (lst1:list A),
  length lst1 = k ->
  forall lst a lst2,
    lst = lst1 ++ a::lst2 ->
    del_nth k lst = lst1 ++ lst2.

Fixpoint update_list (A:Set) (l:list A) (n:nat) (v:A) {struct l} : list A :=
  match l with
    nil => nil
    | hd::tl => match n with
                  O => v::tl
                  | S n' => hd :: update_list _ tl n' v
                end
  end.
Implicit Arguments update_list.

Lemma length_update_list : forall (A:Set) n lst k (v:A),
  length lst = n ->
  length (update_list lst k v) = n.

Lemma update_list_out : forall (A:Set) n (m:A) lst,
  n >= length lst ->
  update_list lst n m = lst.

Lemma nth_update_list : forall (A:Set) n (m:A) lst def_val,
  n < length lst ->
  nth n (update_list lst n m) def_val = m.

Lemma nth_update_list' : forall (A:Set) lst n n' (m:A) def_val,
  n <> n' ->
  nth n (update_list lst n' m) def_val = nth n lst def_val.

Lemma update_list_app : forall (A:Set) n lst (v:A),
  length lst <= n -> forall lst',
    update_list (lst++lst') n v = lst ++ (update_list lst' (n-length lst) v).

Lemma update_list_app' : forall (A:Set) n lst (v:A),
  n < length lst -> forall lst',
    update_list (lst++lst') n v = (update_list lst n v) ++ lst'.

Lemma del_nth_update_list : forall (A:Set) (lst:list A) k m,
  del_nth k (update_list lst k m) =
  del_nth k lst.

Lemma minus_plus': forall n m p, p <= n -> m = n - p -> n = m + p.

Lemma minus_plus_comm : forall a b n p,
  p <= a ->
  a + n - p = b -> a - p + n = b.

Lemma minus_le_plus : forall c a b,
  c - b <= a -> c <= a + b.

Lemma plus_le_minus : forall c a b,
  a + c <= b -> a <= b - c.

Lemma plus_le_minus' : forall c a b,
  a <= b + c -> a - c <= b.

Lemma plus_lt_minus' : forall c a b,
  b > 0 ->
  a < b + c -> a - c < b.

Lemma plus_lt_minus : forall c a b,
  a + c < b -> a < b - c.

Lemma plus_minus_assoc : forall b a c,
  b >= c ->
  a + b - c = a + (b-c).

Lemma minus_minus_comm : forall a b n p,
  p + n <= a ->
  a - n - p = b -> a - p - n = b.

Lemma le2lt : forall n k,
  n < k -> n <= k - 1.

Lemma minus_le_compat_l : forall n a b,
  n <= a ->
  n <= b ->
  a <= b -> a - n <= b - n.

Lemma minus_lt_compat : forall a n m,
  m < n ->
  n <= a ->
  a - n < a - m.

Lemma minus_compat : forall a b a' b',
  a = a' ->
  b = b' ->
  a - b = a' - b'.

Lemma plus_compat : forall a b a' b',
  a = a' ->
  b = b' ->
  a + b = a' + b'.

Lemma scale_le : forall a,
  1 <= a ->
  forall b,
    b <= a * b.

Lemma scale_lt : forall a,
  1 < a ->
  forall b,
    1 <= b ->
    b < a * b.

Lemma le_neq_lt : forall n m,
  n <= m -> n <> m -> n < m.

Lemma my_mult_lt_compat_l: forall a b c,
  a * c < b * c ->
  c >= 1 ->
  a < b.

Lemma S_lt : forall k,
  k > 0 ->
  forall a b,
    a < b ->
    a * k < b * k.

Lemma inv_lt : forall k a b,
  k > 0 ->
  b > 0 ->
  a * k < b * k ->
  a < b.

Lemma tmp : forall n k a b,
  a < b ->
  a + n * b = k * b ->
  a = 0.

Fixpoint power (b:nat) (e:nat) {struct e} : nat :=
  match e with
    O => 1
    | S e' => b * (power b e')
  end.

Lemma power_0 : power 2 0 = 1.

Lemma power_1' : power 2 1 = 2.

Lemma power_2 : power 2 2 = 4.

Lemma power_3 : power 2 3 = 8.

Lemma power_8 : power 2 8 = 256.

Lemma power_1 : forall n, 1 <= power 2 n.

Lemma power_S : forall k n, power k (S n) = k * power k n.

Lemma two_power_nat_power : forall l,
  two_power_nat l = Z_of_nat (power 2 l).

Lemma two_power_nat_is_exp : forall (n m:nat),
  (two_power_nat (n + m) = two_power_nat n * two_power_nat m)%Z.

Lemma power_is_exp : forall (n m:nat),
  power 2 (n + m) = power 2 n * power 2 m.

Lemma two_power_nat_1 : forall l:nat, (1 <= two_power_nat l)%Z.

Lemma two_power_nat_lt : forall k l, l < k ->
  (two_power_nat l < two_power_nat k)%Z.

Lemma two_power_nat_le : forall k l, l <= k ->
  (two_power_nat l <= two_power_nat k)%Z.

Lemma power_2_gt : forall n m,
  n > m ->
  power 2 n > power 2 m.

Lemma power_2_lt : forall n m,
  n < m ->
  power 2 n < power 2 m.

Lemma power_2_ge : forall n m,
  n >= m ->
  power 2 n >= power 2 m.

Lemma power_2_le : forall n m,
  n <= m ->
  power 2 n <= power 2 m.

Lemma power_plus : forall n,
  power 2 n + power 2 n = power 2 (S n).

Definition beta (e:nat) := power 2 (e * 32).

Lemma beta_is_exp : forall n m,
  beta (n + m) = beta n * beta m.

Lemma beta_power : forall (e:nat), beta e = power 2 (e * 32).

Lemma beta_power1 : beta 1 = power 2 32.

Lemma power_64_beta : power 2 64 = beta 2.

Lemma beta_1 : forall l, 1 <= beta l.

Lemma beta_gt : forall n m,
  n > m ->
  beta n > beta m.

Lemma beta_lt : forall m n,
  m < n ->
  beta m < beta n.

Lemma beta_ge : forall n m,
  n >= m ->
  beta n >= beta m.

Lemma beta_le : forall n m,
  n <= m ->
  beta n <= beta m.

Lemma beta_1_2 : beta 1 >= 2.

Lemma beta_1_4 : beta 1 >= 4.

Open Local Scope Z_scope.

  Lemma Zminus_le_compat : forall a b c,
    a <= c -> a - b <= c - b.

Lemma Zplus_compat : forall a b a' b',
       a = a' -> b = b' -> (a + b) = (a' + b').

Lemma Zlt_neg_pos : forall p q,
  (Zneg p < Zpos q)%Z.

Lemma coeff_unique' : forall a b k,
  0 < k ->
  -k < a < k ->
  -k < b < k ->
  a * k + b = 0 -> a = 0 /\ b = 0.

Lemma coeff_unique : forall a b a' b' k,
  0 <= a < k /\ 0 <= b < k /\ 0 <= a' < k /\ 0 <= b' < k ->
  a * k + b = a' * k + b' -> a = a' /\ b = b'.

Fixpoint Zpower (b:Z) (e:nat) {struct e} : Z :=
  match e with
    O => 1
    | S e' => b * (Zpower b e')
  end.

Notation "b ^^ e" := (Zpower b e) (at level 30).

Lemma Zpower_S : forall k n, k^^(S n) = k * k^^n.

Lemma Zpower_is_exp : forall (n m: nat),
  Zpower 2 (n + m) = Zpower 2 n * Zpower 2 m.

Lemma Zpower_0 : forall n, 0 < Zpower 2 n.

Lemma Zpower_1 : forall n, 1 <= Zpower 2 n.

Lemma Zpower_2_le : forall n m,
  (n <= m)%nat ->
  Zpower 2 n <= Zpower 2 m.

Lemma Zpower_2_lt : forall n m,
  (n < m)%nat ->
  Zpower 2 n < Zpower 2 m.

Lemma Zpower_plus : forall n,
  Zpower 2 n + Zpower 2 n = Zpower 2 (S n).

Lemma Zpower_power : forall e,
  Zpower 2 e = Z_of_nat (power 2 e).

Lemma Zeven_2 : forall m,
  Zeven (2*m).

Lemma Zpower_even : forall m,
  Zeven (Zpower 2 (S m)).

Definition Zbeta (e:nat) := Zpower 2 (e * 32).

Lemma Zbeta_power1 : Zbeta 1 = Zpower 2 32.

Lemma Zpower_64_Zbeta : Zpower 2 64 = Zbeta 2.

Lemma Zbeta_is_exp : forall n m,
  Zbeta (n + m) = Zbeta n * Zbeta m.

Lemma Zbeta_0 : forall l, 0 < Zbeta l.

Lemma Zbeta_1 : forall l, 1 <= Zbeta l.

Lemma Zbeta_lt : forall m n,
  (m < n)%nat ->
  Zbeta m < Zbeta n.

Lemma Zbeta_le : forall m n,
  (m <= n)%nat ->
  Zbeta m <= Zbeta n.

Lemma Zpower_shift_2 : forall n,
  4*n < Zbeta 1 ->
  n < Zpower 2 30.

Lemma Zbeta_power : forall (e:nat), Zbeta e = Zpower 2 (e * 32).

Definition eqmod (a b m:Z) := exists k:Z,
  a = b + k * m.

Notation "a == b [[ m ]]" := (eqmod a b m) (at level 80).

Require Import Znumtheory.

Open Local Scope Z_scope.

Lemma Zis_gcd_eq : forall n m, 0 <= n ->
  Zis_gcd n n m -> n = m \/ n = - m.

Close Local Scope Z_scope.