aboutsummaryrefslogtreecommitdiff
path: root/mathcomp/algebra
diff options
context:
space:
mode:
Diffstat (limited to 'mathcomp/algebra')
-rw-r--r--mathcomp/algebra/matrix.v596
-rw-r--r--mathcomp/algebra/mxalgebra.v81
-rw-r--r--mathcomp/algebra/mxpoly.v51
-rw-r--r--mathcomp/algebra/poly.v8
-rw-r--r--mathcomp/algebra/ssralg.v6
-rw-r--r--mathcomp/algebra/ssrint.v30
-rw-r--r--mathcomp/algebra/ssrnum.v77
7 files changed, 701 insertions, 148 deletions
diff --git a/mathcomp/algebra/matrix.v b/mathcomp/algebra/matrix.v
index 21730c3..02097a4 100644
--- a/mathcomp/algebra/matrix.v
+++ b/mathcomp/algebra/matrix.v
@@ -82,6 +82,8 @@ From mathcomp Require Import div prime binomial ssralg finalg zmodp countalg.
(* equal to 1%R when n is of the form n'.+1 (e.g., n >= 1). *)
(* is_scalar_mx A <=> A is a scalar matrix (A = a%:M for some A). *)
(* diag_mx d == the diagonal matrix whose main diagonal is d : 'rV_n. *)
+(* is_diag_mx A <=> A is a diagonal matrix: forall i j, i != j -> A i j = 0 *)
+(* is_trig_mx A <=> A is a triangular matrix: forall i j, i < j -> A i j = 0 *)
(* delta_mx i j == the matrix with a 1 in row i, column j and 0 elsewhere. *)
(* pid_mx r == the partial identity matrix with 1s only on the r first *)
(* coefficients of the main diagonal; the dimensions of *)
@@ -100,6 +102,7 @@ From mathcomp Require Import div prime binomial ssralg finalg zmodp countalg.
(* \adj A == the adjugate matrix of A (\adj A i j = cofactor j i A). *)
(* A \in unitmx == A is invertible (R must be a comUnitRingType). *)
(* invmx A == the inverse matrix of A if A \in unitmx A, otherwise A. *)
+(* A \is a mxOver S == the matrix A has its coefficients in S. *)
(* The following operations provide a correspondence between linear functions *)
(* and matrices: *)
(* lin1_mx f == the m x n matrix that emulates via right product *)
@@ -148,19 +151,19 @@ Local Open Scope ring_scope.
Reserved Notation "''M_' n" (at level 8, n at level 2, format "''M_' n").
Reserved Notation "''rV_' n" (at level 8, n at level 2, format "''rV_' n").
Reserved Notation "''cV_' n" (at level 8, n at level 2, format "''cV_' n").
-Reserved Notation "''M_' ( n )" (at level 8, only parsing).
+Reserved Notation "''M_' ( n )" (at level 8). (* only parsing *)
Reserved Notation "''M_' ( m , n )" (at level 8, format "''M_' ( m , n )").
-Reserved Notation "''M[' R ]_ n" (at level 8, n at level 2, only parsing).
-Reserved Notation "''rV[' R ]_ n" (at level 8, n at level 2, only parsing).
-Reserved Notation "''cV[' R ]_ n" (at level 8, n at level 2, only parsing).
-Reserved Notation "''M[' R ]_ ( n )" (at level 8, only parsing).
-Reserved Notation "''M[' R ]_ ( m , n )" (at level 8, only parsing).
+Reserved Notation "''M[' R ]_ n" (at level 8, n at level 2). (* only parsing *)
+Reserved Notation "''rV[' R ]_ n" (at level 8, n at level 2). (* only parsing *)
+Reserved Notation "''cV[' R ]_ n" (at level 8, n at level 2). (* only parsing *)
+Reserved Notation "''M[' R ]_ ( n )" (at level 8). (* only parsing *)
+Reserved Notation "''M[' R ]_ ( m , n )" (at level 8). (* only parsing *)
-Reserved Notation "\matrix_ i E"
+Reserved Notation "\matrix_ i E"
(at level 36, E at level 36, i at level 2,
format "\matrix_ i E").
Reserved Notation "\matrix_ ( i < n ) E"
- (at level 36, E at level 36, i, n at level 50, only parsing).
+ (at level 36, E at level 36, i, n at level 50). (* only parsing *)
Reserved Notation "\matrix_ ( i , j ) E"
(at level 36, E at level 36, i, j at level 50,
format "\matrix_ ( i , j ) E").
@@ -168,19 +171,19 @@ Reserved Notation "\matrix[ k ]_ ( i , j ) E"
(at level 36, E at level 36, i, j at level 50,
format "\matrix[ k ]_ ( i , j ) E").
Reserved Notation "\matrix_ ( i < m , j < n ) E"
- (at level 36, E at level 36, i, m, j, n at level 50, only parsing).
+ (at level 36, E at level 36, i, m, j, n at level 50). (* only parsing *)
Reserved Notation "\matrix_ ( i , j < n ) E"
- (at level 36, E at level 36, i, j, n at level 50, only parsing).
+ (at level 36, E at level 36, i, j, n at level 50). (* only parsing *)
Reserved Notation "\row_ j E"
(at level 36, E at level 36, j at level 2,
format "\row_ j E").
Reserved Notation "\row_ ( j < n ) E"
- (at level 36, E at level 36, j, n at level 50, only parsing).
+ (at level 36, E at level 36, j, n at level 50). (* only parsing *)
Reserved Notation "\col_ j E"
(at level 36, E at level 36, j at level 2,
format "\col_ j E").
Reserved Notation "\col_ ( j < n ) E"
- (at level 36, E at level 36, j, n at level 50, only parsing).
+ (at level 36, E at level 36, j, n at level 50). (* only parsing *)
Reserved Notation "x %:M" (at level 8, format "x %:M").
Reserved Notation "A *m B" (at level 40, left associativity, format "A *m B").
@@ -204,7 +207,7 @@ Variables m n : nat.
(* We use dependent types (ordinals) for the indices so that ranges are *)
(* mostly inferred automatically *)
-Inductive matrix : predArgType := Matrix of {ffun 'I_m * 'I_n -> R}.
+Variant matrix : predArgType := Matrix of {ffun 'I_m * 'I_n -> R}.
Definition mx_val A := let: Matrix g := A in g.
@@ -248,8 +251,8 @@ Notation "''cV_' n" := 'M_(n, 1) : type_scope.
Notation "''M_' n" := 'M_(n, n) : type_scope.
Notation "''M_' ( n )" := 'M_n (only parsing) : type_scope.
-Notation "\matrix[ k ]_ ( i , j ) E" := (matrix_of_fun k (fun i j => E))
- (at level 36, E at level 36, i, j at level 50): ring_scope.
+Notation "\matrix[ k ]_ ( i , j ) E" := (matrix_of_fun k (fun i j => E)) :
+ ring_scope.
Notation "\matrix_ ( i < m , j < n ) E" :=
(@matrix_of_fun _ m n matrix_key (fun i j => E)) (only parsing) : ring_scope.
@@ -573,8 +576,7 @@ Proof. by apply/matrixP=> i j; rewrite mxE row_mxEr. Qed.
Lemma hsubmxK A : row_mx (lsubmx A) (rsubmx A) = A.
Proof.
-apply/matrixP=> i j; rewrite !mxE.
-by case: splitP => k Dk //=; rewrite !mxE //=; congr (A _ _); apply: val_inj.
+by apply/matrixP=> i j; rewrite !mxE; case: split_ordP => k ->; rewrite !mxE.
Qed.
Lemma col_mxEu A1 A2 i j : col_mx A1 A2 (lshift m2 i) j = A1 i j.
@@ -607,6 +609,18 @@ Proof. by split_mxE. Qed.
Lemma col_mx_const a : col_mx (const_mx a) (const_mx a) = const_mx a.
Proof. by split_mxE. Qed.
+Lemma row_usubmx A i : row i (usubmx A) = row (lshift m2 i) A.
+Proof. by apply/rowP=> j; rewrite !mxE; congr (A _ _); apply/val_inj. Qed.
+
+Lemma row_dsubmx A i : row i (dsubmx A) = row (rshift m1 i) A.
+Proof. by apply/rowP=> j; rewrite !mxE; congr (A _ _); apply/val_inj. Qed.
+
+Lemma col_lsubmx A i : col i (lsubmx A) = col (lshift n2 i) A.
+Proof. by apply/colP=> j; rewrite !mxE; congr (A _ _); apply/val_inj. Qed.
+
+Lemma col_rsubmx A i : col i (rsubmx A) = col (rshift n1 i) A.
+Proof. by apply/colP=> j; rewrite !mxE; congr (A _ _); apply/val_inj. Qed.
+
End CutPaste.
Lemma trmx_lsub m n1 n2 (A : 'M_(m, n1 + n2)) : (lsubmx A)^T = usubmx A^T.
@@ -706,12 +720,10 @@ Proof. by apply/matrixP=> i j; rewrite !(col_mxEd, mxE). Qed.
Lemma col'Kl m n1 n2 j1 (A1 : 'M_(m, n1.+1)) (A2 : 'M_(m, n2)) :
col' (lshift n2 j1) (row_mx A1 A2) = row_mx (col' j1 A1) A2.
Proof.
-apply/matrixP=> i /= j; symmetry; rewrite 2!mxE.
-case: splitP => j' def_j'.
- rewrite mxE -(row_mxEl _ A2); congr (row_mx _ _ _); apply: ord_inj.
- by rewrite /= def_j'.
+apply/matrixP=> i /= j; symmetry; rewrite 2!mxE; case: split_ordP => j' ->.
+ by rewrite mxE -(row_mxEl _ A2); congr (row_mx _ _ _); apply: ord_inj.
rewrite -(row_mxEr A1); congr (row_mx _ _ _); apply: ord_inj => /=.
-by rewrite /bump def_j' -ltnS -addSn ltn_addr.
+by rewrite /bump -ltnS -addSn ltn_addr.
Qed.
Lemma row'Ku m1 m2 n i1 (A1 : 'M_(m1.+1, n)) (A2 : 'M_(m2, n)) :
@@ -860,6 +872,58 @@ by rewrite castmx_comp etrans_id.
Qed.
Definition block_mxAx := block_mxA. (* Bypass Prenex Implicits *)
+Section Induction.
+
+Lemma row_ind m (P : forall n, 'M[R]_(m, n) -> Type) :
+ (forall A, P 0%N A) ->
+ (forall n c A, P n A -> P (1 + n)%N (row_mx c A)) ->
+ forall n A, P n A.
+Proof.
+move=> P0 PS; elim=> [//|n IHn] A.
+by rewrite -[n.+1]/(1 + n)%N in A *; rewrite -[A]hsubmxK; apply: PS.
+Qed.
+
+Lemma col_ind n (P : forall m, 'M[R]_(m, n) -> Type) :
+ (forall A, P 0%N A) ->
+ (forall m r A, P m A -> P (1 + m)%N (col_mx r A)) ->
+ forall m A, P m A.
+Proof.
+move=> P0 PS; elim=> [//|m IHm] A.
+by rewrite -[m.+1]/(1 + m)%N in A *; rewrite -[A]vsubmxK; apply: PS.
+Qed.
+
+Lemma mx_ind (P : forall m n, 'M[R]_(m, n) -> Type) :
+ (forall m A, P m 0%N A) ->
+ (forall n A, P 0%N n A) ->
+ (forall m n x r c A, P m n A -> P (1 + m)%N (1 + n)%N (block_mx x r c A)) ->
+ forall m n A, P m n A.
+Proof.
+move=> P0l P0r PS; elim=> [|m IHm] [|n] A; do ?by [apply: P0l|apply: P0r].
+by rewrite -[A](@submxK 1 _ 1); apply: PS.
+Qed.
+Definition matrix_rect := mx_ind.
+Definition matrix_rec := mx_ind.
+Definition matrix_ind := mx_ind.
+
+Lemma sqmx_ind (P : forall n, 'M[R]_n -> Type) :
+ (forall A, P 0%N A) ->
+ (forall n x r c A, P n A -> P (1 + n)%N (block_mx x r c A)) ->
+ forall n A, P n A.
+Proof.
+by move=> P0 PS; elim=> [//|n IHn] A; rewrite -[A](@submxK 1 _ 1); apply: PS.
+Qed.
+
+Lemma ringmx_ind (P : forall n, 'M[R]_n.+1 -> Type) :
+ (forall x, P 0%N x) ->
+ (forall n x (r : 'rV_n.+1) (c : 'cV_n.+1) A,
+ P n A -> P (1 + n)%N (block_mx x r c A)) ->
+ forall n A, P n A.
+Proof.
+by move=> P0 PS; elim=> [//|n IHn] A; rewrite -[A](@submxK 1 _ 1); apply: PS.
+Qed.
+
+End Induction.
+
(* Bijections mxvec : 'M_(m, n) <----> 'rV_(m * n) : vec_mx *)
Section VecMatrix.
@@ -1035,6 +1099,30 @@ End MapMatrix.
Arguments map_mx {aT rT} f {m n} A.
+Section MultipleMapMatrix.
+Local Notation "M ^ phi" := (map_mx phi M).
+
+Lemma map_mx_id (R : Type) m n (M : 'M[R]_(m,n)) : M ^ id = M.
+Proof. by apply/matrixP => i j; rewrite !mxE. Qed.
+
+Lemma map_mx_comp (R S T : Type) m n (M : 'M[R]_(m,n))
+ (f : R -> S) (g : S -> T) : M ^ (g \o f) = (M ^ f) ^ g.
+Proof. by apply/matrixP => i j; rewrite !mxE. Qed.
+
+Lemma eq_in_map_mx (R S : Type) m n (M : 'M[R]_(m,n)) (g f : R -> S) :
+ (forall i j, f (M i j) = g (M i j)) <-> M ^ f = M ^ g.
+Proof. by rewrite -matrixP; split => fg i j; have := fg i j; rewrite !mxE. Qed.
+
+Lemma eq_map_mx (R S : Type) m n (M : 'M[R]_(m,n)) (g f : R -> S) :
+ f =1 g -> M ^ f = M ^ g.
+Proof. by move=> eq_fg; apply/eq_in_map_mx. Qed.
+
+Lemma map_mx_id_in (R : Type) m n (M : 'M[R]_(m,n)) (f : R -> R) :
+ (forall i j, f (M i j) = M i j) -> M ^ f = M.
+Proof. by rewrite -[RHS]map_mx_id -eq_in_map_mx. Qed.
+
+End MultipleMapMatrix.
+
(*****************************************************************************)
(********************* Matrix Zmodule (additive) structure *******************)
(*****************************************************************************)
@@ -1191,6 +1279,33 @@ Lemma block_mx_eq0 m1 m2 n1 n2 (Aul : 'M_(m1, n1)) Aur Adl (Adr : 'M_(m2, n2)) :
[&& Aul == 0, Aur == 0, Adl == 0 & Adr == 0].
Proof. by rewrite col_mx_eq0 !row_mx_eq0 !andbA. Qed.
+Lemma trmx_eq0 m n (A : 'M_(m, n)) : (A^T == 0) = (A == 0).
+Proof. by rewrite -trmx0 (inj_eq trmx_inj). Qed.
+
+Lemma matrix_eq0 m n (A : 'M_(m, n)) :
+ (A == 0) = [forall i, forall j, A i j == 0].
+Proof.
+apply/eqP/'forall_'forall_eqP => [-> i j|A_eq0]; first by rewrite !mxE.
+by apply/matrixP => i j; rewrite A_eq0 !mxE.
+Qed.
+
+Lemma matrix0Pn m n (A : 'M_(m, n)) : reflect (exists i j, A i j != 0) (A != 0).
+Proof.
+by rewrite matrix_eq0; apply/(iffP forallPn) => -[i /forallPn]; exists i.
+Qed.
+
+Lemma rV0Pn n (v : 'rV_n) : reflect (exists i, v 0 i != 0) (v != 0).
+Proof.
+apply: (iffP (matrix0Pn _)) => [[i [j]]|[j]]; last by exists 0, j.
+by rewrite ord1; exists j.
+Qed.
+
+Lemma cV0Pn n (v : 'cV_n) : reflect (exists i, v i 0 != 0) (v != 0).
+Proof.
+apply: (iffP (matrix0Pn _)) => [[i] [j]|[i]]; last by exists i, 0.
+by rewrite ord1; exists i.
+Qed.
+
Definition nz_row m n (A : 'M_(m, n)) :=
oapp (fun i => row i A) 0 [pick i | row i A != 0].
@@ -1201,8 +1316,177 @@ rewrite /nz_row; symmetry; case: pickP => [i /= nzAi | Ai0].
by rewrite eqxx; apply/eqP/row_matrixP=> i; move/eqP: (Ai0 i) ->; rewrite row0.
Qed.
+Definition is_diag_mx m n (A : 'M[V]_(m, n)) :=
+ [forall i : 'I__, forall j : 'I__, (i != j :> nat) ==> (A i j == 0)].
+
+Lemma is_diag_mxP m n (A : 'M[V]_(m, n)) :
+ reflect (forall i j : 'I__, i != j :> nat -> A i j = 0) (is_diag_mx A).
+Proof. by apply: (iffP 'forall_'forall_implyP) => /(_ _ _ _)/eqP. Qed.
+
+Lemma mx0_is_diag m n : is_diag_mx (0 : 'M[V]_(m, n)).
+Proof. by apply/is_diag_mxP => i j _; rewrite mxE. Qed.
+
+Lemma mx11_is_diag (M : 'M_1) : is_diag_mx M.
+Proof. by apply/is_diag_mxP => i j; rewrite !ord1 eqxx. Qed.
+
+Definition is_trig_mx m n (A : 'M[V]_(m, n)) :=
+ [forall i : 'I__, forall j : 'I__, (i < j)%N ==> (A i j == 0)].
+
+Lemma is_trig_mxP m n (A : 'M[V]_(m, n)) :
+ reflect (forall i j : 'I__, (i < j)%N -> A i j = 0) (is_trig_mx A).
+Proof. by apply: (iffP 'forall_'forall_implyP) => /(_ _ _ _)/eqP. Qed.
+
+Lemma is_diag_mx_is_trig m n (A : 'M[V]_(m, n)) : is_diag_mx A -> is_trig_mx A.
+Proof.
+by move=> /is_diag_mxP A_eq0; apply/is_trig_mxP=> i j lt_ij; rewrite A_eq0// ltn_eqF.
+Qed.
+
+Lemma mx0_is_trig m n : is_trig_mx (0 : 'M[V]_(m, n)).
+Proof. by apply/is_trig_mxP => i j _; rewrite mxE. Qed.
+
+Lemma mx11_is_trig (M : 'M_1) : is_trig_mx M.
+Proof. by apply/is_trig_mxP => i j; rewrite !ord1 ltnn. Qed.
+
+Lemma is_diag_mxEtrig m n (A : 'M[V]_(m, n)) :
+ is_diag_mx A = is_trig_mx A && is_trig_mx A^T.
+Proof.
+apply/is_diag_mxP/andP => [Adiag|[/is_trig_mxP Atrig /is_trig_mxP ATtrig]].
+ by split; apply/is_trig_mxP => i j lt_ij; rewrite ?mxE ?Adiag//;
+ [rewrite ltn_eqF|rewrite gtn_eqF].
+by move=> i j; case: ltngtP => // [/Atrig|/ATtrig]; rewrite ?mxE.
+Qed.
+
+Lemma is_diag_trmx m n (A : 'M[V]_(m, n)) : is_diag_mx A^T = is_diag_mx A.
+Proof. by rewrite !is_diag_mxEtrig trmxK andbC. Qed.
+
+Lemma ursubmx_trig m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :
+ m1 <= n1 -> is_trig_mx A -> ursubmx A = 0.
+Proof.
+move=> leq_m1_n1 /is_trig_mxP Atrig; apply/matrixP => i j.
+by rewrite !mxE Atrig//= ltn_addr// (@leq_trans m1).
+Qed.
+
+Lemma dlsubmx_diag m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :
+ n1 <= m1 -> is_diag_mx A -> dlsubmx A = 0.
+Proof.
+move=> leq_m2_n2 /is_diag_mxP Adiag; apply/matrixP => i j.
+by rewrite !mxE Adiag// gtn_eqF//= ltn_addr// (@leq_trans n1).
+Qed.
+
+Lemma ulsubmx_trig m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :
+ is_trig_mx A -> is_trig_mx (ulsubmx A).
+Proof.
+move=> /is_trig_mxP Atrig; apply/is_trig_mxP => i j lt_ij.
+by rewrite !mxE Atrig.
+Qed.
+
+Lemma drsubmx_trig m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :
+ m1 <= n1 -> is_trig_mx A -> is_trig_mx (drsubmx A).
+Proof.
+move=> leq_m1_n1 /is_trig_mxP Atrig; apply/is_trig_mxP => i j lt_ij.
+by rewrite !mxE Atrig//= -addnS leq_add.
+Qed.
+
+Lemma ulsubmx_diag m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :
+ is_diag_mx A -> is_diag_mx (ulsubmx A).
+Proof.
+rewrite !is_diag_mxEtrig trmx_ulsub.
+by move=> /andP[/ulsubmx_trig-> /ulsubmx_trig->].
+Qed.
+
+Lemma drsubmx_diag m1 m2 n1 n2 (A : 'M[V]_(m1 + m2, n1 + n2)) :
+ m1 = n1 -> is_diag_mx A -> is_diag_mx (drsubmx A).
+Proof.
+move=> eq_m1_n1 /is_diag_mxP Adiag; apply/is_diag_mxP => i j neq_ij.
+by rewrite !mxE Adiag//= eq_m1_n1 eqn_add2l.
+Qed.
+
+Lemma is_trig_block_mx m1 m2 n1 n2 ul ur dl dr : m1 = n1 ->
+ @is_trig_mx (m1 + m2) (n1 + n2) (block_mx ul ur dl dr) =
+ [&& ur == 0, is_trig_mx ul & is_trig_mx dr].
+Proof.
+move=> eq_m1_n1; rewrite {}eq_m1_n1 in ul ur dl dr *.
+apply/is_trig_mxP/and3P => [Atrig|]; last first.
+ move=> [/eqP-> /is_trig_mxP ul_trig /is_trig_mxP dr_trig] i j; rewrite !mxE.
+ do 2![case: split_ordP => ? ->; rewrite ?mxE//=] => lt_ij; rewrite ?ul_trig//.
+ move: lt_ij; rewrite ltnNge -ltnS.
+ by rewrite (leq_trans (ltn_ord _))// -addnS leq_addr.
+ by rewrite dr_trig//; move: lt_ij; rewrite ltn_add2l.
+split.
+- apply/eqP/matrixP => i j; have := Atrig (lshift _ i) (rshift _ j).
+ rewrite !mxE; case: split_ordP => k /eqP; rewrite eq_shift// ?mxE.
+ case: split_ordP => l /eqP; rewrite eq_shift// ?mxE => /eqP-> /eqP<- <- //.
+ by rewrite /= (leq_trans (ltn_ord _)) ?leq_addr.
+- apply/is_trig_mxP => i j lt_ij; have := Atrig (lshift _ i) (lshift _ j).
+ rewrite !mxE; case: split_ordP => k /eqP; rewrite eq_shift// ?mxE.
+ by case: split_ordP => l /eqP; rewrite eq_shift// ?mxE => /eqP<- /eqP<- ->.
+- apply/is_trig_mxP => i j lt_ij; have := Atrig (rshift _ i) (rshift _ j).
+ rewrite !mxE; case: split_ordP => k /eqP; rewrite eq_shift// ?mxE.
+ case: split_ordP => l /eqP; rewrite eq_shift// ?mxE => /eqP<- /eqP<- -> //.
+ by rewrite /= ltn_add2l.
+Qed.
+
+Lemma trigmx_ind (P : forall m n, 'M_(m, n) -> Type) :
+ (forall m, P m 0%N 0) ->
+ (forall n, P 0%N n 0) ->
+ (forall m n x c A, is_trig_mx A ->
+ P m n A -> P (1 + m)%N (1 + n)%N (block_mx x 0 c A)) ->
+ forall m n A, is_trig_mx A -> P m n A.
+Proof.
+move=> P0l P0r PS m n A; elim: A => {m n} [m|n|m n xx r c] A PA;
+ do ?by rewrite (flatmx0, thinmx0); by [apply: P0l|apply: P0r].
+by rewrite is_trig_block_mx => // /and3P[/eqP-> _ Atrig]; apply: PS (PA _).
+Qed.
+
+Lemma trigsqmx_ind (P : forall n, 'M[V]_n -> Type) : (P 0%N 0) ->
+ (forall n x c A, is_trig_mx A -> P n A -> P (1 + n)%N (block_mx x 0 c A)) ->
+ forall n A, is_trig_mx A -> P n A.
+Proof.
+move=> P0 PS n A; elim/sqmx_ind: A => {n} [|n x r c] A PA.
+ by rewrite thinmx0; apply: P0.
+by rewrite is_trig_block_mx => // /and3P[/eqP-> _ Atrig]; apply: PS (PA _).
+Qed.
+
+Lemma is_diag_block_mx m1 m2 n1 n2 ul ur dl dr : m1 = n1 ->
+ @is_diag_mx (m1 + m2) (n1 + n2) (block_mx ul ur dl dr) =
+ [&& ur == 0, dl == 0, is_diag_mx ul & is_diag_mx dr].
+Proof.
+move=> eq_m1_n1.
+rewrite !is_diag_mxEtrig tr_block_mx !is_trig_block_mx// trmx_eq0.
+by rewrite andbACA -!andbA; congr [&& _, _, _ & _]; rewrite andbCA.
+Qed.
+
+Lemma diagmx_ind (P : forall m n, 'M_(m, n) -> Type) :
+ (forall m, P m 0%N 0) ->
+ (forall n, P 0%N n 0) ->
+ (forall m n x c A, is_diag_mx A ->
+ P m n A -> P (1 + m)%N (1 + n)%N (block_mx x 0 c A)) ->
+ forall m n A, is_diag_mx A -> P m n A.
+Proof.
+move=> P0l P0r PS m n A Adiag; have Atrig := is_diag_mx_is_trig Adiag.
+elim/trigmx_ind: Atrig Adiag => // {m n} m n r c {A}A _ PA.
+rewrite is_diag_block_mx => // /and4P[_ /eqP-> _ Adiag].
+exact: PS (PA _).
+Qed.
+
+Lemma diagsqmx_ind (P : forall n, 'M[V]_n -> Type) :
+ (P 0%N 0) ->
+ (forall n x c A, is_diag_mx A -> P n A -> P (1 + n)%N (block_mx x 0 c A)) ->
+ forall n A, is_diag_mx A -> P n A.
+Proof.
+move=> P0 PS n A; elim/sqmx_ind: A => {n} [|n x r c] A PA.
+ by rewrite thinmx0; apply: P0.
+rewrite is_diag_block_mx => // /and4P[/eqP-> /eqP-> _ Adiag].
+exact: PS (PA _).
+Qed.
+
End MatrixZmodule.
+Arguments is_diag_mx {V m n}.
+Arguments is_diag_mxP {V m n A}.
+Arguments is_trig_mx {V m n}.
+Arguments is_trig_mxP {V m n A}.
+
Section FinZmodMatrix.
Variables (V : finZmodType) (m n : nat).
Local Notation MV := 'M[V]_(m, n).
@@ -1275,7 +1559,7 @@ Proof. by apply/matrixP=> i j; rewrite !mxE mulrDr. Qed.
Lemma scalemxA x y A : x *m: (y *m: A) = (x * y) *m: A.
Proof. by apply/matrixP=> i j; rewrite !mxE mulrA. Qed.
-Definition matrix_lmodMixin :=
+Definition matrix_lmodMixin :=
LmodMixin scalemxA scale1mx scalemxDr scalemxDl.
Canonical matrix_lmodType :=
@@ -1288,10 +1572,10 @@ Lemma matrix_sum_delta A :
A = \sum_(i < m) \sum_(j < n) A i j *: delta_mx i j.
Proof.
apply/matrixP=> i j.
-rewrite summxE (bigD1 i) // summxE (bigD1 j) //= !mxE !eqxx mulr1.
-rewrite !big1 ?addr0 //= => [i' | j']; rewrite eq_sym => /negPf diff.
- by rewrite summxE big1 // => j' _; rewrite !mxE diff mulr0.
-by rewrite !mxE eqxx diff mulr0.
+rewrite summxE (bigD1_ord i) // summxE (bigD1_ord j) //= !mxE !eqxx mulr1.
+rewrite !big1 ?addr0 //= => [i' | j'] _.
+ by rewrite summxE big1// => j' _; rewrite !mxE eq_liftF mulr0.
+by rewrite !mxE eqxx eq_liftF mulr0.
Qed.
End RingModule.
@@ -1404,11 +1688,36 @@ Canonical diag_mx_linear n := Linear (@diag_mx_is_linear n).
Lemma diag_mx_sum_delta n (d : 'rV_n) :
diag_mx d = \sum_i d 0 i *: delta_mx i i.
Proof.
-apply/matrixP=> i j; rewrite summxE (bigD1 i) //= !mxE eqxx /=.
-rewrite eq_sym mulr_natr big1 ?addr0 // => i' ne_i'i.
-by rewrite !mxE eq_sym (negPf ne_i'i) mulr0.
+apply/matrixP=> i j; rewrite summxE (bigD1_ord i) //= !mxE eqxx /=.
+by rewrite eq_sym mulr_natr big1 ?addr0 // => i'; rewrite !mxE eq_liftF mulr0.
+Qed.
+
+Lemma row_diag_mx n (d : 'rV_n) i :
+ row i (diag_mx d) = d 0 i *: delta_mx 0 i.
+Proof. by apply/rowP => j; rewrite !mxE eqxx eq_sym mulr_natr. Qed.
+
+Lemma diag_mx_row m n (l : 'rV_n) (r : 'rV_m) :
+ diag_mx (row_mx l r) = block_mx (diag_mx l) 0 0 (diag_mx r).
+Proof.
+apply/matrixP => i j.
+by do ?[rewrite !mxE; case: split_ordP => ? ->]; rewrite mxE eq_shift.
Qed.
+Lemma diag_mxP n (A : 'M[R]_n) :
+ reflect (exists d : 'rV_n, A = diag_mx d) (is_diag_mx A).
+Proof.
+apply: (iffP is_diag_mxP) => [Adiag|[d ->] i j neq_ij]; last first.
+ by rewrite !mxE -val_eqE (negPf neq_ij).
+exists (\row_i A i i); apply/matrixP => i j; rewrite !mxE.
+by case: (altP (i =P j)) => [->|/Adiag->].
+Qed.
+
+Lemma diag_mx_is_diag n (r : 'rV[R]_n) : is_diag_mx (diag_mx r).
+Proof. by apply/diag_mxP; exists r. Qed.
+
+Lemma diag_mx_is_trig n (r : 'rV[R]_n) : is_trig_mx (diag_mx r).
+Proof. exact/is_diag_mx_is_trig/diag_mx_is_diag. Qed.
+
(* Scalar matrix : a diagonal matrix with a constant on the diagonal *)
Section ScalarMx.
@@ -1465,6 +1774,18 @@ Proof. by apply/is_scalar_mxP; exists a. Qed.
Lemma mx0_is_scalar : is_scalar_mx 0.
Proof. by apply/is_scalar_mxP; exists 0; rewrite raddf0. Qed.
+Lemma scalar_mx_is_diag a : is_diag_mx (a%:M).
+Proof. by rewrite -diag_const_mx diag_mx_is_diag. Qed.
+
+Lemma is_scalar_mx_is_diag A : is_scalar_mx A -> is_diag_mx A.
+Proof. by move=> /is_scalar_mxP[a ->]; apply: scalar_mx_is_diag. Qed.
+
+Lemma scalar_mx_is_trig a : is_trig_mx (a%:M).
+Proof. by rewrite is_diag_mx_is_trig// scalar_mx_is_diag. Qed.
+
+Lemma is_scalar_mx_is_trig A : is_scalar_mx A -> is_trig_mx A.
+Proof. by move=> /is_scalar_mx_is_diag /is_diag_mx_is_trig. Qed.
+
End ScalarMx.
Notation "x %:M" := (scalar_mx _ x) : ring_scope.
@@ -1474,9 +1795,8 @@ Proof. by apply/rowP=> j; rewrite ord1 mxE. Qed.
Lemma scalar_mx_block n1 n2 a : a%:M = block_mx a%:M 0 0 a%:M :> 'M_(n1 + n2).
Proof.
-apply/matrixP=> i j; rewrite !mxE -val_eqE /=.
-by do 2![case: splitP => ? ->; rewrite !mxE];
- rewrite ?eqn_add2l // -?(eq_sym (n1 + _)%N) eqn_leq leqNgt lshift_subproof.
+apply/matrixP=> i j; rewrite !mxE.
+by do 2![case: split_ordP => ? ->; rewrite !mxE]; rewrite ?eq_shift.
Qed.
(* Matrix multiplication using bigops. *)
@@ -1562,10 +1882,13 @@ Qed.
Lemma rowE m n i (A : 'M_(m, n)) : row i A = delta_mx 0 i *m A.
Proof.
-apply/rowP=> j; rewrite !mxE (bigD1 i) //= mxE !eqxx mul1r.
-by rewrite big1 ?addr0 // => i' ne_i'i; rewrite mxE /= (negPf ne_i'i) mul0r.
+apply/rowP=> j; rewrite !mxE (bigD1_ord i) //= mxE !eqxx mul1r.
+by rewrite big1 ?addr0 // => i'; rewrite mxE /= lift_eqF mul0r.
Qed.
+Lemma mul_rVP m n A B :((@mulmx 1 m n)^~ A =1 mulmx^~ B) <-> (A = B).
+Proof. by split=> [eqAB|->//]; apply/row_matrixP => i; rewrite !rowE eqAB. Qed.
+
Lemma row_mul m n p (i : 'I_m) A (B : 'M_(n, p)) :
row i (A *m B) = row i A *m B.
Proof. by rewrite !rowE mulmxA. Qed.
@@ -1579,9 +1902,9 @@ Qed.
Lemma mul_delta_mx_cond m n p (j1 j2 : 'I_n) (i1 : 'I_m) (k2 : 'I_p) :
delta_mx i1 j1 *m delta_mx j2 k2 = delta_mx i1 k2 *+ (j1 == j2).
Proof.
-apply/matrixP=> i k; rewrite !mxE (bigD1 j1) //=.
+apply/matrixP => i k; rewrite !mxE (bigD1_ord j1) //=.
rewrite mulmxnE !mxE !eqxx andbT -natrM -mulrnA !mulnb !andbA andbAC.
-by rewrite big1 ?addr0 // => j; rewrite !mxE andbC -natrM; move/negPf->.
+by rewrite big1 ?addr0 // => j; rewrite !mxE andbC -natrM lift_eqF.
Qed.
Lemma mul_delta_mx m n p (j : 'I_n) (i : 'I_m) (k : 'I_p) :
@@ -1726,21 +2049,20 @@ Proof. by apply/matrixP=> i j; rewrite !mxE ltn_ord andbT. Qed.
Lemma pid_mx_row n r : pid_mx r = row_mx 1%:M 0 :> 'M_(r, r + n).
Proof.
apply/matrixP=> i j; rewrite !mxE ltn_ord andbT.
-case: splitP => j' ->; rewrite !mxE // .
-by rewrite eqn_leq andbC leqNgt lshift_subproof.
+by case: split_ordP => j' ->; rewrite !mxE// (val_eqE (lshift n i)) eq_shift.
Qed.
Lemma pid_mx_col m r : pid_mx r = col_mx 1%:M 0 :> 'M_(r + m, r).
Proof.
apply/matrixP=> i j; rewrite !mxE andbC.
-by case: splitP => i' ->; rewrite !mxE // eq_sym.
+by case: split_ordP => ? ->; rewrite !mxE//.
Qed.
Lemma pid_mx_block m n r : pid_mx r = block_mx 1%:M 0 0 0 :> 'M_(r + m, r + n).
Proof.
apply/matrixP=> i j; rewrite !mxE row_mx0 andbC.
-case: splitP => i' ->; rewrite !mxE //; case: splitP => j' ->; rewrite !mxE //=.
-by rewrite eqn_leq andbC leqNgt lshift_subproof.
+do ![case: split_ordP => ? ->; rewrite !mxE//].
+by rewrite (val_eqE (lshift n _)) eq_shift.
Qed.
Lemma tr_pid_mx m n r : (pid_mx r)^T = pid_mx r :> 'M_(n, m).
@@ -1748,7 +2070,7 @@ Proof. by apply/matrixP=> i j; rewrite !mxE; case: eqVneq => // ->. Qed.
Lemma pid_mx_minv m n r : pid_mx (minn m r) = pid_mx r :> 'M_(m, n).
Proof. by apply/matrixP=> i j; rewrite !mxE leq_min ltn_ord. Qed.
-
+
Lemma pid_mx_minh m n r : pid_mx (minn n r) = pid_mx r :> 'M_(m, n).
Proof. by apply: trmx_inj; rewrite !tr_pid_mx pid_mx_minv. Qed.
@@ -2056,6 +2378,15 @@ Prenex Implicits mulmx mxtrace determinant cofactor adjugate.
Arguments is_scalar_mxP {R n A}.
Arguments mul_delta_mx {R m n p}.
+Hint Extern 0 (is_true (is_diag_mx (scalar_mx _))) =>
+ apply: scalar_mx_is_diag : core.
+Hint Extern 0 (is_true (is_trig_mx (scalar_mx _))) =>
+ apply: scalar_mx_is_trig : core.
+Hint Extern 0 (is_true (is_diag_mx (diag_mx _))) =>
+ apply: diag_mx_is_diag : core.
+Hint Extern 0 (is_true (is_trig_mx (diag_mx _))) =>
+ apply: diag_mx_is_trig : core.
+
Notation "a %:M" := (scalar_mx a) : ring_scope.
Notation "A *m B" := (mulmx A B) : ring_scope.
Notation mulmxr := (mulmxr_head tt).
@@ -2155,7 +2486,7 @@ Proof.
by move=> def_gf; apply/matrixP=> i j; rewrite !mxE -map_delta_mx -def_gf mxE.
Qed.
-Lemma map_lin_mx m1 n1 m2 n2 (g : 'M_(m1, n1) -> 'M_(m2, n2)) gf :
+Lemma map_lin_mx m1 n1 m2 n2 (g : 'M_(m1, n1) -> 'M_(m2, n2)) gf :
(forall A, (g A)^f = gf A^f) -> (lin_mx g)^f = lin_mx gf.
Proof.
move=> def_gf; apply: map_lin1_mx => A /=.
@@ -2363,17 +2694,6 @@ Qed.
Lemma detM n' (A B : 'M[R]_n'.+1) : \det (A * B) = \det A * \det B.
Proof. exact: det_mulmx. Qed.
-Lemma det_diag n (d : 'rV[R]_n) : \det (diag_mx d) = \prod_i d 0 i.
-Proof.
-rewrite /(\det _) (bigD1 1%g) //= addrC big1 => [|p p1].
- by rewrite add0r odd_perm1 mul1r; apply: eq_bigr => i; rewrite perm1 mxE eqxx.
-have{p1}: ~~ perm_on set0 p.
- apply: contra p1; move/subsetP=> p1; apply/eqP/permP=> i.
- by rewrite perm1; apply/eqP/idPn; move/p1; rewrite inE.
-case/subsetPn=> i; rewrite !inE eq_sym; move/negPf=> p_i _.
-by rewrite (bigD1 i) //= mulrCA mxE p_i mul0r.
-Qed.
-
(* Laplace expansion lemma *)
Lemma expand_cofactor n (A : 'M[R]_n) i j :
cofactor A i j =
@@ -2421,7 +2741,7 @@ rewrite -tr_row' -tr_col' det_tr; congr (\det _).
by apply/matrixP=> ? ?; rewrite !mxE.
Qed.
-Lemma cofactorZ n a (A : 'M[R]_n) i j :
+Lemma cofactorZ n a (A : 'M[R]_n) i j :
cofactor (a *: A) i j = a ^+ n.-1 * cofactor A i j.
Proof. by rewrite {1}/cofactor !linearZ detZ mulrCA mulrA. Qed.
@@ -2497,6 +2817,17 @@ Lemma det_lblock n1 n2 Aul (Adl : 'M[R]_(n2, n1)) Adr :
\det (block_mx Aul 0 Adl Adr) = \det Aul * \det Adr.
Proof. by rewrite -det_tr tr_block_mx trmx0 det_ublock !det_tr. Qed.
+Lemma det_trig n (A : 'M[R]_n) : is_trig_mx A -> \det A = \prod_(i < n) A i i.
+Proof.
+elim/trigsqmx_ind => [|k x c B Bt IHB]; first by rewrite ?big_ord0 ?det_mx00.
+rewrite det_lblock big_ord_recl [x]mx11_scalar det_scalar IHB//; congr (_ * _).
+ by rewrite -[ord0](lshift0 _ 0) block_mxEul mxE.
+by apply: eq_bigr => i; rewrite -!rshift1 block_mxEdr.
+Qed.
+
+Lemma det_diag n (d : 'rV[R]_n) : \det (diag_mx d) = \prod_i d 0 i.
+Proof. by rewrite det_trig//; apply: eq_bigr => i; rewrite !mxE eqxx. Qed.
+
End ComMatrix.
Arguments lin_mul_row {R m n} u.
@@ -2754,8 +3085,7 @@ have [{detA0}A'0 | nzA'] := eqVneq (row 0 (\adj A)) 0; last first.
pose A' := col' 0 A; pose vA := col 0 A.
have defA: A = row_mx vA A'.
apply/matrixP=> i j; rewrite !mxE.
- case: splitP => j' def_j; rewrite mxE; congr (A i _); apply: val_inj => //=.
- by rewrite def_j [j']ord1.
+ by case: split_ordP => j' ->; rewrite !mxE ?ord1; congr (A i _); apply: val_inj.
have{IHn} w_ j : exists w : 'rV_n.+1, [/\ w != 0, w 0 j = 0 & w *m A' = 0].
have [|wj nzwj wjA'0] := IHn (row' j A').
by apply/eqP; move/rowP/(_ j)/eqP: A'0; rewrite !mxE mulf_eq0 signr_eq0.
@@ -2763,13 +3093,9 @@ have{IHn} w_ j : exists w : 'rV_n.+1, [/\ w != 0, w 0 j = 0 & w *m A' = 0].
rewrite !mxE unlift_none -wjA'0; split=> //.
apply: contraNneq nzwj => w0; apply/eqP/rowP=> k'.
by move/rowP/(_ (lift j k')): w0; rewrite !mxE liftK.
- apply/rowP=> k; rewrite !mxE (bigD1 j) //= mxE unlift_none mul0r add0r.
- rewrite (reindex_onto (lift j) (odflt k \o unlift j)) /= => [|k'].
- by apply: eq_big => k'; rewrite ?mxE liftK eq_sym neq_lift eqxx.
- by rewrite eq_sym; case/unlift_some=> ? ? ->.
-have [w0 [nz_w0 w00_0 w0A']] := w_ 0; pose a0 := (w0 *m vA) 0 0.
-have [j {nz_w0}/= nz_w0j | w00] := pickP [pred j | w0 0 j != 0]; last first.
- by case/eqP: nz_w0; apply/rowP=> j; rewrite mxE; move/eqP: (w00 j).
+ apply/rowP=> k; rewrite !mxE (bigD1_ord j) //= mxE unlift_none mul0r add0r.
+ by apply: eq_big => //= k'; rewrite !mxE/= liftK.
+have [w0 [/rV0Pn[j nz_w0j] w00_0 w0A']] := w_ 0; pose a0 := (w0 *m vA) 0 0.
have{w_} [wj [nz_wj wj0_0 wjA']] := w_ j; pose aj := (wj *m vA) 0 0.
have [aj0 | nz_aj] := eqVneq aj 0.
exists wj => //; rewrite defA (@mul_mx_row _ _ _ 1) [_ *m _]mx11_scalar -/aj.
@@ -2819,7 +3145,7 @@ Qed.
Lemma map_mx_inv n' (A : 'M_n'.+1) : A^-1^f = A^f^-1.
Proof. exact: map_invmx. Qed.
-
+
Lemma map_mx_eq0 m n (A : 'M_(m, n)) : (A^f == 0) = (A == 0).
Proof. by rewrite -(inj_eq map_mx_inj) raddf0. Qed.
@@ -2906,3 +3232,141 @@ by case: unliftP => [j'|] ->; [apply: Uu | rewrite /= mxE].
Qed.
End CormenLUP.
+
+Section mxOver.
+Section mxOverType.
+Context {m n : nat} {T : Type}.
+Implicit Types (S : {pred T}).
+
+Definition mxOver (S : {pred T}) :=
+ [qualify a M : 'M[T]_(m, n) | [forall i, [forall j, M i j \in S]]].
+
+Fact mxOver_key S : pred_key (mxOver S). Proof. by []. Qed.
+Canonical mxOver_keyed S := KeyedQualifier (mxOver_key S).
+
+Lemma mxOverP {S : {pred T}} {M : 'M[T]__} :
+ reflect (forall i j, M i j \in S) (M \is a mxOver S).
+Proof. exact/'forall_forallP. Qed.
+
+Lemma mxOverS (S1 S2 : {pred T}) :
+ {subset S1 <= S2} -> {subset mxOver S1 <= mxOver S2}.
+Proof. by move=> sS12 M /mxOverP S1M; apply/mxOverP=> i j; apply/sS12/S1M. Qed.
+
+Lemma mxOver_const c S : c \in S -> const_mx c \is a mxOver S.
+Proof. by move=> cS; apply/mxOverP => i j; rewrite !mxE. Qed.
+
+Lemma mxOver_constE c S : (m > 0)%N -> (n > 0)%N ->
+ (const_mx c \is a mxOver S) = (c \in S).
+Proof.
+move=> m_gt0 n_gt0; apply/idP/idP; last exact: mxOver_const.
+by move=> /mxOverP /(_ (Ordinal m_gt0) (Ordinal n_gt0)); rewrite mxE.
+Qed.
+
+End mxOverType.
+
+Lemma thinmxOver {n : nat} {T : Type} (M : 'M[T]_(n, 0)) S : M \is a mxOver S.
+Proof. by apply/mxOverP => ? []. Qed.
+
+Lemma flatmxOver {n : nat} {T : Type} (M : 'M[T]_(0, n)) S : M \is a mxOver S.
+Proof. by apply/mxOverP => - []. Qed.
+
+Section mxOverZmodule.
+Context {M : zmodType} {m n : nat}.
+Implicit Types (S : {pred M}).
+
+Lemma mxOver0 S : 0 \in S -> 0 \is a @mxOver m n _ S.
+Proof. exact: mxOver_const. Qed.
+
+Section mxOverAdd.
+Variables (S : {pred M}) (addS : addrPred S) (kS : keyed_pred addS).
+Fact mxOver_add_subproof : addr_closed (@mxOver m n _ kS).
+Proof.
+split=> [|p q Sp Sq]; first by rewrite mxOver0 // ?rpred0.
+by apply/mxOverP=> i j; rewrite mxE rpredD // !(mxOverP _).
+Qed.
+Canonical mxOver_addrPred := AddrPred mxOver_add_subproof.
+End mxOverAdd.
+
+Section mxOverOpp.
+Variables (S : {pred M}) (oppS : opprPred S) (kS : keyed_pred oppS).
+Fact mxOver_opp_subproof : oppr_closed (@mxOver m n _ kS).
+Proof. by move=> A /mxOverP SA; apply/mxOverP=> i j; rewrite mxE rpredN. Qed.
+Canonical mxOver_opprPred := OpprPred mxOver_opp_subproof.
+End mxOverOpp.
+
+Canonical mxOver_zmodPred (S : {pred M}) (zmodS : zmodPred S)
+ (kS : keyed_pred zmodS) := ZmodPred (@mxOver_opp_subproof _ _ kS).
+
+End mxOverZmodule.
+
+Section mxOverRing.
+Context {R : ringType} {m n : nat}.
+
+Lemma mxOver_scalar S c : 0 \in S -> c \in S -> c%:M \is a @mxOver n n R S.
+Proof. by move=> S0 cS; apply/mxOverP => i j; rewrite !mxE; case: eqP. Qed.
+
+Lemma mxOver_scalarE S c : (n > 0)%N ->
+ (c%:M \is a @mxOver n n R S) = ((n > 1) ==> (0 \in S)) && (c \in S).
+Proof.
+case: n => [|[|k]]//= _.
+ by apply/mxOverP/idP => [/(_ ord0 ord0)|cij i j]; rewrite ?mxE ?ord1.
+apply/mxOverP/andP => [cij|[S0 cij] i j]; last by rewrite !mxE; case: eqP.
+by split; [have := cij 0 1|have := cij 0 0]; rewrite !mxE.
+Qed.
+
+Section mxOverScale.
+Variables (S : {pred R}) (mulS : mulrPred S) (kS : keyed_pred mulS).
+Lemma mxOverZ : {in kS & mxOver kS, forall a : R, forall v : 'M[R]_(m, n),
+ a *: v \is a mxOver kS}.
+Proof.
+by move=> a v aS /mxOverP vS; apply/mxOverP => i j; rewrite !mxE rpredM.
+Qed.
+End mxOverScale.
+
+Lemma mxOver_diag (S : {pred R}) k (D : 'rV[R]_k) :
+ 0 \in S -> D \is a mxOver S -> diag_mx D \is a mxOver S.
+Proof.
+move=> S0 DS; apply/mxOverP => i j; rewrite !mxE.
+by case: eqP => //; rewrite (mxOverP DS).
+Qed.
+
+Lemma mxOver_diagE (S : {pred R}) k (D : 'rV[R]_k) : k > 0 ->
+ (diag_mx D \is a mxOver S) = ((k > 1) ==> (0 \in S)) && (D \is a mxOver S).
+Proof.
+case: k => [|[|k]]//= in D * => _.
+ by rewrite [diag_mx _]mx11_scalar [D in RHS]mx11_scalar !mxE.
+apply/idP/andP => [/mxOverP DS|[S0 DS]]; last exact: mxOver_diag.
+split; first by have := DS 0 1; rewrite !mxE.
+by apply/mxOverP => i j; have := DS j j; rewrite ord1 !mxE eqxx.
+Qed.
+
+Section mxOverMul.
+
+Variables (S : predPredType R) (ringS : semiringPred S) (kS : keyed_pred ringS).
+
+Lemma mxOverM p q r : {in mxOver kS & mxOver kS,
+ forall u : 'M[R]_(p, q), forall v : 'M[R]_(q, r), u *m v \is a mxOver kS}.
+Proof.
+move=> M N /mxOverP MS /mxOverP NS; apply/mxOverP => i j.
+by rewrite !mxE rpred_sum // => k _; rewrite rpredM.
+Qed.
+
+End mxOverMul.
+End mxOverRing.
+
+Section mxRingOver.
+Context {R : ringType} {n : nat}.
+
+Section semiring.
+Variables (S : {pred R}) (ringS : semiringPred S) (kS : keyed_pred ringS).
+Fact mxOver_mul_subproof : mulr_closed (@mxOver n.+1 n.+1 _ kS).
+Proof. by split; rewrite ?mxOver_scalar ?rpred0 ?rpred1//; apply: mxOverM. Qed.
+Canonical mxOver_mulrPred := MulrPred mxOver_mul_subproof.
+Canonical mxOver_semiringPred := SemiringPred mxOver_mul_subproof.
+End semiring.
+
+Canonical mxOver_subringPred (S : {pred R}) (ringS : subringPred S)
+ (kS : keyed_pred ringS):= SubringPred (mxOver_mul_subproof kS).
+
+End mxRingOver.
+End mxOver.
diff --git a/mathcomp/algebra/mxalgebra.v b/mathcomp/algebra/mxalgebra.v
index 9a0034d..686da21 100644
--- a/mathcomp/algebra/mxalgebra.v
+++ b/mathcomp/algebra/mxalgebra.v
@@ -490,6 +490,17 @@ rewrite -{4}[B]mulmx_ebase -!mulmxA mulKmx //.
by rewrite (mulmxA (pid_mx _)) pid_mx_id // !mulmxA -{}defA mulmxKV.
Qed.
+Lemma mulmxVp m n (A : 'M[F]_(m, n)) : row_free A -> A *m pinvmx A = 1%:M.
+Proof.
+move=> fA; rewrite -[X in X *m _]mulmx_ebase !mulmxA mulmxK ?row_ebase_unit//.
+rewrite -[X in X *m _]mulmxA mul_pid_mx !minnn (minn_idPr _) ?rank_leq_col//.
+by rewrite (eqP fA) pid_mx_1 mulmx1 mulmxV ?col_ebase_unit.
+Qed.
+
+Lemma mulmxKp p m n (B : 'M[F]_(m, n)) : row_free B ->
+ cancel ((@mulmx _ p _ _)^~ B) (mulmx^~ (pinvmx B)).
+Proof. by move=> ? A; rewrite -mulmxA mulmxVp ?mulmx1. Qed.
+
Lemma submxP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :
reflect (exists D, A = D *m B) (A <= B)%MS.
Proof.
@@ -715,6 +726,21 @@ Proof. by rewrite /ltmx sub1mx submx1. Qed.
Lemma lt1mx m n (A : 'M_(m, n)) : (1%:M < A)%MS = false.
Proof. by rewrite /ltmx submx1 andbF. Qed.
+Lemma pinvmxE n (A : 'M[F]_n) : A \in unitmx -> pinvmx A = invmx A.
+Proof.
+move=> A_unit; apply: (@row_free_inj _ _ _ A); rewrite ?row_free_unit//.
+by rewrite -[pinvmx _]mul1mx mulmxKpV ?sub1mx ?row_full_unit// mulVmx.
+Qed.
+
+Lemma mulVpmx m n (A : 'M[F]_(m, n)) : row_full A -> pinvmx A *m A = 1%:M.
+Proof. by move=> fA; rewrite -[pinvmx _]mul1mx mulmxKpV// sub1mx. Qed.
+
+Lemma pinvmx_free m n (A : 'M[F]_(m, n)) : row_full A -> row_free (pinvmx A).
+Proof. by move=> /mulVpmx pAA1; apply/row_freeP; exists A. Qed.
+
+Lemma pinvmx_full m n (A : 'M[F]_(m, n)) : row_free A -> row_full (pinvmx A).
+Proof. by move=> /mulmxVp ApA1; apply/row_fullP; exists A. Qed.
+
Lemma eqmxP m1 m2 n (A : 'M_(m1, n)) (B : 'M_(m2, n)) :
reflect (A :=: B)%MS (A == B)%MS.
Proof.
@@ -805,6 +831,9 @@ exists (col_ebase A *m pid_mx (\rank A)).
by rewrite mulmxA -(mulmxA _ _ (pid_mx _)) pid_mx_id // mulmx_ebase.
Qed.
+Lemma row_base0 (m n : nat) : row_base (0 : 'M[F]_(m, n)) = 0.
+Proof. by apply/eqmx0P; rewrite !eq_row_base !sub0mx. Qed.
+
Let qidmx_eq1 n (A : 'M_n) : qidmx A = (A == 1%:M).
Proof. by rewrite /qidmx eqxx pid_mx_1. Qed.
@@ -1093,22 +1122,30 @@ Lemma eqmx_sums P n (A B : I -> 'M[F]_n) :
(\sum_(i | P i) A i :=: \sum_(i | P i) B i)%MS.
Proof. by move=> eqAB; apply/eqmxP; rewrite !sumsmxS // => i; move/eqAB->. Qed.
-Lemma sub_sumsmxP P m n (A : 'M_(m, n)) (B_ : I -> 'M_n) :
- reflect (exists u_, A = \sum_(i | P i) u_ i *m B_ i)
- (A <= \sum_(i | P i) B_ i)%MS.
+Lemma sub_sums_genmxP P m n p (A : 'M_(m, p)) (B_ : I -> 'M_(n, p)) :
+ reflect (exists u_ : I -> 'M_(m, n), A = \sum_(i | P i) u_ i *m B_ i)
+ (A <= \sum_(i | P i) <<B_ i>>)%MS.
Proof.
apply: (iffP idP) => [| [u_ ->]]; last first.
- by apply: summx_sub_sums => i _; apply: submxMl.
+ by apply: summx_sub_sums => i _; rewrite genmxE; apply: submxMl.
have [b] := ubnP #|P|; elim: b => // b IHb in P A *.
case: (pickP P) => [i Pi | P0 _]; last first.
rewrite big_pred0 //; move/submx0null->.
by exists (fun _ => 0); rewrite big_pred0.
-rewrite (cardD1x Pi) (bigD1 i) //= => /IHb{b IHb} /= IHi /sub_addsmxP[u ->].
+rewrite (cardD1x Pi) (bigD1 i) //= => /IHb{b IHb} /= IHi.
+rewrite (adds_eqmx (genmxE _) (eqmx_refl _)) => /sub_addsmxP[u ->].
have [u_ ->] := IHi _ (submxMl u.2 _).
-exists [eta u_ with i |-> u.1]; rewrite (bigD1 i Pi) /= eqxx; congr (_ + _).
+exists [eta u_ with i |-> u.1]; rewrite (bigD1 i Pi)/= eqxx; congr (_ + _).
by apply: eq_bigr => j /andP[_ /negPf->].
Qed.
+Lemma sub_sumsmxP P m n (A : 'M_(m, n)) (B_ : I -> 'M_n) :
+ reflect (exists u_, A = \sum_(i | P i) u_ i *m B_ i)
+ (A <= \sum_(i | P i) B_ i)%MS.
+Proof.
+by rewrite -(eqmx_sums (fun _ _ => genmxE _)); apply/sub_sums_genmxP.
+Qed.
+
Lemma sumsmxMr_gen P m n A (B : 'M[F]_(m, n)) :
((\sum_(i | P i) A i)%MS *m B :=: \sum_(i | P i) <<A i *m B>>)%MS.
Proof.
@@ -1174,11 +1211,22 @@ apply: (iffP submxP) => [[D ->]|]; first by rewrite -mulmxA mulmx_ker mulmx0.
by move/mulmxKV_ker; exists (B *m col_ebase A).
Qed.
+Lemma sub_kermx p m n (A : 'M_(m, n)) (B : 'M_(p, m)) :
+ (B <= kermx A)%MS = (B *m A == 0).
+Proof. exact/sub_kermxP/eqP. Qed.
+
+Lemma kermx0 m n : (kermx (0 : 'M_(m, n)) :=: 1%:M)%MS.
+Proof. by apply/eqmxP; rewrite submx1/= sub_kermx mulmx0. Qed.
+
+Lemma mulmx_free_eq0 m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :
+ row_free B -> (A *m B == 0) = (A == 0).
+Proof. by rewrite -sub_kermx -kermx_eq0 => /eqP->; rewrite submx0. Qed.
+
Lemma mulmx0_rank_max m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :
A *m B = 0 -> \rank A + \rank B <= n.
Proof.
move=> AB0; rewrite -{3}(subnK (rank_leq_row B)) leq_add2r.
-by rewrite -mxrank_ker mxrankS //; apply/sub_kermxP.
+by rewrite -mxrank_ker mxrankS // sub_kermx AB0.
Qed.
Lemma mxrank_Frobenius m n p q (A : 'M_(m, n)) B (C : 'M_(p, q)) :
@@ -1192,7 +1240,7 @@ set C1 := _ *m C; rewrite -{2}(subnKC (rank_leq_row C1)) leq_add2l -mxrank_ker.
rewrite -(mxrankMfree _ (row_base_free (A *m B))).
have: (row_base (A *m B) <= row_base B)%MS by rewrite !eq_row_base submxMl.
case/submxP=> D defD; rewrite defD mulmxA mxrankMfree ?mxrankS //.
-by apply/sub_kermxP; rewrite -mulmxA (mulmxA D) -defD -/C2 mulmx_ker.
+by rewrite sub_kermx -mulmxA (mulmxA D) -defD -/C2 mulmx_ker.
Qed.
Lemma mxrank_mul_min m n p (A : 'M_(m, n)) (B : 'M_(n, p)) :
@@ -1218,7 +1266,7 @@ apply/idP/andP=> [sAI | [/submxP[B' ->{A}] /submxP[C' eqBC']]].
rewrite -{1}[K]hsubmxK mul_row_col; move/(canRL (addrK _))->.
by rewrite add0r -mulNmx submxMl.
have: (row_mx B' (- C') <= kermx (col_mx B C))%MS.
- by apply/sub_kermxP; rewrite mul_row_col eqBC' mulNmx subrr.
+ by rewrite sub_kermx mul_row_col eqBC' mulNmx subrr.
case/submxP=> D; rewrite -[kermx _]hsubmxK mul_mx_row.
by case/eq_row_mx=> -> _; rewrite -mulmxA submxMl.
Qed.
@@ -1450,11 +1498,9 @@ apply/eqP; set K := kermx B; set C := (A :&: K)%MS.
rewrite -(eqmxMr B (eq_row_base A)); set K' := _ *m B.
rewrite -{2}(subnKC (rank_leq_row K')) -mxrank_ker eqn_add2l.
rewrite -(mxrankMfree _ (row_base_free A)) mxrank_leqif_sup.
- rewrite sub_capmx -(eq_row_base A) submxMl.
- by apply/sub_kermxP; rewrite -mulmxA mulmx_ker.
+ by rewrite sub_capmx -(eq_row_base A) submxMl sub_kermx -mulmxA mulmx_ker/=.
have /submxP[C' defC]: (C <= row_base A)%MS by rewrite eq_row_base capmxSl.
-rewrite defC submxMr //; apply/sub_kermxP.
-by rewrite mulmxA -defC; apply/sub_kermxP; rewrite capmxSr.
+by rewrite defC submxMr // sub_kermx mulmxA -defC -sub_kermx capmxSr.
Qed.
Lemma mxrank_injP m n p (A : 'M_(m, n)) (f : 'M_(n, p)) :
@@ -1936,10 +1982,7 @@ Definition eigenvalue : pred F := fun a => eigenspace a != 0.
Lemma eigenspaceP a m (W : 'M_(m, n)) :
reflect (W *m g = a *: W) (W <= eigenspace a)%MS.
-Proof.
-rewrite (sameP (sub_kermxP _ _) eqP).
-by rewrite mulmxBr subr_eq0 mul_mx_scalar; apply: eqP.
-Qed.
+Proof. by rewrite sub_kermx mulmxBr subr_eq0 mul_mx_scalar; apply/eqP. Qed.
Lemma eigenvalueP a :
reflect (exists2 v : 'rV_n, v *m g = a *: v & v != 0) (eigenvalue a).
@@ -2155,9 +2198,7 @@ rewrite -sum1_card (partition_big lsubmx nzC) => [|A]; last first.
rewrite -[A]hsubmxK v0 -[n.+1]/(1 + n)%N -col_mx0.
rewrite -[rsubmx _]vsubmxK -det_tr tr_row_mx !tr_col_mx !trmx0.
by rewrite det_lblock [0]mx11_scalar det_scalar1 mxE mul0r.
-rewrite -sum_nat_const; apply: eq_bigr; rewrite /= -[n.+1]/(1 + n)%N => v nzv.
-case: (pickP (fun i => v i 0 != 0)) => [k nza | v0]; last first.
- by case/eqP: nzv; apply/colP=> i; move/eqP: (v0 i); rewrite mxE.
+rewrite -sum_nat_const; apply: eq_bigr => /= v /cV0Pn[k nza].
have xrkK: involutive (@xrow F _ _ 0 k).
by move=> m A /=; rewrite /xrow -row_permM tperm2 row_perm1.
rewrite (reindex_inj (inv_inj (xrkK (1 + n)%N))) /= -[n.+1]/(1 + n)%N.
diff --git a/mathcomp/algebra/mxpoly.v b/mathcomp/algebra/mxpoly.v
index a8cf94b..9d54f35 100644
--- a/mathcomp/algebra/mxpoly.v
+++ b/mathcomp/algebra/mxpoly.v
@@ -188,7 +188,7 @@ have: rj0T (Ss_ dj.+1) = 'X^dj *: rj0T (S_ j1) + 1 *: rj0T (Ss_ dj).
rewrite Sylvester_mxE insubdK; last exact: leq_ltn_trans (ltjS).
by have [->|] := eqP; rewrite (addr0, add0r).
rewrite -det_tr => /determinant_multilinear->;
- try by apply/matrixP=> i j; rewrite !mxE eq_sym (negPf (neq_lift _ _)).
+ try by apply/matrixP=> i j; rewrite !mxE lift_eqF.
have [dj0 | dj_gt0] := posnP dj; rewrite ?dj0 !mul1r.
rewrite !det_tr det_map_mx addrC (expand_det_col _ j0) big1 => [|i _].
rewrite add0r; congr (\det _)%:P.
@@ -297,6 +297,18 @@ Qed.
End HornerMx.
+Lemma horner_mx_diag (R : comRingType) (n' : nat)
+ (d : 'rV[R]_n'.+1) (p : {poly R}) :
+ horner_mx (diag_mx d) p = diag_mx (map_mx (horner p) d).
+Proof.
+apply/matrixP => i j; rewrite !mxE.
+elim/poly_ind: p => [|p c ihp]; first by rewrite rmorph0 horner0 mxE mul0rn.
+rewrite !hornerE mulrnDl rmorphD rmorphM /= horner_mx_X horner_mx_C !mxE.
+rewrite (bigD1 j)//= ihp mxE ?eqxx mulr1n -mulrnAl big1 ?addr0//.
+ by case: (altP (i =P j)) => [->|]; rewrite /= !(mulr1n, addr0, mul0r).
+by move=> k /negPf nkF; rewrite mxE nkF mulr0.
+Qed.
+
Prenex Implicits horner_mx powers_mx.
Section CharPoly.
@@ -434,6 +446,14 @@ rewrite (big_morph _ (fun p q => hornerM p q a) (hornerC 1 a)).
by apply: eq_bigr => i _; rewrite !mxE !(hornerE, hornerMn).
Qed.
+Lemma char_poly_trig {R : comRingType} n (A : 'M[R]_n) : is_trig_mx A ->
+ char_poly A = \prod_(i < n) ('X - (A i i)%:P).
+Proof.
+move=> /is_trig_mxP Atrig; rewrite /char_poly det_trig.
+ by apply: eq_bigr => i; rewrite !mxE eqxx.
+by apply/is_trig_mxP => i j lt_ij; rewrite !mxE -val_eqE ltn_eqF ?Atrig ?subrr.
+Qed.
+
Definition companionmx {R : ringType} (p : seq R) (d := (size p).-1) :=
\matrix_(i < d, j < d)
if (i == d.-1 :> nat) then - p`_j else (i.+1 == j :> nat)%:R.
@@ -598,6 +618,15 @@ Qed.
Lemma mxminpoly_min p : horner_mx A p = 0 -> p_A %| p.
Proof. by move=> pA0; rewrite /dvdp -horner_mxK pA0 mx_inv_horner0. Qed.
+Lemma mxminpoly_minP p : reflect (horner_mx A p = 0) (p_A %| p).
+Proof.
+apply: (iffP idP); last exact: mxminpoly_min.
+by move=> /Pdiv.Field.dvdpP[q ->]; rewrite rmorphM/= mx_root_minpoly mulr0.
+Qed.
+
+Lemma dvd_mxminpoly p : (p_A %| p) = (horner_mx A p == 0).
+Proof. exact/mxminpoly_minP/eqP. Qed.
+
Lemma horner_rVpoly_inj : injective (horner_mx A \o rVpoly : 'rV_d -> 'M_n).
Proof.
apply: can_inj (poly_rV \o mx_inv_horner) _ => u /=.
@@ -634,13 +663,31 @@ rewrite !hornerE rmorphD rmorphM /= horner_mx_X horner_mx_C scalerDl.
by rewrite -scalerA mulmxDr mul_mx_scalar mulmxA -IHp -scalemxAl Av_av.
Qed.
+Lemma root_mxminpoly a : root p_A a = root (char_poly A) a.
+Proof. by rewrite -eigenvalue_root_min eigenvalue_root_char. Qed.
+
End MinPoly.
+Lemma mxminpoly_diag {F : fieldType} {n} (d : 'rV[F]_n.+1)
+ (u := undup [seq d 0 i | i <- enum 'I_n.+1]) :
+ mxminpoly (diag_mx d) = \prod_(r <- u) ('X - r%:P).
+Proof.
+apply/eqP; rewrite -eqp_monic ?mxminpoly_monic ?monic_prod_XsubC// /eqp.
+rewrite mxminpoly_min/=; last first.
+ rewrite horner_mx_diag; apply/matrixP => i j; rewrite !mxE horner_prod.
+ case: (altP (i =P j)) => [->|neq_ij//]; rewrite mulr1n.
+ rewrite (bigD1_seq (d 0 j)) ?undup_uniq ?mem_undup ?map_f// /=.
+ by rewrite hornerD hornerN hornerX hornerC subrr mul0r.
+apply: uniq_roots_dvdp; last by rewrite uniq_rootsE undup_uniq.
+apply/allP => x; rewrite mem_undup root_mxminpoly char_poly_trig//.
+rewrite -(big_map _ predT (fun x => _ - x%:P)) root_prod_XsubC.
+by move=> /mapP[i _ ->]; apply/mapP; exists i; rewrite ?(mxE, eqxx).
+Qed.
Prenex Implicits degree_mxminpoly mxminpoly mx_inv_horner.
Arguments mx_inv_hornerK {F n' A} [B] AnB.
Arguments horner_rVpoly_inj {F n' A} [u1 u2] eq_u12A : rename.
-
+
(* Parametricity. *)
Section MapRingMatrix.
diff --git a/mathcomp/algebra/poly.v b/mathcomp/algebra/poly.v
index d21e690..a33788d 100644
--- a/mathcomp/algebra/poly.v
+++ b/mathcomp/algebra/poly.v
@@ -1093,6 +1093,12 @@ Proof. by rewrite /comm_poly !hornerC !simp. Qed.
Lemma comm_polyX x : comm_poly 'X x.
Proof. by rewrite /comm_poly !hornerX. Qed.
+Lemma commr_horner a b p : GRing.comm a b -> comm_coef p a -> GRing.comm a p.[b].
+Proof.
+move=> cab cpa; rewrite horner_coef; apply: commr_sum => i _.
+by apply: commrM => //; apply: commrX.
+Qed.
+
Lemma hornerM_comm p q x : comm_poly q x -> (p * q).[x] = p.[x] * q.[x].
Proof.
move=> comm_qx.
@@ -1700,7 +1706,7 @@ Arguments rootP {R p x}.
Arguments rootPf {R p x}.
Arguments rootPt {R p x}.
Arguments unity_rootP {R n z}.
-Arguments polyOverP {R S0 addS kS p}.
+Arguments polyOverP {R S0 addS kS p} : rename.
Arguments polyC_inj {R} [x1 x2] eq_x12P.
Arguments eq_poly {R n} [E1] E2 eq_E12.
diff --git a/mathcomp/algebra/ssralg.v b/mathcomp/algebra/ssralg.v
index 2bde8dd..9a3c7d7 100644
--- a/mathcomp/algebra/ssralg.v
+++ b/mathcomp/algebra/ssralg.v
@@ -835,6 +835,9 @@ Qed.
Lemma mulrnAC x m n : x *+ m *+ n = x *+ n *+ m.
Proof. by rewrite -!mulrnA mulnC. Qed.
+Lemma iter_addr_0 n (m : V) : iter n (+%R m) 0 = m *+ n.
+Proof. by elim: n => //= n ->; rewrite mulrS. Qed.
+
Lemma sumrN I r P (F : I -> V) :
(\sum_(i <- r | P i) - F i = - (\sum_(i <- r | P i) F i)).
Proof. by rewrite (big_morph _ opprD oppr0). Qed.
@@ -856,6 +859,9 @@ Lemma sumr_const (I : finType) (A : pred I) (x : V) :
\sum_(i in A) x = x *+ #|A|.
Proof. by rewrite big_const -iteropE. Qed.
+Lemma sumr_const_nat (m n : nat) (x : V) : \sum_(n <= i < m) x = x *+ (m - n).
+Proof. by rewrite big_const_nat iter_addr_0. Qed.
+
Lemma telescope_sumr n m (f : nat -> V) : n <= m ->
\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.
Proof.
diff --git a/mathcomp/algebra/ssrint.v b/mathcomp/algebra/ssrint.v
index 3903609..f54a957 100644
--- a/mathcomp/algebra/ssrint.v
+++ b/mathcomp/algebra/ssrint.v
@@ -40,6 +40,16 @@ Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
+Reserved Notation "n %:Z" (at level 2, left associativity, format "n %:Z").
+Reserved Notation "n = m :> 'in' 't'"
+ (at level 70, m at next level, format "n = m :> 'in' 't'").
+Reserved Notation "n == m :> 'in' 't'"
+ (at level 70, m at next level, format "n == m :> 'in' 't'").
+Reserved Notation "n != m :> 'in' 't'"
+ (at level 70, m at next level, format "n != m :> 'in' 't'").
+Reserved Notation "n <> m :> 'in' 't'"
+ (at level 70, m at next level, format "n <> m :> 'in' 't'").
+
Import Order.TTheory GRing.Theory Num.Theory.
Delimit Scope int_scope with Z.
Local Open Scope int_scope.
@@ -50,19 +60,13 @@ Variant int : Set := Posz of nat | Negz of nat.
(* the Coq module system. *)
(* Coercion Posz : nat >-> int. *)
-Notation "n %:Z" := (Posz n)
- (at level 2, left associativity, format "n %:Z", only parsing) : int_scope.
-Notation "n %:Z" := (Posz n)
- (at level 2, left associativity, format "n %:Z", only parsing) : ring_scope.
-
-Notation "n = m :> 'in' 't'" := (Posz n = Posz m)
- (at level 70, m at next level, format "n = m :> 'in' 't'") : ring_scope.
-Notation "n == m :> 'in' 't'" := (Posz n == Posz m)
- (at level 70, m at next level, format "n == m :> 'in' 't'") : ring_scope.
-Notation "n != m :> 'in' 't'" := (Posz n != Posz m)
- (at level 70, m at next level, format "n != m :> 'in' 't'") : ring_scope.
-Notation "n <> m :> 'in' 't'" := (Posz n <> Posz m)
- (at level 70, m at next level, format "n <> m :> 'in' 't'") : ring_scope.
+Notation "n %:Z" := (Posz n) (only parsing) : int_scope.
+Notation "n %:Z" := (Posz n) (only parsing) : ring_scope.
+
+Notation "n = m :> 'in' 't'" := (Posz n = Posz m) : ring_scope.
+Notation "n == m :> 'in' 't'" := (Posz n == Posz m) : ring_scope.
+Notation "n != m :> 'in' 't'" := (Posz n != Posz m) : ring_scope.
+Notation "n <> m :> 'in' 't'" := (Posz n <> Posz m) : ring_scope.
Definition natsum_of_int (m : int) : nat + nat :=
match m with Posz p => inl _ p | Negz n => inr _ n end.
diff --git a/mathcomp/algebra/ssrnum.v b/mathcomp/algebra/ssrnum.v
index 3bae08e..e09ba9b 100644
--- a/mathcomp/algebra/ssrnum.v
+++ b/mathcomp/algebra/ssrnum.v
@@ -142,7 +142,8 @@ Fact ring_display : unit. Proof. exact: tt. Qed.
Module Num.
-Record normed_mixin_of (R T : zmodType) (Rorder : lePOrderMixin R)
+Record normed_mixin_of (R T : zmodType)
+ (Rorder : Order.POrder.mixin_of (Equality.class R))
(le_op := Order.POrder.le Rorder)
:= NormedMixin {
norm_op : T -> R;
@@ -152,7 +153,8 @@ Record normed_mixin_of (R T : zmodType) (Rorder : lePOrderMixin R)
_ : forall x, norm_op (- x) = norm_op x;
}.
-Record mixin_of (R : ringType) (Rorder : lePOrderMixin R)
+Record mixin_of (R : ringType)
+ (Rorder : Order.POrder.mixin_of (Equality.class R))
(le_op := Order.POrder.le Rorder) (lt_op := Order.POrder.lt Rorder)
(normed : @normed_mixin_of R R Rorder) (norm_op := norm_op normed)
:= Mixin {
@@ -169,7 +171,7 @@ Module NumDomain.
Section ClassDef.
Record class_of T := Class {
base : GRing.IntegralDomain.class_of T;
- order_mixin : lePOrderMixin (ring_for T base);
+ order_mixin : Order.POrder.mixin_of (Equality.class (ring_for T base));
normed_mixin : normed_mixin_of (ring_for T base) order_mixin;
mixin : mixin_of normed_mixin;
}.
@@ -726,22 +728,13 @@ Section ClassDef.
Record class_of R := Class {
base : NumDomain.class_of R;
- nmixin_disp : unit;
- nmixin : Order.Lattice.mixin_of (Order.POrder.Pack nmixin_disp base);
- lmixin_disp : unit;
- lmixin : Order.DistrLattice.mixin_of
- (Order.Lattice.Pack lmixin_disp (Order.Lattice.Class nmixin));
- tmixin_disp : unit;
- tmixin : Order.Total.mixin_of
- (Order.DistrLattice.Pack
- tmixin_disp (Order.DistrLattice.Class lmixin));
+ nmixin : Order.Lattice.mixin_of base;
+ lmixin : Order.DistrLattice.mixin_of (Order.Lattice.Class nmixin);
+ tmixin : Order.Total.mixin_of base;
}.
Local Coercion base : class_of >-> NumDomain.class_of.
Local Coercion base2 T (c : class_of T) : Order.Total.class_of T :=
- @Order.Total.Class
- _ (@Order.DistrLattice.Class
- _ (Order.Lattice.Class (@nmixin _ c)) _ (@lmixin _ c))
- _ (@tmixin _ c).
+ @Order.Total.Class _ (@Order.DistrLattice.Class _ _ (lmixin c)) (@tmixin _ c).
Structure type := Pack {sort; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
@@ -751,13 +744,11 @@ Let xT := let: Pack T _ := cT in T.
Notation xclass := (class : class_of xT).
Definition pack :=
fun bT b & phant_id (NumDomain.class bT) (b : NumDomain.class_of T) =>
- fun mT ndisp n ldisp l mdisp m &
+ fun mT n l m &
phant_id (@Order.Total.class ring_display mT)
- (@Order.Total.Class
- T (@Order.DistrLattice.Class
- T (@Order.Lattice.Class T b ndisp n) ldisp l)
- mdisp m) =>
- Pack (@Class T b ndisp n ldisp l mdisp m).
+ (@Order.Total.Class T (@Order.DistrLattice.Class
+ T (@Order.Lattice.Class T b n) l) m) =>
+ Pack (@Class T b n l m).
Definition eqType := @Equality.Pack cT xclass.
Definition choiceType := @Choice.Pack cT xclass.
@@ -878,7 +869,7 @@ Canonical idomain_orderType.
Canonical normedZmod_orderType.
Canonical numDomain_orderType.
Notation realDomainType := type.
-Notation "[ 'realDomainType' 'of' T ]" := (@pack T _ _ id _ _ _ _ _ _ _ id)
+Notation "[ 'realDomainType' 'of' T ]" := (@pack T _ _ id _ _ _ _ id)
(at level 0, format "[ 'realDomainType' 'of' T ]") : form_scope.
End Exports.
@@ -891,19 +882,13 @@ Section ClassDef.
Record class_of R := Class {
base : NumField.class_of R;
- nmixin_disp : unit;
- nmixin : Order.Lattice.mixin_of (Order.POrder.Pack nmixin_disp base);
- lmixin_disp : unit;
- lmixin : Order.DistrLattice.mixin_of
- (Order.Lattice.Pack lmixin_disp (Order.Lattice.Class nmixin));
- tmixin_disp : unit;
- tmixin : Order.Total.mixin_of
- (Order.DistrLattice.Pack
- tmixin_disp (Order.DistrLattice.Class lmixin));
+ nmixin : Order.Lattice.mixin_of base;
+ lmixin : Order.DistrLattice.mixin_of (Order.Lattice.Class nmixin);
+ tmixin : Order.Total.mixin_of base;
}.
Local Coercion base : class_of >-> NumField.class_of.
Local Coercion base2 R (c : class_of R) : RealDomain.class_of R :=
- RealDomain.Class (@tmixin R c).
+ @RealDomain.Class _ _ (nmixin c) (lmixin c) (@tmixin R c).
Structure type := Pack {sort; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
@@ -913,10 +898,9 @@ Let xT := let: Pack T _ := cT in T.
Notation xclass := (class : class_of xT).
Definition pack :=
fun bT (b : NumField.class_of T) & phant_id (NumField.class bT) b =>
- fun mT ndisp n ldisp l tdisp t
- & phant_id (RealDomain.class mT)
- (@RealDomain.Class T b ndisp n ldisp l tdisp t) =>
- Pack (@Class T b ndisp n ldisp l tdisp t).
+ fun mT n l t
+ & phant_id (RealDomain.class mT) (@RealDomain.Class T b n l t) =>
+ Pack (@Class T b n l t).
Definition eqType := @Equality.Pack cT xclass.
Definition choiceType := @Choice.Pack cT xclass.
@@ -999,7 +983,7 @@ Canonical numField_distrLatticeType.
Canonical numField_orderType.
Canonical numField_realDomainType.
Notation realFieldType := type.
-Notation "[ 'realFieldType' 'of' T ]" := (@pack T _ _ id _ _ _ _ _ _ _ id)
+Notation "[ 'realFieldType' 'of' T ]" := (@pack T _ _ id _ _ _ _ id)
(at level 0, format "[ 'realFieldType' 'of' T ]") : form_scope.
End Exports.
@@ -1579,7 +1563,7 @@ Arguments ler01 {R}.
Arguments ltr01 {R}.
Arguments normr_idP {R x}.
Arguments normr0P {R V v}.
-Hint Resolve @ler01 @ltr01 ltr0Sn ler0n : core.
+Hint Resolve ler01 ltr01 ltr0Sn ler0n : core.
Hint Extern 0 (is_true (0 <= norm _)) => exact: normr_ge0 : core.
Section NumDomainOperationTheory.
@@ -2016,6 +2000,11 @@ Lemma ler_sum I (r : seq I) (P : pred I) (F G : I -> R) :
\sum_(i <- r | P i) F i <= \sum_(i <- r | P i) G i.
Proof. exact: (big_ind2 _ (lexx _) ler_add). Qed.
+Lemma ler_sum_nat (m n : nat) (F G : nat -> R) :
+ (forall i, (m <= i < n)%N -> F i <= G i) ->
+ \sum_(m <= i < n) F i <= \sum_(m <= i < n) G i.
+Proof. by move=> le_FG; rewrite !big_nat ler_sum. Qed.
+
Lemma psumr_eq0 (I : eqType) (r : seq I) (P : pred I) (F : I -> R) :
(forall i, P i -> 0 <= F i) ->
(\sum_(i <- r | P i) (F i) == 0) = (all (fun i => (P i) ==> (F i == 0)) r).
@@ -3821,7 +3810,8 @@ Notation "[ 'arg' 'max_' ( i > i0 ) F ]" := [arg max_(i > i0 | true) F]
Variable R : realDomainType.
Implicit Types x y z t : R.
-Hint Resolve (@num_real R) : core.
+Let numR_real := @num_real R.
+Hint Resolve numR_real : core.
Lemma sgr_cp0 x :
((sg x == 1) = (0 < x)) *
@@ -5008,17 +4998,12 @@ move=> x y; move: (real (x - y)).
by rewrite unfold_in !ler_def subr0 add0r opprB orbC.
Qed.
-Let R_distrLatticeType := DistrLatticeType (LatticeType R le_total) le_total.
-
-Definition totalMixin : Order.Total.mixin_of R_distrLatticeType := le_total.
-
End RealMixin.
Module Exports.
Coercion le_total : real_axiom >-> totalPOrderMixin.
-Coercion totalMixin : real_axiom >-> totalOrderMixin.
Definition RealDomainOfNumDomain (T : numDomainType) (m : real_axiom T) :=
- [realDomainType of (OrderOfPOrder m)].
+ [realDomainType of OrderOfPOrder m].
End Exports.
End RealMixin.