(* Substitution *)
Definition tsubst i j (t : tuple) :=
  let (i1,i2,i3) := t in
  match tvcompare i i1 with
  | Eq => Tuple j i2 i3
  | _ =>
      match tvcompare i i2 with
     | Eq => Tuple i1 j i3
     | _ =>
         match tvcompare i i3 with
         | Eq => Tuple i1 i2 j
         | _ => t
         end
     end
  end.Definition s2k (s: sign) : K :=
  match s with S0 => 0%f | S1 => 1%f | Sm1 => (-(1))%f end.(* Add an element in a tuple  i1 [? i2 i3] *)
Definition mk_tuplel i1 i2 i3 :=
match tvcompare i1 i2 with
| Eq => (S0, Tuple i1 i2 i3)
| Lt => (S1, Tuple i1 i2 i3)
| Gt => 
  match tvcompare i1 i3 with
  | Eq => ( S0, Tuple i1 i2 i3)
  | Lt => (Sm1, Tuple i2 i1 i3)
  | Gt => ( S1, Tuple i2 i3 i1)
  end
end.(* Add an element in a tuple  [i1 i2 ?] i3 *)
Definition mk_tupler i1 i2 i3 :=
match tvcompare i2 i3 with
| Eq => (S0, Tuple i1 i2 i3)
| Lt => (S1, Tuple i1 i2 i3)
| Gt => 
  match tvcompare i1 i3 with
  | Eq => ( S0, Tuple i1 i2 i3)
  | Lt => (Sm1, Tuple i1 i3 i2)
  | Gt => ( S1, Tuple i3 i1 i2)
  end
end.Inductive sprod := SProd (s : sign) (t1 t2 : tuple).Inductive sprod := SProd (s : sign) (t1 t2 : tuple).Definition elsprod (l : list sprod) :=
  fold_left (fun res s => (res + esprod s)%f) l 0%f.(* i1 <= j1 *)
Definition tsplit3 (i1 i2 i3 j1 j2 j3 : tvar) := 
  match tvcompare i2 j2 with
  | Gt => 
     (*
             [i1 j1 j2] [i2 i3 j3]
           - [i1 j1 j3] [i2 i3 j2]
             [i1 j2 j3] [i2 i3 j1]
      *)
     let   (s1,t1) := mk_tuplel i1 j1 j2 in
     let (s'1,t'1) := mk_tupler i2 i3 j3 in
     let   (s2,t2) := mk_tuplel i1 j1 j3 in
     let (s'2,t'2) := mk_tupler i2 i3 j2 in
     let   (s3,t3) := mk_tuplel i1 j2 j3 in
     let (s'3,t'3) := mk_tupler i2 i3 j1 in
       SProd (smult s1 s'1) t1 t'1 ::
       SProd (sopp (smult s2 s'2)) t2 t'2 ::
       SProd (smult s3 s'3) t3 t'3 :: nil
  | _  =>
    match tvcompare i3 j3 with
    | Gt =>
        (*
            [i1 i2 j1] [i3 j2 j3]
           -[i1 i2 j2] [i3 j1 j3]
            [i1 i2 j3] [i3 j1 j2]
         *)
       let   (s1,t1) := mk_tupler i1 i2 j1 in
       let (s'1,t'1) := mk_tuplel i3 j2 j3 in
       let   (s2,t2) := mk_tupler i1 i2 j2 in
       let (s'2,t'2) := mk_tuplel i3 j1 j3 in
       let   (s3,t3) := mk_tupler i1 i2 j3 in
       let (s'3,t'3) := mk_tuplel i3 j1 j2 in
         SProd (smult s1 s'1) t1 t'1 ::
         SProd (sopp (smult s2 s'2)) t2 t'2 ::
         SProd (smult s3 s'3) t3 t'3 :: nil
    | _  => SProd S1 (Tuple i1 i2 i3) (Tuple j1 j2 j3)::nil
    end
  end.

(* Specifications: *)
Lemma s2km m1 m2 : s2k (smult m1 m2) = (s2k m1 * s2k m2)%f.
Lemma s2ko m : s2k (sopp m) = ((-(1)) * s2k m)%f.