#include "def.h"
#include "macro.h"
#ifdef DGTRUE
/* Darstellungen werden benoetigt */

#define ALLOCOFFSET 0
#define TL_calloc(a,b) SYM_calloc(a+ALLOCOFFSET,b)
#define TL_malloc(a) SYM_malloc(a+ALLOCOFFSET)
#define TL_free(a) SYM_free(a)

typedef signed char TL_BYTE;
typedef signed short TL_2BYTE;

static INT _assoziiere(TL_BYTE*, TL_BYTE*, INT);
static INT _ber_idx_pelem(INT, INT, INT, INT*);
static INT _ber_inx_dec(OP, INT*);
static INT darmod(TL_BYTE*, INT, TL_BYTE*, INT, INT*, TL_BYTE*, TL_BYTE**);
static INT fak(INT);
static INT homtestp(TL_BYTE**, INT, INT, INT);
static INT idmat(TL_BYTE*, INT);
static INT k_dimmod(TL_BYTE*, INT, INT);
static INT lmatmulp(TL_BYTE*, TL_BYTE*, INT, INT);
static INT matcopy(TL_BYTE*, TL_BYTE*, TL_BYTE);
static INT nexgitt(TL_BYTE*, TL_BYTE*, INT*);
static INT rmatmulp(TL_BYTE*, TL_BYTE*, INT, INT);


static inline INT TL_MOD(INT a, INT b)
{
    INT AK_buf = a % b;
    return (AK_buf < 0) ? AK_buf + b : AK_buf;
}

/* mod(a,b)=a mod b >= 0 */
#define TL_ADP(x,y,p) TL_MOD((x)+(y),(INT)p)
#define TL_MULP(x,y,p) TL_MOD(((INT)x)*((INT)y),(INT)p)
#define TL_DIVP(x,y,p) TL_MULP((x),invp((INT)y,(INT)p),(INT)p)

/*
 * Global variables
 */

static INT MAXDM = (INT)5000;
static INT ZYK = (INT)50;

static INT PZ[] = {
	(INT)2,(INT)3,(INT)5,(INT)7,(INT)11,(INT)13,(INT)17,(INT)19,(INT)23,(INT)29,(INT)31};


/*
 * Defines of possible errors
 */
#define LmbNul (INT)-10
#define LmbEmp (INT)-11
#define LmbLt_null (INT)-12
#define LmbNRg (INT)-13
#define NLe_null (INT)-14
#define NGtMax (INT)-15
#define ZzGtMx (INT)-16
#define SzGtMx (INT)-17
#define DmGtMx ((INT)-18)
#define BzNul (INT)-19
#define CntOFl (INT)-20
#define DimLe_null (INT)-21
#define DrtNul (INT)-22
#define GzlNul (INT)-23
#define NoPrm (INT)-24
#define PrmLe_null (INT)-25
#define PrmGtN (INT)-26
#define NoSolu (INT)-27
#define DDmLt_null (INT)-28
#define DDmGMx (INT)-29
#define PerNul (INT)-30
#define PerLe_null (INT)-31
#define PerGtN (INT)-32
#define PeLgGN (INT)-33
#define RTabFt (INT)-99
#define NtEMem (INT)-109


/*
 * Macros for modulararithmetic
 *
 *
 * Die Modulararithmetik berechnet Summen (adp), Produkte (mulp),
 * Inverse (invp) und Quotienten (divp) modulo p. Bei Verwendung der
 * entsprechenden Funktionen muss p als Parameter uebergeben werden.
 */

/*
 * und schliesslich globale Variablen.
*/
static INT _zeilenz;
static INT q_zeilenz;
static INT _spaltenz;
static INT _n;
static INT _zyk;
static INT COEFF(INT x, INT y, INT z)
{
	return ((z-y)%(INT)2)?(((INT)-1)*fak(x+y-(INT)2*z)*fak(z-y)*fak(z))
	    : (fak(x+y-(INT)2*z)*fak(z-y)*fak(z)) ;
}


/*
 * berechnet die Koeffizientenmatrix B zu einer Partition lambda, deren
 * Laenge gleich zwei ist. Dabei werden die Elemente der Matrix modulo pz
 * abgelegt. (Vgl. MODULKFF.C Funktion zweikonmat().)
 * Variablen:  lambda, Partition;
 *             pz, Primzahl.
 * Reuckgabe Koeffizientenmatrix bz.
 * Rueckgabewerte: >(INT)0, Dimension der gewoehnlichen irred. Darstellung;
 *              (INT)-109, falls nicht genuegend Speicher zur Verfuegung stand.
 */
static INT _k_zweikonmat(TL_BYTE *lambda, TL_BYTE *bz, INT pz)
{
	INT i,j,l,z,zaehl,mdim,dim;
	TL_BYTE *g_i,*g_j;
	TL_BYTE *start;
	TL_BYTE *_bz;
	INT g_im,g_jm;

	start=(TL_BYTE *)TL_calloc((int)_n*3,sizeof(TL_BYTE));
	if (!start) return no_memory();
	g_i=start+(INT)_n;
	g_j=g_i+(INT)_n;
	mdim=MAXDM;
	g_im=FALSE;
	if (nexgitt(start,lambda,&g_im))
	{
		SYM_free(start);
		return no_memory();
	}
	for (z=0;z<_n;g_i[z]=start[z],z++);
	_bz=bz;
	for (i=0,g_im=TRUE;g_im;i++)
	{
		for (z=0;z<_n;g_j[z]=start[z],z++);

		for (j=0,g_jm=TRUE;g_jm;j++)
		{
			for (l=0,zaehl=(INT)0;l<_n;l++)
				if (g_i[l]==(TL_BYTE)1 && g_j[l]==(TL_BYTE)1) zaehl++;
			*_bz++ = (TL_BYTE) TL_MOD( COEFF(_n,zaehl,(INT)lambda[1]) ,pz);
			if (nexgitt(g_j,lambda,&g_jm))
			{
				SYM_free(start);
				return  no_memory();
			}
		}
		if (!i)
		{
			dim=j;
			if (dim>MAXDM)
			{
				dim *= ((INT)-1);
				break;
			}
		}
		if (dim<mdim)
			mdim=dim;
		if (nexgitt(g_i,lambda,&g_im))
		{
			SYM_free(start);
			return no_memory();
		}
	}
	SYM_free(start);
	return(dim);
} /* k_zweikonmat */


/*
 * Externe Funktion der Modulararithmetik
 */

/*
 * berechnet das Inverse von z in GF(p) mit Hilfe Euklids.
 * Variablen:  z,  ganze Zahl;
 *             p,  Primzahl.
 * Rueckgabewert:  Inverses von z in GF(p).
 */
static INT invp(INT z, INT p)
{
	INT x[2],y[2],yh,i,q,r;

	x[0]=(INT)1;
	x[1]=(INT)abs(z);
	y[0]=(INT)0;
	y[1]=(INT)abs(p);
	if (x[1]<y[1])
		for (i=(INT)0;i<2L;++i)
		{
			yh=y[i];
			y[i]=x[i];
			x[i]=yh;
		}
	while (y[1]>(INT)0)
	{
		while ((INT)2*y[1]>x[1])
			for (i=(INT)0;i<2L;++i)
			{
				yh=y[i];
				y[i]=x[i]-y[i];
				x[i]=yh;
			}
		q=x[1]/y[1];
		r=x[1]%y[1];
		yh=y[0];
		y[0]=x[0]-q*y[0];
		x[0]=yh;
		x[1]=y[1];
		y[1]=r;
	}
	x[0]= z<(INT)0 ? -x[0] : x[0];
	return(((z=(x[0]%p))<(INT)0) ? z+p : z);
}


/*
 * Interne makros zur modulararithmetik
 */
#define IND(a,b,c) ((INT)(a)*(INT)(c)+(b))
#define INDEX(x) ZYK/2+x


/*
 * Funktionen fuer Mengenoperationen ...
 *
 * Mengen sind Felder a mit Eintraegen a[i]:
 * Element i nicht enthalten => a[i]=0
 * Element i enthalten => a[i]=1
 */


/*
 * errechnet das Minimum der Menge a.
 * Rueckgabewerte: Elementnummer m, falls m Minimum ist;
 *                 -1L, falls kein Minimum existiert.
 */
static INT setmin(TL_BYTE *a)
{
	TL_BYTE *_a;
	INT m;

	for (m=(INT)0,_a=a;m<_n;m++,_a++)
		if (*_a)
			return(m);
	return(-1L);
}


/*
 * ueberprueft, ob Menge a Teilmenge von Menge b ist.
 * Rueckgabewerte: TRUE, falls a Teilmenge von b ist;
 *                 FALSE, falls a nicht Teilmenge von b ist.
 */
static INT a_teilmenge_b(TL_BYTE *a, TL_BYTE *b)
{
	TL_BYTE *_a,*_b;
	INT m;

	for (m=(INT)0,_a=a,_b=b;m<_n;m++,_a++,_b++)
		if (*_a)
		{
			if (! *_b)
				return(FALSE);
		}
	return(TRUE);
}


/*
 * ueberprueft, ob die Menge a leer ist.
 * Rueckgabewerte: TRUE, falls a leer ist;
 *                FALSE, falls a nicht leer ist.
 */
static INT leer(TL_BYTE *a)
{
	INT m;

	for (m=(INT)0;m<_n;m++,a++)
		if (*a)
			return (FALSE);
	return (TRUE);
}


/*
 * berechnet die Menge a\b.
 * Rueckgabe Menge c = a\b.
 */
static INT a_ohne_b_gl_c(TL_BYTE *a, TL_BYTE *b, TL_BYTE *c)
{
	INT m;

	for (m=(INT)0;m<_n;m++,a++,b++,c++)
	{
		if (*b)
			*c = (TL_BYTE)0;
		else
			*c = *a;
	}
	return OK;
}



/*
 * Funktionen fuer die Bestimmung der Koeffizientenmatrix (B,C_eins,C_zwei)...
 *
 */


/*
 * berechnet Schnittmatrix zykmt in Abhaengigkeit von der Permutation perm.
 * Rueckgabewerte: (INT)0, falls alles ohne Fehler durchgefuehrt werden konnte;
 *             (INT)-109, falls nicht genuegend Speicher zu Verfuegung steht.
 * Rueckgabe Schnittmatrix zykmt.
 */
static INT zykschnitt(TL_BYTE *t_eins, TL_BYTE *t_zwei, TL_BYTE *perm, TL_BYTE *zykmt)
{
	INT i,j;
	TL_BYTE *zeile,*z;
	INT enthalten;

	zeile=(TL_BYTE *)TL_calloc((int)_n*(int)_n,sizeof(TL_BYTE));
	if (!zeile) return no_memory();
	for (i=q_zeilenz,z=zykmt;i>(INT)0;i--,*z++ = (INT)0);
	/* Berechnung der Zeilenziffernmengen von (perm)T2: */
	for (i=_n-1L;i>=(INT)0;--i)
		zeile[IND(t_zwei[i],perm[i]-1L,_n)]=1L;
	for (j=(INT)0;j<_n;++j)
	{
		enthalten=FALSE;
		i=(INT)0;
		do
		{
			if (zeile[IND(i,j,_n)])
			{
				++zykmt[IND(t_eins[j],i,_zeilenz)];
				enthalten=TRUE;
			}
			else
				++i;
		} while (!enthalten);
	}
	SYM_free(zeile);
	return (INT)0;
}



/*
 * bestimmt, falls moeglich, paarweise verschiedene Ziffern i_eins,i2L,...,ilambda1L,
 * welche die injektive erste Zeile eines Elementes von [Ts]c darstellen.
 * (Weitere Erlaeuterung in:
 *   Golembiowski, Andreas
 *     Zur Berechnung modular irreduzibler Matrixdarstellungen symmetrischer
 *     Gruppen mit Hilfe eines Verfahrens von M.Clausen
 *   Bayreuther Mathematische Schriften Heft 25L, Bayreuth 1987
 *   SS. 162ff)
 * Variablen:  la, Teil der konjugierten Partition;
 *             zmat, Schnittmatrix.
 * Rueckgabewerte: (INT)-109, falls kein Speicher zur Verfuegung stand;
 *                     (INT)0, sonst.
 * Rueckgabe Matrix fln.
 */
static INT inzeil(INT la, TL_BYTE *zmat, TL_BYTE *fln)
{
	INT i,i_eins,j,j_eins,r,k,m,oz;
	TL_BYTE **xm,**qu,*ze[2],*un,*hilf;

	xm=(TL_BYTE **)TL_calloc((int)(_zeilenz+_zeilenz+2L),sizeof(TL_BYTE *));
	if (!xm)
		return no_memory();
	qu=xm+(INT)_zeilenz+1L;
	hilf=(TL_BYTE *)TL_calloc((int)(_zeilenz+_zeilenz+6L)*(INT)_n,sizeof(TL_BYTE));
	if (!hilf)
	{
		SYM_free(xm);
		return no_memory();
	}
	un=hilf+(INT)_n;
	ze[0]=un+(INT)_n;
	ze[1]=ze[0]+(INT)_n;
	xm[0]=ze[1]+(INT)_n;
	for (i=1L;i<=_zeilenz;xm[i]=xm[i-1]+(INT)_n,i++);
	qu[0]=xm[_zeilenz]+(INT)_n;
	for (i=1L;i<=_zeilenz;qu[i]=qu[i-1]+(INT)_n,i++);
	for (j=(INT)0;j<la;fln[j++]= (TL_BYTE) -1);
	i=(INT)0;
	while (fln[0]<(INT)0)
		if (zmat[IND(i,(INT)0,_zeilenz)])
			fln[0]=i;
		else
			++i;
	ze[0][fln[0]]=(TL_BYTE)1;
	ze[1][0]=(TL_BYTE)1;
	r=1L;
	while (r<la)
	{
		for (m=(INT)0;m<la;xm[0][m]=(ze[0][m]?(TL_BYTE)0:(TL_BYTE)1), m++);
		for (m=(INT)0;m<_n;qu[0][m]=(TL_BYTE)0,m++);
		for (j=(INT)0;j<la;++j)
		{
			i=(INT)0;
			oz=(INT)0;
			while (!oz && i<la)
				if (xm[0][i] && zmat[IND(i,j,_zeilenz)])
				{
					qu[0][j]=(TL_BYTE)1;
					oz=1L;
				}
				else
					++i;
		}
		for (m=(INT)0;m<_n;un[m]=qu[0][m],m++);
		k=(INT)0;
		while (a_teilmenge_b(qu[k],ze[1]) && (oz!=2L))
		{
			++k;
			for (m=(INT)0;m<_n;xm[k][m]=(TL_BYTE)0,m++);
			for (j=(INT)0;j<la;++j)
				if (qu[k-1][j])
					xm[k][fln[j]]=1L;
			for (m=(INT)0;m<_n;qu[k][m]=(INT)0,m++);
			for (j=(INT)0;j<la;++j)
			{
				for (m=0;m<la;m++)
					if (un[m] == 0)
						hilf[m]=1;
					else
						hilf[m]=0;
				if (hilf[j])
				{
					i=(INT)0;
					oz=(INT)0;
					while (!oz && i<la)
						if ((xm[k][i]) && (zmat[IND(i,j,_zeilenz)]))
						{
							qu[k][j]=(TL_BYTE)1;
							oz=1L;
						}
						else
							++i;
				}
			}
			if (leer(qu[k]))
			{
				oz=2L;
				fln[0]= -1L;
			}
			else
				for (m=(INT)0;m<_n;++m)
					if (qu[k][m])
						un[m]=1L;
		}
		if (oz!=2L)
		{
			a_ohne_b_gl_c(qu[k],ze[1],hilf);
			j_eins=setmin(hilf);
			ze[1][j_eins]=(TL_BYTE)1;
			++r;
			i_eins=(INT)0;
			while (fln[j_eins]<(INT)0)
				if (xm[k][i_eins] && zmat[IND(i_eins,j_eins,_zeilenz)])
					fln[j_eins]=i_eins;
				else
					++i_eins;
			while (k>=1L)
			{
				for (j=(INT)0;fln[j]!=i_eins || j==j_eins;j++);
				j_eins=j;
				i=(INT)0;
				while (fln[j_eins]==i_eins)
					if (xm[k-1][i] && zmat[IND(i,j_eins,_zeilenz)])
						fln[j_eins]=i;
					else
						++i;
				i_eins=i;
				--k;
			}
			ze[0][i_eins]=(TL_BYTE)1;
		}
		else
			r=la;
	}
	SYM_free(hilf);
	SYM_free(xm);
	return((INT)0);
}


/*
 * berechnet Menge der Zyklen (j_null j_eins ... jk).
 * (Weitere Erlaeuterung in:
 *   Golembiowski, Andreas
 *     Zur Berechnung modular irreduzibler Matrixdarstellungen symmetrischer
 *     Gruppen mit Hilfe eines Verfahrens von M.Clausen
 *   Bayreuther Mathematische Schriften Heft 25L, Bayreuth 1987
 *   SS. 166ff)
 * Variablen:  la, Element der konjugierten Partition;
 *             j_zwei, erstes Element des Zykels;
 *             xm, Mengen.
 * Rueckgabewerte: (INT)-109, nicht genug Speicher;
 *                     (INT)0, sonst.
 * Rueckgabe Vektor zh.
 */
static INT j_zyk(INT la, INT j_zwei, TL_BYTE **xm, TL_BYTE *zh)
{
	INT i,k,l,nr,m;
	static TL_BYTE *j=NULL;
	static TL_BYTE *ym=NULL,*hilf=NULL,**xm_eins=NULL;
	static INT old_z = (INT)-1;

	if (la == (INT)-15) {
		if (j != NULL) {
			SYM_free(j);
			j = NULL;
		}
		if (xm_eins != NULL) {
			SYM_free(xm_eins);
			xm_eins = NULL;
		}
		old_z = (INT)-1;
		return (INT)0;
	}

	if (old_z < _zeilenz) {
		if (j != NULL) SYM_free(j);
		if (xm_eins != NULL) SYM_free(xm_eins);
		j=(TL_BYTE *)TL_calloc((int)_zeilenz+1
		    + (int)(_zeilenz+2L)*(int)_n ,sizeof(TL_BYTE));
		xm_eins=(TL_BYTE **)
		    TL_calloc((int)_zeilenz,sizeof(TL_BYTE *));

		if (!j)
			return no_memory();
		if (!xm_eins)
		{
			SYM_free(j);
			return no_memory();
		}

		hilf = j + (int)_zeilenz+1;
		ym=hilf+_n;
		xm_eins[0]=ym+_n;
		for (i=1L;i<_zeilenz;xm_eins[i]=xm_eins[i-1]+_n,i++);
		old_z = _zeilenz;

	}
	j[0]=j_zwei;


	memset(&zh[INDEX(-la)],0,(ZYK+la+1) * sizeof(TL_BYTE) );

	if (la >= ZYK) error("internal error MO-5");
	for (i= 0;i<la;++i)
		memcpy(xm_eins[i],xm[i],_n * sizeof(TL_BYTE));

	l=(INT)0;
	nr=1L;
	while (!leer(xm_eins[j_zwei]))
	{
		for (m=(INT)0;m<_n;ym[m++]=(INT)0);
		k=1L;
		do
		{
			a_ohne_b_gl_c(xm_eins[j[k-1]],ym,hilf);
			j[k]=setmin(hilf);
			if (xm_eins[j[k]][j[0]])
			{
				++nr;
				zh[INDEX(-nr)]=l+1L;
				++zh[INDEX(-1L)];
				if (l==(INT)0)
					zh[INDEX(0)]=k+1L;
				else if ((k+1L)<(zh[INDEX(0)]))
					zh[INDEX(0)]=k+1L;
				zh[INDEX(l+1L)]=k+1L;
				zh[INDEX(l+2L)]=j[0]+1L;
				for (i=k+1L;i>=2L;--i)
					zh[INDEX(l+k+4-i)]=j[i-1]+1L;
				l=l+k+3L;
			}
			ym[j[k-1]]=1L;
			a_ohne_b_gl_c(xm_eins[j[k]],ym,hilf);
			if (!leer(hilf))
				++k;
			else
			{
				while (leer(hilf) && (k>=1L))
				{
					xm_eins[j[k-1]][j[k]]=(INT)0;
					ym[j[k]]=(INT)0;
					for (m=(INT)0;m<_n;xm_eins[j[k]][m]=xm[j[k]][m],m++);
					--k;
					a_ohne_b_gl_c(xm_eins[j[k]],ym,hilf);
				}
				if (k>=1L)
					++k;
			}
		} while (k);
	}
	return((INT)0);
}


/*
 * initialisiert Felder, die im Unterprogramm j_zyk benoetigt werden, und ruft
 * j_zyk auf.
 * (Weitere Erlaeuterung in:
 *   Golembiowski, Andreas
 *     Zur Berechnung modular irreduzibler Matrixdarstellungen symmetrischer
 *     Gruppen mit Hilfe eines Verfahrens von M.Clausen
 *   Bayreuther Mathematische Schriften Heft 25L, Bayreuth 1987
 *   SS. 168ff)
 * Variablen:  la, Element der konjugierten Partition;
 *             zmat, Schnittmatrix;
 *             fln, Matrix aus inzeil.
 * Rueckgabewerte: (INT)-109,  nicht genug Speicher;
 *     (INT)0,  sonst.
 * Rueckgabe Matrix aller Zyklen.
 */
static INT k_alzyk(INT la, TL_BYTE *zmat, TL_BYTE *fln, TL_BYTE *cy)
{
	INT i,j_eins,j_zwei,m;
	TL_BYTE *zh;
	TL_BYTE *z_eins,*z_zwei;
	TL_BYTE **xm;

	xm=(TL_BYTE **)TL_calloc((int)_zeilenz,sizeof(TL_BYTE *));
	if (!xm)
		return no_memory();
	xm[0]=(TL_BYTE *)TL_calloc((int)_zeilenz*(int)_n,sizeof(TL_BYTE));
	if (!xm[0])
	{
		SYM_free(xm);
		return no_memory();
	}
	zh=(TL_BYTE *)TL_calloc((int)_zyk,sizeof(TL_BYTE));
	if (!zh)
	{
		SYM_free(xm[0]);
		SYM_free(xm);
		return no_memory();
	}
	for (i=1L;i<_zeilenz;xm[i]=xm[i-1]+_n,i++);
	for (j_eins=(INT)0,z_eins=zmat;j_eins<la;j_eins++,z_eins++)
	{
		j_zwei=fln[j_eins];
		for (m=(INT)0;m<_n;(xm[j_zwei])[m++]=(TL_BYTE)0);
		for (i=(INT)0,z_zwei=z_eins;i<la;i++,z_zwei += _zeilenz)
			if (*z_zwei && (i!=j_zwei))
				xm[j_zwei][i]=1L;
	}
	for (j_eins=(INT)0;j_eins<la;++j_eins)
	{
		j_zwei=fln[j_eins];
		if (j_zyk(la,j_zwei,xm,zh))
		{
			SYM_free(xm[0]);
			SYM_free(xm);
			SYM_free(zh);
			return no_memory();
		}

		memcpy(&cy[IND(j_zwei,(INT)0,_zyk)],
		    &zh[INDEX(-(ZYK/2L))],
		    sizeof(TL_BYTE)*(ZYK+ZYK/2 + 1));
		for (m=(INT)0;m<_n;xm[j_zwei][m++]=(INT)0);
	}
	SYM_free(xm[0]);
	SYM_free(xm);
	SYM_free(zh);
	j_zyk((INT) -15,0,NULL,NULL);
	return((INT)0);
}


/*
 * ruft inzeil und k_alzyk koordiniert auf.
 * Variablen:  la, Element der konjugierten Partition;
 *             zmat, Schnittmatrix.
 * Rueckgabewerte: (INT)-109, nicht genug Speicher;
 *                     (INT)0, sonst.
 * Rueckgabe Matrix cy aller Zyklen und Matrix fln paarweise verschiedene
 *     Ziffern i_eins,...,ilambda1.
 */
static INT alzyk(INT la, TL_BYTE *zmat, TL_BYTE *fln, TL_BYTE *cy)
{
	if (inzeil(la,zmat,fln))
		return no_memory();
	if (fln[0]>=(INT)0)
	{
		if (k_alzyk(la,zmat,fln,cy))
			return no_memory();
	}
	return((INT)0);
}


/*
 * berechnet sgn(fln).
 * Variablen:  fln, gewisses pi* aus inzeil;
 *             la, Element aus konjugierter Partition.
 * Rueckgabewert:  (INT)-109, falls nicht genuegend Speicher;
 *                signum, sonst.
*/
static INT sigper(TL_BYTE *fln, TL_BYTE la)
{
	TL_BYTE *hilf;
	INT i,j,k,l,v;

	hilf=(TL_BYTE *)TL_calloc((int)_zeilenz,sizeof(TL_BYTE));
	if (!hilf)
		return no_memory();
	for (i=(INT)0;i<_zeilenz;hilf[i]=fln[i],i++);
	v=1L;
	for (i=(INT)0;i<la;++i)
		if ((hilf[i]>=(INT)0) && (hilf[i]!=i))
		{
			l=1L;
			j=hilf[i];
			while (j>=(INT)0 && hilf[j]!=i)
			{
				++l;
				k=hilf[j];
				hilf[j]= -1L;
				j=k;
			}
			if (j>=(INT)0) /* AK 030194 */
				hilf[j]= -1L;
			if (l%2L)
				v *= (-1L);
		}
	SYM_free(hilf);
	return(v);
}


/*
 * berechnet einen Faktor des Koeffizienten zur Schnittmatrix mat.
 * (Weitere Erlaeuterung in:
 *   Golembiowski, Andreas
 *     Zur Berechnung modular irreduzibler Matrixdarstellungen symmetrischer
 *     Gruppen mit Hilfe eines Verfahrens von M.Clausen
 *   Bayreuther Mathematische Schriften Heft 25L, Bayreuth 1987
 *   SS. 170ff)
 * Variablen:  mat, Schnittmatrix;
 *             slambda, konjugierte Partition;
 *             li, Element aus slambda.
 * Rueckgabewerte: (INT)-108, falls Resttableau falsch;
 *                 (INT)-109, falls nicht genug Speicher;
 *                     (INT)0, sonst.
 * Rueckgabe Koeffizientenfaktor tsc.
 */
static INT symdet(TL_BYTE *mat, TL_BYTE *slambda, INT li, INT *tsc)
{
	TL_BYTE *cy,*pi,*zmat,*fln,*hfl,*afl,*ii,*z;
	INT lpi,i,j,k,l,d,la,_li,signum,bv,ik,r,err;
	TL_BYTE *piset,*mpi,*zm;

	_li=li;
	la=slambda[_li];
	++_li;
	if (la==1L)
	{
		if (mat[0]==(_spaltenz-_li+1L))
		{
			*tsc=1L;
			return((INT)0);
		}
		else
		{
			*tsc=(INT)0;
			return((INT)0);
		}
	}
	cy=(TL_BYTE *)TL_calloc((int)_zeilenz*((int)_zyk+2*(int)_zeilenz+5),
	    sizeof(TL_BYTE));
	if (!cy)  return no_memory();
	mpi=(TL_BYTE *)TL_calloc((int)q_zeilenz+(int)_zeilenz,sizeof(TL_BYTE));
	if (!mpi)
	{
		SYM_free(cy);
		return no_memory();
	}
	pi=cy+_zeilenz*_zyk;
	zmat=pi+_zeilenz*(_zeilenz+1L);
	fln=zmat+q_zeilenz;
	hfl=fln+_zeilenz;
	afl=hfl+_zeilenz;
	ii=afl+_zeilenz;
	piset=mpi+_zeilenz;
	*tsc=(INT)0;
	matcopy(zmat,mat,_zeilenz);
	if (alzyk(la,zmat,fln,cy))
	{
		SYM_free(cy);
		SYM_free(mpi);
		return no_memory();
	}
	if (fln[0]>=(INT)0)
	{
		for (r=(INT)0;r<_zeilenz;afl[r]=fln[r],r++);
		signum=sigper(fln,la);
		bv= *tsc;
		if (_li == _spaltenz)
			*tsc=signum;
		else
		{
			for (j=(INT)0;j<la;++j)
				--zmat[IND(fln[j],j,_zeilenz)];
			if ((err=symdet(zmat,slambda,_li,tsc))!=(INT)0)
			{
				SYM_free(cy);
				SYM_free(mpi);
				return(err);
			}
			*tsc *= signum;
		}
		*tsc +=  bv;
		matcopy(zmat,mat,_zeilenz);
		if (_li == _spaltenz)
		{
			SYM_free(cy);
			SYM_free(mpi);
			return((INT)0);
		}
		for (k=(INT)0,z=pi+1L;k<la;k++,z += (_zeilenz+1L))
			*z=(INT)0;
		for (r=(INT)0;r<_zeilenz;mpi[r++]=(INT)0);
		lpi=(INT)0;
		k=(INT)0;
fl111:
		if ((lpi+cy[IND(k,INDEX((INT)0),_zyk)])<=la)
		{
			ii[k]=1L;
fl100:
			if (ii[k]<=cy[IND(k,INDEX(-1L),_zyk)])
			{
				ik=ii[k];
				i=cy[IND(k,INDEX(-ik-1L),_zyk)];
				d=(INT)0;
				l=1L;
				while ((d!=1L) && (l<=cy[IND(k,INDEX(i),_zyk)]))
				{
					if (mpi[cy[IND(k,INDEX(i+1L),_zyk)]-1])
						d=1L;
					++l;
				}
				if (d==(INT)0)
				{
					for (r=(INT)0,zm= &piset[IND(k,(INT)0,_zeilenz)];r<_zeilenz;r++,zm++)
						*zm=(INT)0;
					for (j=i+1L;j<=(i+cy[IND(k,INDEX(i),_zyk)]);++j)
					{
						pi[IND(k,(INT)0,_zeilenz+1L)]=cy[IND(k,INDEX(i),_zyk)];
						pi[IND(k,j-i,_zeilenz+1L)]=cy[IND(k,INDEX(j),_zyk)];
						piset[IND(k,cy[IND(k,INDEX(j),_zyk)]-1L,_zeilenz)]=1L;
					}
					for (r=(INT)0,zm= &piset[IND(k,(INT)0,_zeilenz)];r<_zeilenz;r++,zm++)
						if (*zm)
							mpi[r]=1L;
					lpi += pi[IND(k,(INT)0,_zeilenz+1L)];
					for (r=(INT)0;r<_zeilenz;hfl[r]=fln[r],r++);
					l=pi[IND(k,(INT)0,_zeilenz+1L)];
					for (j=1L,z= &pi[IND(k,1L,_zeilenz+1L)];j<=l;j++,z++)
						for (i=(INT)0;i<la;++i)
							if (*z==fln[i]+1L)
								hfl[i]= (j==1L)?pi[IND(k,l,_zeilenz+1L)]-1
								    :pi[IND(k,j-1L,_zeilenz+1L)]-1L;
					for (r=(INT)0;r<_zeilenz;fln[r]=hfl[r],r++);
					for (j=(INT)0;j<la;++j)
						--zmat[IND(fln[j],j,_zeilenz)];
					bv= *tsc;
					if ((err=symdet(zmat,slambda,_li,tsc))!=(INT)0)
					{
						SYM_free(cy);
						SYM_free(mpi);
						return(err);
					}
					if ((l+1L)%(INT)2)
						signum *= (INT)(-1);
					*tsc = bv + signum * (*tsc);
					matcopy(zmat,mat,_zeilenz);
					if ((lpi<=(la-(INT)2)) && (k<la-1L))
					{
						++k;
						goto fl111;
					}
					else
					{
						for(r=(INT)0;r<_zeilenz;fln[r]=afl[r],r++);
						pi[IND(k,1L,_zeilenz+1L)]=(INT)0;
						for (r=(INT)0,zm= &piset[IND(k,(INT)0,_zeilenz)];r<_zeilenz;r++,zm++)
							if (*zm)
								mpi[r]=(INT)0;
						--lpi;
						if ((l+1L)%2L)
							signum *= (-1L);
						++ii[k];
						goto fl100;
					}
				}
				else
				{
					++ii[k];
					goto fl100;
				}
			}
			else
			{
				if (k<la-1L)
				{
					pi[IND(k,1L,_zeilenz+1L)]=(INT)0;
					++k;
					goto fl111;
				}
				else
					goto fl222;
			}
		}
		else
fl222:
			{
				while ((pi[IND(k-1L,1L,_zeilenz+1L)]==(INT)0) && k>1L)
					--k;
				if (pi[IND(k-1L,1L,_zeilenz+1L)])
				{
					--k;
					for (r=(INT)0;r<_zeilenz;fln[r]=afl[r],r++);
					pi[IND(k,1L,_zeilenz+1L)]=(INT)0;
					for (r=(INT)0,zm= &piset[IND(k,(INT)0,_zeilenz)];r<_zeilenz;r++,zm++)
						if (*zm)
							mpi[r]=(INT)0;
					lpi -= pi[IND(k,(INT)0,_zeilenz+1L)];
					if ((pi[IND(k,(INT)0,_zeilenz+1L)]+1L)%2L)
						signum *= (-1L);
					++ii[k];
					goto fl100;
				}
			}
	}
	SYM_free(cy);
	SYM_free(mpi);
	return((INT)0);
}


/*
 * berechnet aus der Schnittmatrix mat und Partition slambda den Koeffizienten.
 * Variablen:  mat, Schnittmatrix;
 *             slambda, konjugierte Partition zu lambda;
 * Rueckgabewerte: koeff, Koeffizient zu mat und slambda;
 *                 (INT)-108, falls ein Resttableau falsch war;
 *                 (INT)-109, falls kein Speicherplatz vorhanden war.
*/
static INT alcoeff(TL_BYTE *mat, TL_BYTE *slambda)
{
	TL_BYTE *z;
	INT i,tsc,faktor;

	faktor=symdet(mat,slambda,(INT)0,&tsc);
	if (faktor)
		return(faktor);
	if (tsc)
	{
		for (i=q_zeilenz,z=mat,faktor=1L;i>(INT)0;i--,z++)
			if (*z)
				faktor *= fak((INT) *z);
		return(faktor*tsc);
	}
	else
		return (INT)0;
}


/*
 * berechnet die Koeffizientenmatrix bz fuer Partitionen lambda der
 * Laenge 2.
 * Variablen:  lambda, eigentliche Partition;
 *             perm, Permutation.
 * Rueckgabe Koeffizientenmatrix bz.
 * Rueckgabewerte: dim, Dimension der gewoehnlichen Darstellungen, dim ist
 *                      negativ, falls dim groesser MAXDM;
 *               (INT)-109, falls kein Speicherplatz vorhanden war.
 */
static INT zweikonmat(TL_BYTE *lambda, TL_BYTE *perm, TL_BYTE *bz)
{
	INT i,j,k,l,z,zaehl[3],mdim,dim;
	TL_BYTE *hz,*g_i,*g_j,*start,*hilf_zwei,*hilf_drei,*_hz,*_bz,*z_eins;
	INT g_im,g_jm;

	start=(TL_BYTE *)TL_calloc((int)_n*5+(int)MAXDM*3,sizeof(TL_BYTE));
	if (!start)
		return no_memory();
	g_i=start+_n;
	g_j=g_i+_n;
	hilf_zwei=g_j+_n;
	hilf_drei=hilf_zwei+_n;
	hz=hilf_drei+_n;
	mdim=MAXDM;
	g_im=FALSE;
	if (nexgitt(start,lambda,&g_im))
	{
		SYM_free(start);
		return no_memory();
	}
	for (z=(INT)0;z<_n;g_i[z]=start[z],z++);
	for (i=(INT)0,g_im=TRUE;g_im;++i)
	{
		for (z=(INT)0;z<_n;g_j[z]=start[z],z++);
		for (z=3L*mdim,_hz=hz;z>(INT)0;z--,*_hz++ = (INT)0);
		for (j=(INT)0,g_jm=TRUE,_hz=hz;g_jm;j++,_hz++)
		{
			for (z=(INT)0;z<3L;zaehl[z++]=(INT)0);
			for (z=(INT)0;z<_n;hilf_zwei[z]=hilf_drei[perm[z]-1]=g_j[z],z++);
			hilf_zwei[1]=(INT)0;
			for (l=(INT)0;l<_n;++l)
				if (g_i[l]==1L)
				{
					if (g_j[l]==1L) ++zaehl[0];
					if (hilf_zwei[l]==1L) ++zaehl[1];
					if (hilf_drei[l]==1L) ++zaehl[2];
				}
			for (z=(INT)0,z_eins=_hz;z<3L;z++,z_eins += mdim)
				*z_eins=COEFF(_n,(INT)zaehl[z],(INT)lambda[1]);
			if (nexgitt(g_j,lambda,&g_jm))
			{
				SYM_free(start);
				return no_memory();
			}
		}
		if (!i)
		{
			dim=j;
			if (dim>MAXDM)
			{
				dim *= (-1L);
				break;
			}
			else
				_bz=bz;
		}
		for (z=(INT)0,_hz=hz;z<3L;z++,_hz += mdim)
			for (k=(INT)0,z_eins=_hz;k< dim;k++)
				*_bz++ = *z_eins++;
		if (dim<mdim)
			mdim=dim;
		if(nexgitt(g_i,lambda,&g_im))
		{
			SYM_free(start);
			return no_memory();
		}
	}
	SYM_free(start);
	g_im = 280194L;
	nexgitt(NULL,NULL,&g_im);
	return(dim);
}


/*
 * konjugiert die eigentliche Partition lambda mit Ergebnis lambdastrich.
 * Variablen:  lambda, eigentliche Partition.
 * Rueckgabe lambdastrich.
 */
static INT konjugiere(TL_BYTE *lambda, TL_BYTE *lambdastrich)
{
	INT i,j;

	for (i=(INT)0;i<lambda[0];++i)
	{
		for (j=(INT)0;j<_zeilenz && lambda[j]>=i+1L;++j);
		if ((j<_n) && (lambda[j] < i+1L))
			lambdastrich[i]=j;
		else
			lambdastrich[i]=_zeilenz;
	}
	return OK;
}


/*
 * berechnet Schnittmatrix zu den Tableaux t_eins und t_zwei.
 * Variablen:  t_eins, Tableau;
 *             t_zwei, Tableau.
 * Rueckgabe Schnittmatrix mat.
 */
static INT schnitt(TL_BYTE *t_eins, TL_BYTE *t_zwei, TL_BYTE *mat)
{
	TL_BYTE  *z;
	INT i;


	memset(mat,0,q_zeilenz * sizeof(TL_BYTE));

	for (i=(INT)0;i<_n;++i)
		++mat[IND(t_eins[i],t_zwei[i],_zeilenz)];
	return OK;
}

static INT tl_prime = (INT) 9973;
static INT tl_max_numb = (INT) 8;
static INT tl_index_inc = (INT) 1;
static TL_BYTE **mat_table;
static TL_2BYTE **koeff_table;
static INT *mat_length;
static INT mat_size;
INT tl_set_prime(INT p)
{
	tl_prime = p;
	return OK;
}
INT tl_set_max_numb(INT p)
{
	tl_max_numb = p;
	return OK;
}
INT tl_set_index_inc(INT p)
{
	tl_index_inc = p;
	return OK;
}

static void init_mat(void)
{
	INT i,size;
	TL_BYTE *a,*b;
	mat_table = (TL_BYTE **) TL_calloc(tl_prime,sizeof(TL_BYTE *));
	mat_length = (INT *) TL_calloc(tl_prime,sizeof(INT));
	koeff_table = (TL_2BYTE **) TL_calloc(tl_prime,sizeof(TL_2BYTE *));
	mat_size = q_zeilenz;

	size = tl_prime * tl_max_numb * (q_zeilenz +  sizeof(TL_2BYTE));
	a = (TL_BYTE *) TL_malloc(size * sizeof(TL_BYTE));
	b = a;

	for (i=(INT)0;i<tl_prime;i++)
	{
		mat_length[i] = (INT)0;
		mat_table[i] = a;
		a += (tl_max_numb * q_zeilenz );
		koeff_table[i] = (TL_2BYTE *) a;
		a += tl_max_numb * sizeof(TL_2BYTE) ;
	}
}


static void close_mat(void)
{
	INT i;
	if (mat_size != q_zeilenz) error("MO-35");
	TL_free(mat_table[0]);
	TL_free(mat_table);
	TL_free(koeff_table);
	for (i=(INT)0;i<tl_prime;i++)
	{
		mat_length[i] = (INT)0;
	}
	TL_free(mat_length);
}

static UINT offset[32] = {
	1,1<<1,1<<2,1<<3,1<<4,1<<5,1<<6,1<<7,
	1<<8,1<<9,1<<10,1<<11,1<<12,1<<13,1<<14,1<<15,
	1<<16,1<<17,1<<18,1<<19,1<<20,1<<21,1<<22,1<<23,
	1<<24,1<<25,1<<26,1<<27,1<<28,1<<29,1<<30,((UINT)1)<<31 };

static void write_mat(TL_BYTE *mat, TL_2BYTE koeff)
{
	INT i,j,k;
	UINT index=(INT)0;
	/* compute adress */

	i=(INT)0;
	if (q_zeilenz > 31)
	{
		k = q_zeilenz / 32;
		for (;k>0;k--)
			for (j=(INT)0; j<32;i+=tl_index_inc,j+=tl_index_inc)
				if (mat[i]) index += offset[j];
	}

	for (j=(INT)0; i<q_zeilenz;i+=tl_index_inc,j+=tl_index_inc)
		if (mat[i]) index += offset[j];

	index = index % tl_prime;

	if (mat_length[index] >= tl_max_numb)
	{
		mat_length[index]++;
		* (koeff_table[index]+
		    (mat_length[index] % tl_max_numb)
		    ) = koeff;
		memcpy(mat_table[index]+
		    (q_zeilenz*
		    (mat_length[index]%tl_max_numb)
		    ),
		    mat, q_zeilenz * sizeof(TL_BYTE));
	}
	else {
		mat_length[index]++;
		* (koeff_table[index]+mat_length[index]-1) = koeff;
		memcpy(mat_table[index]+
		    (q_zeilenz*(mat_length[index]-1)),
		    mat, q_zeilenz * sizeof(TL_BYTE));
	}

	return;
}


static INT search_mat(INT *co, TL_BYTE *mat, TL_2BYTE *koeff)
	{
	INT  i=(INT)0,k,j;
	UINT index=(INT)0;
	/* compute adress */

	if (q_zeilenz > 31)
	{
		k = q_zeilenz / 32;
		for (;k>0;k--)
			for (j=(INT)0; j<32;i+=tl_index_inc,j+=tl_index_inc)
				if (mat[i]) index += offset[j];
	}

	for (j=0; i<q_zeilenz;i+=tl_index_inc,j+=tl_index_inc)
		if (mat[i]) index += offset[j];

	index = index % tl_prime;
	for (i=mat_length[index]%tl_max_numb -1 ; i>=0 ; i--)
		if (memcmp(mat,(mat_table[index])+(q_zeilenz * i),
		    sizeof(TL_BYTE) * q_zeilenz) == 0)
		{
			*koeff = * (koeff_table[index] + i);
			return OK;
		}

	return -12L;
}


/*
 * ueberprueft die Schnittmatrix mat, ob mit dieser schon gerechnet wurde. Ist
 * dies der Fall, so ist der Koeffizient gleich. Ansonsten wird fuer mat der
 * neue Koeffizient berechnet.
 * Variablen:  co, Zaehler der verschiedenen Schnittmatrizen;
 *             mat, Schnittmatrix;
 *             slambda, konjugierte Partition zu lambda;
 * Rueckgabe co mit alter bzw. neuer Anzahl der verschiedenen Schnittmatrizen.
 * Rueckgabewerte: koeff,  Koeffizient zu mat und slambda;
 *                 (INT)-109,  falls nicht genuegend Speicher vorhanden ist.
 */
static INT mat_comp(INT *co, TL_BYTE *mat, TL_BYTE *slambda)
{
	INT  gefunden, i,erg;
	TL_BYTE *schnittmat  ,*z_eins,*z_zwei ,rr ;
	TL_2BYTE koeff;
	TL_BYTE *ak_buffer;
	i=1L;
	if ((*co)>(INT)0)
	{
		erg = search_mat(co,mat,&koeff);
		if (erg == OK) return koeff;
	}
	++(*co);
	koeff = alcoeff(mat,slambda);
	if (koeff==RTabFt || koeff==NtEMem)
		return(koeff);
	write_mat(mat,koeff);
	return koeff;
}


/*
 * berechnet zu einer Partition lambda und einer Permutation perm die Koeffi-
 * zientenmatrix (B|C(12)|C(perm)).
 * Variablen:  lambda, eigentliche Partition;
 *             perm, Permutation.
 * Rueckgabewerte: >(INT)0, kein Fehler aufgetreten;
 *                (INT)-10, falls Pointer auf lambda NULL ist;
 *                (INT)-11, falls lambda leer ist;
 *                (INT)-12, falls ein Element von lambda kleiner 0 ist;
 *                (INT)-13, falls lambda keine eigentliche Partition ist;
 *                // -15L, falls n > MAXN;
 *                // -16L, falls Laenge von lambda groesser MAXZEILENZ ist;
 *                // -17L, falls erstes Element von lambda groesser MAXSPALTENZ ist;
 *                (INT)-18, falls Dimension der gew. irred. Dg. >MAXDIM;
 *                (INT)-19, falls Pointer auf bz NULL ist;
 *                (INT)-20, falls sich der temporaere File nicht oeffnen laesst;
 *                (INT)-30, falls Pointer auf perm NULL ist;
 *                (INT)-31, falls Teil von perm <= 0 ist;
 *                (INT)-32, falls Teil von perm > n ist;
 *                (INT)-33, falls perm zu viele Elemente hat;
 *              (INT)-108, falls Resttableau in SYMDET falsch ist;
 *              (INT)-109, falls nicht genuegend Speicher vorhanden ist.
 *  Rueckgabe Koeffizientenmatrix bz.
 */
static INT alkonmat(TL_BYTE *lambda,TL_BYTE *perm, TL_BYTE *bz)
{
	TL_BYTE *mat,*transmt,*zykmt,*hz,*t_eins,*t_zwei;
	TL_BYTE *ht,*asslambda,*_hz,*_bz,*z_eins;
	INT ii,jj,kk,i,k,z,co = (INT)0,co_eins,co_zwei,dim,diag,mdim,dim_,koeff;
	INT mehr_eins,mehr_zwei;

	/* Moegliche Eingabefehler...  */
	if (!lambda)
		return(LmbNul);
	else if (!lambda[0])
		return(LmbEmp);
	else if (!bz)
		return(BzNul);
	for (i=(INT)0,_n=(INT)0;lambda[i];++i)
		if (lambda[i]<(TL_BYTE)0)
			return(LmbLt_null);
		else
			_n += lambda[i];
	if (perm==NULL)
	  return(PerNul);

for (i=(INT)0;i<_n;i++)
if (perm[i]<=(INT)0)
return(PerLe_null);
else if (perm[i]>_n)
return(PerGtN);
for (i=1L;lambda[i];++i)
if (lambda[i]>lambda[i-1])
return(LmbNRg);


/*
  Na denn ma' los...
*/
_zyk=ZYK/2+ZYK+1L;
_spaltenz=lambda[0];
_zeilenz = i ;

q_zeilenz=_zeilenz*_zeilenz;
if (_zeilenz==2L)
{
	dim_=zweikonmat(lambda,perm,bz);
	if (dim_<(INT)0)
		dim=DmGtMx;
	else
		dim=dim_;
}
else
{ /* allgemeine Partition/Anfang */
	init_mat();
	mat=(TL_BYTE *)TL_calloc((int)(q_zeilenz+MAXDM)*3+(int)(4*_n),sizeof(TL_BYTE));
	if (mat == NULL)
	{
		close_mat();
		return no_memory();
	}
	transmt=mat+q_zeilenz;
	zykmt=transmt+q_zeilenz;
	t_eins=zykmt+q_zeilenz;
	t_zwei=t_eins+_n;
	ht=t_zwei+_n;
	asslambda=ht+_n;
	hz=asslambda+_n;
	mdim=MAXDM;
	konjugiere(lambda,asslambda);
	for (ii=(INT)0,diag=1L;ii<_zeilenz;++ii)
		diag *= fak(lambda[ii]);
	for (ii=(INT)0,kk=(INT)0;ii<_n && lambda[ii];++ii)
	{
		for (jj=kk;jj < (kk+lambda[ii]);ht[jj++]= ii);
		kk += lambda[ii];
	}
	for (z=(INT)0;z<_n;t_zwei[z]=ht[z],z++);
	co_eins=co_zwei=(INT)0;
	for (i=(INT)0,mehr_zwei=TRUE;mehr_zwei;++i)
	{
		for (z=(INT)0;z<_n;t_eins[z]=ht[z],z++);
		for (z=3L*mdim,_hz=hz;z>(INT)0;z--,*_hz++ =(INT)0);
		for (k=(INT)0,mehr_eins=TRUE;mehr_eins;++k)
		{
			if (i==k)
			/*Hauptdiag. von B(lambda) und C(lambda/(12))*/
			{
				hz[i]=diag;
				if (t_zwei[1]== 1)
					hz[i+mdim]=((TL_BYTE) -1)*(hz[i]/lambda[0]);
				else
					hz[i+mdim]=hz[i];
			}
			else if (i<k)
			{
				schnitt(t_eins,t_zwei,mat);
				/*Rest von B(lambda)*/
				koeff=mat_comp(&co,mat,asslambda);
				if (koeff!=NtEMem && koeff!=RTabFt)
					hz[k]=koeff;
				else
				{
					close_mat();
					SYM_free(mat);
					return(koeff);
				}
				if ((t_zwei[1]==1L) && (t_eins[1]==1L))
				/*Rest von C(lambda/(12))*/
				{
					matcopy(transmt,mat,_zeilenz);
					--transmt[0];
					--transmt[_zeilenz+1];
					++transmt[1];
					++transmt[_zeilenz];
					ii=co;
					koeff=mat_comp(&co,transmt,asslambda);
					if (koeff!=NtEMem && koeff!=RTabFt)
						hz[k+mdim]=koeff;
					else
					{
						close_mat();
						SYM_free(mat);
						return(koeff);
					}
					if (co>ii) co_eins++;
				}
				else
					hz[k+mdim]= hz[k];
			}
			if (zykschnitt(t_zwei,t_eins,perm,zykmt))
			{
				close_mat();
				SYM_free(mat);
				return no_memory();
			}
			/*Berechnung von C(lambda/(1..n)).*/
			if (!i && !k)
			{
				co=(INT)0;
				koeff=mat_comp(&co,zykmt,asslambda);
				if (koeff!=NtEMem && koeff!=RTabFt)
					hz[2L*mdim]=koeff;
				else
				{
					close_mat();
					SYM_free(mat);
					mehr_zwei = 280194L;
					nexgitt(NULL,NULL,&mehr_zwei);
					return(koeff);
				}
			}
			ii=co;
			koeff=mat_comp(&co,zykmt,asslambda);
			if (koeff!=NtEMem && koeff!=RTabFt)
				hz[k+2L*mdim]=koeff;
			else
			{
				close_mat();
				SYM_free(mat);
				mehr_zwei = 280194L;
				nexgitt(NULL,NULL,&mehr_zwei);
				return(koeff);
			}
			if (co>ii) ++co_zwei;
			if (nexgitt(t_eins,lambda,&mehr_eins))
			{
				close_mat();
				SYM_free(mat);
				return no_memory();
			}
		}
		if ((_zeilenz==1L) || (_spaltenz==1L))
			co=1L;
		if (!i)
		{
			dim=dim_=k;
			if (dim>MAXDM)
			{
				dim_ *= (-1L);
				dim=DmGtMx;
				break;
			}
			else
				_bz=bz;
		}
		for (z=(INT)0,_hz=hz;z<3L;z++,_hz += mdim)
			for (k=(INT)0,z_eins=_hz;k<dim;k++)
				*_bz++ = *z_eins++;
		if (dim<mdim)
			mdim=dim;
		if (nexgitt(t_zwei,lambda,&mehr_zwei))
		{
			close_mat();
			SYM_free(mat);
			return no_memory();
		}
	}
	close_mat();
	SYM_free(mat);


} /*allgemeine Partition/Ende*/


mehr_zwei = 280194L;
nexgitt(NULL,NULL,&mehr_zwei);
return(dim);
}


static INT dm;
static INT dm_zwei;
static INT qdm;

/*
 * berechnet die Koeffizientenmatrix B fuer alle Partitionen lambda. Dabei
 * werden die Eintraege der Matrix modulo pz abgelegt.
 * (Vgl. in MODULKFF.C Funktion alkonmat().)
 * Variablen:  lambda, Partition;
 *             pz, Primzahl.
 * Rueckgabe Koeffizientenmatrix bz.
 * Rueckgabewerte: >(INT)0, Dimension der gew. irred. Darstellung;
 *              sonst, s. MODULKFF.C Funktion alkonmat().
 */
static INT k_alkonmat(TL_BYTE *lambda, TL_BYTE *bz, INT pz)
{
	TL_BYTE *mat,*t_eins,*t_zwei,*ht,*slambda,*hz;
	INT ii,jj,kk,i,k,z,co = (INT)0,dim,diag,mdim,dim_,koeff;
	INT mehr_eins,mehr_zwei;
	TL_BYTE *_bz;

	/* Moegliche Eingabefehler... */
	if (!lambda) return(LmbNul);
	else if (!lambda[0]) return(LmbEmp);
	else if (!bz) return(BzNul);
	for (i=(INT)0,_n=(INT)0;lambda[i];++i)
		if (lambda[i]<0) return(LmbLt_null);
		else _n += (INT)lambda[i];

	if (pz<=(INT)0) return(PrmLe_null);
	else if (pz)
	{
		for (i=(INT)0;PZ[i]<=pz;i++);
		if (pz!=PZ[i-1]) return(NoPrm);
	}
	for (i=1L;lambda[i];++i)
		if (lambda[i]>lambda[i-1]) return(LmbNRg);


	/* Na denn ma' los... */
	_zyk=ZYK/2L+ZYK+1L;
	_zeilenz = i;
	_spaltenz = lambda[0];
	q_zeilenz=_zeilenz*_zeilenz;
	if (_zeilenz==2L)
	{
		dim_=_k_zweikonmat(lambda,bz,pz);

		if (dim_<(INT)0)
			dim=DmGtMx;
		else
			dim=dim_;
	}
	else
	{ /* allgemeine Partition/Anfang */
		init_mat();
		mat=(TL_BYTE *)TL_calloc((int)(q_zeilenz)+(int)(4*_n)+1,sizeof(TL_BYTE));
		if (mat == NULL)
		{
			close_mat();
			return no_memory();
		}
		t_eins=mat+(INT)q_zeilenz;
		t_zwei=t_eins+(INT)_n;
		ht=t_zwei+(INT)_n;
		slambda=ht+_n;
		mdim=MAXDM;
		_assoziiere(lambda,slambda,_n);
		for (ii=(INT)0,diag=1L;ii<_zeilenz;++ii)
			diag *= fak((INT)lambda[ii]);
		for (ii=(INT)0,kk=(INT)0;ii<_n && lambda[ii];++ii)
		{
			for (jj=kk;jj < (kk+lambda[ii]);jj++)
				ht[jj]=(TL_BYTE)ii;
			kk += lambda[ii];
		}
		for (z=(INT)0;z<_n;t_zwei[z]=ht[z],z++);
		_bz=bz;
		for (i=(INT)0,mehr_zwei=TRUE;mehr_zwei;++i)
		{
			for (z=(INT)0;z<_n;t_eins[z]=ht[z],z++);
			for (k=0,hz=bz+i,mehr_eins=TRUE;mehr_eins;++k)
			{
				if (i==k)
					*_bz++ = (TL_BYTE) TL_MOD(diag,pz);
				else if (k<i)
					_bz++;
				else if (i<k)
				{
					schnitt(t_eins,t_zwei,mat);
					koeff=mat_comp(&co,mat,slambda);
					if (koeff!=NtEMem && koeff!=RTabFt)
					{
						*_bz++ = TL_MOD(koeff,pz);
					}
					else
					{
						close_mat();
						SYM_free(mat);
						mehr_zwei = 280194L;
						nexgitt(NULL,NULL,&mehr_zwei);
						return(koeff);
					}
				}

				if (nexgitt(t_eins,lambda,&mehr_eins))
				{
					close_mat();
					SYM_free(mat);
					return no_memory();
				}
			}
			if ((_zeilenz==1L) || (_spaltenz==1L))
				co=1L;
			if (!i)
			{
				dim=dim_=k;
				if (dim>MAXDM)
				{
					dim_ *= (-1L);
					dim=DmGtMx;
					error("mo.c:internal error 400");
					break;
				}
			}
			if (dim<mdim)
				mdim=dim;
			if (nexgitt(t_zwei,lambda,&mehr_zwei))
			{
				close_mat();
				SYM_free(mat);
				return no_memory();
			}
		}

		close_mat();
		SYM_free(mat);


#define AKSIZE 100
		hz = (TL_BYTE *) TL_malloc(sizeof(TL_BYTE) * MAXDM * AKSIZE);
		for (kk=MAXDM -1; kk>0; kk-= AKSIZE)
		{
			for (jj=0;jj<kk;jj++)
				for (ii=0;(ii<AKSIZE) && (kk-ii > 0) ;ii++)
				{
					hz[MAXDM*ii+jj] = bz[jj*MAXDM+(kk-ii)];
				}
			for (ii=0;(ii<AKSIZE) && (kk-ii > 0) ;ii++)
				memcpy(&bz[(kk-ii)*MAXDM], &hz[ii * MAXDM], kk-ii);
		}
		SYM_free(hz);

	} /*allgemeine Partition/Ende*/

	mehr_zwei = 280194L;
	nexgitt(NULL,NULL,&mehr_zwei);
	return(dim);
}


/*
 * bringt die Matrix bz mit Hilfe des Gaussalgorithmus ueber GF(pz) auf obere
 * Dreiecksform mit 1 oder 0 auf der Hauptdiagonalen.
 * (Vgl. in MODULDG.C Funktion moddreimat().)
 * Variablen:  bz, Koeffizientenmatrix aus k_alkonmat();
 *             pz, Primzahl;
 * Rueckgabe bz.
 */
static INT _k_moddreimat(TL_BYTE *_bz, INT pz)
{
	TL_BYTE *jz, *z_eins,*z_zwei;
	TL_BYTE qu,mu;
	INT i,j,k;

	for (i=0;i<dm;i++,_bz += (dm+1))
	{
		for (k=i+1,jz=_bz+dm;!*_bz && k<dm;k++,jz += dm)
			if (*jz)
				for (j=dm,z_eins=jz,z_zwei=_bz;j>i;j--)
				{
					mu= *z_zwei;
					*z_zwei++ = *z_eins;
					*z_eins++ = mu;
				}
		if (*_bz)
		{
			if ((qu= *_bz)!=(TL_BYTE)1)
				for (j=dm,z_eins=_bz;j>i;j--,z_eins++)
				{
					if (*z_eins) 
						*z_eins=(TL_BYTE)TL_DIVP(*z_eins,qu,pz);
				}
			if (i<dm-(INT)1)
				for (k=i+1L,jz=_bz+dm;k<dm;k++,jz += dm)
					if ((qu= *jz)!=(TL_BYTE)0)
						for (j=dm,z_eins=jz,z_zwei=_bz;j>i;j--,z_eins++,z_zwei++)
							if (*z_zwei)
							{
								*z_eins = TL_MOD( *z_eins - qu * *z_zwei, pz);
							}
		}
	}
	return OK;
}


/*
 * berechnet mit Hilfe des Gaussalgorithmus ueber GF(pz) die Dimension der
 * modular irreduziblen Darstellung.
 * (Vgl. in MODULDG.C Funktion modgauss().)
 * Variablen:  bz, Matrix mit Basis;
 *             pz, Primzahl.
 * Rueckgabe bz.
 * Rueckgabewert: Dimension der mod. irred. Darstellung.
 */
static INT _k_modgauss(TL_BYTE *bz, INT pz)
{
	TL_BYTE *_bz,*z_eins,*z_zwei,*z_drei,*z_vier,qu;
	INT i,j,k,prang;

	TL_BYTE mu;

	prang=(INT)0;
	for (i=dm-1,_bz= &bz[qdm-1];i>0;i--,_bz -= (dm+1L))
		if (*_bz)
		{
			if ((qu= *_bz)!=(TL_BYTE)1)
				for (k=i,z_eins=_bz;k<dm;k++,z_eins++)
					if (*z_eins)
						*z_eins=(TL_BYTE)TL_DIVP(*z_eins,qu,pz);

			for (j=i-1L,z_eins= &bz[i*dm+i],z_zwei=z_eins-dm;j>=0;j--,z_zwei -= dm)
				if ((qu= *z_zwei)!=(TL_BYTE)0)
					for (k=dm,z_drei=z_eins,z_vier=z_zwei;k>i;k--,z_drei++,z_vier++)
						if (*z_drei)
						{
							*z_vier = TL_MOD(*z_vier - qu * *z_drei, pz);
						}
		}
		else
			prang++;

	if (bz[0]!=(TL_BYTE)1)
	{
		if ((qu=bz[0])==(TL_BYTE)0)
			prang++;
		else
			for (j=0,_bz=bz;j<dm;j++,_bz++)
				if (*_bz)
					*_bz= (TL_BYTE)TL_DIVP(*_bz,qu,pz);
	}
	return(dm-prang);
}


/* eingabe primzahl p und schnittmatrix m */
INT co_070295(OP m, OP p)
{
	TL_BYTE *bz,*z;
	INT i,j;
	bz = (TL_BYTE *) TL_calloc(S_M_HI(m) * S_M_LI(m), sizeof(TL_BYTE));

	for (i=0,z=bz;i<S_M_HI(m);i++)
		for(j=0;j<S_M_LI(m);j++,z++)
			*z = TL_MOD((TL_BYTE)S_M_IJI(m,i,j), S_I_I(p));
	i= k_dimmod(bz,S_M_HI(m),S_I_I(p));
	TL_free(bz);
	return i;
}

INT co_k_dimmod(signed char *bz, INT dim, INT pz)
{
	return k_dimmod(bz,dim,pz);
}


/*
 * berechnet aus bz, der Koeffizientenmatrix aus k_alkonmat(), die Dimension
 * der modular irreduziblen Darstellung fuer ein pz.
 * Variablen:  bz, Koeffizientenmatrix aus k_alkonmat();
 *             dim, Dimension der Matrix;
 *             pz, Primzahl.
 * Rueckgabewert:  Dimension der mod. irred. Darstellung.
 */
static INT k_dimmod(TL_BYTE *bz, INT dim, INT pz)
{
	dm=dim;
	dm_zwei=(INT)2*dm;
	qdm=(INT)dm*(INT)dm;
	_k_moddreimat(bz,pz);
	return(_k_modgauss(bz,pz));
}


/*
 *Defines...
 */
#define _H_IJ(l,i,sl,j) (l[i]-i+sl[j]-j-1L) /* Macro Hook_length */


/*
 * berechnet die naechste Partition von n. Dabei enthaelt r die r[0] Teile der
 * Partition und m die Vielfachheiten.
 * Variablen:  n, die zu partitionierende Zahl;
 *             mode, =0 erste Partitionierung,
 *                   !=0 weitere Partitionierungen.
 * Rueckgabe r und m.
 * Rueckgabewerte: (INT)0, falls keine weitere Partitionierung moeglich;
 *                 1L, falls weitere Partitionen von n existieren.
 */
static INT _nexpart(INT n, INT mode, TL_BYTE *r, TL_BYTE *m)
{
	INT d,s,sum,f;

	if (sym_timelimit > 0L) /* AK 230996 */
		check_time();

	d=r[0];
	if (mode)
	{
		sum=(r[d]==1L)? m[d--]+1L : 1L;
		f=r[d]-1L;
		if (m[d]!=1L) m[d++]--;
		r[d]=f;
		m[d]=(sum/f)+1L;
		s=sum % f;
		if (s>(INT)0)
		{
			r[++d]=s;
			m[d]=1L;
		}
		r[0]=d;
		return(m[d]!=n);
	}
	else
	{
		r[0]=m[1]=1L;
		r[1]=n;
		return(n!=1L);
	}
}


/*
 * ueberprueft die Partition gegeben durch r und m, ob sie p-regulaer ist.
 * Variablen:  p, Primzahl;
 *             r, Partition mit r[0]=Laenge von r und m,
 *                r[1]...r[r[0]] Elemente der Partition;
 *             m, Vielfachheiten von r[1]...r[r[0]].
 * Rueckgabewerte: (INT)0, falls Partition nicht p-regulaer;
 *                 1L, falls Partition p-regulaer ist.
 */
static INT _part_reg(INT p, TL_BYTE *r, TL_BYTE *m)
{
	INT i;
	for (i=1L;i<=r[0];i++)
		if (m[i]>=p)
			return((INT)0);
	return(1L);
}


/*
 * berechnet  fuer pz=0 die Anzahl der Partitionen zu n und fuer pz!=0 die
 * Anzahl der regulaeren Partitionen.
 * Variablen:  n, die zu partitionierende Zahl;
 *             pz, Primzahl oder 0.
 * Rueckgabewerte: >(INT)0, die Anzahl der (p-regulaeren) Partitionen von n;
 *              (INT)-109, falls nicht genuegend Speicher vorhanden war.
 */
static INT _num_part(INT n, INT pz)
{
	INT num,d,e;
	TL_BYTE *r,*m;

	r=(TL_BYTE *)SYM_calloc(2*(int)(n+1),sizeof(TL_BYTE));
	m=r+(INT)n+1L;
	num=(INT)0;
	e=1L;
	d=(INT)0;
	while (e)
	{
		e=d=_nexpart(n,d,r,m);
		if (pz)
		{
			if (_part_reg(pz,r,m)) num++;
		}
		else num++;
	}
	SYM_free(r);
	return(num);
}


/*
 * ueberprueft die Moeglichkeit einer r-Induktion des zur Partition lambda
 * gehoerenden Tableaux in der Zeile i.
 * Variablen:  lambda, Partition zu n;
 *             n;
 *             pz, Primzahl;
 *             i, Zeile des Tableaux;
 *             r, die "Ordnung" des anzuhaengenden Knotens.
 * Rueckgabewerte: (INT)0, falls r-Induktion nicht moeglich;
 *                 1L, falls r-Induktion moeglich ist.
 */
static INT _r_induk(TL_BYTE *lambda, INT n, INT pz, INT i, INT r)
{
	INT len;

	for (len=(INT)0;len<n && lambda[len];len++);
	if (!i) return(TL_MOD(lambda[0],pz)==r);
	else if (i<len)
	{
		if (lambda[i-1]>lambda[i]) return(TL_MOD(lambda[i]-i,pz)==r);
		else return((INT)0);
	}
	else if (i==len) return(TL_MOD(-i,pz)==r);
	else return((INT)0);
}


/*
 * berechnet fuer p=0 alle eigentlichen Partitionen von n und fuer p!=(INT)0, p
 * Primzahl, alle p-regulaeren Partitionen von n.
 * Variablen:  n, die zu partitionierende Zahl;
 *             p, Primzahl oder (INT)0;
 * Rueckgabe lambda, Vektor von Partitionen.
 * Rueckgabewerte: (INT)0, falls alle Partitionen ohne Fehler berechnet wurden;
 *             (INT)-109, falls kein Speicher zur Verfuegung stand.
 */
static INT _ber_lambdas(TL_BYTE **lambda, INT n, INT p)
{
	TL_BYTE *r,*m;
	INT d,e,i,j,k,l;

	r=(TL_BYTE *)TL_calloc((int)(n+1)*2,sizeof(TL_BYTE));
	if (r == NULL) return no_memory();
	m=r+(INT)(n+1L);
	e=1L;
	k=d=(INT)0;
	while(e)
	{
		d=e=_nexpart(n,d,r,m);
		if (!p)
		{
			for (i=(INT)0;i<n;lambda[k][i++]=(TL_BYTE)0);
			for (i=1L,l=(INT)0;i<=r[0];i++)
				for (j=(INT)0;j<m[i];j++)
					lambda[k][l++]=r[i];
			k++;
		}
		else
		{
			if (_part_reg(p,r,m))
			{
				for (i=(INT)0;i<n;lambda[k][i++]=(TL_BYTE)0);
				for (i=1L,l=(INT)0;i<=r[0];i++)
					for (j=(INT)0;j<m[i];j++)
						lambda[k][l++]=r[i];
				k++;
			}
		}
	}
#ifndef __TURBOC__ /* leider gibt Turbo C hier nicht sauber frei?? */
	SYM_free(r);
#endif
	return((INT)0);
} /* _ber_lambdas */



/* berechnet n! und gibt das Ergebnis als Langzahl zurueck. */
static INT _fakul(INT n)
{
	if (n > 12) error("mo:internal error: 500");
	if (n<=1L) return(1L);
	else return ((INT)n*_fakul(n-1L));
}


/*
 * berechnet die Dimension der Darstellung zu einer eigentlichen Partition
 * mit Hilfe der Hakenformel.
 * Variablen:  lambda, Partition;
 *             n, die partitionierte Zahl.
 * Rueckgabewert: Dimension.
 */
static INT _dimension(TL_BYTE *lambda, INT n)
{
	INT i,j,l;
	INT zz,zn;
	TL_BYTE *slambda;
	if (n > (INT)12)
	{
		OP p,a;
		a = callocobject();
		p = callocobject();
		for (l=(INT)0;lambda[l]>0;l++);
		b_ks_pa(VECTOR,callocobject(),p);
		m_il_v(l,S_PA_S(p));
		l--;
		for (i=0;l>=0;i++,l--)
			m_i_i((INT)(lambda[l]),S_PA_I(p,i));

		dimension_partition(p,a);
		l=s_i_i(a);
		freeall(a);
		freeall(p);
		return l;
	}

	slambda=(TL_BYTE *)TL_calloc((int)(n+1),sizeof(TL_BYTE));
	if (slambda == NULL) return no_memory();
	_assoziiere(lambda,slambda,n);
	zz=_fakul(n);
	for (l=(INT)0;l<n && lambda[l];l++);
	for (i=(INT)0,zn=1L;i<l;i++)
		for (j=(INT)0;j<lambda[i];j++)
			zn *= (INT)_H_IJ(lambda,i,slambda,j);
	SYM_free(slambda);
	return((INT)(zz/zn));
}


/*
 * berechnet fuer p=0 die Dimensionen zu allen eigentlichen Partitionen lambda
 * und fuer p!=(INT)0, p Primzahl, die p-Dimensionen zu allen p-regulaeren Parti-
 * tionen lambda.
 * Variablen:  lambda, Vektor von Partitionen;
 *             lda, Laenge des Vektors lambda;
 *             n, die partitionierte Zahl;
 *             p, Primzahl oder 0.
 * Rueckgabe dim, Vektor der Dimensionen.
 * Rueckgabewerte: (INT)0, falls alles ohne Fehler berechnet wurde;
 *                <(INT)0, s. Datei MODULKFF.C Funktion alkonmat().
 */
static INT _ber_dim(INT *dim, TL_BYTE **lambda, INT lda, INT n, INT p)
{
	TL_BYTE *slambda;
	INT i,dm,omaxdim,k;
	TL_BYTE *bz;

	omaxdim=MAXDM;
	for (i=(INT)0;i<lda;dim[i++]=(INT)0);
	for (i=(INT)0;i<lda;i++)
	{
		if (p) /* D.h. keine gewoehnliche darstellung */
		{

			MAXDM=_dimension(lambda[i],n);
			if (MAXDM<(INT)0)
			{
				MAXDM=omaxdim;
				return(MAXDM);
			}
			slambda=(TL_BYTE *)TL_calloc((int)(n+1),sizeof(TL_BYTE));
			if (slambda == NULL)
			{
				MAXDM=omaxdim;
				return no_memory();
			}
			bz=(TL_BYTE *)TL_calloc((int)MAXDM*(int)MAXDM,sizeof(TL_BYTE));
			if (bz == NULL)
			{
				MAXDM=omaxdim;
				SYM_free(slambda);
				return no_memory();
			}
			if (lambda[i][0]==5 && lambda[i][1]==4 && lambda[i][2]==2 && n==11L && p==2L)
				dim[i]=416L;
			else
			{
				_assoziiere(lambda[i],slambda,n);
				if ((dm=k_alkonmat(slambda,bz,p))<(INT)0)
				{
					MAXDM=omaxdim;
					SYM_free(slambda);
					SYM_free(bz);
					error("mo:internal error : 345");
					return(dm);
				}
				if ((dim[i]=k_dimmod(bz,MAXDM,p))<(INT)0)
				{
					MAXDM=omaxdim;
					SYM_free(slambda);
					SYM_free(bz);
					error("mo:internal error : 346");
					return(dim[i]);
				}
			}
			SYM_free(bz);
			SYM_free(slambda);

		}
		else
			if ((dim[i]=_dimension(lambda[i],n))<(INT)0)
			{
				MAXDM=omaxdim;
				error("mo:internal error : 347");
				return(dim[i]);
			}
	}
	MAXDM=omaxdim;
	j_zyk((INT) -15,0,NULL,NULL);
	return((INT)0);
}



/*
 * zaehlt das Vorkommen der durch r-Induktion erhaltenen Partition part von
 * n in lambda. Dabei wird der Eintrag der Zerlegungsmatrix fuer n-1 berueck-
 * sichtigt.
 * Variablen:  lambda, Vektor der Partitionen von n;
 *             lanz, Laenge des Vektors lambda;
 *             part, Partition, errechnet durch r-Induktion von n-1 nach n;
 *             v, Spalte der Zerlegungsmatrix;
 *             vv, Eintrag der Partition part vor der r-Induktion in der Zer-
 *                 legungsmatrix fuer n-1L;
 *             n, partitionierte Zahl.
 * Rueckgabewerte: (INT)0, alles in Ordnung;
 *                -1L, warum existiert kein solches lambda?????
 */
static INT _v_eintrag(TL_BYTE **lambda, INT lanz, TL_BYTE *part, TL_BYTE *v, INT vv, INT n)
{
	INT i,j;
	INT gefunden;

	for (i=0,gefunden=0;i<lanz && !gefunden;i++)
	{
		for (j=0;j<n;j++)
			if (lambda[i][j]!=part[j])
				break;
		gefunden= (j==n);
	}
	if (gefunden)
	{
		v[i-1] += (TL_BYTE)vv;
		return (INT)0;
	}
	else
		return (INT)-1L;
}


/* berechnet mit Hilfe Euklids den ggT zweier Zahlen a und b. */
static INT _ggT(INT a, INT b)
{
	INT x,y,r;

	if (a==b)    return(a);
	else if (!a) return(b);
	else if (!b) return(a);
	x=a;
	y=b;
	if (x<y)
	{
		r=x;
		x=y;
		y=r;
	}
	x=a;
	y=b;
	while(y)
	{
		r=x%y;
		x=y;
		y=r;
	}
	return(x);
}


/* berechnet den ggT der Eintraege eines Vektors v der Laenge vl und
 * multipliziert den Vektor mit 1/ggT.
 */
static INT _ggT_v(TL_BYTE *v, INT vl)
{
	INT i,ggT;

	for (i=0;i<vl;i++)
		if (v[i]==(TL_BYTE)1)
			return OK;
	ggT=_ggT((INT)v[0],(INT)v[1]);
	for (i=2;i<vl;i++)
		ggT=_ggT(ggT,(INT)v[i]);
	if (ggT>1)
	{
		for (i=0;i<vl;i++)
			v[i] = (TL_BYTE)(v[i]/ggT);
	}
	return OK;
}


/*
 * vergleicht zwei Spalten col_eins und col_zwei.  Ist col_eins (lexikographisch)
 * kleiner als col_zwei, so gibt _kleiner eine 1 zurueck, sonst 0.
 * Variablen:  col_eins, erste Spalte;
 *             col_zwei, zweite Spalte;
 *             len, Laenge der Spalten.
 * Rueckgabewerte: 1L, falls col_eins kleiner col_zwei;
 *                 (INT)0, sonst.
 */
static INT _kleiner(TL_BYTE *col_eins, TL_BYTE *col_zwei, INT len)
{
	INT i;

	if (!col_zwei) return((INT)0);
	if (!col_eins) return(1L);
	for (i=(INT)0;i<len;i++)
		if (col_eins[i] || col_zwei[i])
		{
			if (col_eins[i]<col_zwei[i]) return(1L);
			else if (col_eins[i]==col_zwei[i]) continue;
			else break;
		}
	return((INT)0);
}


/*
 * berechnet die Differenz erg=col_eins-col_zwei. Existiert in erg ein Eintrag
 * kleiner als (INT)0, so gibt _diff 0 zurueck, sonst 1.
 * Variablen:  col_eins, erste Spalte;
 *             col_zwei, zweite Spalte;
 *             len, Laenge der Spalten.
 * Rueckgabe Ergebnis erg.
 * Rueckgabewerte: (INT)0, falls Eintrag von erg <(INT)0;
 *                 1L, sonst.
 */
static INT _diff(TL_BYTE *col_eins, TL_BYTE *col_zwei, TL_BYTE *erg, INT len)
{
	INT i;

	for (i=0;i<len;erg[i++]=(TL_BYTE)0);
	for (i=0;i<len;i++)
		if ((erg[i]=col_eins[i]-col_zwei[i])<(TL_BYTE)0)
			return (INT)0;
	return (INT)1;
}


/*
 * untersucht die Matrix r_mat auf Spalten, die (INT)0, gleich oder von
 * anderen abgezogen werden koennen.
 * Variablen:  r_mat, Matrix aller durch r-Induktion entstandenen
 *                    Spalten;
 *             col, Anzahl der Spalten von r_mat;
 *             row, Anzahl der Zeilen von r_mat;
 * Rueckgabe ausreduzierte Matrix r_mat.
 * Rueckgabewerte: (INT)0, alles ohne Fehler gelaufen;
 *             (INT)-109, falls nicht genuegend Speicher verfuegbar war.
 */
static INT _red_r_mat(TL_BYTE **r_mat, INT col, INT row)
{
	INT i,j,k,l,max;
	TL_BYTE *r;
	TL_BYTE *hp,*c;
	INT gleiche;

	c=(TL_BYTE *)TL_calloc((int)(col+row),sizeof(TL_BYTE));
	if (c == NULL)
		return no_memory();
	r=c+(int)row;
	for (i=0;i<col;i++) /* pruefe, ob in r_mat Spalte=0 existiert */
	{
		if (r_mat[i] == NULL)
			continue;
		for (j=0;j<row;j++)
			if (r_mat[i][j] != (TL_BYTE)0)
				break;
		if (j==row)       /* wenn ja, vergesse Spalte */
			r_mat[i]=(TL_BYTE *)NULL;
	}
	for (i=0;i<col-1;i++)
	/* pruefe, ob in r_mat zwei Spalten gleich sind */
	{
		if (r_mat[i] == NULL) continue;
		for (j=i+1L;j<col;j++)
		{
			if (!r_mat[j])
				continue;
			for (k=0;k<row;k++)
				if (r_mat[i][k]!=r_mat[j][k])
					break;
			if (k==row)      /* wenn ja, vergesse eine davon */
				r_mat[j]=NULL;
		}
	}
	for (i=0;i<col-1;i++) /* sortiere Spalten in r_mat lexikographisch */
	{                     /* absteigend */
		max=i;
		for (j=i+1L;j<col;j++)
			if (_kleiner(r_mat[max],r_mat[j],row))
				max=j;
		if (max!=i)
		{
			hp=r_mat[i];
			r_mat[i]=r_mat[max];
			r_mat[max]=hp;
		}
	}
	for (i=0;i<col;i++)      /* belege r[i] mit der Zeilennummer des ersten */
		if (!r_mat[i]) r[i]=(TL_BYTE)0; /* Eintrags in  der Spalte r_mat[i] */
		else
			for (j=0;j<row;j++)
				if (r_mat[i][j])
				{
					r[i]=(TL_BYTE)j+1;
					break;
				}
	for (i=0,gleiche=0;i<col-1 && !gleiche;i++)
	{ /* ueberpruefe r auf gleiche Eintraege */
		if (!r[i]) continue;
		for (j=i+1L;j<col;j++)
		{
			if (!r[j]) continue;
			if (r[i]==r[j]) /* existieren zwei gleiche Eintraege: */
			{
				if (_diff(r_mat[i],r_mat[j],c,row)) /* probiere, die zwei Spalten */
					for (k=0;k<row;k++)               /* voneinander abzuziehen */
						r_mat[i][k]=c[k];
				else /* lassen sie sich nicht abziehen, probiere, hintere Spalten */
					/* von der lex. kleineren der beiden Spalten abzuziehen */
					for (k=col-(INT)1;k>j;k--)
					{
						if (!r_mat[k]) continue;
						if (_diff(r_mat[j],r_mat[k],c,row))
						{
							for (l=0;l<row;l++)
								r_mat[j][l]=c[l];
							break;
						}
					}
				gleiche=1;
				break;
			}
		}
	}
	if (gleiche)                     /* gab es gleiche Spalten, so */
		if (_red_r_mat(r_mat,col,row)) /* untersuche r_mat nochmals */
		{
			SYM_free(c);
			return no_memory();
		}
	SYM_free(c);
	return (INT)0;
}


/*
 * untersucht die Zeilen von r_mat auf Richtigkeit. Dabei werden die p-Dimen-
 * sionen der p-regulaeren Partitionen multipliziert mit den korrespon-
 * dierenden Eintraegen in den Zeilen von r_mat aufsummiert und schliesslich
 * mit den jeweiligen gewoehnlichen Dimensionen zu den Partitionen verglichen.
 * Variablen:  r_mat, vorher mit _red_r_mat() ueberpruefte Matrix der mit
 *                    r-Induktion erhaltenen Spalten;
 *             col, Anzahl der p-regulaeren Partitionen;
 *             row, Anzahl der eigentlichen Partitionen;
 *             dim, Dimensionen der gew. irred. Dg.en zu den eigentlichen
 *                  Partitionen;
 *             rg_dim, p-Dimensionen der mod. irred. Dg.en zu den p-regulaeren
 *                     Partitionen.
 * Rueckgabe Matrix r_mat, ueberprueft und eventl. mit neuen Spalten, die
 *   durch Abziehen lexikographisch kleinerer Spalten von der alten entstanden
 *   ist.
 * Rueckgabewerte: (INT)0, alles ohne Fehler abgelaufen;
 *             (INT)-109, falls nicht genuegend Speicher vorhanden war.
 */
static INT _teste_r_mat_dim(TL_BYTE ** r_mat, INT col, INT row, INT p, INT *dim, INT *rg_dim, INT ab)
{
	INT i,j,k,clmn,dm;
	TL_BYTE *c,*r, *hp;
	INT err,l;

	clmn=col*p;
	c=(TL_BYTE *)TL_calloc((int)row*2+(int)clmn,sizeof(TL_BYTE));
	if (c == NULL) return no_memory();
	hp=c+(int)row;
	r=hp+(int)row;

	for (i=ab;i<row;i++)
	{
		for (j=0,k=0,dm=0;j<clmn;j++)
		/* summiere in den Zeilen die Produkte */
		{                             /* aus Eintraegen von r_mat und Dimen- */
			if (r_mat[j] == NULL) continue;    /* sionen der p-regulaeren Partitionen */
			dm += (rg_dim[k++]*(INT)r_mat[j][i]);
		}
		if (dm>dim[i]) break;
		else if (dm<dim[i])
		{
			fprintf(stderr,"\n dm = %d : %d \n",dm,dim[i]);
			SYM_free(c);
			error("MO-1:internal error");
			return (INT)-1;
		}
	}
	if (i==row)
	{
		SYM_free(c);
		return((INT)0);
	}
	for (j=(INT)0;j<clmn;j++)     /* belege r[i] mit der Zeilennummer des ersten */
		if (r_mat[j])          /* Eintrags in  der Spalte r_mat[i] */
			for (k=(INT)0;k<row;k++)
			{
				if (r_mat[j][k])
				{
					r[j]=(TL_BYTE)k+1;
					break;
				}
			}
		else r[j]=(INT)0;
	for (j=(INT)0;j<clmn-(INT)1;j++)
	{
		if (!r_mat[j]) continue;
		if (r_mat[j][i])
		{
			for (k=j+1L;k<clmn;k++)
			{
				if (!r[k]) continue;
				if (i+1!=r[k]) continue;
				if (r_mat[k][i])
				{
					if (_diff(r_mat[j],r_mat[k],c,row))
					{
						for (l=(INT)0;l<row;l++)
						{
							hp[l]=r_mat[j][l];
							r_mat[j][l]=c[l];
						}
						if ((err=_teste_r_mat_dim(r_mat,col,row,p,dim,rg_dim,i))<(INT)0 )
						{
							for (l=(INT)0;l<row;l++)
								r_mat[j][l]=hp[l];
							if (err == (INT)-109)
							{
								SYM_free(c);
								return(err);
							}
							break;
						}
						SYM_free(c);
						return((INT)0);
					}
				}
			}
		}
	}
	SYM_free(c);
	return (INT)0;
} /* _teste_r_mat_dim */


/*
 * berechnet die (row x col)-Zerlegungsmatrix decomp zu n und der Primzahl pz.
 * Variablen:  col, Spaltenzahl der Zerlegungsmatrix;
 *             row, Zeilenzahl der Zerlegungsmatrix;
 *             n;
 *             pz, Primzahl.
 * Rueckgabe Zerlegungsmatrix decomp.
 * Rueckgabewerte: (INT)0, alles ohne Fehler;
 *             sonst, s. Datei MODULKFF.C Funktion alkonmat().
 */
static INT d_mat(TL_BYTE *decomp, INT col, INT row, INT n, INT pz)
{
	TL_BYTE  **lambda,**rg_lambda,*part,*pr,*mr,*v;
	INT *dim,*rg_dim;
	INT num,i,j,k,l,r,e,d,o,p,m,err,vv;
	TL_BYTE  *odec;
	INT orow,ocol;
	TL_BYTE **r_mat,*z;
	TL_BYTE **hr,*hrc;
	INT erg = OK;

	if (n<=1L)
	{
		decomp[0]=(TL_BYTE)1;
		return((INT)0);
	}
	else
	{
		if ((orow=_num_part(n-1L,(INT)0))<(INT)0) return(orow);
		ocol=_num_part(n-1L,pz);
		odec=(TL_BYTE *)TL_calloc((int)ocol*(int)orow,sizeof(TL_BYTE));
		if (!odec) return no_memory();
		if ((err=d_mat(odec,ocol,orow,n-1L,pz))<(INT)0)
		{
			SYM_free(odec);
			return error("d_mat:error in n-1");
		}
		lambda=(TL_BYTE **)TL_calloc((int)row+(int)col,sizeof(TL_BYTE *));
		if (lambda == NULL)
		{
			SYM_free(odec);
			return no_memory();
		}
		rg_lambda=lambda+(INT)row;
		lambda[0]=(TL_BYTE *)TL_calloc((int)(row+col)*(int)(n+1),sizeof(TL_BYTE));
		if (lambda[0] == NULL)
		{
			SYM_free(odec);
			SYM_free(lambda);
			return no_memory();
		}
		for (i=1L;i<row;i++)
			lambda[i]=lambda[i-1]+n;
		if ((err=_ber_lambdas(lambda,n,(INT)0))<(INT)0)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			return error("d_mat:error in ber_lambdas");
		}
		rg_lambda[0]=lambda[row-1]+(TL_BYTE)n;
		for (i=1L;i<col;i++)
			rg_lambda[i]=rg_lambda[i-1]+(INT)n;
		if ((err=_ber_lambdas(rg_lambda,n,pz))<(INT)0)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			return error("d_mat:error in ber_rlambdas");
		}
		/* dim=rg_lambda[col-1]+(INT)n; */
		dim = (INT *) TL_calloc(row+col,sizeof(INT));
		rg_dim=dim+(INT)row;
		if ((err=_ber_dim(dim,lambda,row,n,(INT)0))<(INT)0)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			SYM_free(dim);
			return error("d_mat: error in ber_dim");
		}
		if ((err=_ber_dim(rg_dim,rg_lambda,col,n,pz))<(INT)0)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			SYM_free(dim);
			return error("d_mat: error in ber_dim rlambdas");
		}
		hr=r_mat=(TL_BYTE **)TL_calloc((int)(col*pz),sizeof(TL_BYTE *));

		if (!r_mat)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			SYM_free(dim);
			return no_memory();
		}
		hrc=r_mat[0]=(TL_BYTE *)TL_calloc((int)(col*pz)*(int)row,sizeof(TL_BYTE));
		if (!r_mat[0])
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			SYM_free(r_mat);
			SYM_free(dim);
			return no_memory();
		}

		for (i=1L;i<col*pz;i++)
			r_mat[i]=r_mat[i-1]+row;
		part=(TL_BYTE *)TL_calloc(3*(int)n+2+(int)row,sizeof(TL_BYTE));
		if (!part)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			SYM_free(r_mat[0]);
			SYM_free(r_mat);
			SYM_free(dim);
			return no_memory();
		}
		pr=part+(INT)n;
		mr=pr+(INT)n+1L;
		v=mr+(INT)n+1L;
		k=(INT)0;

		/* Berechne alle r-Induktionen und lege die Ergebnisse
		 * in der Matrix r_mat spaltenweise ab. */

		for (l=(INT)0;l<ocol && k<(col*pz);l++)
		{
			for (i=(INT)0,num=(INT)0;i<orow;i++)
				if (odec[i*ocol+l])
					num ++;
			for (r=(INT)0;r<pz && k<(col*pz);r++)
			{
				e=1L;
				d=(INT)0;
				j=(INT)0;
				for (i=(INT)0;i<row;v[i++]=(TL_BYTE)0);
				for (i=(INT)0;i<num;i++)
				{
					do
					{
						e=d=_nexpart(n-1L,d,pr,mr);
						vv=odec[j*ocol+l];
						j++;
					} while(!vv && e);
					for (o=(INT)0;o<n;part[o++]=(TL_BYTE)0);
					for (p=1L,m=(INT)0;p<=pr[0];p++)
					{
						for (o=(INT)0;o<mr[p];o++)
							part[m++]=pr[p];
					}
					for (p=(INT)0;p<n;p++)
						if (_r_induk(part,(INT)n-1,pz,p,r))
						{
							part[p]++;
							_v_eintrag(lambda,row,part,v,vv,n);
							part[p]--;
						}
				}
				for (i=0;i<row;i++)
					if(v[i])
					{
						_ggT_v(v,row);
						break;
					}
				for (i=0;i<row;i++)
					r_mat[k][i]=v[i];
				k++;
			}
		}

		/* Durchsuche nun r_mat nach ueberfluessigen Spalten
		 * und errechne schliesslich die entgueltige
		 * Zerlegungsmatrix fuer n und pz. */
		if ((err=_red_r_mat(r_mat,col*pz,row))<(INT)0)
		{
			SYM_free(odec);
			SYM_free(lambda[0]);
			SYM_free(lambda);
			SYM_free(hrc);
			SYM_free(hr);
			SYM_free(part);
			SYM_free(dim);
			erg += error("d_mat:red_r_mat");
			goto dm1;
		}

		if ((err=_teste_r_mat_dim(r_mat,col,row,pz,dim,rg_dim,(INT)0))<(INT)0)

		{
			erg += SYM_free(odec);
			erg += SYM_free(lambda[0]);
			erg += SYM_free(lambda);
			erg += SYM_free(hrc);
			erg += SYM_free(hr);
			erg += SYM_free(part);
			erg += SYM_free(dim);
			erg += error("d_mat:teste_r_mat_dim");
			goto dm1;

		}
		for (i=(INT)0,k=(INT)0;i<col*pz;i++)
			if (r_mat[i])
			{
				for (j=(INT)0,z=decomp+k;j<row;j++,z +=col)
					*z = r_mat[i][j];
				k++;
			}

		SYM_free(lambda[0]);
		SYM_free(lambda);
		SYM_free(hrc);
		SYM_free(hr);
		SYM_free(odec);
		SYM_free(part);
		SYM_free(dim);
dm1:
		if (erg != OK)
			EDC("mo.c:d_mat");
		return (INT)0;
	}
}


/*
 * berechnet zu einer Primzahl prime, einer Partition llambda und einer
 * Permutation pi die modulare Matrixdarstellung dmat.
 * Variablen:  prime,  Primzahl  (objectkind: INTEGER);
 *     lambda, Partition (objectkind: PARTITION);
 *     pi, Permutation (objectkind: PERMUTATION).
 * Rueckgabewerte: >=(INT)0, Dimension der Darstellung;
 *     -1L,  falls Fehler Aufgetreten ist.
 * Rueckgabe darstellende Matrix dmat, die erst hier dimensioniert wird,
 *   falls die Dimension groesser 0 ist.
 */
INT moddg(OP prime, OP llambda, OP pi, OP dmat)
{
	TL_BYTE *part,*bz,*perm;
	TL_BYTE *darmat[2],*dar;
	INT pz,dim;
	INT spe,i,j,l_pa,l_p,gzl;
	OP   dimen;
	OP lambda;

	if (equal_parts(llambda,prime))
	{
		fprint(stderr,llambda);
		fprintln(stderr,prime);
		return error("moddg: wrong partition, wrong prime");
	}


	if (S_PA_LI(llambda) == 1L)
		if (S_PA_II(llambda,(INT)0) == 1L)
		{
			m_ilih_m(1L,1L,dmat);
			m_i_i(1L,S_M_IJ(dmat,(INT)0,(INT)0));
			return OK;
		}

	dimen=callocobject();
        weight(llambda,dimen);
        if (neq(dimen,S_P_L(pi))) {
	    fprint(stderr,llambda);
	    fprintln(stderr,pi);
	    error("moddg: wrong permutation, wrong degree");
            freeall(dimen);
            return ERROR;
            }
	lambda=callocobject();

	conjugate(llambda,lambda);

	l_pa=S_PA_LI(lambda);
	l_p=S_P_LI(pi);
	spe=l_pa+l_p+2L;
	dimension(lambda,dimen);
	MAXDM=(INT)S_I_I(dimen);
	spe += ((INT)MAXDM*(INT)MAXDM*5L);
	part=(TL_BYTE *)TL_calloc(spe,sizeof(TL_BYTE));
	if (!part)
                {
                freeall(dimen);
                freeall(lambda);
		return(-1L);
                }
	perm=part+l_pa+1;
	bz=perm+l_p+1;
	for (i=0;i<l_pa;i++)
		part[i]=(TL_BYTE)S_PA_II(lambda,(l_pa-1L-i));
	for (i=0;i<l_p;i++)
		perm[i]=(TL_BYTE)S_P_II(pi,i);
	if ((dim=alkonmat(part,perm,bz))<(INT)0)
	{
		freeall(dimen);
		freeall(lambda);
		SYM_free(part);
		return error("mo.c: internal MO-12");
	}
	darmat[0]=(TL_BYTE *)TL_calloc((int)dim*(int)dim,sizeof(TL_BYTE));
	darmat[1]=(TL_BYTE *)TL_calloc((int)dim*(int)dim,sizeof(TL_BYTE));
	if (!darmat[0])
	{
		freeall(dimen);
		freeall(lambda);
		SYM_free(part);
		return error("mo.c: internal MO-13");
	}
	if (!darmat[1])
	{
		freeall(dimen);
		freeall(lambda);
		SYM_free(part);
		return error("mo.c: internal MO-14");
	}
	pz=(INT)S_I_I(prime);
	gzl=1L;
	if ((dim=darmod(part,dim,bz,pz,&gzl,perm,darmat))
	    <=(INT)0)
	{
		freeall(dimen);
		freeall(lambda);
		SYM_free(part);
		SYM_free(darmat[0]);
		SYM_free(darmat[1]);
		fprintf(stderr, "error-no = %" PRIINT "\n" ,dim);
		return error("mo.c: internal MO-15");
	}
	m_ilih_m(dim,dim,dmat);
	for (i=(INT)0,dar=darmat[1];i<dim;i++)
		/* darmat[1] statt darmat[0] */
		for (j=(INT)0;j<(INT)dim;j++)
			m_i_i((INT)(*dar++),s_m_ij(dmat,i,j));
	freeall(dimen);
	freeall(lambda);
	SYM_free(part);
	SYM_free(darmat[0]);
	SYM_free(darmat[1]);
	return((INT)dim);
}


/*
 * berechnet zu Sn und einer Primzahl prime die Zerlegungsmatrix dmat.
 * Variablen:    sn, Sn;
 *               prime, Primzahl.
 * Rueckgabewerte: (INT)0, falls kein Fehler aufgetreten ist;
 *                -1L, falls Fehler aufgetreten ist.
 * Rueckgabe Zerlegungsmatrix dmat.
 */
INT decp_mat(OP sn, OP prime, OP dmat)
{
	INT TL_n,p,row,col;
	TL_BYTE *dec,*d;
	INT i,j,erg=OK;

	TL_n=(INT)S_I_I(sn);
	p=(INT)S_I_I(prime);
	if ((col=_num_part(TL_n,p))<(INT)0) return(ERROR);
	row=_num_part(TL_n,(INT)0);
	dec=(TL_BYTE *)TL_calloc((int)col*(int)row,sizeof(TL_BYTE));
	if (!dec) return(ERROR);
	if (d_mat(dec,col,row,TL_n,p))
	{
		SYM_free(dec);
		return EDC("decp_mat");
	}
	m_ilih_m((INT)col,(INT)row,dmat);
	for (i=(INT)0,d=dec;i<(INT)row;i++)
		for (j=(INT)0;j<(INT)col;j++)
			m_i_i((INT)(*d++),S_M_IJ(dmat,i,j));
	SYM_free(dec);
	return((INT)0);
}


/*
 * testet die Darstellung ueber die darstellenden Matrizen einer
 * Transposition und eines n-Zykels.
 * Variablen:  transmat, darstellende Matrix einer Transposition
 *       (objectkind: MATRIX);
 *     nzykmat,  darstellende Matrix eines n-Zykels
 *       (objectkind: MATRIX);
 *     sn,  Sn (objectkind: INTEGER);
 *     prime,  Primzahl,fuer welche die darstellenden Matrizen
 *       berechnet wurden (objectkind: INTEGER).
 * Rueckgabewerte: (INT)0,  alle Relationen sind erfuellt;
 *     >(INT)0, Relation ... ist nicht erfuellt;
 *     -1L,  Fehler aufgetreten.
 * Rueckgabe relation erhaelt die Nummer der nicht erfuellten Relation
 *   oder 0.
 */
static INT homp(OP transmat, OP nzykmat, OP sn, OP prime, OP relation)
{
	TL_BYTE  *darmat[2],*d[2];
	INT dm,i_n,rl,pz;
	INT i,j;

	if (!S_M_LI(transmat))
	{
		m_i_i((INT)0,relation);
		return((INT)0);
	}
	dm=(INT)S_M_LI(transmat);
	i_n=(INT)S_I_I(sn);
	pz=(INT)S_I_I(prime);
	darmat[0]=(TL_BYTE *)TL_calloc((int)dm*(int)dm*2,sizeof(TL_BYTE));
	if (!darmat[0])
		return(-1L);
	darmat[1]=darmat[0]+(INT)dm*(INT)dm;
	for (i=(INT)0,d[0]=darmat[0],d[1]=darmat[1];i<(INT)dm;i++)
		for (j=(INT)0;j<(INT)dm;j++)
		{
			*d[0]++ =(INT)S_M_IJI(transmat,i,j);
			*d[1]++ =(INT)S_M_IJI(nzykmat,i,j);
		}
	if ((rl=homtestp(darmat,i_n,dm,pz))<(INT)0)
	{
		SYM_free(darmat[0]);
		return(-1L);
	}
	m_i_i((INT)rl,relation);
	SYM_free(darmat[0]);
	return((INT)rl);
}


/*
 * berechnet die Charaktertafel der Brauercharaktere der Sn zur Primzahl prime.
 * Variablen:    sn, Sn (objectkind:INTEGER);
 *               prime,Primzahl (objectkind:INTEGER).
 * Rueckgabewerte: (INT)0, falls fehlerfrei;
 *                -1L, falls Fehler aufgetreten ist.
 * Rueckgabe der Charaktertafel bc.
 */
INT brauer_char(OP sn, OP prime, OP bc)
{
	INT _n,p,col,*idx,*idm;
	INT i,j,k,erg = OK;
	OP  tafel,decomp, su, mu, _su;

	if (not primep(prime))
		return error("brauer_char:second parameter no prime");


	_n=(INT)S_I_I(sn);
	p=(INT)S_I_I(prime);
	if ((col=_num_part(_n,p))<(INT)0)
		return(-1L);
	idx=(INT *)TL_calloc((int)col*2,sizeof(INT));
	if (!idx)
	{
		return ERROR;
	}
	idm=idx+(INT)col;
	if (_ber_idx_pelem(_n,p,col,idx))
	{
		SYM_free(idx);
		return(-1L);
	}

	tafel=callocobject();
	decomp=callocobject();
	su=callocobject();
	mu=callocobject();
	_su=callocobject();

	if (decp_mat(sn,prime,decomp))
	{
		SYM_free(idx);
		freeall(tafel);
		freeall(decomp);
		freeall(su);
		freeall(mu);
		freeall(_su);
		return(-1L);
	}
	_ber_inx_dec(decomp,idm);
	chartafel(sn,tafel);
	m_ilih_m((INT)col,(INT)col,bc);
	for (i=(INT)0;i<(INT)col;i++)
		for (j=(INT)0;j<(INT)col;j++)
		{
			copy(S_M_IJ(tafel,(INT)idm[i],(INT)idx[j]),su);
			for (k=(INT)0;k<i;k++)
			{
				erg += mult(S_M_IJ(decomp,(INT)idm[i],k),S_M_IJ(bc,k,j),mu);
				erg += addinvers(mu,_su);
				erg += add_apply(_su,su);
			}
			erg += copy(su,S_M_IJ(bc,i,j));
		}
	SYM_free(idx);
	erg += freeall(tafel);
	erg += freeall(decomp);
	erg += freeall(su);
	erg += freeall(_su);
	erg += freeall(mu);
	ENDR("brauer_char");
}


/*
 * test the functions moddg(...), homp(...), decp_mat(...) and
 * brauer_char(...).
 */
INT test_mdg(void)
{
	OP  lambda=callocobject();
	OP  trans=callocobject();
	OP  transmat=callocobject();
	OP  nzyk=callocobject();
	OP  nzykmat=callocobject();
	OP  prime=callocobject();
	OP  sn=callocobject();
	OP  relation=callocobject();
	INT i_n,i,dim;

	scan(PARTITION,lambda);
	scan(INTEGER,prime);
	weight(lambda,sn);
	i_n=S_I_I(sn);
	init(PERMUTATION,trans);
	m_il_v(i_n,S_P_S(trans));
	m_i_i(2L,S_P_I(trans,(INT)0));
	m_i_i(1L,S_P_I(trans,1L));
	for (i=2L;i<i_n;i++) m_i_i(i+1L,S_P_I(trans,i));
	println(trans);
	if ((dim=moddg(prime,lambda,trans,transmat))<(INT)0)
	{
		freeall(lambda);
		freeall(prime);
		freeall(trans);
		freeall(transmat);
		freeall(nzyk);
		freeall(nzykmat);
		freeall(sn);
		freeall(relation);
		return(-1L);
	}
	println(transmat);
	init(PERMUTATION,nzyk);
	m_il_v(i_n,S_P_S(nzyk));
	for(i=(INT)0;i<i_n-1L;i++) m_i_i(i+2L,S_P_I(nzyk,i));
	m_i_i(1L,S_P_I(nzyk,i_n-1L));
	println(nzyk);
	if ((dim=moddg(prime,lambda,nzyk,nzykmat))<(INT)0)
	{
		freeall(lambda);
		freeall(prime);
		freeall(trans);
		freeall(transmat);
		freeall(nzyk);
		freeall(nzykmat);
		freeall(sn);
		freeall(relation);
		return(-1L);
	}
	println(nzykmat);
	if (homp(transmat,nzykmat,sn,prime,relation)<(INT)0)
	{
		freeall(lambda);
		freeall(prime);
		freeall(trans);
		freeall(transmat);
		freeall(nzyk);
		freeall(nzykmat);
		freeall(sn);
		freeall(relation);
		return(-1L);
	}
	println(relation);
	freeall(lambda);
	freeall(relation);
	freeall(trans);
	freeall(transmat);
	freeall(nzyk);
	freeall(nzykmat);
	freeall(sn);
	freeall(prime);
	return OK;
}


INT test_dcp(void)
{
	OP  prime=callocobject();
	OP  sn=callocobject();
	OP  decmat=callocobject();

	scan(INTEGER,sn);
	scan(INTEGER,prime);
	if (decp_mat(sn,prime,decmat))
	{
		freeall(prime);
		freeall(sn);
		freeall(decmat);
		return(-1L);
	}
	println(decmat);
	freeall(prime);
	freeall(sn);
	freeall(decmat);
	return((INT)0);
}


INT test_brc(void)
{
	OP  prime=callocobject();
	OP  sn=callocobject();
	OP  tafel=callocobject();

	scan(INTEGER,sn);
	scan(INTEGER,prime);
	if (brauer_char(sn,prime,tafel))
	{
		freeall(prime);
		freeall(sn);
		freeall(tafel);
		return(-1L);
	}
	println(tafel);
	freeall(prime);
	freeall(sn);
	freeall(tafel);
	return((INT)0);
}


/*
 * berechnet Index eines p-Elements in der Liste der Partitionen der Sn.
 * Variablen:    sn, Sn;
 *               p, Primzahl;
 *               c, Anzahl der p-Elemente.
 * Rueckgabewerte: (INT)0, kein Fehler aufgetreten;
 *             (INT)-109, nicht genuegend Speicher.
 * Rueckgabe Indexvektor idx.
 */
static INT _ber_idx_pelem(INT sn, INT p, INT c, INT *idx)
{
	INT i,j,e,d;
	TL_BYTE *r,*m;
	INT *id;

	for (i=(INT)0;i<c;idx[i++]=(INT)0);
	r=(TL_BYTE *)TL_calloc((int)(sn+1)*2,sizeof(TL_BYTE));
	if (r == NULL) return no_memory();
	m=r+sn+1L;
	e=1L;
	d=(INT)0;
	i=(INT)0;
	id=idx;
	while (e)
	{
		e=d=_nexpart(sn,d,r,m);
		for (j=1L;j<=r[0];j++)
			if (!(r[j]%p))
				break;
		if (j>r[0]) *id++ =i;
		i++;
	}
	SYM_free(r);
	return((INT)0);
}


/*
 * berechnet in den Spalten der Zerlegungsmatrix dcm den Zeilenindex des ersten
 * Elements !=0.
 * Variablen:    dcm, Zerlegungsmatrix;
 *               col, Spaltenanzahl der Zerlegungsmatrix;
 *               row, Zeilenanzahl der Zerlegungsmatrix.
 * Rueckgabe Indexvektor idx.
 */
static INT _ber_inx_dec(OP dcm, INT *idx)
{
	INT i,j,col,row;
	INT *id;

	col=S_M_LI(dcm);
	row=S_M_HI(dcm);
	for (i=(INT)0;i<col;idx[i++]=(INT)0);
	for (j=(INT)0,id=idx;j<col;j++)
		for (i=(INT)0;i<row;i++)
			if (!nullp(S_M_IJ(dcm,i,j)))
			{

				*id++ = (INT)i;
				break;
			}
	return OK;
}


/*
 * ueberprueft, ob die im Buch von Carmichael auf Seite 175  (Aufgabe 2)
 * angegebenen Relationen erfuellt sind, d.h. eine treue Darstellung von Sn
 * erzeugt wird. Dabei wird ueber GF(pz) gerechnet. Es handelt sich insgesamt
 * um 4+[n/2] Relationen.
 * Indexnummern: 1.  t^2 = I,
 *               2.  s^n = I,
 *               3.  (st)^(n-1L) = I,
 *               4.  (ts^(-1L)ts)^3 = I,
 *               3+j.  (ts^(-j)ts^j)^2 = I fuer j=2L,...,[n/2].
 * Variablen:  darmat, darstellende Matrizen einer Transposition
 *                     und eines n-Zykels;
 *             n,  Sn;
 *             ddim, Dimension der darstellenden Matrizen;
 *             pz, Primzahl.
 * Rueckgabewerte: (INT)0,  falls alle Relationen erfuellt sind;
 *             index,  falls Relation mit Indexnummer index nicht
 *                     erfuellt ist;
 *               -14L,  falls n kleiner 1 ist;
 *               // -15L,  falls n groesser MAXN ist;
 *               -22L,  falls Pointer auf darmat NULL ist;
 *               -24L,  falls pz keine Primzahl ist;
 *               -25L,  falls pz kleiner 1 ist;
 *               -26L,  falls pz groesser n ist;
 *               -28L,  falls ddim kleiner 0 ist;
 *               -29L,  falls ddim groesser MAXDM ist;
 *             (INT)-109,  falls nicht genuegend Speicher zu Verfuegung war.
 */
static INT homtestp(TL_BYTE **darmat, INT n, INT ddim, INT pz)
{
	TL_BYTE *invzyk,*mat,*mat_eins;
	INT k,i,j,az;

	if (ddim<(INT)0) return(DDmLt_null);
	else if (ddim==(INT)0) return((INT)0);
	else if (ddim>MAXDM) return(DDmGMx);
	else if (darmat==NULL) return (DrtNul);
	else if (n<=(INT)0) return(NLe_null);
	else if (pz<=(INT)0) return(PrmLe_null);
	else if (pz>n) return(PrmGtN);
	for (i=(INT)0;PZ[i]<=n && PZ[i]<=pz;i++);
	if (pz!=PZ[i-1]) return(NoPrm);

	/* Kein Eingabefehler, also koennen wir loslegen: */
	mat=(TL_BYTE *)TL_calloc((int)ddim*(int)ddim*3,sizeof(TL_BYTE));
	if (!mat)
		return no_memory();
	mat_eins= &mat[(INT)ddim*(INT)ddim];
	invzyk= &mat_eins[(INT)ddim*(INT)ddim];
	matcopy(mat,darmat[0],ddim);
	if (rmatmulp(mat,darmat[0],ddim,pz)<(INT)0)
	{
		SYM_free(mat);
		return no_memory();
	}
	if (!idmat(mat,ddim)) /* t^2 = 1 ? */
	{
		SYM_free(mat);
		return(1L);
	}
	matcopy(mat,darmat[1],ddim);
	rmatmulp(mat,darmat[0],ddim,pz);
	matcopy(mat_eins,mat,ddim);
	az=1L;
	while (2L*az <= (n-1L))
	{
		matcopy(invzyk,mat_eins,ddim);
		rmatmulp(mat_eins,invzyk,ddim,pz);
		az *= 2L;
	}
	for (i=az+2L; i<= n; i++)
		rmatmulp(mat_eins,mat,ddim,pz);
	if (!idmat(mat_eins,ddim))  /* (s * t) ^ (n-1L) =1 ? */
	{
		SYM_free(mat);
		return(3L);
	}
	matcopy(mat,darmat[1],ddim);
	az=1L;
	while (2L*az <= n-1L)
	{
		matcopy(mat_eins,mat,ddim);
		rmatmulp(mat,mat_eins,ddim,pz);
		az*=2L;
	}
	for (i=az+2L;i<=n;++i)
		rmatmulp(mat,darmat[1],ddim,pz);
	matcopy(invzyk,mat,ddim); /* s^(-1L) = s^(n-1L) */
	rmatmulp(mat,darmat[1],ddim,pz);
	if (!idmat(mat,ddim)) /* s^n = 1 ? */
	{
		SYM_free(mat);
		return(2L);
	}
	matcopy(mat,darmat[0],ddim);
	rmatmulp(mat,invzyk,ddim,pz);
	rmatmulp(mat,darmat[0],ddim,pz);
	rmatmulp(mat,darmat[1],ddim,pz);
	matcopy(mat_eins,mat,ddim);
	rmatmulp(mat_eins,mat,ddim,pz);
	rmatmulp(mat_eins,mat,ddim,pz);
	if (!idmat(mat_eins,ddim))  /* (t * s^(-1L) * t * s) ^ 3 = 1 ? */
	{
		SYM_free(mat);
		return(4L);
	}
	k=n/2L;
	for (j=2L; j<=k; j++)
	{
		rmatmulp(mat,darmat[1],ddim,pz);  /* in mat ist noch t*s^1*t*s */
		lmatmulp(darmat[0],mat,ddim,pz);
		lmatmulp(invzyk,mat,ddim,pz);
		lmatmulp(darmat[0],mat,ddim,pz);
		matcopy(mat_eins,mat,ddim);
		rmatmulp(mat_eins,mat,ddim,pz);
		if (!idmat(mat_eins,ddim))  /* (t*s^(-j)*t*s^j)^2 = 1 fuer j=2L,...k ? */
		{
			SYM_free(mat);
			return(j+3L);
		}
	}
	SYM_free(mat);
	return((INT)0);
}


/*
 * multipliziert die (pdim x pdim)-Matrix lmat von rechts mit der
 * (pdim x pdim)-Matrix rmat. Dabei werden Multiplikationen und Additionen
 * modulo pz ausgefuehrt.
 * Variablen:  lmat, Matrix;
 *             rmat, Matrix;
 *             pdim, Dimension der Matrizen;
 *             pz, Primzahl.
 * Rueckgabe Ergebnismatrix lmat.
 * Ruechgabewerte: (INT)0,  falls alles geklappt hat;
 *             (INT)-109,  falls der noetige Speicher nicht vorhanden war.
 */
static INT rmatmulp(TL_BYTE *lmat, TL_BYTE *rmat, INT pdim, INT pz)
{
	INT h,i,j,k,o_eins,o_zwei;
	TL_BYTE *aa,*bb,*hilf,*aa_eins;

	hilf=(TL_BYTE *)TL_calloc((int)pdim,sizeof(TL_BYTE));
	if (hilf == NULL) return no_memory();
	aa_eins=lmat;
	for (i=(INT)0 ; i < pdim; ++i)
	{
		for (j=(INT)0 ; j < pdim; ++j)
		{
			h=(INT)0;
			bb= &rmat[(INT)j];
			aa=aa_eins;
			for (k=(INT)0; k<pdim; k++,bb+=(INT)pdim)
			{
				if ((o_eins= *aa++)==(INT)0) continue;
				if ((o_zwei= *bb)==(INT)0) continue;
				h=TL_ADP(h,TL_MULP(o_eins,o_zwei,pz),pz);
			}
			hilf[j]=h;
		}
		for (j=(INT)0; j < pdim; ++j) *aa_eins++=hilf[j];
	}
	SYM_free(hilf);
	return((INT)0);
}


/*
 * multipliziert die (pdim x pdim)-Matrix rmat von links mit der
 * (pdim x pdim)-Matrix lmat. Dabei werden Multiplikationen und Additionen
 * modulo pz ausgefuehrt.
 * Variablen:  lmat, Matrix;
 *             rmat, Matrix;
 *             pdim, Dimension der Matrizen;
 *             pz, Primzahl.
 * Rueckgabe Ergebnismatrix rmat.
 * Rueckgabewerte: (INT)0,  falls kein Fehler aufgetreten ist;
 *             (INT)-109,  falls kein Speicher zu Verfuegung stand.
 */
static INT lmatmulp(TL_BYTE *lmat, TL_BYTE *rmat, INT pdim, INT pz)
{
	INT h,i,j,k;
	TL_BYTE *hilf,*_a,*_b;
	INT o_eins,o_zwei;

	hilf=(TL_BYTE *)TL_calloc((int)pdim,sizeof(TL_BYTE));
	if (hilf==NULL) no_memory();

	for (j=(INT)0 ;j < pdim; ++j)
	{
		_a=lmat;
		for (i=(INT)0 ; i < pdim; ++i)
		{
			_b=rmat+j;
			h=(INT)0;
			for (k=(INT)0 ; k < pdim; k++,_b+=pdim)
			{
				if ((o_eins= *_a++)==(INT)0) continue;
				if ((o_zwei= *_b)==(INT)0) continue;
				h=TL_ADP(h,TL_MULP(o_eins,o_zwei,pz),pz);
			}
			hilf[i]=h;
		}
		_b=rmat+j;
		for (i=(INT)0; i < pdim; ++i)
		{
			*_b=hilf[(INT)i];
			_b+=pdim;
		}
	}
	SYM_free(hilf);
	return((INT)0);
}


/*
 * testet die (dm x dm)-Matrix z, ob sie die Einheitsmatrix ist.
 * Variablen:  z,  Matrix;
 *             dm, Dimension der Matrix.
 * Rueckgabewerte: TRUE, falls z Einheitsmatrix ist;
 *                FALSE, falls z keine Einheitsmatrix ist.
 */
static INT idmat(TL_BYTE *z, INT dm)
{
	INT i,j,o_eins;
	TL_BYTE *zz;

	zz=z;
	for (i=(INT)0; i<dm; ++i)
		for (j=(INT)0; j<dm; ++j)
		{
			o_eins= *zz++;
			if (i==j)
			{
				if (o_eins!=1L) return(FALSE);
			}
			else
			{
				if (o_eins) return(FALSE);
			}
		}
	return(TRUE);
}

/*
 * und globale Variablen.
*/
static INT _dm;
static INT _dm_zwei;
static INT _dm_drei;



/*
 * Funktionen fuer die Bestimmung gew./p-mod. irred. Darstellungen...
 *
 */


/*
 * mode=1:
 *   bringt die erste (_dm x _dm)-Teilmatrix von hz mit Hilfe des Gaussalgorith-
 *   mus ueber GF(pz) auf obere Dreiecksform mit 1 oder 0 auf der Hauptdiago-
 *   nalen,
 * mode=3:
 *   wendet auf das (_dm x 3_dm)-Gleichungsschema hz den Gaussalgorithmus ueber
 *   GF(pz) an, bis die erste der drei (_dm x _dm)-Teilmatrizen eine obere Drei-
 *   ecksmatrix mit 1 oder 0 auf der Hauptdiagonalen ist.
 *   (Simultanes Loesen von 2_dm linearen Gleichungssystemen.)
 * Variablen:  hz, Matrix mit Basis und Darstellungen;
 *             pz, Primzahl;
 *             mode, s.o.
 * Rueckgabe Matrix hz.
 */
static INT moddreimat(TL_BYTE *hz, INT pz, INT mode)
{
	TL_BYTE  *_hz,*jz,*z_eins,*z_zwei,qu,mu;
	INT i,j,k,mdm;

	mdm=mode*_dm;
	for (i=(INT)0,_hz=hz;i<_dm;i++,_hz += (_dm_drei+1L))
	{
		for (k=i+1L,jz=_hz+_dm_drei;!*_hz && k<_dm;k++,jz += _dm_drei)
			if (*jz)
				for (j=mdm,z_eins=jz,z_zwei=_hz;j>i;j--)
				{
					mu= *z_zwei;
					*z_zwei++ = *z_eins;
					*z_eins++ = mu;
				}
		if (*_hz)
		{
			if ((qu= *_hz)!=1L)
				for (j=mdm,z_eins=_hz;j>i;j--,z_eins++)
				{
					if (*z_eins)
						*z_eins=TL_DIVP(*z_eins,qu,pz);
				}
			if (i<_dm-1L)
				for (k=i+1L,jz=_hz+_dm_drei;k<_dm;k++,jz += _dm_drei)
					if ((qu= *jz)!=(INT)0)
						for (j=mdm,z_eins=jz,z_zwei=_hz;j>i;j--,z_eins++,z_zwei++)
							if (*z_zwei)
							{
								*z_eins = TL_MOD((-1 * qu * *z_zwei) + *z_eins, pz);
							}
		}
	}
	return OK;
}


/*
 * wird benoetigt fuer die Funktionen modgauss und r_modgauss.
 * Variablen:  hz, Matrix mit Basis und Darstellungen;
 *             pz, Primzahl;
 *             i, Anfangswert der Schleife;
 *             mode, =1L, fuer modgauss,
 *                   =3L, fuer r_modgauss;
 * Rueckgabe Matrix hz.
 */
static INT _modgauss(TL_BYTE *hz, INT pz, INT i, INT mode)
{
	TL_BYTE mu,qu,*_hz,*jz,*z_eins,*z_zwei;
	INT j,k,mdm;

	mdm=mode*_dm;
	for (j=i-1L,_hz= &hz[IND(i,i,_dm_drei)],jz=_hz-_dm_drei;j>=(INT)0;j--,jz -= _dm_drei)
		if ((qu= *jz)!=(TL_BYTE)0)
			for (k=mdm,z_eins=_hz,z_zwei=jz;k>i;k--,z_zwei++,z_eins++)
				if (*z_eins)
				{
					mu=(TL_BYTE) (-1L)*(TL_MULP(qu,*z_eins,pz));
					*z_zwei= TL_ADP(*z_zwei,mu,pz);
				}
	return OK;
}


/*
 * Funktionen zur Bestimmung der gew. irred. Darstellungen...
 *
 */


/*
 * wendet den Gaussalgorithmus ueber GF(pz) auf das (_dm x 3_dm)-Koeffizienten-
 * schema an, wobei die erste (_dm x _dm)-Teilmatrix eine obere Dreiecksmatrix
 * mit 0 oder 1 auf der Hauptdiagonalen sein muss.
 * (Simultanes Loesen von 2_dm linearen Gleichungssystemen.)
 * Variablen:  hz, Matrix mit Basis und Darstellungen;
 *             pz, Primzahl.
 * Rueckgabe Matrix hz.
 */
static INT r_modgauss(TL_BYTE *hz, INT pz)
{
	TL_BYTE *_hz;
	INT i;

	for (i=_dm-1L,_hz= &hz[IND(_dm-1L,_dm-1L,_dm_drei)];i>(INT)0;i--,_hz -= (_dm_drei+1L))
		if (*_hz)
			_modgauss(hz,pz,i,3L);
	return OK;
}


/*
 * loest simultan die in dem (_dm x 3_dm)-Koeffizientenschema bz kodierten 2_dm
 * linearen Gleichungssysteme. Am Ende stehen die Loesungen fuer die gew.
 * irred. Darstellungen in den letzten 2_dm Spalten von bz.
 * Koennen keine ganzz. Loesungen errechnet werden, wird die Berechnung abge-
 * brochen.
 * Variablen:  bz, Matrix aus alkonmat;
 *             hz, Matrix wie bz.
 * Rueckgabe Matrix hz mit Basis und Matrizen der gewoehnlichen Darstellungen.
 * Rueckgabewerte: (INT)0, falls alles geglueckt ist;
 *               -27L, falls keine ganzzahlige Loesung existiert.
 */
static INT ganzgaussmod(TL_BYTE *bz, TL_BYTE *hz)
{
	TL_BYTE  *_hz,*_bz,*z_eins,*z_zwei,*z_drei;
	INT i,j,k,pz,su;
	INT  il,cl;
	INT chance;

	pz=(INT)29;
	chance=TRUE;
	while (chance)
	{
		/* Interpretation von bz ueber GF(pz) und Uebergabe an hz */
		for (il=(INT)_dm*(INT)_dm_drei,_hz=hz,_bz=bz;il>(INT)0;il--,_hz++,_bz++)
			if (*_bz)
				*_hz = (TL_BYTE) TL_MOD(*_bz,pz);
			else
				*_hz = (TL_BYTE) 0;
		/* Anwendung des Gaussalgorithmus ueber GF(pz) */
		moddreimat(hz,pz,3L);
		r_modgauss(hz,pz);
		/* Rekonstruktion der ganzzahligen Loesungen */
		for (i=(INT)0,_hz=hz+_dm;i<_dm;i++,_hz += _dm_drei)
			for (j=_dm,z_eins=_hz;j<_dm_drei;j++,z_eins++)
				if (*z_eins)
				{
					if ((*z_eins + *z_eins) > pz)
						*z_eins -= pz;
				}
		/* Verifikation der Loesungen: Die Koeffizientenmatrix
		 * der Gleichungssysteme (die ersten _dm Spalten von
		 * bz) wird mit der Loesungsmatrix (die letzten 2_dm
		 * Spalten von hz) multipliziert. Jeder Eintrag der
		 * Produktmatrix wird unmittelbar nach seiner
		 * Berechnung mit dem entsprechenden Eintrag in den
		 * letzten 2_dm Spalten von bz verglichen.  cl gibt
		 * die Anzahl der Uebereinstimmungen an. */
		for(i=(INT)0,cl=(INT)0,_bz=bz;i<_dm;i++,_bz += _dm_drei)
			for (j=_dm,z_eins=_bz+_dm,_hz=hz+_dm;j<_dm_drei;j++,z_eins++,_hz++)
			{
				for (k=(INT)0,su=(INT)0,z_zwei=_hz,z_drei=_bz;k<_dm;k++,z_drei++,z_zwei +=_dm_drei)
				{
					if (! *z_zwei) continue;
					if (! *z_drei) continue;
					su += (*z_zwei * *z_drei);
				}
				if (su == *z_eins)
					++cl;
			}
		if (cl==((INT)_dm_zwei*(INT)_dm))
			chance=FALSE;
		else
		{
			if (pz==(INT)211)
			{
				error("internal error: MO_50");
				return(NoSolu);
			}
			pz=(INT)211;
			chance=TRUE;
		}
	}
	return((INT)0);
}



/*
 * Funktionen zur Bestimmung der p-mod. irred. Darstellungen...
 *
 */


/*
 * transformiert die (_dm x 3_dm)-Matrix hz nach (hz mod pr).
 * Variablen:  hz, Matrix mit Basis und Darstellungen;
 *             pr, Primzahl.
 * Rueckgabe Matrix hz gerechnet modulo pr.
 */
static INT modmat(TL_BYTE *hz, INT pr)
{
	TL_BYTE *_hz;
	INT  il;

	for (il=(INT)_dm*(INT)_dm_drei,_hz=hz;il>(INT)0;il--,_hz++)
		if (*_hz)
			*_hz=(TL_BYTE)TL_MOD(*_hz,pr);
		else
			*_hz=(TL_BYTE)0;
	return OK;
}


/*
 * berechnet mit Hilfe des Gaussalgorithmus ueber GF(pr) die Dimension der
 * p-mod. irred. Darstellung. Der Gaussalgorithmus wird dabei auf die erste
 * (_dm x _dm)-Teilmatrix von hz angewendet, wobei diese eine obere Dreiecks-
 * matrix mit 0 oder 1 auf der Hauptdiagonalen sein muss.
 * Variablen:  hz, Matrix mit Basis und Darstellungen;
 *             pr, Primzahl.
 * Rueckgabe Nummernvektor v der abhaengigen Spalten in hz.
 * Rueckgabewerte: prang, Dimension der p-modular irreduziblen Darstellung.
*/
static INT modgauss(TL_BYTE *hz, TL_BYTE *v, INT pr)
{
	TL_BYTE *_hz,*z_eins,*z_zwei,*_v,qu,su;
	INT z,i,j,k,prang;

	prang=(INT)0;
	for (i=(INT)0;i<_dm;v[i++]=(TL_BYTE)0);

	for (i=_dm-1L,_hz= &hz[IND(_dm-1L,_dm-1L,_dm_drei)],_v= &v[_dm-1];i>(INT)0;
	    i--,_hz -= (_dm_drei+1L),_v--)
		if (*_hz)
		{
			if ((qu = *_hz)!=(TL_BYTE)1)
				for (k=i,z_eins=_hz;k<_dm;k++,z_eins++)
					if (*z_eins)
						*z_eins= TL_DIVP(*z_eins,qu,pr);
			_modgauss(hz,pr,i,1L);
		}
		else
		{
			*_v = (TL_BYTE)i+1;
			++prang;
		}
	if (hz[0]!=(TL_BYTE)1)
	{
		if ((qu=hz[0])==(TL_BYTE)0)
		{
			v[0]=(TL_BYTE)1;
			++prang;
		}
		else
			for (j=(INT)0,_hz=hz;j<_dm;j++,_hz++)
				if (*_hz)
					*_hz = TL_DIVP(*_hz,qu,pr);
	}
	prang=_dm-prang;


	for (i=_dm-2L,_v= &v[_dm-2],_hz= &hz[IND(_dm-2L,_dm-1L,_dm_drei)];i>=(INT)0;
	    i--,_v--,_hz -= (_dm_drei+1L))
		if (*_v == (TL_BYTE) i+1)
		{
			for (j=i+1L,su=(TL_BYTE)0,z_eins=_hz;!su && j<_dm;j++,z_eins++)
				if (*z_eins)
					su=(TL_BYTE)j;
			if (su)
			{
				v[su]=(TL_BYTE)0;
				z_eins= &hz[IND(i,su,_dm_drei)];
				z_zwei= &hz[IND(su,su,_dm_drei)];
				for (j=su;j<_dm;++j)
				{
					z= *z_eins;
					*z_eins++ = *z_zwei;
					*z_zwei++ = z;
				}
			}
			_modgauss(hz,pr,su,1L);
		}
	return(prang);
}


/*
 * Simultane Ermittlung und Anwendung der p-Relationen.
 * (Lineare Algebra!)
 * Variablen:  v, Nummern der abhaengigen Spalten in hz;
 *             pr, Primzahl;
 *             hz, Matrix mit Basis und Darstellungen.
 * Rueckgabe Matrix hz.
 */
static INT p_rel(TL_BYTE *hz, TL_BYTE *v, INT pr)
{
	TL_BYTE  *_v,*_hz,*z_eins,*z_zwei,*z_drei,*z_vier,mu,su;
	INT i,j,k;

	for (i=(INT)0,_v=v,_hz=hz;i<_dm;i++,_v++,_hz += _dm_drei)
		if (*_v == i+1L)
			for (j=(INT)0,z_eins=_hz+_dm,z_zwei=hz+_dm;j<_dm_zwei;j++,z_eins++,z_zwei++)
				if ((mu= *z_eins)!=(TL_BYTE)0)
					for (k=(INT)0,z_drei=hz+i,z_vier=z_zwei;k<=i-1L;k++,z_drei += _dm_drei,z_vier +=
					    _dm_drei)
						if (*z_drei != (TL_BYTE)0)
						{
							su= TL_MULP(mu,*z_drei,pr);
							*z_vier=TL_ADP(su,*z_vier,pr);
						}
	return OK;
}


/*
 * berechnet die Zykelschreibweise einer Permutation liste aus ihrer Listen-
 * schreibweise. Dabei steht eine negative Zahl immer als Ende des Zykels.
 * Variablen:  liste, Pointer auf die Permutation in Listenschreibweise.
 * Rueckgabe Permutation zyk in Zykelschreibweise.
 * Rueckgabewerte: (INT)0, falls kein Fehler aufgetreten ist;
 *             (INT)-109, falls nicht genuegend Speicher vorhanden war.
 */
static INT zykel(TL_BYTE *liste, TL_BYTE *zyk)
{
	TL_BYTE *z;
	INT merk,merk_eins,i,j,n;
	INT fertig;
	TL_BYTE *besucht;

	for (n=(INT)0;liste[n];n++);
	if ((besucht=(TL_BYTE *)TL_calloc((int)n,sizeof(TL_BYTE)))==NULL)
		return no_memory();
	z=zyk;
	i=(INT)0;
	*z++ =(TL_BYTE)(merk=merk_eins=1L);
	fertig=FALSE;
	do
	{
		besucht[i]=(TL_BYTE)1;
		if (liste[i]==merk_eins)
		{
			z--;
			*z++ = -merk;
			for (j=(INT)0;j<n && besucht[j] && liste[j];j++);
			i=j;
			if (i>=n || !liste[i])
				fertig=TRUE;
			else
				*z++ =(TL_BYTE)(merk=merk_eins=i+1L);
		}
		else
		{
			merk= *z++ =(TL_BYTE)liste[i];
			i=liste[i]-1L;
		}
	} while (!fertig && i<n && liste[i]);
	return((INT)0);
}


/*
 * schreibt die in darmod berechneten Matrizen unter Beruecksichtigung der
 * pr-Relationen auf stream. In darmat stehen die Darstellungsmatrizen, falls
 * sie mindestens eine Spalte und eine Zeile enthalten.
 * Rueckgabe Darstellungsmatrizen darmat.
 * Rueckgabewerte: (INT)0, falls alles ohne Fehler durchgefuehrt wurde;
 *             (INT)-109, falls nicht genuegend Speicherplatz vorhanden ist.
 */
static INT p_writemat(TL_BYTE *hz, TL_BYTE *v, TL_BYTE * lambda, INT pr, TL_BYTE *perm, TL_BYTE **darmat, INT prang)
{
	TL_BYTE *dar,*_hz,*vi,*vj,*z_eins,*z_zwei,*z;
	INT i,j,n;
	INT q,klam;

	if (prang)
	{
		for (n=(INT)0;perm[n];n++);
		n++;
		for (q=(INT)0,_hz=hz+_dm;q<2L;q++,_hz += _dm)
		{
			for (i=(INT)0,vi=v,z_eins=_hz,dar=darmat[q];i<_dm;i++,vi++,z_eins += _dm_drei)
				if (! *vi)
					for (j=(INT)0,vj=v,z_zwei=z_eins;j<_dm;j++,vj++,z_zwei++)
						if (! *vj)
							*dar++ = *z_zwei;
		}
	}
	return((INT)0);
}


/*
 * berechnet die pr-modular irreduziblen Darstellungsmatrizen fuer zwei Permu-
 * tationen. Dazu muessen die Spalten der ersten (_dm x _dm)-Teilmatrix von hz
 * die zugrunde gelegte Basis kodieren sowie die naechsten beiden (_dm x _dm)-
 * Teilmatrizen von hz die  zugehoerigen gewoehnlichen darstellenden Matrizen
 * sein. (_dm ist die gewoehnliche Dimension der Darstellung.)
 * Variablen:  hz, Matrix mit der zugrunde gelegten Basis und die zugehoerigen
 *                 gewoehnlichen Darstellungsmatrizen;
 *             lambda, Partition;
 *             pr, Primzahl;
 *             perm, Permutation.
 * Rueckgabe Matrizen darmat der p-modular irreduziblen Darstellungen.
 * Rueckgabewerte: prang, Dimension der p-modular irreduziblen Darstellungen;
 *                 (INT)-109, falls nicht genuegend Speicher vorhanden war.
 */
static INT TL_darmod(TL_BYTE *hz, TL_BYTE *lambda, INT pr, TL_BYTE *perm, TL_BYTE **darmat)
{
	TL_BYTE *v;
	INT prang;

	if ((v=(TL_BYTE *)TL_calloc((int)_dm,sizeof(TL_BYTE)))==NULL)
		return no_memory();
	modmat(hz,pr);
	moddreimat(hz,pr,1L);
	prang=modgauss(hz,v,pr);
	p_rel(hz,v,pr);
	if (p_writemat(hz,v,lambda,pr,perm,darmat,prang))
		return no_memory();
	SYM_free(v);
	return(prang);
} /* TL_darmod */


/*
 * Hauptfunktion zur Berechnung der p-mod. irred. Darstellungen...
 *
 */


/*
 * koordiniert die Berechnung der gew. irred. Darstellungen mit der Berechnung
 * der p-mod. irred.
 * Variablen:  lambda, Partition;
 *             dim, Dimension der gewoehnlichen Darstellungen;
 *             bz, Koeffizientenschema aus alkonmat;
 *             pz, Primzahl,fuer welche die p-mod. Darstellungsmatrizen be-
 *                 rechnet werden;
 *             gzl, #(INT)0, d.h. berechne zuerst die gew. irred. Darstellungen,
 *                  =(INT)0, d.h. gew. irred. Darstellungen existieren schon;
 *             perm, Permutation, fuer die die Darstellungen berechnet werden.
 * Rueckgabe Matrizen darmat der p-modular irreduziblen Darstellungen.
 * Rueckgabewerte: prang, Dimension der Darstellung;
 *                   (INT)-10, falls Pointer auf lambda NULL ist;
 *                   -11L, falls lambda keinen Eintrag hat;
 *                   -12L, falls lambda einen Eintrag kleiner 0 hat;
 *                   -13L, falls lambda keine eigentliche Partition ist;
 *                   // -15L, falls n MAXN uebersteigt;
 *                   -18L, falls dim groesser MAXDM ist;
 *                   -19L, falls Pointer auf bz NULL ist;
 *                   -21L, falls dim kleiner 1 ist;
 *                   -22L, falls Pointer auf darmat NULL ist;
 *                   -23L, falls Pointer auf gzl NULL ist;
 *                   -24L, falls pz keine Primzahl ist;
 *                   -25L, falls pz kleiner 1 ist;
 *                   -26L, falls pz groesser n ist;
 *                   -27L, falls keine ganzzahlige Loesung bei der Berechnung
 *                        der gewoehnlichen Darstellungen existiert;
 *                   (INT)-30, falls Pointer auf perm NULL ist;
 *                   -31L, falls ein Element von perm kleiner 1 ist;
 *                   -32L, falls ein Element von perm groesser n ist;
 *                   -33L, falls Laenge von perm groesser n ist;
 *                 (INT)-109, falls nicht genuegend Speicher zu Verfuegung steht.
 * Bemerkungen:
 *   gzl veraendert sich selbststaendig. Wird darmod mit einem von alkonmat
 *   neuberechneten bz aufgerufen, muss gzl einen von 0 verschiedenen Wert
 *   haben. Sind die ganzzahligen Loesungen der gewoenlichen  Darstellungen
 *   berechnet, so ist gzl=(INT)0, und man kann durch nochmaliges Aufrufen von
 *   darmod mit diesem die Berechnungen der gew. Darstellungen ueberspringen.
 */
static INT darmod(TL_BYTE *lambda, INT dim, TL_BYTE *bz, INT pz, INT *gzl, TL_BYTE *perm, TL_BYTE **darmat)
{
	TL_BYTE  *_hz,*z_eins,*z_zwei,*z_drei;
	INT prang,n,j,i;
	TL_BYTE  *hz;  /* dim x 3dim */
	INT  il;

	/* Abfangen moeglicher Uebergabefehler... */
	if (lambda==NULL)
		return(LmbNul);
	else if (!lambda[0])
		return(LmbEmp);
	for (j=(INT)0,n=(INT)0;lambda[j];j++)
		if (lambda[j]<(TL_BYTE)0)
			return(LmbLt_null);
		else
			n+=lambda[j];
	for (j=1L;lambda[j];j++)
		if (lambda[j]>lambda[j-1])
			return(LmbNRg);

	if (darmat==NULL)
		return(DrtNul);
	else if (gzl==NULL)
		return(GzlNul);
	else if (bz==NULL)
		return(BzNul);
	else if (dim<=(INT)0)
		return(DimLe_null);
	else if (dim>MAXDM)
		return(DmGtMx);
	else if (pz<=(INT)0)
		return(PrmLe_null);
	else if (pz>n)
		return(PrmGtN);
	else if (pz)
	{
		for (j=(INT)0;PZ[j]<=n && PZ[j]<=pz;j++);
		if (pz!=PZ[j-1])
			return(NoPrm);
	}
	else if (perm==NULL)
		return(PerNul);



	for (j=(INT)0;j<n;j++)
		if (perm[j]<=(INT)0)
			return(PerLe_null);
		else if (perm[j]>n)
			return(PerGtN);

	/* Auf geht's... */
	_dm=dim;
	_dm_zwei=2L*_dm;
	_dm_drei=3L*_dm;
	if ((hz=(TL_BYTE *)TL_calloc((int)_dm_drei*(int)_dm,sizeof(TL_BYTE)))==NULL)
		return no_memory();
	for (il=(INT)_dm*(INT)_dm_drei,z_eins=hz,z_zwei=bz;il>(INT)0;il--)
		*z_eins++ = *z_zwei++;
	if (*gzl)
	{
		if (lambda[2])
			for (i=(INT)0,_hz=hz+1,z_zwei=hz+_dm_drei;i<_dm-1L;i++,_hz += (_dm_drei+1L),z_zwei += (_dm_drei+1L))
			{
				for (j=i+1L,z_eins=_hz,z_drei=z_zwei;j<_dm;j++,z_eins++,z_drei += _dm_drei)
					*z_drei = *z_eins;
				for (j=i+1L,z_eins=_hz+_dm,z_drei=z_zwei+_dm;j<_dm;j++,z_eins++,z_drei += _dm_drei)
					*z_drei = *z_eins;
			}
		for (il=(INT)_dm*(INT)_dm_drei,z_eins=bz,z_zwei=hz;il>(INT)0;il--)
			*z_eins++ = *z_zwei++;
		/* Berechnung der gewoehnlichen irreduziblen Darstellung mit Hilfe
		 * einer modularen Arithmetik. */
		*gzl=ganzgaussmod(bz,hz);
		for (i=(INT)0,z_eins=hz,z_zwei=bz;i<_dm;++i)
		{
			for (j=(INT)0;j<_dm;++j)
				*z_eins++ = *z_zwei++;
			for (j=_dm;j<_dm_drei;++j)
				*z_zwei++ = *z_eins++;
		}
	}
	if (!(*gzl))
		/* Berechnung der modular irred. Darstellg. */
		prang=TL_darmod(hz,lambda,pz,perm,darmat);
	else
		prang= *gzl;
	SYM_free(hz);
	return(prang);
}


INT dimension_mod(OP part, OP prim, OP res)
{
	TL_BYTE  *lambda;
	TL_BYTE *slambda;
	INT erg = OK;
	INT i,dm,omaxdim;
	INT ak_j;
	TL_BYTE *bz;
	INT res_dim;
	INT n,p;
	OP w;
	CTO(INTEGER,"dimension_mod",prim);
	CTO(PARTITION,"dimension_mod",part);
	C2R(part,prim,"dimension_mod",res);

	if (S_I_I(prim) < (INT)0)
	{
		fprintf(stderr,"number = %" PRIdPTR "\n",S_I_I(prim));
		error("dimension_mod: prime number (2. parameter) is negativ");
		goto endr_ende;
	}
	if (S_I_I(prim) == (INT)0) /* ordinary dimension */
	{
		erg +=  dimension(part,res);
		goto s2r;
	}
	if (not primep(prim))
	{
		fprintf(stderr,"number = %" PRIdPTR "\n",S_I_I(prim));
		error("dimension_mod: prime number (2. parameter) is not prime");
		goto endr_ende;
	}

	if (equal_parts(part,prim))
	{
		erg += m_i_i((INT)0,res);
		goto s2r;
	}

	omaxdim=MAXDM;
	w = callocobject();
	weight(part,w);
	n = S_I_I(w);
	p = S_I_I(prim);
	lambda = (TL_BYTE *)TL_calloc((int)n, sizeof(TL_BYTE));
	if (lambda == NULL)
	{
		MAXDM=omaxdim;
		erg += ERROR;
		goto endr_ende;
	}

	for (i=(INT)0;i<n;i++) lambda[i]=(INT)0;

	for (i=S_PA_LI(part)-(INT)1,ak_j=(INT)0; i>=(INT)0;i--,ak_j++)
		lambda[ak_j]=S_PA_II(part,i);

	dimension(part,w);
	MAXDM= S_I_I(w);
	freeall(w);
	if (MAXDM<(INT)0)
	{
		MAXDM=omaxdim;
		SYM_free(lambda);
		error("dimension_mod:internal error");

		erg =MAXDM;
		goto endr_ende;
	}

	slambda=(TL_BYTE *)TL_calloc((int)(n+1),sizeof(TL_BYTE));
	if (slambda == NULL)
	{
		MAXDM=omaxdim;
		SYM_free(lambda);
		erg += ERROR;
		goto endr_ende;
	}
	bz=(TL_BYTE *)TL_calloc((int)MAXDM*(int)MAXDM,sizeof(TL_BYTE));
	if (bz == NULL)
	{
		MAXDM=omaxdim;
		SYM_free(slambda);
		SYM_free(lambda);
		erg += ERROR;
		goto endr_ende;
	}
	_assoziiere(lambda,slambda,n);
	if ((dm=k_alkonmat(slambda,bz,p))<(INT)0)
	{
		res_dim=dm;
		MAXDM=omaxdim;
		goto dme;
	}
	if ((res_dim=k_dimmod(bz,MAXDM,p))<(INT)0)
	{
		MAXDM=omaxdim;
		SYM_free(bz);
		SYM_free(slambda);
		SYM_free(lambda);
		goto endr_ende;

	}
dme:
	SYM_free(bz);
	SYM_free(slambda);
	SYM_free(lambda);
	m_i_i(res_dim,res);
	j_zyk((INT)-15,(INT)0,NULL,NULL);

s2r:
	S2R(part,prim,"dimension_mod",res);
	ENDR("dimension_mod");
}


/* input: partition part
 *        prime number: p
 * output integer matrix modulo p, whose rang = degree of mod irrep
 */
INT schnitt_mat(OP part, OP prim, OP res)
{
	TL_BYTE  *lambda;
	TL_BYTE *slambda;
	INT i,j,dm,omaxdim;
	INT ak_j;
	TL_BYTE *bz;
	INT res_dim;
	INT n,p;
	OP w;
	INT erg = OK;

	CE3(part,prim,res,schnitt_mat);

	if (equal_parts(part,prim))
		return m_i_i((INT)0,res);

	C2R(part,prim,"schnitt_mat",res);
	omaxdim=MAXDM;
	w = callocobject();
	weight(part,w);
	n = S_I_I(w);
	p = S_I_I(prim);
	lambda = (TL_BYTE *)TL_calloc((int)n, sizeof(TL_BYTE));
	if (lambda == NULL)
	{
		MAXDM=omaxdim;
		return no_memory();
	}

	for (i=(INT)0;i<n;i++) lambda[i]=(INT)0;

	for (i=S_PA_LI(part)-(INT)1,ak_j=(INT)0; i>=(INT)0;i--,ak_j++)
		lambda[ak_j]=S_PA_II(part,i);

	dimension(part,w);
	MAXDM= S_I_I(w);
	freeall(w);
	/* _dimension(lambda,n); */
	if (MAXDM<(INT)0)
	{
		MAXDM=omaxdim;
		SYM_free(lambda);
		error("dimension_mod:internal error");
		return(MAXDM);
	}

	slambda=(TL_BYTE *)TL_calloc((int)(n+1),sizeof(TL_BYTE));
	if (slambda == NULL)
	{
		MAXDM=omaxdim;
		SYM_free(lambda);
		return no_memory();
	}
	bz=(TL_BYTE *)TL_calloc((int)MAXDM*(int)MAXDM,sizeof(TL_BYTE));
	if (bz == NULL)
	{
		MAXDM=omaxdim;
		SYM_free(slambda);
		SYM_free(lambda);
		return no_memory();
	}
	_assoziiere(lambda,slambda,n);
	if ((dm=k_alkonmat(slambda,bz,p))<(INT)0)
	{
		res_dim=dm;
		MAXDM=omaxdim;
		goto dme;
	}

	erg += m_ilih_m(MAXDM,MAXDM,res);
	for (i=0;i<MAXDM;i++)
		for (j=0;j<MAXDM;j++)
			M_I_I((INT)(bz[i*MAXDM+j]),S_M_IJ(res,i,j));
dme:
	SYM_free(bz);
	SYM_free(slambda);
	SYM_free(lambda);
	S2R(part,prim,"schnitt_mat",res);

	j_zyk((INT)-15,(INT)0,NULL,NULL);
	ENDR("schnitt_mat");
}


/*
 * konjugiert die eigentliche Partition lambda mit Ergebnis slambda.
 * Variablen:  lambda, eigentliche Partition.
 * Rueckgabe slambda.
 */
static INT _assoziiere(TL_BYTE *lambda, TL_BYTE *slambda, INT n)
{
	INT i,j,llen;

	for (i=(INT)0;i<=n;slambda[i++]=(TL_BYTE)0);
	for (llen=(INT)0;llen<n && lambda[llen];llen++);
	for (i=(INT)0;i<lambda[0];++i)
	{
		for (j=(INT)0;j<llen && lambda[j]>=i+1;++j);
		if ((j<n) && (lambda[j] < i+1))
			slambda[i]=(TL_BYTE)j;
		else
			slambda[i]=(TL_BYTE)llen;
	}
	return OK;
}


/*
 * kopiert die (dim x dim)-Matrix quelle auf die (dim x dim)-Matrix ziel.
 * Variablen:  quelle, Matrix;
 *             dim,  Dimension beider Matrizen.
 * Rueckgabe Matrix ziel, Kopie von Matrix quelle.
 */
static INT matcopy(TL_BYTE *ziel, TL_BYTE *quelle, TL_BYTE dim)
{
	INT  i;
	TL_BYTE *bb,*aa;

	bb=ziel;
	aa=quelle;
	for (i=(INT)dim*(INT)dim; i>(INT)0 ; i--)
		*bb++= *aa++;
	return OK;
}


/*
 * berechnet x!.
 * Variable: x,  natuerliche Zahl.
 * Rueckgabewert:  x!.
 */
static INT fak(INT x)
{
	if (x<=1L)
		return(1L);
	else
		return (x*fak(x-1L));
}


/*
 * berechnet aus Tableau y und Partition lambda das naechste Tableau y.
 * Variablen:  y, Tableau;
 *             lambda, Partition.
 * Rueckgabe neues Tableau y, falls ein neues existiert (mtc = TRUE).
 * Rueckgabewerte: (INT)0, falls kein Fehler aufgetreten ist;
 *             (INT)-109,  falls kein Speicherplatz vorhanden war.
 */
static INT nexgitt(TL_BYTE *y, TL_BYTE *lambda, INT *mtc)
{
	TL_BYTE *hilf;
	static TL_BYTE *h=NULL;
	static int _nn = 0;
	INT  m,i,j,l,merke;
	INT durch;

	if (*mtc == 280194L) {
		if (h != NULL) SYM_free(h);
		h = NULL;
		return OK;
	}
	if (_nn != _n)
	{
		if (h != NULL) SYM_free(h);
		h = NULL;
	}

	if (h == NULL)
	{
		h=(TL_BYTE *)TL_calloc(_n+_n,sizeof(TL_BYTE));
		_nn = _n;
	}

	if (!h)
		return no_memory();

	hilf=h+_n;
	memcpy(h,y,_n * sizeof(TL_BYTE));

	if (!(*mtc))
		for (i=(INT)0,j=(INT)0;lambda[i];++i)
		{
			for (l=j;l<j+lambda[i];h[l++]=(TL_BYTE)i);
			j += lambda[i];
		}
	else
	{
		memset(hilf,0,_n * sizeof(TL_BYTE));
		i=_n-(INT)1;
		durch=FALSE;
		do
		{
			++ hilf[m=h[i]];
			if (m>(l=h[i-1]))
			{
				if ((lambda[l]-lambda[m])>
				    (hilf[l]-hilf[m]+(TL_BYTE)1))
				{
					durch=TRUE;
					merke=l;
					j=merke+(TL_BYTE)1;
					while ((hilf[j]==(TL_BYTE)0) ||
					    ((lambda[l]-lambda[j])<
					    (hilf[l]-hilf[j]+(TL_BYTE)2)))
						++j;
					h[i-1]=j;
					--hilf[j];
					++hilf[merke];
					for (l=i;l<_n;++l)
						if (j<_n)
						{
							for (j=(TL_BYTE)0;!hilf[j];++j);
							h[l]=j;
							--hilf[j];
						}
				}
			}
			--i;
			if (i == (INT)0)
				*mtc=FALSE;
		} while (!durch && *mtc);
	}
	memcpy(y,h,_n * sizeof(TL_BYTE) );
	return (INT)0;
}


#endif /* DGTRUE */
