(* (c) Copyright 2006-2016 Microsoft Corporation and Inria.                  *)
(* Distributed under the terms of CeCILL-B.                                  *)
From mathcomp
From mathcomp
(******************************************************************************)
(*  * Finite dimensional vector spaces                                        *)
(*           vectType R == interface structure for finite dimensional (more   *)
(*                         precisely, detachable) vector spaces over R, which *)
(*                         should be at least a ringType.                     *)
(*     Vector.axiom n M <-> type M is linearly isomorphic to 'rV_n.           *)
(*                         := {v2r : M -> 'rV_n| linear v2r & bijective v2r}. *)
(*       VectMixin isoM == packages a proof isoV of Vector.axiom n M as the   *)
(*                         vectType mixin for an n-dimensional R-space        *)
(*                         structure on a type M that is an lmodType R.       *)
(*      VectType K M mT == packs the vectType mixin mT to into a vectType K   *)
(*                         instance for T; T should have an lmodType K        *)
(*                         canonical instance.                                *)
(* [vectType R of T for vS] == a copy of the vS : vectType R structure where  *)
(*                         the sort is replaced by T; vS : lmodType R should  *)
(*                         be convertible to a canonical lmodType for T.      *)
(*    [vectType R of V] == a clone of an existing vectType R structure on V.  *)
(*          {vspace vT} == the type of (detachable) subspaces of vT; vT       *)
(*                         should have a vectType structure over a fieldType. *)
(*           subvs_of U == the subtype of elements of V in the subspace U.    *)
(*                         This is canonically a vectType.                    *)
(*               vsval u == linear injection of u : subvs_of U into V.        *)
(*            vsproj U v == linear projection of v : V in subvs U.            *)
(*         'Hom(aT, rT) == the type of linear functions (homomorphisms) from  *)
(*                         aT to rT, where aT and rT ARE vectType structures. *)
(*                         Elements of 'Hom(aT, rT) coerce to Coq functions.  *)
(* --> Caveat: aT and rT must denote actual vectType structures, not their    *)
(*     projections on Type.                                                   *)
(*             linfun f == a vector linear function in 'Hom(aT, rT) that      *)
(*                         coincides with f : aT -> rT when f is linear.      *)
(*             'End(vT) == endomorphisms of vT (:= 'Hom(vT, vT)).             *)
(* --> The types subvs_of U, 'Hom(aT, rT), 'End(vT), K^o, 'M[K]_(m, n),       *)
(*     vT * wT, {ffun I -> vT}, vT ^ n all have canonical vectType instances. *)
(*                                                                            *)
(*  Functions:                                                                *)
(*             <[v]>%VS == the vector space generated by v (a line if v != 0).*)
(*                 0%VS == the trivial vector subspace.                       *)
(*         fullv, {:vT} == the complete vector subspace (displays as fullv).  *)
(*           (U + V)%VS == the join (sum) of two subspaces U and V.           *)
(*         (U :&: V)%VS == intersection of vector subspaces U and V.          *)
(*             (U^C)%VS == a complement of the vector subspace U.             *)
(*         (U :\: V)%VS == a local complement to U :& V in the subspace U.    *)
(*               \dim U == dimension of a vector space U.                     *)
(*     span X, <<X>>%VS == the subspace spanned by the vector sequence X.     *)
(*          coord X i v == i'th coordinate of v on X, when v \in <<X>>%VS and *)
(*                         where X : n.-tuple vT and i : 'I_n. Note that      *)
(*                         coord X i is a scalar function.                    *)
(*              vpick U == a nonzero element of U if U= 0%VS, or 0 if U = 0.  *)
(*             vbasis U == a (\dim U).-tuple that is a basis of U.            *)
(*                \1%VF == the identity linear function.                      *)
(*          (f \o g)%VF == the composite of two linear functions f and g.     *)
(*            (f^-1)%VF == a linear function that is a right inverse to the   *)
(*                         linear function f on the codomain of f.            *)
(*          (f @: U)%VS == the image of vs by the linear function f.          *)
(*       (f @^-1: U)%VS == the pre-image of vs by the linear function f.      *)
(*               lker f == the kernel of the linear function f.               *)
(*               limg f == the image of the linear function f.                *)
(*         fixedSpace f == the fixed space of a linear endomorphism f         *)
(*         daddv_pi U V == projection onto U along V if U and V are disjoint; *)
(*                         daddv_pi U V + daddv_pi V U is then a projection   *)
(*                         onto the direct sum (U + V)%VS.                    *)
(*              projv U == projection onto U (along U^C, := daddv_pi U U^C).  *)
(*         addv_pi1 U V == projection onto the subspace U :\: V of U along V. *)
(*         addv_pi2 U V == projection onto V along U :\: V; note that         *)
(*                         addv_pi1 U V and addv_pi2 U V are (asymmetrical)   *)
(*                         complementary projections on (U + V)%VS.           *)
(*   sumv_pi_for defV i == for defV : V = (V \sum_(j <- r | P j) Vs j)%VS,    *)
(*                         j ranging over an eqType, this is a projection on  *)
(*                         a subspace of Vs i, along a complement in V, such  *)
(*                         that \sum_(j <- r | P j) sumv_pi_for defV j is a   *)
(*                         projection onto V if filter P r is duplicate-free  *)
(*                         (e.g., when V := \sum_(j | P j) Vs j).             *)
(*          sumv_pi V i == notation the above when defV == erefl V, and V is  *)
(*                         convertible to \sum_(j <- r | P j) Vs j)%VS.       *)
(*                                                                            *)
(*  Predicates:                                                               *)
(*              v \in U == v belongs to U (:= (<[v]> <= U)%VS).               *)
(*          (U <= V)%VS == U is a subspace of V.                              *)
(*               free B == B is a sequence of nonzero linearly independent    *)
(*                         vectors.                                           *)
(*         basis_of U b == b is a basis of the subspace U.                    *)
(*            directv S == S is the expression for a direct sum of subspaces. *)
(******************************************************************************)
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Local Open Scope ring_scope.
Reserved Notation "{ 'vspace' T }" (at level 0, format "{ 'vspace'  T }").
Reserved Notation "''Hom' ( T , rT )" (at level 8, format "''Hom' ( T ,  rT )").
Reserved Notation "''End' ( T )" (at level 8, format "''End' ( T )").
Reserved Notation "\dim A" (at level 10, A at level 8, format "\dim  A").
Delimit Scope vspace_scope with VS.
(* Finite dimension vector space *)
Module Vector.
Section ClassDef.
Variable R : ringType.
Definition axiom_def n (V : lmodType R) of phant V :=
{v2r : V -> 'rV[R]_n | linear v2r & bijective v2r}.
Inductive mixin_of (V : lmodType R) := Mixin dim & axiom_def dim (Phant V).
Structure class_of V := Class {
base : GRing.Lmodule.class_of R V;
mixin : mixin_of (GRing.Lmodule.Pack _ base)
}.
Local Coercion base : class_of >-> GRing.Lmodule.class_of.
Structure type (phR : phant R) := Pack {sort; _ : class_of sort}.
Local Coercion sort : type >-> Sortclass.
Variables (phR : phant R) (T : Type) (cT : type phR).
Definition class := let: Pack _ c := cT return class_of cT in c.
Definition clone c of phant_id class c := @Pack phR T c.
Let xT := let: Pack T _ := cT in T.
Notation xclass := (class : class_of xT).
Definition dim := let: Mixin n _ := mixin class in n.
Definition pack b0 (m0 : mixin_of (@GRing.Lmodule.Pack R _ T b0)) :=
fun bT b & phant_id (@GRing.Lmodule.class _ phR bT) b =>
fun    m & phant_id m0 m => Pack phR (@Class T b m).
Definition eqType := @Equality.Pack cT xclass.
Definition choiceType := @Choice.Pack cT xclass.
Definition zmodType := @GRing.Zmodule.Pack cT xclass.
Definition lmodType := @GRing.Lmodule.Pack R phR cT xclass.
End ClassDef.
Notation axiom n V := (axiom_def n (Phant V)).
Section OtherDefs.
Local Coercion sort : type >-> Sortclass.
Local Coercion dim : type >-> nat.
Inductive space (K : fieldType) (vT : type (Phant K)) (phV : phant vT) :=
Space (mx : 'M[K]_vT) & <<mx>>%MS == mx.
Inductive hom (R : ringType) (vT wT : type (Phant R)) :=
Hom of 'M[R]_(vT, wT).
End OtherDefs.
Module Import Exports.
Coercion base : class_of >-> GRing.Lmodule.class_of.
Coercion mixin : class_of >-> mixin_of.
Coercion sort : type >-> Sortclass.
Coercion eqType: type >->  Equality.type.
Bind Scope ring_scope with sort.
Canonical eqType.
Coercion choiceType: type >-> Choice.type.
Canonical choiceType.
Coercion zmodType: type >-> GRing.Zmodule.type.
Canonical zmodType.
Coercion lmodType: type>->  GRing.Lmodule.type.
Canonical lmodType.
Notation vectType R := (@type _ (Phant R)).
Notation VectType R V mV :=
(@pack _ (Phant R) V _ mV _ _ id _ id).
Notation VectMixin := Mixin.
Notation "[ 'vectType' R 'of' T 'for' cT ]" := (@clone _ (Phant R) T cT _ idfun)
(at level 0, format "[ 'vectType'  R  'of'  T  'for'  cT ]") : form_scope.
Notation "[ 'vectType' R 'of' T ]" := (@clone _ (Phant R) T _ _ idfun)
(at level 0, format "[ 'vectType'  R  'of'  T ]") : form_scope.
Notation "{ 'vspace' vT }" := (space (Phant vT)) : type_scope.
Notation "''Hom' ( aT , rT )" := (hom aT rT) : type_scope.
Notation "''End' ( vT )" := (hom vT vT) : type_scope.
Prenex Implicits Hom.
Delimit Scope vspace_scope with VS.
Bind Scope vspace_scope with space.
Delimit Scope lfun_scope with VF.
Bind Scope lfun_scope with hom.
End Exports.
(* The contents of this module exposes the matrix encodings, and should       *)
(* therefore not be used outside of the vector library implementation.        *)
Module InternalTheory.
Section Iso.
Variables (R : ringType) (vT rT : vectType R).
Local Coercion dim : vectType >-> nat.
Fact v2r_subproof : axiom vT vT. Proof. by case: vT => T [bT []]. Qed.
Definition v2r := s2val v2r_subproof.
Let v2r_bij : bijective v2r := s2valP' v2r_subproof.
Fact r2v_subproof : {r2v | cancel r2v v2r}.
Definition r2v := sval r2v_subproof.

(* Specifications: *)
Lemma r2vK : cancel r2v v2r.   Proof. exact: (svalP r2v_subproof). Qed.
Lemma r2v_inj : injective r2v. Proof. exact: can_inj r2vK. Qed.
Lemma v2rK : cancel v2r r2v.   Proof. by have/bij_can_sym:= r2vK; apply. Qed.
Lemma v2r_inj : injective v2r. Proof. exact: can_inj v2rK. Qed.
Canonical v2r_linear := Linear (s2valP v2r_subproof : linear v2r).