#############################################################################
##
#A  genVortho            CHEVIE library          Meinolf Geck & Frank L"ubeck
##
#Y  Copyright 1992--1993,  Lehrstuhl D f"ur Mathematik,    RWTH Aachen,   and
#Y                         IWR   der   Universit"at    Heidelberg,   Germany.
##
####################################################################
##
##  Norm(t,i)
##  Norm(t,l)
##  Norm(t)
## 
Norm:=proc(t)
  local cl,nr,n1,n2,ct,w,tt,erg,ll,i,Summe;
  nr:=tablenumber(t);
  if nargs = 1 then 
    ll := [$ 1..t[-2,2]];
  elif nargs = 2 then 
    ll := makelist(args[2]);
  else
    ERROR(`Wrong number of arguments`);
  fi;
  if nargs=2 and type(args[2], integer) then
    i := ll[1];
    NENNER:={};
    cl:=t[-2,4];
    if NurPolynom.nr=true then
      n1:=0;
      for ct to cl do
        n1:=n1+t[i,ct]^2*t[0,ct]*KlassentypOrd.nr[ct];
      od;
      RETURN([factor(n1/t[-2,1]),{}]);
    else
      setCongruence.nr();
      n1:=[[],[[1,0,1]]];
      for ct to cl do
        if t[i,ct]<>0 then
          w:=GEW2qscew(t[i,ct]);
          tt:=malqscew(w,conjqscew(w));
          n2:=Klassen.nr.Summe.ct(tt);
          n2:=smalqscew(t[0,ct],n2);
          n1:=addqscew(n1,n2);
        fi;
      od;
      NENNER:=verkleinere(NENNER);
      erg:=qscew2GEW(n1)/expand(t[-2,1]);
      unsetCongruence.nr();
      RETURN([normal(eval(erg),expanded),map(normal,NENNER)]);
    fi;
  else 
    for i in ll do
      erg:=Norm(t,i);
      if NENNER<>{} then
        lprint(`Possible Exceptions:  `,erg[2]);
      fi;
      lprint(`Norm_`.t.`(`.i.`)=`);
      print(erg[1]);
      lprint();
    od;
    RETURN(NULL);
  fi;
end:



####################################################################
##
##  Scalar(t1,i1,t2,i2)
##  Scalar(t1,ll1,t2,ll2)
##  Scalar(t1,ll1,t2)
##  Scalar(t1,ll1)
##  Scalar(t1,t2)
##  Scalar(t1)
## 
Scalar:=proc(t1)
  local cl,nr,s1,s2,ct,w1,w2,tt,erg,ll1,t2,ll2,`1`,`2`,Summe,i,j;
  nr:=tablenumber(t1);
  if nargs=4 then
    ll1:=makelist(args[2]);
    if nr=tablenumber(args[3]) then
      t2:=args[3];
    else
      ERROR(`Tables must have the same "tablenumber"`);
    fi;
    ll2:=makelist(args[4]);
  elif nargs=3 then
    ll1:=makelist(args[2]);
    if nr=tablenumber(args[3]) then
      t2:=args[3];
    else
      ERROR(`Tables must have the same "tablenumber"`);
    fi;
    ll2:=[$ 1..t2[-2,2]];
  elif nargs=2 and type(args[2], array) then
    if nr=tablenumber(args[2]) then
      t2:=args[2];
    else
      ERROR(`Tables must have the same "tablenumber"`);
    fi;
    ll1:=[$ 1..t1[-2,2]];
    ll2:=[$ 1..t2[-2,2]];
  elif nargs=2 then
    ll1:=makelist(args[2]);
    t2:=t1;
    ll2:=[$ 1..t2[-2,2]];
  elif nargs=1 then
    ll1:=[$ 1..t1[-2,2]];
    t2:=t1;
#    ll2:=[$ 1..t2[-2,2]];
  else
    ERROR(`Wrong arguments`);
  fi;
  
  if nargs=4 and type(args[2], integer) and 
                         type(args[4], integer) then
    i:=ll1[1];
    j:=ll2[1];                     
    NENNER:={};
    cl:=t1[-2,4];
    if NurPolynom.nr=true then
      s1:=0;
      for ct to cl do
        s1:=s1+t1[i,ct]*t2[j,ct]*t1[0,ct]*KlassentypOrd.nr[ct];
      od;
      RETURN([factor(s1/t1[-2,1]),{}]);
    fi;
    setCongruence.nr();
    s1:=[[],[[1,0,1]]];
    for ct to cl do
      if t1[i,ct]<>0 and t2[j,ct]<>0 then
        w1:=GEW2qscew(parameter.nr(t1[i,ct],`1`,``));
        w2:=GEW2qscew(parameter.nr(t2[j,ct],`2`,``));
        tt:=malqscew(w1,conjqscew(w2));
        if tt[1]<>[] then
          s2:=Klassen.nr.Summe.ct(tt);
          s2:=smalqscew(t1[0,ct],s2);
          s1:=addqscew(s1,s2);
        fi;
      fi;
    od;
    NENNER:=verkleinere(NENNER);
    erg:=qscew2GEW(s1)/expand(t1[-2,1]);
    unsetCongruence.nr();
    RETURN([normal(eval(erg),expanded),map(normal,NENNER)]);
  elif nargs=1 then
    for i in ll1 do 
      for j to i do
        erg:=Scalar(t1,i,t2,j);
        if NENNER<>{} then
          lprint(`Possible Exceptions:  `,erg[2]);
        fi;
        lprint(`Scalar_`.t1.`,`.t2.`(`.i.`,`.j.`)=`);
        print(erg[1]);
        lprint();
      od;
    od;
    RETURN(NULL);
  else
    for i in ll1 do 
      for j in ll2 do
        erg:=Scalar(t1,i,t2,j);
        if NENNER<>{} then
          lprint(`Possible Exceptions:  `,erg[2]);
        fi;
        lprint(`Scalar_`.t1.`,`.t2.`(`.i.`,`.j.`)=`);
        print(erg[1]);
        lprint();
      od;
    od;
    RETURN(NULL);
  fi;
end:


####################################################################
##
##  Ortho2Norm(t,i)
##  Ortho2Norm(t,l)
##  Ortho2Norm(t)
## 
Ortho2Norm:=proc(t)
  local nr,n1,n2,ct,w,tt,erg,ll,i,Summe,ch;
  nr:=tablenumber(t);
  if nargs = 1 then 
    ll := [$ 1..t[-2,4]];
  elif nargs = 2 then 
    ll := makelist(args[2]);
  else
    ERROR(`Wrong number of arguments`);
  fi;
  if nargs=2 and type(args[2], integer) then
    i := ll[1];
    NENNER:={};
    ch:=t[-2,2];
    setCongruence.nr();
    n1:=[[],[[1,0,1]]];
    for ct to ch do
      if t[ct,i]<>0 then
        w:=GEW2qscew(t[ct,i]);
        tt:=malqscew(w,conjqscew(w));
        n2:=Char.nr.Summe.ct(tt);
        if n2[1]<>[] then
          n1:=addqscew(n1,n2);
        fi;
      fi;
    od;
    NENNER:=verkleinere(NENNER);
    erg:=qscew2GEW(n1)*expand(t[0,i])/expand(t[-2,1]);
    unsetCongruence.nr();
    RETURN([normal(eval(erg),expanded),map(normal,NENNER)]);
  else 
    for i in ll do
      erg:=Ortho2Norm(t,i);
      if NENNER<>{} then
        lprint(`Possible Exceptions:  `,erg[2]);
      fi;
      lprint(`Ortho2Norm_`.t.`(`.i.`)=`);
      print(erg[1]);
      lprint();
    od;
    RETURN(NULL);
  fi;
end:

####################################################################
##
##  Ortho2Scalar(t1,i1,t2,i2)
##  Ortho2Scalar(t1,ll1,t2,ll2)
##  Ortho2Scalar(t1,ll1,t2)
##  Ortho2Scalar(t1,ll1)
##  Ortho2Scalar(t1,t2)
##  Ortho2Scalar(t1)
## 
Ortho2Scalar:=proc(t1)
  local nr,s1,s2,ct,w1,w2,tt,erg,
        ll1,t2,ll2,`1`,`2`,Summe,ch,i, j;
  nr:=tablenumber(t1);
  if nargs=4 then
    ll1:=makelist(args[2]);
    if nr=tablenumber(args[3]) then
      t2:=args[3];
    else
      ERROR(`Tables must have the same "tablenumber"`);
    fi;
    ll2:=makelist(args[4]);
  elif nargs=3 then
    ll1:=makelist(args[2]);
    if nr=tablenumber(args[3]) then
      t2:=args[3];
    else
      ERROR(`Tables must have the same "tablenumber"`);
    fi;
    ll2:=[$ 1..t2[-2,4]];
  elif nargs=2 and type(args[2], array) then
    if nr=tablenumber(args[2]) then
      t2:=args[2];
    else
      ERROR(`Tables must have the same "tablenumber"`);
    fi;
    ll1:=[$ 1..t1[-2,4]];
    ll2:=[$ 1..t2[-2,4]];
  elif nargs=2 then
    ll1:=makelist(args[2]);
    t2:=t1;
    ll2:=[$ 1..t2[-2,4]];
  elif nargs=1 then
    ll1:=[$ 1..t1[-2,4]];
    t2:=t1;
#    ll2:=[$ 1..t2[-2,4]];
  else
    ERROR(`Wrong arguments`);
  fi;
  
  if nargs=4 and type(args[2], integer) and 
                         type(args[4], integer) then
    i:=ll1[1];
    j:=ll2[1];                     
    NENNER:={};
    ch:=t1[-2,2];
    setCongruence.nr();
    s1:=[[],[[1,0,1]]];
    for ct to ch do
      w1:=GEW2qscew(parameter.nr(t1[ct,i],``,`1`));
      w2:=GEW2qscew(parameter.nr(t2[ct,j],``,`2`));
      tt:=malqscew(w1,conjqscew(w2));
      if tt[1]<>[] then
        s2:=Char.nr.Summe.ct(tt);
        if s2[1]<>[] then
          s1:=addqscew(s1,s2);
        fi;
      fi;
    od;
    NENNER:=verkleinere(NENNER);
    erg:=qscew2GEW(s1)*expand(t1[0,i])/expand(t1[-2,1]);
    unsetCongruence.nr();
    RETURN([normal(eval(erg),expanded),map(normal,NENNER)]);
  elif nargs=1 then
    for i in ll1 do 
      for j to i do
        erg:=Ortho2Scalar(t1,i,t2,j);
        if NENNER<>{} then
          lprint(`Possible Exceptions:  `,erg[2]);
        fi;
        lprint(`Ortho2Scalar_`.t1.`,`.t2.`(`.i.`,`.j.`)=`);
        print(erg[1]);
        lprint();
      od;
    od;
    RETURN(NULL);
  else
    for i in ll1 do 
      for j in ll2 do
        erg:=Ortho2Scalar(t1,i,t2,j);
        if NENNER<>{} then
          lprint(`Possible Exceptions:  `,erg[2]);
        fi;
        lprint(`Ortho2Scalar_`.t1.`,`.t2.`(`.i.`,`.j.`)=`);
        print(erg[1]);
        lprint();
      od;
    od;
    RETURN(NULL);
  fi;
end:

####################################################################
##
##   ClassMult(t,i,j,k)
##   ClassMult(t,ll1,ll2,ll3)
##   ClassMult(t,ll1,ll2)
##   ClassMult(t,ll1)
##   ClassMult(t)
## 
ClassMult:=proc(t)
   local ch,nr,c1,c2,w1,w2,w3,tt,ct,erg,
         ll1,ll2,ll3,i,j,k,`1`,`2`,`3`,Summe;
   nr:=tablenumber(t);
   if nargs=4 then
     ll1:=makelist(args[2]);
     ll2:=makelist(args[3]);
     ll3:=makelist(args[4]);
   elif nargs=3 then
     ll1:=makelist(args[2]);
     ll2:=makelist(args[3]);
     ll3:=[$ 1..t[-2,4]];
   elif nargs=2 then
     ll1:=makelist(args[2]);
     ll2:=[$ 1..t[-2,4]];
     ll3:=[$ 1..t[-2,4]];
   elif nargs=1 then
     ll1:=[$ 1..t[-2,4]];
     ll2:=[$ 1..t[-2,4]];
     ll3:=[$ 1..t[-2,4]];
   fi;
   if nargs=4 and type(args[2], integer) and
                  type(args[3], integer) and
                  type(args[4], integer)    then
     i:=ll1[1];
     j:=ll2[1];
     k:=ll3[1];
     NENNER:={};
     ch:=t[-2,2];
     setCongruence.nr();
     c1:=[[],[[1,0,1]]];
     for ct to ch do
       w1:=GEW2qscew(parameter.nr(t[ct,i],``,`1`));
       w2:=GEW2qscew(parameter.nr(t[ct,j],``,`2`));
       w3:=GEW2qscew(parameter.nr(t[ct,k],``,`3`));
       tt:=malqscew(w1,w2);
       tt:=malqscew(tt,conjqscew(w3));
       if tt[1]<>[] then
         c2:=Char.nr.Summe.ct(tt);
         if c2[1]<>[] then
           c1:=addqscew(c1,smalqscew(normal(t[-2,1]/t[ct,0]), c2));
         fi;
       fi;
     od;
     NENNER:=verkleinere(NENNER);
     erg:=qscew2GEW(c1)*expand(t[0,i]*t[0,j])/expand(t[-2,1]^2);
     unsetCongruence.nr();
     RETURN([normal(eval(erg),expanded),map(normal,NENNER)]);
   else
     for i in ll1 do 
       for j in ll2 do
         for k in ll3 do
           erg:=ClassMult(t,i,j,k);  
           if NENNER<>{} then
             lprint(`Possible Exceptions:  `,erg[2]);
           fi;
           lprint(`ClassMult_`.t.`(`.i.`,`.j.`,`.k.`)=`);
           print(erg[1]);
           lprint();
         od;
       od;
     od;
     RETURN(NULL);
   fi;
end:

