162 lines
4.1 KiB
OCaml
162 lines
4.1 KiB
OCaml
(** Generating primes *)
|
|
|
|
open Builtin
|
|
open Basic_arithmetics
|
|
|
|
(* Initializing list of integers for eratosthenes's sieve. Naive
|
|
version.
|
|
*)
|
|
|
|
(** List composed of 2 and then odd integers starting at 3.
|
|
@param n number of elements in the list of integers.
|
|
*)
|
|
let init_eratosthenes n =
|
|
let rec init_eratosthenes_rec i =
|
|
match i with
|
|
i when i > n -> []
|
|
| i when modulo i 2 = 1 -> i::init_eratosthenes_rec (i+2)
|
|
| i -> init_eratosthenes_rec (i+1)
|
|
in if n > 1 then
|
|
2::init_eratosthenes_rec 3
|
|
else [];;
|
|
|
|
(* Eratosthenes sieve. *)
|
|
|
|
(** Eratosthene sieve.
|
|
@param n limit of list of primes, starting at 2.
|
|
*)
|
|
let rec remove_multiples_from_list e l =
|
|
match l with
|
|
[] -> []
|
|
| e1::l1 -> begin
|
|
match modulo e1 e with
|
|
0 -> remove_multiples_from_list e l1
|
|
| _ -> e1::remove_multiples_from_list e l1
|
|
end;;
|
|
|
|
let eratosthenes n =
|
|
let list = init_eratosthenes n in
|
|
let rec eratosthenes_rec l =
|
|
match l with
|
|
[] -> []
|
|
| e::l1 -> begin
|
|
let l1 = remove_multiples_from_list e l1 in
|
|
e::eratosthenes_rec l1
|
|
end
|
|
in eratosthenes_rec list
|
|
|
|
(* Write and read into file functions for lists. *)
|
|
|
|
(** Write a list into a file. Element seperator is newline.
|
|
@param file path to write to.
|
|
*)
|
|
let write_list li file =
|
|
let oc = open_out file in
|
|
let rec write l =
|
|
match l with
|
|
[] -> close_out oc
|
|
| e::l1 -> Printf.fprintf oc "%d\n" e; write l1
|
|
in write li;;
|
|
|
|
(** Write a list of prime numbers up to limit into a txt file.
|
|
@param n limit of prime numbers up to which to build up a list of primes.
|
|
@param file path to write to.
|
|
*)
|
|
let write_list_primes n file =
|
|
let list = eratosthenes n in
|
|
write_list list file;;
|
|
|
|
(** Read file safely ; catch End_of_file exception.
|
|
@param in_c input channel.
|
|
*)
|
|
let input_line_opt in_c =
|
|
try Some (input_line in_c)
|
|
with End_of_file -> None
|
|
|
|
(** Create a list out of reading a line per line channel.
|
|
@param in_c input channel.
|
|
*)
|
|
let create_list in_c =
|
|
let rec read acc =
|
|
match input_line_opt in_c with
|
|
None -> acc
|
|
| Some l -> l::read acc
|
|
in read [];;
|
|
|
|
(** Load list of primes into OCaml environment.
|
|
@param file path to load from.
|
|
*)
|
|
let read_list_primes file =
|
|
let list = create_list (open_in file) in
|
|
let rec put list =
|
|
match list with
|
|
[] -> []
|
|
| e::l -> (int_of_string e)::put l
|
|
in put list;;
|
|
|
|
(* Auxiliary functions to extract big prime numbers for testing
|
|
purposes.
|
|
*)
|
|
|
|
(** Get biggest prime.
|
|
@param l list of prime numbers.
|
|
*)
|
|
let rec last_element l = match l with
|
|
| [] -> failwith "Builtin.generate_primes.last_element: Your list \
|
|
is empty. "
|
|
| e::[] -> e
|
|
| h::t -> last_element t
|
|
|
|
(** Get two biggest primes.
|
|
@param l list of prime numbers.
|
|
*)
|
|
let rec last_two l = match l with
|
|
| [] | [_] -> failwith "Builtin.generate_primes.last_two: List has \
|
|
to have at least two prime numbers."
|
|
| e::g::[] -> (e, g)
|
|
| h::t -> last_two t
|
|
;;
|
|
|
|
(* Generating couples of prime numbers for specific or fun
|
|
purposes.
|
|
*)
|
|
|
|
(** Finding couples of primes where second entry is twice the first
|
|
plus 1.
|
|
@param limit positive integer bounding searched for primes.
|
|
@param isprime function testing for (pseudo)primality.
|
|
*)
|
|
|
|
|
|
let double_primes limit isprime =
|
|
let list = eratosthenes limit in
|
|
let rec double_primes_rec l =
|
|
match l with
|
|
[] -> []
|
|
| e::l1 -> begin
|
|
let double = e * 2 + 1 in
|
|
if isprime double then
|
|
(e, double)::double_primes_rec l1
|
|
else
|
|
double_primes_rec l1
|
|
end
|
|
in double_primes_rec list;;
|
|
|
|
(** Finding twin primes.
|
|
@param limit positive integer bounding searched for primes.
|
|
@param isprime function testing for (pseudo)primality.
|
|
*)
|
|
let twin_primes limit isprime =
|
|
let list = eratosthenes limit in
|
|
let rec double_primes_rec l =
|
|
match l with
|
|
[] -> []
|
|
| e::l1 -> begin
|
|
let double = e + 2 in
|
|
if isprime double then
|
|
(e, double)::double_primes_rec l1
|
|
else
|
|
double_primes_rec l1
|
|
end
|
|
in double_primes_rec list;;
|