(* Polynômes à une variable, avec coefficients dans un anneau quelconque Voir d'abord l'exercice 2.45. *) module type Ring = sig type t val zero : t val one : t val add : t -> t -> t val mul : t -> t -> t val equal : t -> t -> bool end module Poly(R: Ring) : sig include Ring val create: (R.t * int) list -> t val eval: t -> R.t -> R.t end = struct type monomial = { coef : R.t; degree : int } (* coef <> R.zero *) type t = monomial list (* triée par degrés décroissants *) let zero = [] let one = [ { coef = R.one; degree = 0 } ] (* construit un monôme, en assurant que le coefficient n'est pas nul *) let monomial c d = if R.equal c R.zero then [] else [{ coef = c; degree = d }] (* faire la somme de deux polynômes revient à fusionner deux listes triées *) let rec add p1 p2 = match p1, p2 with [], _ -> p2 _, [] -> p1 m1 :: r1, m2 :: r2 -> if m1.degree > m2.degree then m1 :: add r1 p2 else if m1.degree < m2.degree then m2 :: add p1 r2 else let c = R.add m1.coef m2.coef in if R.equal c R.zero then add r1 r2 else { coef = c; degree = m1.degree } :: add r1 r2 (* pour assurer que les monômes sont bien triés par degrés décroissants, on les ajoute un par un avec la fonction add *) let create ml = List.fold_left (fun p (c, d) -> add (monomial c d) p) zero ml let mul p1 p2 = (* multiplication par un monôme *) let mul_monomial m p = List.fold_right (fun m' acc -> let c = R.mul m.coef m'.coef in if R.equal c R.zero then acc else { coef = c; degree = m.degree + m'.degree } :: acc) p [] in List.fold_left (fun p m -> add (mul_monomial m p2) p) zero p1 (* exponentiation efficace *) let rec power x n = if n = 0 then R.one else let y = power x (n / 2) in if n mod 2 = 0 then R.mul y y else R.mul x (R.mul y y) (* l'évaluation parcourt la liste en partant des degrés les plus faibles *) let eval p x = (* v = valeur courante, xk = x^k *) let rec loop v k xk = function [] -> v { coef = c; degree = d } :: l -> assert (d >= k); let xd = R.mul xk (power x (d - k)) in loop (R.add v (R.mul c xd)) d xd l in loop R.zero 0 R.one (List.rev p) (* la représentation triée permet une comparaison efficace *) let rec equal p1 p2 = match p1, p2 with [], [] -> true [], _ _, [] -> false m1 :: r1, m2 :: r2 -> m1.degree = m2.degree && R.equal m1.coef m2.coef && equal r1 r2 end (* Test *) module Int : Ring with type t = int = struct type t = int let zero = 0 let one = 1 let add = ( + ) let mul = ( * ) let equal = ( = ) end module P = Poly(Int) let p = P.create [1,0; 1,2; 1,4] let q = P.create [1,1] let () = assert (P.eval (P.mul p q) 2 = 42)
This document was generated using caml2html