(*  polynomial over Z as coef
     var -> nat 
    coef -> list (list (Z * list nat))
*)

Definition var := nat.Definition term := (Z * (list var))%type.Notation "{vs[ x ]}" := (intervs x).Notation "{m[ x ]}" := (interm x).Definition term_add (t1 t2 : term) :=
  let (z1,l) := t1 in
  let (z2,_) := t2 in ((z1 + z2)%Z, l).Definition term_cmp (t1 t2 : term) :=
  let (_,l1) := t1 in
  let (_,l2) := t2 in list_compare _ natc l1 l2.Definition term_opp (t : term): term :=
  let (z,l) := t in ((-z)%Z, l).Fixpoint list_insert (i: nat) (l : list nat) :=
  match l with
  | nil => (i :: nil)
  | j :: l1 =>
      match natc j i with
      | Lt => j :: list_insert i l1
      | _  => i :: l
      end
   end.Definition term_scale (v : nat) (t : term) : term :=
  let (z, l) := t in
  (z, list_insert v l).Definition term_zerop (t : term) :=
  let (z,l) := t in Zeq_bool 0%Z z.Definition coef := list term.Definition c0 : coef := nil.Definition c1 : coef := (1%Z,@nil var)::nil.Definition copp (c : coef) : coef := map term_opp c.Definition cscale (v : var) (c : coef) : coef := 
  map (term_scale v) c.Definition ccons (t : term) (c : coef) :=
  if term_zerop t then c else t :: c.Fixpoint cadd (a b : coef) : coef :=
  match a with
  | nil => b
  | t1 :: a1 =>
      (fix cadd1 (b : coef) : coef :=
        match  b with
        | nil => a
        | t2 :: b1 =>
            match term_cmp t1 t2 with
            | Eq => ccons (term_add t1 t2) (cadd a1 b1)
            | Lt => ccons t1 (cadd a1 b)
            | Gt => ccons t2 (cadd1 b1)
            end
        end) b
  end.Definition ccmp (c1 c2 : coef) :=
  list_compare _ term_cmp c1 c2.Definition czerop (c : coef) :=
  match c with nil => true | _ => false end.Definition conep (c : coef) :=
  match c with (Zpos xH,nil) :: nil => true | _ => false end.

(* Specifications: *)
Lemma natc_id n : natc n n = Eq.
Lemma list_compare_id l : list_compare _ natc l l = Eq.
Lemma cadd_opp a: cadd a (copp a) = nil.
Lemma czerop_opp a : czerop (cadd a (copp a)) = true.