Library additions.More_on_positive


From Coq Require Import Arith NArith Lia Recdef.
From additions Require Import Pow Compatibility Wf_transparent.
Open Scope positive_scope.
Import Monoid_def.

Basic lemmas about positive and N


Definition pos_eq_dec : p p':positive, {p = p'}+{p p'}.

Lemma N_0_le_n: n:N, (0 n)%N.

Lemma Pos_to_nat_neq_0 : p, Pos.to_nat p 0%nat.

#[global] Hint Resolve Pos_to_nat_neq_0 : chains.

Relationship with nat and N

Lemma Npos_diff_zero : p, N.pos p 0%N.

Lemma Npos_gt_0 : p, (0 < N.pos p)%N.

#[global] Hint Resolve Npos_diff_zero Npos_gt_0 : chains.

Lemma pos2N_inj_lt : n p, (n < p)%positive (N.pos n < N.pos p)%N.

Lemma pos2N_inj_add : n p, N.pos (n + p) = (N.pos n + N.pos p)%N.

Ltac pos2nat_inj_tac :=
  repeat (rewrite Pos2Nat.inj_add || rewrite Pos2Nat.inj_mul ||
          rewrite Pos2Nat.inj_lt || rewrite Pos2Nat.inj_le).

Lemma Pos2Nat_le_1_p : p, (1 Pos.to_nat p)%nat.

Lemma N_le_1_pos : p, (1 N.pos p)%N.

Lemma pos_le_mul : p q , (p p × q)%positive.

Lemma pos_lt_mul : p q , (1 < q p < p × q)%positive.

Lemma Pos2Nat_le_n_pn :
   p q,
    (Pos.to_nat p Pos.to_nat p × Pos.to_nat q)%nat.

#[global] Hint Resolve Pos2Nat_le_1_p : chains.

Surjection from N into positive


Definition N2pos (n:N) : positive :=
 match n with 0%NxH | Npos pp end.

Lemma N2pos_pos :
   i, N2pos (Npos i) = i.

Lemma N_pos_N2pos : n, 0%N n n = Npos (N2pos n).

Lemma N2pos_lt_switch : n p, (0%N < n)%N
                                     ( (N.pos p < n)%N (p < N2pos n)%positive).

Ltac N2pos_simpl x := simpl (N2pos (N.pos x)) in ×.

Ltac N2pos_destruct t y :=
 destruct t as [| y] ; [try (discriminate || contradiction) | N2pos_simpl y].

Lemma N2pos_lt_switch2 : n p, (0%N < n)%N
                                      ((N2pos n < p)%positive
                                        (n < N.pos p)%N).

Lemma pos_lt_wf : well_founded Pos.lt.

Partial exact log2 function

Fixpoint exact_log2(p:positive) : option positive :=
match p with
  | 1%positive | xI _None
  | 2%positiveSome xH
  | xO qmatch exact_log2 q with
              | Some lSome (l+1)%positive
              | _None
            end
end.

Compute exact_log2 16. = Some 4 : option positive
Compute exact_log2 10. = None : option positive

Lemma exact_log2xOx0 :
   p i, exact_log2 (xO p) = Some i
              exact_log2 (xO (xO p)) = Some (i+1)%positive.

Lemma exact_log2_spec :
   p i: positive, exact_log2 p = Some i p = (2 ^ i)%positive.

Another induction principle for positive

Lemma positive_4step_ind : P : positive Prop,
   P 1%positive P 2%positive P 3%positive
  ( p, P p P (xO (xO p)) P (xI (xO p)) P (xO (xI p))
               P (xI (xI p)))
   p, P p.

Lemma pos_gt_3 : p:positive,
  p 1 p 3 exact_log2 p = None 3 < p.

#[global] Hint Resolve pos_gt_3 : chains.

Lemmas on Euclidean division

N.pos_div_eucl (a:positive) (b:N) : N * N

Lemma pos_div_eucl_quotient_pos : a b q r,
                                    N.pos_div_eucl a b = (q, r)
                                    (b N.pos a)%N
                                    b 0%N
                                    (q 0%N).

Lemma pos_div_eucl_quotient_lt : a b q r,
                                   N.pos_div_eucl a b = (q, r)
                                   (1 < b)%N
                                   (q < N.pos a)%N.

Lemma N_pos_div_eucl_divides : i b q,
                                 N.pos_div_eucl i (N.pos b) = (q, 0%N)
                                 (b × N2pos q)%positive = i.

 Lemma N_pos_div_eucl_rest : i b q r,
                               N.pos_div_eucl i (N.pos b) = (q, r)
                               (0 < r)%N (0 < q)%N
                               (b × N2pos q + N2pos r)%positive = i.

 Lemma N_pos_div_eucl_q0 : i b r,
                             N.pos_div_eucl i (N.pos b) = (0%N, r)
                             i = N2pos r.

An auxiliary lemma
Lemma lt_S_2i :
i j:nat, (i < j 2 × i + 1 < 2 × j)%nat.

Lemma N_le_mul_pos : q p, (q q × N.pos p)%N.

Ltac quotient_small div_equation H :=
  match type of div_equation with
    (N.pos_div_eucl ?a ?b = (?q,?r)) ⇒
    assert (H : (q < N.pos a)%N);
    [apply (pos_div_eucl_quotient_lt _ _ _ _ div_equation); auto|]
  end.

Ltac rest_small div_equation H :=
  match type of div_equation with
    (N.pos_div_eucl ?a ?b = (?q,?r)) ⇒
    let H0 := fresh "H" in
    assert (H : (r < b)%N);
    [generalize (N.pos_div_eucl_remainder a b); simpl; intro H0;
     rewrite div_equation in H0; apply H0 ; try discriminate| ]
  end.