Section GenField.
Variables (F : fieldType) (gT : finGroupType) (G : {group gT}) (n' : nat).
Local Notation n := n'.+1.
Variables (rG : mx_representation F G n) (A : 'M[F]_n).
Local Notation d := (degree_mxminpoly A).
Local Notation Ad := (powers_mx A d).
Local Notation pA := (mxminpoly A).
Let d_gt0 := mxminpoly_nonconstant A.
Local Notation irr := mx_irreducible.
Hypotheses (irrG : irr rG) (cGA : centgmx rG A).
Notation FA := (gen_of irrG cGA).
Let inFA := Gen irrG cGA.
Canonical gen_subType := Eval hnf in [newType for rVval : FA -> 'rV_d].
Definition gen_eqMixin := Eval hnf in [eqMixin of FA by <:].
Canonical gen_eqType := Eval hnf in EqType FA gen_eqMixin.
Definition gen_choiceMixin := [choiceMixin of FA by <:].
Canonical gen_choiceType := Eval hnf in ChoiceType FA gen_choiceMixin.
Definition gen0 := inFA 0.
Definition genN (x : FA) := inFA (- val x).
Definition genD (x y : FA) := inFA (val x + val y).
Canonical gen_additive := Additive gen_is_rmorphism.
Canonical gen_rmorphism := RMorphism gen_is_rmorphism.
(* The generated field contains a root of the minimal polynomial (in some  *)
(* cases we want to use the construction solely for that purpose).         *)
Definition groot := inFA (poly_rV ('X %% pA)).
(* Plugging the extension morphism gen into the ext_repr construction   *)
(* yields a (reducible) tensored representation.                           *)
(* An alternative to the above, used in the proof of the p-stability of       *)
(* groups of odd order, is to reconsider the original vector space as a       *)
(* vector space of dimension n / e over FA. This is applicable only if G is   *)
(* the largest group represented on the original vector space (i.e., if we    *)
(* are not studying a representation of G induced by one of a larger group,   *)
(* as in B & G Theorem 2.6 for instance). We can't fully exploit one of the   *)
(* benefits of this approach -- that the type domain for the vector space can *)
(* remain unchanged -- because we're restricting ourselves to row matrices;   *)
(* we have to use explicit bijections to convert between the two views.       *)
Definition subbase nA (B : 'rV_nA) : 'M_(nA * d, n) :=
\matrix_ik mxvec (\matrix_(i, k) (row (B 0 i) (A ^+ k))) 0 ik.
Definition gen_dim := ex_maxn gen_dim_ex_proof gen_dim_ub_proof.
Notation nA := gen_dim.
Definition gen_base : 'rV_nA := odflt 0 [pick B | row_free (subbase B)].
Definition base := subbase gen_base.
End Bijection.
Prenex Implicits val_genK in_genK.
End Bijection2.
Definition gen_mx g := \matrix_i in_gen (row (gen_base 0 i) (rG g)).
Let val_genJmx m :
{in G, forall g, {morph @val_gen m : W / W *m gen_mx g >-> W *m rG g}}.
Canonical gen_repr := MxRepresentation gen_mx_repr.
Local Notation rGA := gen_repr.
Definition rowval_gen m U :=
<<\matrix_ik
mxvec (\matrix_(i < m, k < d) (row i (val_gen U) *m A ^+ k)) 0 ik>>%MS.
Let Ad'T := mx_term (pinvmx Ad).
Let mulT (u v : 'rV_d) := mulmx_term (mxvec (mulmx_term (mxT u) (mxT v))) Ad'T.
Fixpoint gen_term t := match t with
| 'X_k => row_var _ d k
| x%:T => mx_term (val (x : FA))
| n1%:R => mx_term (val (n1%:R : FA))%R
| t1 + t2 => \row_i (gen_term t1 0%R i + gen_term t2 0%R i)
| - t1 => \row_i (- gen_term t1 0%R i)
| t1 *+ n1 => mulmx_term (mx_term n1%:R%:M)%R (gen_term t1)
| t1 * t2 => mulT (gen_term t1) (gen_term t2)
| t1^-1 => gen_term t1
| t1 ^+ n1 => iter n1 (mulT (gen_term t1)) (mx_term (val (1%R : FA)))
end%T.
Definition gen_env (e : seq FA) := row_env (map val e).
Fixpoint gen_form f := match f with
| Bool b => Bool b
| t1 == t2 => mxrank_form 0 (gen_term (t1 - t2))
| GRing.Unit t1 => mxrank_form 1 (gen_term t1)
| f1 /\ f2 => gen_form f1 /\ gen_form f2
| f1 \/ f2 =>  gen_form f1 \/ gen_form f2
| f1 ==> f2 => gen_form f1 ==> gen_form f2
| ~ f1 => ~ gen_form f1
| ('exists 'X_k, f1) => Exists_row_form d k (gen_form f1)
| ('forall 'X_k, f1) => ~ Exists_row_form d k (~ (gen_form f1))
end%T.

Lemma sat_gen_form e f : GRing.rformula f ->
reflect (GRing.holds e f) (GRing.sat (gen_env e) (gen_form f)).