Module Import PrimeDecompAux.
(* We start with faster mod-2 and 2-valuation functions. *)
Fixpoint edivn2 q r := if r is r'.+2 then edivn2 q.+1 r' else (q, r).
Fixpoint elogn2 e q r {struct q} :=
match q, r with
| 0, _ | _, 0 => (e, q)
| q'.+1, 1 => elogn2 e.+1 q' q'
| q'.+1, r'.+2 => elogn2 e q' r'
end.
Arguments elogn2 : simpl nomatch.
Variant elogn2_spec n : nat * nat -> Type :=
Elogn2Spec e m of n = 2 ^ e * m.*2.+1 : elogn2_spec n (e, m).
Definition ifnz T n (x y : T) := if n is 0 then y else x.
Variant ifnz_spec T n (x y : T) : T -> Type :=
| IfnzPos of n > 0 : ifnz_spec n x y x
| IfnzZero of n = 0 : ifnz_spec n x y y.
Arguments primeP {p}.
Arguments primePn {n}.
Arguments primePns {n}.
(* "prime" logarithms and p-parts. *)
Fixpoint logn_rec d m r :=
match r, edivn m d with
| r'.+1, (_.+1 as m', 0) => (logn_rec d m' r').+1
| _, _ => 0
end.
Definition logn p m := if prime p then logn_rec p m m else 0.
(* Some combinatorial formulae. *)
(* Truncated real log. *)
Definition trunc_log p n :=
let fix loop n k :=
if k is k'.+1 then if p <= n then (loop (n %/ p) k').+1 else 0 else 0
in if p <= 1 then 0 else loop n n.
(* Truncated up real logarithm *)
Definition up_log p n :=
if (p <= 1) then 0 else
let v := trunc_log p n in if n <= p ^ v then v else v.+1.

Lemma up_log2_double n : 0 < n -> up_log 2 n.*2 = (up_log 2 n).+1.