Section Vect.
(* This is our scalar space with its dimension *)
Variable p : params.
(* The operations for scalar have the expected properties *)
Hypothesis Hp : fparamsProp p.
Delimit Scope g_scope with g.
Open Scope g_scope.
Open Scope vector_scope.
(* We recover the usual mathematical notation *)
Definition K1 := K.
Notation "'K'" := (K1 p) : g_scope.
Notation projk := (Kn.proj p _).
Notation gvp := (Grassmann.vn_eparams p).
Notation "x '∧' y" := (join p _ x y) (at level 40, left associativity).
Notation "x + y" := (addE _ x y).
Notation "k .* x" := (scalE (gvp _) k x).
Notation "k .* x" := (scalE _ k x) : Kn_scope.
Notation vect := (vect p).
Notation "x ^_'f" := (conj p _ false x)  (at level 30).
Notation "'C[ x ]" := (const p _ x).
Notation " [ k ] " := (genk p  _ k%f) (at level 9).
Notation kn := (kn p).
Notation "#< l , x ># " := (contra p _ l x).
Notation "'v_ x" := (k2g  p _ x) (at level 9).
Notation "''e_' i" := (gen p _ i).
Notation "'@ x " := (dual p _ x) (at level 9).
Notation E := (all p _).
Canonical Structure vn_eparams (n : nat) :=
Build_eparams (vect n) K [0] (eq p n) (add p n) (scal p n).
Ltac Vfold n :=
change (VectorSpace.K p) with (K1 p);
change (add p n) with (addE (gvp n));
change (scal p n) with (scalE (gvp n));
change (genk p n 0%f) with (E0 (gvp n)).
Hint Resolve (fn _ Hp).
(* The geometric product (Clifford product)    *)
(* the quadratic form is encoded as the list l *)
Fixpoint gprod (n : nat) : kn n -> vect n -> vect n -> vect n :=
match n return (kn n -> vect n -> vect n -> vect n) with
| 0%nat => fun k x y => (x * y)%f
| S n1 =>
fun l x y =>
let (k1, l1) := l in
let (x1, x2) := x in
let (y1, y2) := y in
(     gprod n1 l1 x1 y2  +      gprod n1 l1 (x2 ^_'f) y1,
gprod n1 l1 x2 y2 + k1 .* gprod n1 l1 (x1 ^_'f) y1)
end.
Notation "a [*  l ]  b " := (gprod _ l a b) (at level 9).

(* Specifications: *)
Lemma grpod_l0_join n x y : x [* 0] y = x ∧ y :> vect n.
Lemma gprodE n l (M1 M2 : vect n.+1) :
M1 [* l] M2 =
( (fst M1) [* snd l] (snd M2)  +  ((snd M1) ^_'f) [* snd l]  (fst M2),
(snd M1) [* snd l] (snd M2) +
fst l .* (((fst M1) ^_'f) [* snd l]  (fst M2))).
Lemma gprod0l n l y : 0 [* l] y = 0 :> vect n.
Lemma gprodkl n l k y : [k] [* l] y = k .* y :> vect n.
Lemma gprodkr n l k x : (x [* l] [k]) = k .* x :> vect n.
Lemma gprod_spec1 n l i :
i < n -> 'e_i [* l] 'e_i =  [projk i l] :> vect n.
Lemma gprod_spec2 n l i j : i < n -> j < n -> i <> j ->
'e_i [* l] 'e_j =  (-(1))%f .* 'e_j [* l] 'e_i :> vect n.
Lemma gprod_scall n l k x y : (k .* x) [* l] y = k .* (x [* l] y) :> vect n.
Lemma gprod_scalr n l k x y : x [* l] (k .* y) = k .* (x [* l] y) :> vect n.
Lemma gprod_addl n l x y z :
(x + y) [* l] z = x [* l] z + y [* l] z :> vect n.
Lemma gprod_addr n l x y z :
x [* l] (y + z) = x [* l] y + x [* l] z :> vect n.
Lemma conjf_gprod n l (x y: vect n) :
(x [* l] y) ^_'f = (x ^_'f) [* l] (y ^_'f) :> vect n.
Lemma gprod_assoc n l x y z :
(x [* l] y) [* l] z = x [* l] (y [* l] z) :> vect n.
Lemma gprod_e0 n l (M : vect n.+1 ) :
'e_0 [* l] M = (snd M, fst l .* fst M).
Lemma gprod_ei n l i (M : vect n.+1) :
i < n ->
'e_i.+1 [* l] M =
((-(1))%f .* ('e_i [* snd l] (fst M)), 'e_i [* snd l] (snd M)).
Lemma gprodE_ei n l i M :
i < n ->
'e_i [* l] M =  'e_i ∧ M + #<('e_i [*] l)%Kn, M># :> vect n.
Lemma gprodE_v n l x M :
'v_x [* l] M = 'v_x ∧ M + #< (x [*] l)%Kn, M ># :> vect n.