Section prime.
Hint Resolve divides_0 divides_mult divides_refl divides_0_inv : core.
Infix "<d" := divides (at level 70, no associativity).
Definition prime p := p <> 1 /\ forall q, q <d p -> q = 1 \/ q = p.
Fact prime_2 : prime 2.
Hint Resolve prime_2 : core.
Fact prime_algo p : prime p <-> p = 2 \/ 3 <= p /\ ~ 2 <d p /\ forall n, 3+2*n < p -> ~ 3+2*n <d p.
Definition divides_bool n p :=
match p mod n with
| 0 => true
| _ => false
end.
Fact modS_divide n p : p mod S n = 0 <-> S n <d p.
Fact divides_bool_spec n p : divides_bool (S n) p = true <-> S n <d p.
Fact divides_bool_spec' n p : divides_bool (S n) p = false <-> ~ S n <d p.
Fixpoint prime_bool_rec n p : bool :=
match n with
| 0       => true
| 1       => true
| 2       => true
| S (S n') => negb (divides_bool n p) && prime_bool_rec n' p
end.
Fact prime_bool_rec_spec n p : n <= p -> prime_bool_rec n p = true <-> forall k, 3 <= n-2*k -> ~ n-2*k <d p.
(* This is a somewhat naive algo. to test for primality *)
Definition prime_bool p :=
Nat.eqb p 2 || Nat.leb 3 p && negb (divides_bool 2 p) && prime_bool_rec (p-2) p.
Fact prime_ge_2 p : prime p -> 2 <= p.
Fact prime_gcd p q : prime p -> is_gcd p q 1 \/ p <d q.
Fact prime_div_mult p x y : prime p -> p <d x*y -> p <d x \/ p <d y.
Definition prime_or_div p : 2 <= p -> { q | 2 <= q < p /\ q <d p } + { prime p }.

Theorem prime_factor n : 2 <= n -> { p | prime p /\ p <d n }.