type complexe = {re : float; im : float};;
let float_to_c r = {re = r; im = 0.};;
let rec lf_to_lc = function
| [] -> []
| e::q -> float_to_c e::lf_to_lc q;;
let zero = {re = 0.; im = 0.};;
let un = {re = 1.; im = 0.};;
let conj z = {re = z.re; im = -.z.im};;
let add z1 z2 = {re = z1.re +. z2.re; im = z1.im +. z2.im};;
let mul z1 z2 = {re = z1.re *. z2.re -. z1.im *. z2.im; im = z1.im *. z2.re +. z2.im *. z1.re};;
let rec horner p x = match p with
| [] -> zero
| a::q -> add a (mul x (horner q x));;
horner (lf_to_lc [1.; 2.; 3.]) un;;
let rec divise p = match p with
| [] -> [], []
| [a] -> failwith "le nombre de coefficients doit être pair"
| a::b::q -> let p0, p1 = divise q in
a::p0, b::p1;;
let rec fft p w =
if List.tl p = [] then p
else let p0, p1 = divise p in
let wcarre = mul w w in
let t0, t1 = fft p0 wcarre, fft p1 wcarre in
let rec aux wk l0 l1 = match l0, l1 with
| [], [] -> []
| y0::q0, y1::q1 -> (add y0 (mul wk y1))::aux (mul w wk) q0 q1 in
aux un (t0@t0) (t1@t1);;
let rec est_puiss2 n =
if n = 1 then true
else if n mod 2 = 0 then est_puiss2 (n/2)
else false;;
let puiss2 l =
let rec aux n li = match li with
| [] -> if est_puiss2 n then [] else zero::aux (n+1) []
| e::q -> e::aux (n+1) q in
aux 0 l;;
puiss2 [un; un; un; un; un];;
let completer l =
let rec aux n li = match li with
| [] -> if n = 0 then [] else zero::aux (n-1) []
| e::q -> e::aux n q in
aux (List.length l) l;;
completer [un; un; un];;
let rec mul_ft p q = match p, q with
| [], [] -> []
| p0::p', q0::q' -> (mul p0 q0)::mul_ft p' q';;
let coeff r =
let n = List.length r in
let rec aux = function
| [] -> []
| e::q -> (mul {re = 1./. float n; im = 0.} e)::aux q in
aux r;;
let mul_poly p q =
let p', q' = completer p, completer q in
let n = List.length p' in
let theta = 2.*.3.14159265 /. float n in
let w = {re = cos(theta); im = sin(theta)} in
let ftp, ftq = fft p' w, fft q' w in
let r = mul_ft ftp ftq in
let rhat = fft r (conj w) in
coeff rhat;;
mul_poly (lf_to_lc ([1.; 0.; 3.; 1.])) (lf_to_lc ([2.; 1.; 0.; 2.]));;