Canonical cfun_vectType := VectType algC classfun cfun_vectMixin.
Canonical cfun_FalgType := [FalgType algC of classfun].
Definition cfun_base A : #|classes B ::&: A|.-tuple classfun :=
[tuple of [seq '1_xB | xB in classes B ::&: A]].
Definition classfun_on A := <<cfun_base A>>%VS.
Definition cfdot phi psi := #|B|%:R^-1 * \sum_(x in B) phi x * (psi x)^*.
Definition cfdotr_head k psi phi := let: tt := k in cfdot phi psi.
Definition cfnorm_head k phi := let: tt := k in cfdot phi phi.
Coercion seq_of_cfun phi := [:: phi].
Definition cforder phi := \big[lcmn/1%N]_(x in <<B>>) #[phi x]%C.
End Defs.
Bind Scope cfun_scope with classfun.
Arguments classfun {gT} B%g.
Arguments classfun_on {gT} B%g A%g.
Arguments cfun_indicator {gT} B%g.
Arguments cfAut {gT B%g} u phi%CF.
Arguments cfReal {gT B%g} phi%CF.
Arguments cfdot {gT B%g} phi%CF psi%CF.
Arguments cfdotr_head {gT B%g} k psi%CF phi%CF.
Notation "''CF' ( G )" := (classfun G) : type_scope.
Notation "''CF' ( G )" := (@fullv _ (cfun_vectType G)) : vspace_scope.
Notation "''1_' A" := (cfun_indicator _ A) : ring_scope.
Notation "''CF' ( G , A )" := (classfun_on G A) : ring_scope.
Notation "1" := (@GRing.one (cfun_ringType _)) (only parsing) : cfun_scope.
Notation "phi ^*" := (cfAut conjC phi) : cfun_scope.
Notation cfConjC_closed := (cfAut_closed conjC).
Prenex Implicits cfReal.
(* Workaround for overeager projection reduction. *)
Notation eqcfP := (@eqP (cfun_eqType _) _ _) (only parsing).
Notation "#[ phi ]" := (cforder phi) : cfun_scope.
Notation "''[' u , v ]_ G":=  (@cfdot _ G u v) (only parsing) : ring_scope.
Notation "''[' u , v ]" := (cfdot u v) : ring_scope.
Notation "''[' u ]_ G" := '[u, u]_G (only parsing) : ring_scope.
Notation "''[' u ]" := '[u, u] : ring_scope.
Notation cfdotr := (cfdotr_head tt).
Notation cfnorm := (cfnorm_head tt).
Section Predicates.
Variables (gT rT : finGroupType) (D : {set gT}) (R : {set rT}).
Implicit Types (phi psi : 'CF(D)) (S : seq 'CF(D)) (tau : 'CF(D) -> 'CF(R)).
Definition cfker phi := [set x in D | [forall y, phi (x * y)%g == phi y]].
Definition cfaithful phi := cfker phi \subset [1].
Definition ortho_rec S1 S2 :=
all [pred phi | all [pred psi | '[phi, psi] == 0] S2] S1.
Fixpoint pair_ortho_rec S :=
if S is psi :: S' then ortho_rec psi S' && pair_ortho_rec S' else true.
(* We exclude 0 from pairwise orthogonal sets. *)
Definition pairwise_orthogonal S := (0 \notin S) && pair_ortho_rec S.
Definition orthonormal S := all [pred psi | '[psi] == 1] S && pair_ortho_rec S.
Definition isometry tau := forall phi psi, '[tau phi, tau psi] = '[phi, psi].
Definition isometry_from_to mCFD tau mCFR :=
prop_in2 mCFD (inPhantom (isometry tau))
/\ prop_in1 mCFD (inPhantom (forall phi, in_mem (tau phi) mCFR)).
End Predicates.
(* Outside section so the nosimpl does not get "cooked" out. *)
Definition orthogonal gT D S1 S2 := nosimpl (@ortho_rec gT D S1 S2).
Arguments cfker {gT D%g} phi%CF.
Arguments cfaithful {gT D%g} phi%CF.
Arguments orthogonal {gT D%g} S1%CF S2%CF.
Arguments pairwise_orthogonal {gT D%g} S%CF.
Arguments orthonormal {gT D%g} S%CF.
Arguments isometry {gT rT D%g R%g} tau%CF.
Notation "{ 'in' CFD , 'isometry' tau , 'to' CFR }" :=
(isometry_from_to (mem CFD) tau (mem CFR))
(at level 0, format "{ 'in'  CFD ,  'isometry'  tau ,  'to'  CFR }")
: type_scope.
Section ClassFun.
Variables (gT : finGroupType) (G : {group gT}).
Implicit Types (A B : {set gT}) (H K : {group gT}) (phi psi xi : 'CF(G)).
Local Notation "''1_' A" := (cfun_indicator G A).

(* Specifications: *)
Lemma cfun0 phi x : x \notin G -> phi x = 0.
Lemma support_cfuni A : A <| G -> support '1_A =i A.
Lemma exp_cfunE phi n x : x \in G -> (phi ^+ n) x = phi x ^+ n.
Lemma cfun_classE x y : '1_(x ^: G) y = ((x \in G) && (y \in x ^: G))%:R.
Lemma cfun_on_sum A :
'CF(G, A) = (\sum_(xG in classes G | xG \subset A) <['1_xG]>)%VS.
Lemma cfun_onP A phi :
reflect (forall x, x \notin A -> phi x = 0) (phi \in 'CF(G, A)).