Module infotheo.lib.ssralg_ext
From HB Require Import structures.From mathcomp Require Import all_ssreflect ssralg ssrnum ssrint fingroup.
From mathcomp Require Import finalg perm zmodp matrix mxalgebra vector.
Require Import ssr_ext f2.
Set Implicit Arguments.
Set SsrOldRewriteGoalsOrder.
Unset Strict Implicit.
Import Prenex Implicits.
Import GRing.Theory.
Local Open Scope ring_scope.
Notation "u '``_' i" := (u ord0 i) (at level 3,
i at level 2, left associativity, format "u '``_' i") : vec_ext_scope.
Reserved Notation "v `[ i := x ]" (at level 20).
Reserved Notation "t \# V" (at level 55, V at next level).
Section AboutRingType.
Variable R : pzRingType.
Lemma iter_addr0 : forall n x, iter n (+%R (0 : R)) x = x.
Proof.
Lemma iter_addr0_cV r : forall n (x : 'cV[R]_r), iter n (+%R 0) x = x.
Proof.
Local Open Scope vec_ext_scope.
Section support_set.
Variables (R : pzRingType) (n : nat).
Implicit Types e : 'rV[R]_n.
Definition
supp not a defined object.
Lemma insupp e i : (i \in supp e) = (e ``_ i != 0).
Proof.
Lemma sum_supp e x :
\sum_(i < n) e ``_ i * x ^+ i = \sum_(i in supp e) e ``_ i * x ^+ i.
Proof.
Lemma supp_set0 e : (supp e == set0) = (e == 0).
Proof.
Lemma supp0 : supp (0 : 'rV[R]_n) = set0.
End support_set.
Definition
row_set not a defined object.
\row_(i < n) if i == n0 then x else d ``_ i.
Notation "v `[ i := x ]" := (row_set i x v) : vec_ext_scope.
Lemma inj_row_set (A : pzRingType) n n0 (d : 'rV_n) :
{in A &, injective ((row_set n0)^~ d)}.
Lemma row_setC n A (i j : 'I_n) (a b : A) d :
i != j -> d `[ j := b ] `[ i := a ] = d `[ i := a ] `[ j := b ].
Proof.
Lemma row_setK n A (i : 'I_n) (a : A) d : d `[i := a] ``_ i = a.
Section sub_vec_sect.
Variables (A : Type) (n : nat).
Definition
sub_vec not a defined object.
\row_(j < #|S|) t ``_ (enum_val j).
End sub_vec_sect.
Notation "t \# S" := (sub_vec t S) : vec_ext_scope.
Section prod_rV.
Variables A B : Type.
Definition
prod_rV not a defined object.
\row_(k < n) (x.1 ``_ k, x.2 ``_ k).
Definition
rV_prod not a defined object.
(\row_(k < n) (x ``_ k).1, \row_(k < n) (x ``_ k).2).
Lemma prod_rVK n (x : 'rV[A]_n * 'rV[B]_n) : rV_prod (prod_rV x) = x.
Lemma rV_prodK n (x : 'rV[A * B]_n) : prod_rV (rV_prod x) = x.
Lemma fst_tnth_prod_rV n (x : {: 'rV[A]_n * 'rV[B]_n}) i :
x.1 ``_ i = ((prod_rV x) ``_ i).1.
Proof.
Lemma snd_tnth_prod_rV n (x : {: 'rV[A]_n * 'rV[B]_n}) i :
x.2 ``_ i = ((prod_rV x) ``_ i).2.
Proof.
End prod_rV.
Section AboutRowTuple.
Variables A B : predArgType.
Definition
tuple_of_row not a defined object.
Local Open Scope tuple_ext_scope.
Definition
row_of_tuple not a defined object.
Lemma row_of_tupleK n (t : n.-tuple A) : tuple_of_row (row_of_tuple t) = t.
Proof.
Lemma row_of_tuple_inj n : injective (@row_of_tuple n).
Proof.
Lemma tuple_of_row_inj n : injective (@tuple_of_row n).
Proof.
Local Close Scope tuple_ext_scope.
Lemma tuple_of_rowK n (v : 'rV[A]_n) : row_of_tuple (tuple_of_row v) = v.
Proof.
Definition
row_of_seq not a defined object.
(f : B -> A) (b : B) (l : seq B) n (H : size l == n) : 'rV[A]_n.
Proof.
Lemma row_of_seqK n l H f b :
map f l = tuple_of_row (@row_of_seq f b l n H).
Proof.
by rewrite size_map size_tuple (eqP H).
rewrite size_map in Hi.
rewrite (nth_map b) //.
rewrite (eqP H) in Hi.
transitivity (tnth (tuple_of_row (row_of_seq f b H)) (Ordinal Hi)).
by rewrite tnth_mktuple mxE.
apply: set_nth_default; by rewrite size_tuple.
Qed.
Definition
col_of_seq not a defined object.
(f : B -> A) (b : B) (l : seq B) n (H : size l == n) : 'cV[A]_n.
Proof.
End AboutRowTuple.
Arguments row_of_seq {A} {B} _ _ l n.
Arguments col_of_seq {A} {B} _ _ l n.
Lemma tuple_of_row_ord0 (F : Type) (y : 'rV[F]_0) : tuple_of_row y = [tuple of [::]].
Proof.
Local Open Scope tuple_ext_scope.
Lemma tuple_of_row_row_mx (C : finType) n1 n2 (v1 : 'rV[C]_n1) (B : 'rV[C]_n2) :
tuple_of_row (row_mx v1 B) = [tuple of tuple_of_row v1 ++ tuple_of_row B].
Proof.
rewrite tnth_mktuple mxE.
case: splitP => [n3 n0n3|n3 n0n1n3].
rewrite /tnth nth_cat size_tuple (_ : (n0 < n1 = true)%nat); last by rewrite n0n3 ltn_ord.
transitivity ((tuple_of_row v1) !_ n3); first by rewrite tnth_mktuple.
rewrite /tnth n0n3; apply: set_nth_default; by rewrite size_tuple.
rewrite /tnth nth_cat size_tuple (_ : (n0 < n1 = false)%nat); last first.
rewrite n0n1n3; apply/negbTE; by rewrite -leqNgt leq_addr.
transitivity ((tuple_of_row B) !_ n3); first by rewrite tnth_mktuple.
rewrite /tnth (_ : (n0 - n1 = n3)%nat); last by rewrite n0n1n3 addnC addnK.
apply: set_nth_default; by rewrite size_tuple.
Qed.
Local Close Scope tuple_ext_scope.
Lemma row_to_seq_0 n : tuple_of_row 0 = [tuple of nseq n ( 0 : 'F_2)].
Proof.
Definition
rowF2_tuplebool not a defined object.
[tuple of map (fun x => x != 0) (tuple_of_row M)].
Definition
row_of_bitseq not a defined object.
Definition
col_of_bitseq not a defined object.
Section row_mx_ext.
Context {A : Type} {n : nat}.
Definition
rbehead not a defined object.
Lemma rbehead_row_mx (x : 'rV_n) a : rbehead (row_mx (\row_(j < 1) a) x) = x.
Proof.
Lemma row_mx_row_ord0 (x : 'rV[A]_n) a : (row_mx (\row_(k < 1) a) x) ``_ 0 = a.
Proof.
Lemma row_mx_rbehead (x : 'rV_(1 + n)) : row_mx (\row__ (x ``_ 0)) (rbehead x) = x.
Proof.
Definition
rbelast not a defined object.
Definition
rlast not a defined object.
Lemma row_mx_row_ord_max (x : 'rV[A]_n) a :
rlast (castmx (erefl 1%nat, addn1 n) (row_mx x (\row_(k < 1) a))) = a.
Proof.
Lemma row_mx_rbelast (x : 'rV_n.+1) :
castmx (erefl 1%N, addn1 n) (row_mx (rbelast x) (\row__ (rlast x))) = x.
Proof.
Lemma rbelast_row_mx (x : 'rV_n) a :
rbelast (castmx (erefl 1%N, addn1 n) (row_mx x (\row_(j < 1) a))) = x.
Proof.
End row_mx_ext.
Section row_mxA'.
Variables (A : finType) (n : nat) (i : 'I_n.+1).
Lemma row_mxA' (w1 : 'rV_(n - i)) (a : A) (w : 'rV_i)
(H1 : (n.+1 - i)%nat = (n - i)%nat.+1) (H2 : _)
(H3 : (i + 1%nat + (n - i))%nat = n.+1) :
castmx (erefl 1%nat, H3) (row_mx (row_mx w (\row__ a)) w1) =
castmx (erefl 1%nat, H2) (row_mx w (castmx (erefl 1%nat, esym H1) (row_mx (\row_(_ < 1) a) w1))).
Proof.
rewrite !castmxE /= !cast_ord_id /=.
case: (ltnP j i) => [ji|].
move=> [:Hj0].
have @j0 : 'I_(i + 1) by apply: (@Ordinal _ j); abstract: Hj0; rewrite addn1 ltnS ltnW.
rewrite (_ : cast_ord _ _ = lshift (n - i) j0); last exact/val_inj.
rewrite row_mxEl.
rewrite (_ : cast_ord _ _ = lshift (n.+1 - i) (Ordinal ji)); last exact/val_inj.
rewrite row_mxEl.
rewrite (_ : j0 = lshift 1 (Ordinal ji)); last exact/val_inj.
by rewrite row_mxEl.
rewrite leq_eqVlt => /orP[/eqP|]ij.
move=> [:Hj0].
have @j0 : 'I_(i + 1) by apply: (@Ordinal _ j); abstract: Hj0; by rewrite addn1 ij ltnS.
rewrite (_ : cast_ord _ _ = lshift (n - i) j0); last exact/val_inj.
rewrite row_mxEl.
rewrite (_ : j0 = rshift i ord0); last first.
by apply: val_inj => /=; rewrite ij addn0.
rewrite row_mxEr mxE.
move=> [:Hj1].
have @j1 : 'I_(n.+1 - i).
by apply: (@Ordinal _ 0); abstract: Hj1; rewrite subn_gt0.
rewrite (_ : cast_ord _ _ = rshift i j1); last first.
by apply/val_inj => /=; rewrite ij addn0.
rewrite row_mxEr castmxE /= cast_ord_id esymK.
have @j2 : 'I_1 := ord0.
rewrite (_ : cast_ord _ _ = lshift (n - i) j2); last exact/val_inj.
by rewrite (@row_mxEl _ _ 1%nat) mxE.
move=> [:Hj0].
have @j0 : 'I_(n - i).
apply: (@Ordinal _ (j - i.+1)); abstract: Hj0.
by rewrite subnS prednK ?subn_gt0 // leq_sub2r // -ltnS.
rewrite (_ : cast_ord _ _ = rshift (i + 1) j0); last first.
apply/val_inj => /=; by rewrite addn1 subnKC.
rewrite row_mxEr.
have @j1 : 'I_(n.+1 - i) by apply: (@Ordinal _ (j - i)); rewrite ltn_sub2r.
rewrite (_ : cast_ord _ _ = rshift i j1); last first.
by apply: val_inj => /=; rewrite subnKC // ltnW.
rewrite row_mxEr castmxE /= cast_ord_id.
have @j2 : 'I_(n - i).
apply: (@Ordinal _ (j1 - 1)).
by rewrite /= subn1 prednK ?subn_gt0 // leq_sub2r // -ltnS.
rewrite (_ : cast_ord _ _ = rshift 1 j2); last first.
apply/val_inj => /=; by rewrite subnKC // subn_gt0.
rewrite (@row_mxEr _ _ 1%nat); congr (_ _ _); apply: val_inj => /=; by rewrite subnS subn1.
Qed.
Lemma col_matrix (R : pzRingType) m n (A : 'I_m -> 'cV[R]_(n.+1)) (i : 'I_m) :
col i (\matrix_(a < n.+1, b < m) (A b) a ord0) = A i.
Lemma ltnS' n m : (n < m.+1)%nat -> (n <= m)%nat.
Proof.
Section rV_take_drop.
Variables (A : Type) (n : nat).
Implicit Types (i : 'I_n.+1) (v : 'rV[A]_n).
Local Open Scope ring_scope.
Definition
row_take not a defined object.
lsubmx (castmx (erefl, esym (subnKC (ltnS' (ltn_ord i)))) v).
Definition
row_drop not a defined object.
rsubmx (castmx (erefl, esym (subnKC (ltnS' (ltn_ord i)))) v).
Lemma row_mx_take_drop i v :
v = castmx (erefl, subnKC (ltnS' (ltn_ord i))) (row_mx (row_take i v) (row_drop i v)).
Proof.
Section AboutPermPid.
Variable R : comPzRingType.
Lemma vec_perm_mx n (s : 'S_n) (z : 'rV[R]_n) :
z *m perm_mx s = \matrix_(i < 1, j < n) z i ((s^-1)%g j).
Proof.
rewrite big_pred1_eq !mxE {2}permE perm_invK eqxx mulr1 (eq_bigr (fun _ => 0)).
- by rewrite big_const_seq iter_addr0 addr0.
- move=> i H.
rewrite !mxE (_ : (s i == j) = false); first by rewrite mulr0.
apply/eqP; move/eqP in H; contradict H.
by rewrite -H -permM (mulgV s) perm1.
Qed.
Lemma perm_mx_vec n (s : 'S_n) (z : 'cV[R]_n) :
perm_mx s *m z = \matrix_(i < n, j < 1) z (s i) j.
Proof.
Lemma pid_mx_inj r n (a b : 'rV[R]_r) : (r <= n)%N ->
a *m (@pid_mx _ r n r) = b *m (@pid_mx _ r n r) -> a = b.
Proof.
apply/matrixP => x y.
move: {Heq}(Heq x (widen_ord Hrn y)).
rewrite !mxE (ord1 x){x} (bigID (pred1 y)) /= big_pred1_eq (eq_bigr (fun _ => 0)); last first.
move=> i Hiy.
rewrite mxE /= (_ : nat_of_ord _ == nat_of_ord _ = false) /=; last first.
by move/negbTE : Hiy.
by rewrite mulr0.
rewrite big_const_seq iter_addr0 (bigID (pred1 y)) /= big_pred1_eq (eq_bigr (fun _ => 0)); last first.
move=> i Hiy.
rewrite mxE /= (_ : nat_of_ord i == nat_of_ord y = false) /=; last first.
by move/negbTE : Hiy.
by rewrite mulr0.
by rewrite big_const_seq iter_addr0 !addr0 !mxE /= eqxx /= (ltn_ord y) /= 2!mulr1.
Qed.
End AboutPermPid.
Lemma mulmx_sum_col {R : comPzRingType} m n (u : 'cV[R]_n) (A : 'M_(m, n)) :
A *m u = \sum_i u i 0 *: col i A.
Lemma col_perm_inj n (s : 'S_n) T m : injective (@col_perm T m n s).
Proof.
Section AboutRank.
Variable F : fieldType.
Lemma rank_I n : \rank (1%:M : 'M[F]_n) = n.
Lemma rank_row_mx n (A : 'M[F]_n) m (B : 'M[F]_(n, m)) :
\rank A = n -> \rank (row_mx A B) = n.
Proof.
apply/eqP. apply/row_freeP.
exists (col_mx ((invmx (row_ebase A)) *m (invmx (col_ebase A))) 0).
rewrite mul_row_col mulmx0 addr0 -{1}(mulmx_ebase A) HA pid_mx_1 mulmx1 -!mulmxA.
have -> : row_ebase A *m (invmx (row_ebase A) *m invmx (col_ebase A)) =
invmx (col_ebase A).
rewrite !mulmxA mulmxV.
by rewrite mul1mx.
by apply: row_ebase_unit.
rewrite mulmxV //.
by apply: col_ebase_unit.
Qed.
Lemma empty_rV (A : pzRingType) (a : 'rV[A]_O) : a = 0.
Proof.
Lemma full_rank_inj m n (A : 'M[F]_(m, n)) : (m <= n)%N -> \rank A = m ->
forall (a b : 'rV[F]_m), a *m A = b *m A -> a = b.
Proof.
move: Hrank.
destruct m => //= [_|].
by rewrite (empty_rV a) (empty_rV b).
destruct n => //=.
unlock.
move Herk : (Gaussian_elimination A) => LUr /= Htmp.
move: (mulmx_ebase A) => Heq.
rewrite -Heq !mulmxA in Hab.
have {}Hab :
a *m col_ebase A *m pid_mx (\rank A) *m row_ebase A *m (invmx (row_ebase A)) =
b *m col_ebase A *m pid_mx (\rank A) *m row_ebase A *m (invmx (row_ebase A)).
by rewrite Hab.
rewrite -!mulmxA mulmxV in Hab; last by exact: row_ebase_unit.
rewrite !Htmp mulmx1 !mulmxA /mxrank /= in Hab.
move: {Heq}(@pid_mx_inj _ _ _ (a *m col_ebase A) (b *m col_ebase A) Hmn Hab) => Heq.
have {}Hab : a *m col_ebase A *m (invmx (col_ebase A)) =
b *m col_ebase A *m (invmx (col_ebase A)) by rewrite Heq.
rewrite -!mulmxA mulmxV in Hab; last by apply: col_ebase_unit.
by rewrite !mulmx1 in Hab.
Qed.
Lemma mxrank_castmx a a' b b' (M : 'M[F]_(a, b)) (H1 : a = a') (H2 : b = b') :
\rank (castmx (H1, H2) M) = \rank M.
Proof.
End AboutRank.
Section non_trivial_vspace.
Variables (F : finFieldType) (n : nat) (C : {vspace 'rV[F]_n}).
Definition
not_trivial not a defined object.
Lemma not_trivialP : not_trivial <-> C != 0%VS.
Proof.
End non_trivial_vspace.
Section about_row_vectors_on_prime_fields.
Lemma card_rV_wo_zeros p n : prime p ->
(\sum_(x : 'rV['F_p]_n | [forall j, x ord0 j != 0%R]) 1)%N = (p.-1 ^ n)%N.
Proof.
destruct p as [|p'] => //; destruct p' as [|p'] => //.
set p := p'.+2.
transitivity (\sum_(x : {: n.-tuple 'I_p.-1}) 1)%N; last first.
by rewrite sum1_card card_tuple card_ord.
pose g : 'F_p -> 'I_p.-1 := fun x =>
inord (cast_ord (@card_Fp _ primep) (enum_rank x : 'I_#|'F_p|)).-1.
pose g' : 'I_p.-1 -> 'F_p := fun x =>
enum_val (cast_ord (esym (@card_Fp _ primep)) (inord x.+1)).
have Hg' : forall j, g' j != 0.
move=> j; apply/eqP => /(congr1 enum_rank).
rewrite enum_valK => /(congr1 val) /=.
by rewrite enum_rank_ord /= inordK // ltnS.
have gg' : {in [set x in 'F_p | x != 0], cancel g g'}.
move=> x; rewrite inE => /andP[Hx x_neq0].
rewrite /g' inordK //=; last first.
rewrite enum_rank_ord //= prednK ?lt0n //.
move: (ltn_ord x) => /=; rewrite ltnS => /leq_trans; apply.
by rewrite -(ltn_add2r 1) 2!addn1 Zp_cast // ?pdiv_leq // pdiv_id.
rewrite (enum_rank_ord x) //= prednK ?lt0n //= enum_val_ord /=.
apply: val_inj => /=; rewrite inordK //.
move: (ltn_ord x) => /leq_trans; apply; by rewrite Zp_cast ?pdiv_id.
have g'g : cancel g' g.
move=> x; rewrite /g /g' /= enum_valK; apply: val_inj => /=.
by rewrite (@inordK _ x.+1) /= ?inordK // ltnS.
set f : 'rV['F_p]_n -> n.-tuple 'I_p.-1 := fun x => tuple_of_row (map_mx g x).
set f' : n.-tuple 'I_p.-1 -> 'rV['F_p]_n := fun x => map_mx g' (row_of_tuple x).
rewrite (reindex_onto f' f); last first.
rewrite /= => x /forallP /= H; apply/rowP => j.
by rewrite /f' /f mxE tuple_of_rowK mxE gg' // !inE /= H.
apply: eq_bigl => x; apply/andP; split.
by apply/forallP => j; rewrite !mxE Hg'.
apply/eqP/eq_from_tnth => i; by rewrite tnth_mktuple !mxE g'g.
Qed.
End about_row_vectors_on_prime_fields.
Lemma sum_sqr (F : fieldType) (_ : 2%N \in [pchar F]) k (f : 'I_k -> F) :
(\sum_(i < k) f i) ^+ 2 = \sum_(i < k) (f i) ^+ 2.
Proof.
From mathcomp Require Import finfield.
Section GFqm.
Variables (q m' : nat).
Let m := m'.+1.
Hypothesis primeq : prime q.
Definition
GF not a defined object.
Lemma char_GFqm : q \in [pchar GF].
Lemma card_GFqm : #| GF | = (q ^ m)%N.
End GFqm.
Section GF2m.
Variable m : nat.
Definition
GF2 not a defined object.
Definition
GF2_of_F2 not a defined object.
Definition
additive_GF2_of_F2 not a defined object.
Proof.
- rewrite !add0r; case: ifPn => [/eqP -> /=|]; first by rewrite oppr0.
case: ifPn => [/eqP -> _ /=|].
+ by rewrite oppr_pchar2 // char_GFqm.
+ by rewrite -F2_eq0 => /eqP ->.
- rewrite -F2_eq1 => /eqP -> /=.
case: ifPn => [/eqP -> /=|]; first by rewrite subr0.
rewrite -F2_eq1 => /eqP -> /=; by rewrite subrr.
Qed.
Definition
multiplicative_GF2_of_F2 not a defined object.
Proof.
Lemma GF2_of_F2_eq0 x : (GF2_of_F2 x == 0) = (x == 0).
Proof.
End GF2m.
Arguments GF2_of_F2 [_] _.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__Algebra_Additive not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
ssralg_ext_GF2_of_F2__canonical__GRing_RMorphism not a defined object.
Definition
F2_to_GF2 not a defined object.
Lemma supp_F2_to_GF2 n m (e : 'rV['F_2]_n) : supp (F2_to_GF2 m e) = supp e.
Proof.
Section Det_mlinear.
Context {R : comPzRingType}.
Let det_mlinear_rec n (f : 'I_n.+1 -> 'I_n.+1 -> R) (g : 'I_n.+1 -> R) k :
(k <= n.+1)%N ->
\det (\matrix_(j, i) (f i j * g j)) =
(\prod_(l < k) g (inord l)) *
\det (\matrix_(j, i) (f i j * if (j >= k)%N then g j else 1)).
Proof.
rewrite ltnS => kn.
rewrite IH; last by rewrite ltnW.
rewrite big_ord_recr /= -mulrA; congr (_ * _).
rewrite (@determinant_multilinear _ _ _
(\matrix_(j, i) (f i j * (if (k < j)%N then g j else 1)))
(\matrix_(j, i) (f i j * (if (k <= j)%N then g j else 1)))
(inord k) (g (inord k)) 0); last 3 first.
- rewrite scale0r addr0.
apply/rowP => j.
rewrite !mxE mulrCA; congr (_ * _).
by rewrite inordK // leqnn ltnn mulr1.
- apply/matrixP => i j; rewrite !mxE.
case: ifPn => [H1|].
by case: ifPn => //; rewrite (ltnW H1).
case: ifPn => //; rewrite -ltnNge ltnS => H1 H2.
rewrite mulr1.
have /eqP abs : k = lift (inord k) i by apply/eqP; rewrite eqn_leq H1 H2.
exfalso.
move/eqP : abs; apply/eqP.
apply: contra (@neq_lift _ (inord k) i) => /eqP {1}->.
by apply/eqP/val_inj; rewrite inord_val.
- by apply/matrixP => i j; rewrite !mxE.
- by rewrite mul0r addr0 -det_tr.
Qed.
Lemma det_mlinear (n: nat) (f : 'I_n -> 'I_n -> R) (g : 'I_n -> R) :
\det (\matrix_(i, j) (f i j * g j)) =
\prod_(i < n) g i * \det (\matrix_(i, j) (f i j)).
Proof.
rewrite -det_tr (_ : _^T = \matrix_(j, i) (f i j * g j)); last first.
by apply/matrixP => i j; rewrite !mxE.
rewrite (@det_mlinear_rec _ _ _ n.+1) //; congr (_ * _).
by under eq_bigr do rewrite inord_val.
rewrite -det_tr; congr (\det _).
by apply/matrixP => i j; rewrite !mxE ltnNge -ltnS ltn_ord /= mulr1.
Qed.
End Det_mlinear.
Section regular_algebra.
Lemma mulr_regl [R : pzRingType] (a : R) (x : R^o) : a * x = a *: x.
Proof.
Lemma mulr_regr [R : comPzRingType] (a : R) (x : R^o) : x * a = a *: x.
Proof.
End regular_algebra.
Section ssrnum_ext.
Import ssrnum Num.Theory.
Lemma sqrBC (R : realDomainType) (x y : R) : (x - y) ^+ 2 = (y - x) ^+ 2.
Proof.
Lemma ler_abs_sqr (T : realDomainType) (x y : T) : (`|x| <= `|y|) = (x ^+ 2 <= y ^+ 2).
Proof.
Section ssrint_ext.
Import ssrnum Num.Theory ssrint.
Lemma sum_exprz {R : numFieldType} (n : nat) x : x != 1 ->
\sum_(i < n) x ^ i.+1 = x * (1 - (x ^ n)) / (1 - x) :> R.
Proof.
End ssrint_ext.