(* Ad-hoc conjugate function in order to define the join *)
Fixpoint dconj (n : nat) (b: bool) {struct n} : vect n -> vect n :=
match n return (vect n -> vect n) with
| 0%nat => fun a => if b then (- a)%f else a
| S n1 =>
fun l1 =>
let (l2, l3) := l1 in (dconj n1 b l2, dconj n1 (negb b) l3)
end.
Notation "x ^d_ b" := (dconj _ b x)  (at level 29, left associativity).
Notation "x ^d_'t" := (dconj _ true x)  (at level 29, left associativity).
Notation "x ^d_'f" := (dconj _ false x)  (at level 29, left associativity).

(* Specifications: *)
Lemma dconj0 n b : 0 ^d_ b = 0 :> vect n.
Hint Rewrite dconj0: GRm0.
Lemma dconj_all n b :
E ^d_ b = (if b then (-(1)) .* E else E) :> vect n.
Lemma dconj_scal n b k (x: vect n) : (k .* x)^d_ b = k .* x ^d_ b.
(* Dual conjugate behave well with the sum *)
Lemma dconj_add n b (x y: vect n) : (x + y) ^d_ b = x ^d_ b + y ^d_ b.
(* Dual conjugate is involutive *)
Lemma dconj_invo n b (v: vect n) : v ^d_ b ^d_ b = v.
Lemma dconj_neg n b (v: vect n) : v ^d_ (negb b) = (-(1)) .*  (v ^d_ b).
Lemma dconjt n (v: vect n) : v ^d_'t = (-(1)) .*  (v ^d_'f).
Lemma dconjt_hom n k (M: vect n) :
hom n k M -> M ^d_'t = (- (1))^(n + k).+1 .* M.
Lemma dconj_swap n b1 b2 (x: vect n) : x ^d_ b2 ^d_ b1 = x ^d_ b1 ^d_ b2.
Lemma dconj_conj_swap n b1 b2 (x: vect n) : (x ^_ b2) ^d_  b1 = x ^d_ b1 ^_ b2.
Lemma dconj_conj n b (x: vect n) : (x ^_ b) ^d_ b = (-(1))^n .* x.
Lemma dconj_hom n b k (x: vect n) : hom n k x -> hom n k (x ^d_ b).
Hint Resolve dconj_hom.
Lemma dconjf_joinl n (x y: vect n) : (x ∨ y) ^d_'f = x ^d_'f ∨ y ^_'f.
Lemma dconjf_joinr n (x y: vect n) : (x ∨ y) ^d_'f = x ^_'f ∨ y ^d_'f.
Lemma conj_dual n b (x: vect n): '@(x ^_ b) = '@x ^d_ b.
Lemma dconj_dual n b (x: vect n) : '@(x ^d_ b) = '@x ^_ b.
Lemma dualk n k : '@([k]) = k .* E :> vect n.
Definition dconst n (x: vect n) := 'C['@x].