(** Sometimes it is convenient to make a distinction between "syntactic" coefficients and "real" coefficients that are used to actually compute *)
Variable C_of_S : S -> C.
Variable phiS : S -> R.
Variable phi_C_of_S :   forall c,  phiS c =  phi (C_of_S c).
Fixpoint map_PExpr (e : PExpr S) : PExpr C :=
match e with
| PEc c => PEc (C_of_S c)
| PEX p => PEX p
| PEadd e1 e2 => PEadd (map_PExpr e1) (map_PExpr e2)
| PEsub e1 e2 => PEsub (map_PExpr e1) (map_PExpr e2)
| PEmul e1 e2 => PEmul (map_PExpr e1) (map_PExpr e2)
| PEopp e     => PEopp (map_PExpr e)
| PEpow e n   => PEpow (map_PExpr e) n
end.
Definition map_Formula (f : Formula S)  : Formula C :=
let (l,o,r) := f in
Build_Formula (map_PExpr l) o (map_PExpr r).
Definition eval_sexpr : PolEnv -> PExpr S -> R :=
PEeval rplus rtimes rminus ropp phiS pow_phi rpow.
Definition eval_sformula (env : PolEnv) (f : Formula S) : Prop :=
let (lhs, op, rhs) := f in
(eval_op2 op) (eval_sexpr env lhs) (eval_sexpr env rhs).

(* Specifications: *)
Lemma eval_pexprSC : forall env s, eval_sexpr env s = eval_pexpr env (map_PExpr s).
(** equality might be (too) strong *)
Lemma eval_formulaSC : forall env f, eval_sformula env f = eval_formula env (map_Formula f).
Definition simpl_cone (e:Psatz) : Psatz :=
match e with
| PsatzSquare t =>
match t with
| Pc c   => if ceqb cO c then PsatzZ else PsatzC (ctimes c c)
| _ => PsatzSquare t
end
| PsatzMulE t1 t2 =>
match t1 , t2 with
| PsatzZ      , _        => PsatzZ
|    _     , PsatzZ      => PsatzZ
| PsatzC c ,  PsatzC c' => PsatzC (ctimes c c')
| PsatzC p1 , PsatzMulE (PsatzC p2)  x => PsatzMulE (PsatzC (ctimes p1 p2)) x
| PsatzC p1 , PsatzMulE x (PsatzC p2)  => PsatzMulE (PsatzC (ctimes p1 p2)) x
| PsatzMulE (PsatzC p2)  x  , PsatzC p1   => PsatzMulE (PsatzC (ctimes p1 p2)) x
| PsatzMulE x (PsatzC p2)   , PsatzC p1   => PsatzMulE (PsatzC (ctimes p1 p2)) x
| PsatzC x   , PsatzAdd y z   => PsatzAdd (PsatzMulE (PsatzC x) y) (PsatzMulE (PsatzC x) z)
| PsatzC c ,  _        => if ceqb cI c then t2 else PsatzMulE t1 t2
| _ ,  PsatzC c        => if ceqb cI c then t1 else PsatzMulE t1 t2
|     _     , _   => e
end
| PsatzAdd t1 t2 =>
match t1 ,  t2 with
| PsatzZ     , x => x
|   x     , PsatzZ => x
|   x     , y   => PsatzAdd x y
end
|   _     => e
end.