Notation "''M_' ( n )" := 'M_n (only parsing) : type_scope.Notation "\tr A" := (mxtrace A) : ring_scope.Canonical matrix_eqType (R : eqType) m n:=
  Eval hnf in EqType 'M[R]_(m, n) (matrix_eqMixin R m n).Canonical matrix_choiceType (R : choiceType) m n :=
  Eval hnf in ChoiceType 'M[R]_(m, n) (matrix_choiceMixin R m n).Canonical matrix_countType (R : countType) m n :=
  Eval hnf in CountType 'M[R]_(m, n) (matrix_countMixin R m n).Canonical matrix_finType (R : finType) m n :=
  Eval hnf in FinType 'M[R]_(m, n) (matrix_finMixin R m n).(* Constant matrix *)
Fact const_mx_key : unit.Definition const_mx m n a : 'M[R]_(m, n) := \matrix[const_mx_key]_(i, j) a.Definition conform_mx m' n' B A :=
  match m =P m', n =P n' with
  | ReflectT eq_m, ReflectT eq_n => castmx (eq_m, eq_n) A
  | _, _ => B
  end.(* Transpose a matrix *)
Fact trmx_key : unit.Definition trmx A := \matrix[trmx_key]_(i, j) A j i.(* Permute a matrix vertically (rows) or horizontally (columns) *)
Fact row_perm_key : unit.Fact col_perm_key : unit.(* Exchange two rows/columns of a matrix *)
Definition xrow i1 i2 := row_perm (tperm i1 i2).Definition xcol j1 j2 := col_perm (tperm j1 j2).(* Row/Column sub matrices of a matrix *)
Definition row i0 A := \row_j A i0 j.Definition col j0 A := \col_i A i j0.(* Removing a row/column from a matrix *)
Definition row' i0 A := \matrix_(i, j) A (lift i0 i) j.Definition col' j0 A := \matrix_(i, j) A i (lift j0 j).

Lemma castmx_comp m1 n1 m2 n2 m3 n3 (eq_m1 : m1 = m2) (eq_n1 : n1 = n2) (eq_m2 : m2 = m3) (eq_n2 : n2 = n3) A : castmx (eq_m2, eq_n2) (castmx (eq_m1, eq_n1) A) = castmx (etrans eq_m1 eq_m2, etrans eq_n1 eq_n2) A.