/* FILE:nu.c */
#include "def.h"
#include "macro.h"

static INT mult_apply_co ();

#ifdef SQRADTRUE
INT squareroot(a,b) OP a,b;
/* AK 040291 V1.2 */ /* AK 140891 V1.3 */
/* b becomes the squareroot of a */
{
	INT erg=OK;

	if (check_equal_2(a,b,squareroot,&erg) == EQUAL)
		return erg;

	switch (S_O_K(a))
	{
#ifdef BRUCHTRUE 
	case BRUCH:  
		erg += squareroot_bruch(a,b); 
		break;
#endif /* BRUCHTRUE */
#ifdef INTEGERTRUE 
	case INTEGER:  
		erg += squareroot_integer(a,b); 
		break;
#endif /* INTEGERTRUE */
#ifdef LONGINTTRUE 
	case LONGINT:  
		erg += squareroot_longint(a,b); 
		break;
#endif /* LONGINTTRUE */
	default:
		erg += WTO("squareroot",a); break;
	}
sqende:
	ENDR("squareroot");

}
#endif /* SQRADTRUE */

#ifdef SQRADTRUE
INT ganzsquareroot(a,b) OP a,b;
/* AK 040291 V1.2 */ /* b becomes the integer squareroot of a */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	if (check_equal_2(a,b,ganzsquareroot,&erg) == EQUAL)
		return erg;

	switch (S_O_K(a))
	{
#ifdef INTEGERTRUE 
	case INTEGER:  
		erg+= ganzsquareroot_integer(a,b);
		break;
#endif /* INTEGERTRUE */
#ifdef LONGINTTRUE
	case LONGINT:
		erg += ganzsquareroot_longint(a,b);
		break;
#endif /* LONGINTTRUE */
	default: 
		erg+=  WTO("ganzsquareroot",a); break;
	}
gsqende:
	ENDR("ganzsquareroot");
}
#endif /* SQRADTRUE */


INT max(a,b) OP a,b;
/* AK 280689 V1.0 */ /* AK 010290 V1.1 */
/* b is a copy of the maximum element */

/* AK 140891 V1.3 */
{
	INT erg = OK;
	if (check_equal_2(a,b,max,&erg) == EQUAL)
		return erg;

	switch (S_O_K(a))
	{
#ifdef MATRIXTRUE
	case MATRIX: 
		erg += max_matrix(a,b);
		break;
#endif /* MATRIXTRUE */
#ifdef VECTORTRUE
	case WORD:
	case INTEGERVECTOR:
	case VECTOR: 
		erg += max_vector(a,b); 
		break;
#endif  /* VECTORTRUE */
	default:
		erg += WTO("max",a); break;
	};
	ENDR("max");
}

INT absolute(a,c) OP a,c;
/* AK 100888 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg=OK;
	if (check_equal_2(a,c,absolute,&erg) == EQUAL)
		return erg;

	switch(S_O_K(a))
	{
#ifdef BRUCHTRUE
	case BRUCH: 
		erg += absolute_bruch(a,c); break;
#endif /* BRUCHTRUE */
#ifdef INTEGERTRUE
	case INTEGER: 
		return 
		    m_i_i((S_I_I(a) > 0 ? S_I_I(a): - S_I_I(a)),c);
#endif /* INTEGERTRUE */
#ifdef LONGINTTRUE
	case LONGINT: 
		erg +=  absolute_longint(a,c); break;
#endif /* LONGINTTRUE */
#ifdef MATRIXTRUE
	case MATRIX: 
		erg +=  absolute_matrix(a,c); break;
#endif /* MATRIXTRUE */
#ifdef VECTORTRUE
	case WORD:
	case COMP:
	case VECTOR: 
	case INTEGERVECTOR: 
		erg += absolute_vector(a,c); break;
#endif /* VECTORTRUE */
	default:
		erg += WTO("absolute",a); break;
	}
	ENDR("absolute");
}

INT transpose(a,b) OP a,b;
/* AK 280388 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg;
	if (check_equal_2(a,b,transpose,&erg) == EQUAL)
		return erg;

	switch (S_O_K(a))
	{
#ifdef MATRIXTRUE
	case KOSTKA:
	case KRANZTYPUS:
	case MATRIX: 
		return transpose_matrix(a,b);
#endif /* MATRIXTRUE */
	default:
		{
			printobjectkind(a);
			return error("transpose: wrong type");
		}
	};
}

INT sub(a,b,c)	OP a,b,c;
/* AK 300388 */ /* c = a - b */ /* AK 280689 V1.0 */ /* AK 131289 V1.1 */
/* AK 270291 V1.2 */ /* AK 140891 V1.3 */
{
	INT erg = OK; /* 270291 */
	OP d;
	if  	(S_O_K(a) == INTEGER)  /* AK 201192 */
		if  	(S_O_K(b) == INTEGER)
			/* 	if 	((a != c) && (b != c)) */
			if      ((S_I_I(a) < 10000000L) && (S_I_I(a) > -10000000L))
				if      ((S_I_I(b) < 10000000L) && (S_I_I(b) > -10000000L))
					return m_i_i(S_I_I(a) - S_I_I(b) , c);
	d=callocobject();
	erg += addinvers(b,d);
	erg += add(a,d,c);
	erg += SYMfreeall(d);
	if (erg != OK)
	{
		printobjectkind(a);
		printobjectkind(b);
		error("sub: errors in computing");
	}
	return erg;
}

INT kgv(first,second,d) OP first, second, d;
/* 031186 */ /* d = kgv(first,second) */
/* AK 280689 V1.0 */ /* AK 131289 V1.1 */ /* AK 290591 V1.2 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	OP a=callocobject(), b=callocobject();
	erg += mult(first,second,a);
	erg += ggt(first,second,b);
	erg += div3(a,b,d);
	erg += SYMfreeall(a);
	erg += SYMfreeall(b);
	ENDR("kgv");
}

INT signum(a,c) OP a,c;
/* AK 280689 V1.0 */ /* AK 181289 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg=OK;
	if (check_equal_2(a,c,signum,&erg) == EQUAL)
		return erg;

	switch (S_O_K(a))
	{
#ifdef PERMTRUE
	case PERMUTATION: 
		erg += signum_permutation(a,c);break;
#endif /* PERMTRUE */
	default:
		erg += WTO("signum",a); break;
	};
	ENDR("signum");
}


INT lehmercode(a,b) OP a,b;
/* berechnet den lehmercode entweder einer permuation oder eines vectors
AK 270787 */
/* AK 280689 V1.0 */ /* AK 181289 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg;
	if (check_equal_2(a,b,lehmercode,&erg) == EQUAL)
		return erg;

	switch (S_O_K(a))
	{
#ifdef PERMTRUE
	case PERMUTATION: 
		erg += lehmercode_permutation(a,b);
		break;
	case VECTOR: 
	case INTEGERVECTOR: 
		erg += lehmercode_vector(a,b);
		break;
#endif /* PERMTRUE */
	default: 
		WTO("lehmercode",a); break;
	};
	ENDR("lehmercode");
}

INT add(a,b,d) OP a,b,d;
/* AK 160986 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 270291 V1.2 */ /* AK 070891 V1.3 */
{
	INT erg=OK;
	if 	((a == d)&&(b == d))
	{
		OP c=callocobject();
		*c = *a;
		C_O_K(d, EMPTY);
		erg += add(c,c,d);
		erg += SYMfreeall(c);
		goto add_ende;
	}
	else if	(a == d)
	{
		OP c=callocobject();
		*c = *a;
		C_O_K(d, EMPTY);
		erg += add(c,b,d);
		erg += SYMfreeall(c);
		goto add_ende;
	}
	else if	(b == d)
	{
		OP c=callocobject();
		*c = *b;
		C_O_K(d, EMPTY);
		erg += add(a,c,d);
		erg += SYMfreeall(c);
		goto add_ende;
	}


	else if	(EMPTYP(a))
	{
		erg +=  copy(b,d);
		goto add_ende;
	}
	else if	(EMPTYP(b))
	{
		erg +=  copy(a,d);
		goto add_ende;
	}
	if (not EMPTYP(d))
		if (S_O_K(d) != INTEGER)
			erg += freeself(d);

	switch(S_O_K(b))
	{
#ifdef	MONOPOLYTRUE
	case MONOPOLY: 
		erg += add_monopoly (b,a,d);
		goto add_ende;
#endif /* MONOPOLYTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: 
		erg += add_cyclo (b,a,d);
		goto add_ende;
#endif /* CYCLOTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL: 
		erg += add_sqrad (b,a,d);
		goto add_ende;
#endif /* SQRADTRUE */
#ifdef REIHETRUE
	case REIHE:  /* AK 020893 */
		erg += add_reihe(b,a,d);
		goto add_ende;
#endif  /* REIHETRUE */
	}

	switch(S_O_K(a))
	{
#ifdef	MONOPOLYTRUE
	case MONOPOLY: 
		erg += add_monopoly (a,b,d);
		goto add_ende;
#endif /* MONOPOLYTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: 
		erg += add_cyclo (a,b,d);
		goto add_ende;
#endif /* CYCLOTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL: 
		erg += add_sqrad (a,b,d);
		goto add_ende;
#endif /* SQRADTRUE */
	case INTEGER : 	erg += add_integer(a,b,d); break;
	case LAURENT : 	erg += add_laurent(a,b,d); break;
#ifdef FFTRUE
	case FF: 
		erg += add_ff(a,b,d);
		break;
#endif  /* FFTRUE */
#ifdef REIHETRUE
	case REIHE: 
		erg += add_reihe(a,b,d);
		break;
#endif  /* REIHETRUE */
#ifdef PARTTRUE
	case PARTITION: 
		erg += add_partition(a,b,d);
		break;
#endif  /* PARTTRUE */
#ifdef POLYTRUE
	case GRAL:
	case POLYNOM : 
		erg += add_polynom(a,b,d);
		break;
	case MONOM : 
		erg += add_monom(a,b,d);
		break;
#endif /* POLYTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 
		erg += add_vector(a,b,d);
		break;
#endif /* VECTORTRUE */
#ifdef SCHURTRUE
	case SCHUR : 
		erg += add_schur(a,b,d); 
		break;
#endif  /* SCHURTRUE */
#ifdef LONGINTTRUE
	case LONGINT : 
		erg += add_longint(a,b,d);
		break;
#endif /* LONGINTTRUE */
#ifdef MATRIXTRUE
	case KRANZTYPUS:
	case MATRIX : 
		erg += add_matrix(a,b,d);
		break;
#endif /* MATRIXTRUE */
#ifdef MONOMIALTRUE
	case MONOMIAL : 
		erg += add_monomial(a,b,d);
		break;
#endif /* MONOMIALTRUE */
#ifdef ELMSYMTRUE
	case ELM_SYM : 
		erg += add_elmsym(a,b,d);
		break;
#endif /* ELMSYMTRUE */
#ifdef HOMSYMTRUE
	case HOM_SYM : 
		erg += add_homsym(a,b,d);
		break;
#endif /* HOMSYMTRUE */
#ifdef POWSYMTRUE
	case POW_SYM : 
		erg += add_powsym(a,b,d);
		break;
#endif /* POWSYMTRUE */
#ifdef SCHUBERTTRUE
	case SCHUBERT:
		{
			switch(S_O_K(b))
			{
			case SCHUBERT : 
				erg += add_schubert_schubert(
				    a,b,d);
				break;
			default :
				{ 
				printobjectkind(b);
				return error("add_schubert:wrong second type");
				}
			};
			break;
		}
#endif /* SCHUBERTTRUE */
#ifdef CHARTRUE
	case SYMCHAR: 
		erg += add_symchar(a,b,d);
		break;
#endif
#ifdef BRUCHTRUE
	case BRUCH : 
		erg += add_bruch (a,b,d);
		break;
#endif /* BRUCHTRUE */
	default:
		{
			if (nullp(a)) {
				erg += copy(b,d); 
				break; 
			}
			if (nullp(b)) {
				erg += copy(a,d); 
				break; 
			}
			printobjectkind(a);
			printobjectkind(b);
			return error("add: wrong types");
		}
	};
add_ende:
	if (erg != OK)
	{
		printobjectkind(a);
		printobjectkind(b);
		return error("add: error during computation");
	}
	return erg;
}

INT sort(a) OP a;
/* sortiert das object in aufsteigender reihenfolge AK 270787 */
/* AK 160986 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 070891 V1.3 */
{
	INT erg = OK;

	if (a == NULL)
		return ERROR;

	switch(S_O_K(a))
	{
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 
		erg += sort_vector(a);break;
#endif /* VECTORTRUE */
	default:
		erg += WTO("sort",a); break;
	};
	ENDR("sort");
}

INT length(a,d) OP a,d;
/* 160986 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	OP c;
	if (check_equal_2(a,d,length,&erg) == EQUAL)
		return erg;

	switch(S_O_K(a))
	{
#ifdef LISTTRUE
	case GRAL:
	case HOM_SYM:
	case POW_SYM:
	case ELM_SYM:
	case MONOMIAL:
	case SYMLIST:
	case POLYNOM:
	case MONOPOLY:  /* MD */
	case SCHUBERT:
	case SCHUR: 
		erg += length_list(a,d);
		break;
#endif /* LISTTRUE */
#ifdef PARTTRUE
	case PARTITION : 
		erg += length_partition(a,d);
		break;
#endif /* PARTTRUE */
#ifdef PERMTRUE
	case PERMUTATION : 
		erg += length_permutation(a,d);
		break;
#endif /* PERMTRUE */
#ifdef REIHETRUE
	case REIHE : 
		erg += length_reihe(a,d);
		break;
#endif /* REIHETRUE */
#ifdef SKEWPARTTRUE
	case SKEWPARTITION : 
		erg += length_skewpartition(a,d);
		break;
#endif /* SKEWPARTTRUE */
#ifdef VECTORTRUE
	case WORD:
	case COMP:
	case INTEGERVECTOR:
	case VECTOR : 
		erg += length_vector(a,d);
		break;
#endif /* VECTORTRUE */
	default:
		erg += WTO("length",a); break;
	};
	ENDR("length");
}

INT inhalt(a,b) OP a,b;
/* AK 280689 V1.0 */ /* AK 050390 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg=OK;
	if (check_equal_2(a,b,inhalt,&erg) == EQUAL)
		return erg;

	switch(S_O_K(a))
	{
#ifdef TABLEAUXTRUE
	case TABLEAUX : 
		erg +=  inhalt_tableaux(a,b );
		break;
#endif /* TABLEAUXTRUE */
#ifdef WORDTRUE  
	case WORD : 
		erg +=  inhalt_word(a,b);
		break;
#endif /* WORDTRUE */
	default:
		erg += WTO("inhalt",a); break;
	};
	ENDR("inhalt");
}

INT sum(a,res) OP a,res;
/* AK 280689 V1.0 */ /* AK 050390 V1.1 */ /* AK 120391 V1.2 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	if (check_equal_2(a,res,sum,&erg) == EQUAL)
		return erg;

	switch(S_O_K(a))
	{
#ifdef VECTORTRUE 
	case COMP :
	case INTEGERVECTOR:
	case VECTOR : 
		erg += sum_vector(a,res); 
		break;
#endif /* VECTORTRUE */
#ifdef MATRIXTRUE
	case MATRIX :
	case KOSTKA :
	case KRANZTYPUS :
	case INTEGERMATRIX :
		erg += sum_matrix(a,res); 
		break;
#endif /* MATRIXTRUE */
	default:
		erg += WTO("sum",a); break;
	};

	ENDR("sum");
}


INT conjugate(a,res) OP a,res;
/* AK 280689 V1.0 */ /* AK 281289 V1.1 */ /* AK 120891 V1.3 */
{
	INT erg = OK;

	if (check_equal_2(a,res,conjugate,&erg) == EQUAL)
		goto endr_ende;

	if (EMPTYP(a))
		return OK;

	switch(S_O_K(a))
	{
#ifdef PARTTRUE
	case PARTITION : 
		erg += fastconjugate_partition(a,res);
		break;
#endif /* PARTTRUE */
#ifdef SKEWPARTTRUE
	case SKEWPARTITION :  /* AK 020890 V1.1 */
		erg += b_gk_spa(
		    callocobject(), callocobject(), res);
		erg += conjugate(S_SPA_G(a),S_SPA_G(res));
		erg += conjugate(S_SPA_K(a),S_SPA_K(res));
		break;
#endif /* SKEWPARTTRUE */
#ifdef MONOMTRUE
	case MONOM:	
		erg += b_sk_mo(callocobject(),callocobject(),res);
		erg += copy(S_MO_K(a),S_MO_K(res));
		erg += conjugate(S_MO_S(a),S_MO_S(res));
		break;
#endif /* MONOMTRUE */
#ifdef SCHURTRUE
	case SCHUR: 
	case MONOMIAL: 
	case HOM_SYM: 
	case ELM_SYM:
	case POW_SYM:
		erg += transformlist(a,res,conjugate);
		break;
#endif /* SCHURTRUE */
	default:
		erg +=  WTO("conjugate",a); break;
	};
conj_ende:
	ENDR("conjugate");
}


INT addinvers(a,res) OP a,res;
/* AK 280689 V1.0 */ /* AK 131289 V1.1 */ /* AK 270291 V1.2 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	if (check_equal_2(a,res,addinvers,&erg) == EQUAL)
		return erg;

	if (EMPTYP(a)) 
		return(OK);

	switch(S_O_K(a))
	{
#ifdef BRUCHTRUE
	case BRUCH : 	
		erg += addinvers_bruch(a,res);
		break;
#endif /* BRUCHTRUE */
#ifdef CYCLOTRUE
	case CYCLOTOMIC: 
		erg +=  addinvers_cyclo (a,res);
		break;
#endif /* CYCLOTRUE */
#ifdef FFTRUE
	case FF : 	
		erg += addinvers_ff(a,res);
		break;
#endif /* FFTRUE */
#ifdef INTEGERTRUE
	case INTEGER : 	  
		erg+= addinvers_integer(a,res);
		break;
#endif /* INTEGERTRUE */	
#ifdef LONGINTTRUE
	case LONGINT : 	 
		erg+= addinvers_longint(a,res);
		break;
#endif /* LONGINTTRUE */
#ifdef MATRIXTRUE
	case MATRIX : 	  
		erg+= addinvers_matrix(a,res);
		break;
#endif /* MATRIXTRUE */	
#ifdef MONOMTRUE
	case MONOM :  
		erg+= addinvers_monom(a,res);
		break;
#endif /* MONOMTRUE */
#ifdef MONOPOLYTRUE
	case MONOPOLY: 
		erg+= addinvers_monopoly (a,res);
		break;
#endif /* MONOPOLYTRUE */
#ifdef POLYTRUE
	case ELM_SYM:
	case POW_SYM:
	case MONOMIAL:
	case HOM_SYM:
	case SCHUR:
	case SCHUBERT:
	case GRAL:
	case POLYNOM : 	
		erg += addinvers_polynom(a,res);
		break;
#endif /* POLYTRUE */
#ifdef REIHETRUE /* AK 020893 */
	case REIHE :	
		erg += addinvers_reihe(a,res);
		break;
#endif /* REIHETRUE */
#ifdef SQRADTRUE
	case SQ_RADICAL: 
		erg+=  addinvers_sqrad (a,res);
		break;
#endif /* SQRADTRUE */
#ifdef CHARTRUE
	case SYMCHAR : 	
		erg += addinvers_symchar(a,res);
		break;
#endif /* CHARTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 	 
		erg += addinvers_vector(a,res);
		break;
#endif /* VECTORTRUE */
	default:
		erg +=  WTO("addinvers",a); break;
	};
	ENDR("addinvers");
}

INT binom(oben , unten, d) OP oben, unten, d;
/* AK 041186 */
/* d = oben ! / unten ! * (oben -unten)! */
/* auf integer umgestellt am 120187 */
/* AK 280689 V1.0 */ /* AK 010290 V1.1 */
/* AK 140891 V1.3 */
/* AK 030892 oben may be POLYNOM */
{
	OP a,b,c;
	INT i;
	INT erg = OK;
	if (S_O_K(oben) == POLYNOM) /* AK 030892 */
	{
		if (S_O_K(unten) != INTEGER)
			return(error("binom:unten not INTEGER"));
		if (S_I_I(unten) < 0 )
			return(error("binom:unten < 0"));
		c = callocobject();
		b = callocobject();
		erg += copy(oben,c);
		erg += m_i_i(-1L,b);
		erg += copy(oben,d);
		for (i=1L;i<S_I_I(unten);i++)
		{
			erg += add_apply(b,c);
			erg += mult_apply(c,d);
		}
		erg += fakul(unten,c);
		erg += invers_apply(c);
		erg += mult_apply(c,d);
		erg += SYMfreeall(c);
		erg += SYMfreeall(b);
		return erg;
	}
	if (S_O_K(oben) != INTEGER)
		return(error("binom:oben not INTEGER"));
	else if (S_O_K(unten) != INTEGER)
		return(error("binom:unten not INTEGER"));
	else if (S_I_I(unten) < 0 )
		return(error("binom:unten < 0"));

	if (oben == d)
	{
		c = callocobject();
		*c = *oben;
		C_O_K(d,EMPTY);
		erg += binom(c,unten,d);
		erg += SYMfreeall(c);
		return erg;
	}

	if (unten == d)
	{
		c = callocobject();
		*c = *unten;
		C_O_K(d,EMPTY);
		erg += binom(oben,c,d);
		erg += SYMfreeall(c);
		return erg;
	}

	if (not EMPTYP(d))
		freeself(d);

	if (S_I_I(oben) == (-1L))
	{
		(S_I_I(unten) % 2L == 0L ?
		    M_I_I(1L,d) :
		    M_I_I(-1L,d));
		return(OK);
	}

	if (negp(oben))
	{
		INT schalter = 0L;
		b = callocobject();
		c = callocobject();
		a = callocobject();
		COPY_INTEGER(unten,b); 
		COPY_INTEGER(oben,a);
		INC_INTEGER(a);
		while(S_I_I(b) >= 0L)
		{
			binom(a,b,c);
			(schalter++ % 2L == 0L ? add(c,d,d):
			    sub(d,c,d));
			dec(b);
		};
		goto binomende;
	}



	if (lt(oben,unten)) return(M_I_I(0L,d));
	if (eq(oben,unten)) return(M_I_I(1L,d));


	a = callocobject();
	erg += fakul(oben,a);
	b = callocobject();
	erg += fakul(unten,b);
	c = callocobject();
	erg += sub(oben,unten,c);
	erg += fakul(c,c);

	erg += mult(b,c,c);
	erg += ganzdiv(a,c,d);
binomende:
	erg += SYMfreeall(a); 
	erg += SYMfreeall(b); 
	erg += SYMfreeall(c); 
	ENDR("binom");
}


INT inc(a) OP a;
/* AK 280689 V1.0 */ /* AK 081289 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg = OK;
	switch(S_O_K(a))
	{
#ifdef INTEGERTRUE
	case INTEGER : erg += INC_INTEGER(a);break;
#endif /* INTEGERTRUE */	
#ifdef LONGINTTRUE
	case LONGINT : erg += inc_longint(a);break;
#endif /* LONGINTTRUE */
#ifdef MATRIXTRUE
	case KRANZTYPUS:
	case INTEGERMATRIX:
	case MATRIX : 
		erg += inc_matrix(a);break;
#endif /* MATRIXTRUE */
#ifdef PARTTRUE
	case PARTITION : 
		erg += INC_PARTITION(a);break;
#endif /* PARTTRUE */
#ifdef PERMTRUE
	case PERMUTATION : 
		erg += inc_permutation(a);break;
#endif /* PERMTRUE */
#ifdef REIHETRUE
	case REIHE : 
		erg += inc_reihe(a);break;
#endif /* REIHETRUE */	
#ifdef TABLEAUXTRUE
	case TABLEAUX : 
		erg += inc_tableaux(a);break;
#endif /* TABLEAUXTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 
		erg += inc_vector(a);break;
#endif /* VECTORTRUE */
	default: 
		erg += WTO("inc",a);break;
	};
	ENDR("inc");
}

INT dec(a) OP a;
/* AK 280689 V1.0 */ /* AK 131289 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg = OK;
	switch(S_O_K(a))
	{
#ifdef INTEGERTRUE
	case INTEGER : 
		erg += dec_integer(a);
		break;
#endif /* INTEGERTRUE */	
#ifdef LONGINTTRUE
	case LONGINT : 
		erg += dec_longint(a);
		break;
#endif /* LONGINTTRUE */
#ifdef PARTTRUE
	case PARTITION : 
		erg += dec_partition(a);
		break;
#endif /* PARTTRUE */
#ifdef PERMTRUE
	case PERMUTATION : 
		erg += dec_permutation(a);
		break;
#endif /* PERMTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 
		erg += dec_vector(a);
		break;
#endif /* VECTORTRUE */
	default: 
		erg += WTO("dec",a); break;
	};
	ENDR("dec");
}


INT qdimension(n,d) OP n, d;
/* AL 180393 */
{
	INT erg = OK;
	if (check_equal_2(n,d,qdimension,&erg) == EQUAL)
		return erg;

	switch (S_O_K(n))
	{
#ifdef SCHUBERTTRUE /* AL 180393 */
	case SCHUBERT: 
		erg +=  dimension_schubert(n,d); break;
#endif /* SCHUBERTTRUE */
	default: 
		erg += WTO("qdimension",n); break;
	}
	ENDR("qdimension");
}


INT dimension(n,d) OP n, d;
/* AK 011288 */ /* AK 060789 V1.0 */ /* AK 131289 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	if (check_equal_2(n,d,dimension,&erg) == EQUAL)
		return erg;

	switch (S_O_K(n))
	{
#ifdef PARTTRUE
	case AUG_PART: 
		erg +=  dimension_augpart(n,d);
		break;
	case PARTITION: 
		erg +=  dimension_partition(n,d);
		break;
#endif /* PARTTRUE */
#ifdef SCHUBERTTRUE /* AL 180393 */
	case SCHUBERT: 
		erg +=  dimension_schubert(n,d);
		break;
#endif /* SCHUBERTTRUE */
#ifdef SCHURTRUE /* AK 020890 V1.1 */
	case SCHUR: 
		erg +=  dimension_schur(n,d);
		break;
#endif /* SCHURTRUE */
#ifdef SKEWPARTTRUE /* AK 020890 V1.1 */
	case SKEWPARTITION: 
		erg +=  dimension_skewpartition(n,d);
		break;
#endif /* SKEWPARTTRUE */
	default: 
		erg += WTO("dimension",n); break;
	}
	ENDR("dimension");
}


INT SYM_AK_div(a,b,d) OP a,b,d;
/* AK 280689 V1.0 */ /* AK 071289 V1.1 */ /* AK 250391 V1.2 */
/* AK 140891 V1.3 */
{
	/* AK 031286 als invers*mult */
	INT erg = OK;
	OP c = callocobject();
	erg += invers(b,c);
	erg += mult(a,c,d);
	erg += SYMfreeall(c);
	ENDR("div3");
}

INT quores(a,b,c,d) OP a,b,c,d;
/* c = ganzdiv(a,b)  d = mod(a,b) */
/* AK 050291 V1.2 */ /* AK 140891 V1.3 */
{
	OP e;
	INT erg=OK;
	if (c == d)
		return error("quores: two result in one variable");
	if (a == c)
	{ 
		e =callocobject(); 
		*e = *a; 
		C_O_K(c,EMPTY); 
		erg +=quores(e,b,c,d);
		erg += SYMfreeall(e); 
		goto quoresende;
	}
	if (a == d)
	{ 
		e =callocobject(); 
		*e = *a; 
		C_O_K(d,EMPTY); 
		erg +=quores(e,b,c,d);
		erg += SYMfreeall(e); 
		goto quoresende;
	}
	if (b == c)
	{ 
		e =callocobject(); 
		*e = *b; 
		C_O_K(c,EMPTY); 
		erg +=quores(a,e,c,d);
		erg += SYMfreeall(e); 
		goto quoresende;
	}
	if (b == d)
	{ 
		e =callocobject(); 
		*e = *b; 
		C_O_K(d,EMPTY); 
		erg +=quores(a,e,c,d);
		erg += SYMfreeall(e); 
		goto quoresende;
	}
	if (not EMPTYP(d)) 
		erg += freeself(d);
	if (not EMPTYP(c)) 
		erg += freeself(c);
	if (EMPTYP(a) || EMPTYP(b)) 
		goto quoresende;
	if (nullp(b))	
		return error("quores:null division");
	if (einsp(b)) 
		{
		erg += copy(a,c);
		erg += m_i_i(0L,d);
		goto quoresende;
		}


	switch(S_O_K(a))
	{
#ifdef INTEGERTRUE
	case INTEGER : 	 
		erg += quores_integer(a,b,c,d);break;
#endif /* INTEGERTRUE */	
#ifdef LONGINTTRUE
	case LONGINT : 	
		erg += quores_longint(a,b,c,d);break;
#endif /* LONGINTTRUE */
#ifdef MONOPOLYTRUE
	case MONOPOLY : 	
		erg += quores_monopoly(a,b,c,d);break;
#endif /* MONOPOLYTRUE */
	default:
		erg +=  WTT("quores",a,b);
		break;
	}
quoresende:
	ENDR("quores");
}

INT mod(a,b,c) OP a,b,c;
/* AK 040393 */
{
	OP d;
	INT erg = OK;
	CE3(a,b,c,mod);

	if (matrixp(a)) /* AK 300793 */
		{
		if (S_O_K(b) == INTEGER)
			{
			erg +=  mod_matrix(a,b,c);
			goto mod_ende;
			}
		}
	d = callocobject();
	erg += quores(a,b,d,c);
	erg += SYMfreeall(d);
mod_ende:
	ENDR("mod");
}

INT ganzdiv(a,b,c) OP a,b,c;
/*AK 040393 */
{
	OP d = callocobject();
	INT erg = OK;
	erg += quores(a,b,c,d);
	erg += SYMfreeall(d);
	ENDR("ganzdiv");
}

INT ganzdiv_apply(a,b) OP a,b;
/* AK 151294 */
{
	INT erg = OK;
	if (a == b)
		{
		erg += m_i_i((INT)1,b);
		goto endr_ende;
		}

	switch(S_O_K(b))
		{
		case INTEGER:
			if (S_O_K(a) == INTEGER)
				{ 
				M_I_I(S_I_I(b)/S_I_I(a),b); 
				goto endr_ende; 
				}
			break;
		default:
			break;
		}
	erg += ganzdiv(b,a,b);
	ENDR("ganzdiv_apply");
}


INT fakul(n,d) OP n, d;
/* AK 081086 */ /* d = n! */ /* auf integer umgestellt 120187 */
/* AK 280689 V1.0 */ /* AK 181289 V1.1 */ /* AK 060391 V1.2 */
/* AK 140891 V1.3 */
{
	INT i = 2,res = 1;
	INT erg = OK;

	CTO(INTEGER,"fakul",n);
	CE2(n,d,fakul);

	if (S_I_I(n) < 0L)
	{
		debugprint(n);
		error("fakul:negativ INTEGER");
		return ERROR;
	}

	if (S_I_I(n) > (INT)12)   {
#ifdef LONGINTTRUE
		erg+=fakul_longint(n,d);goto ende;
#else /* LONGINTTRUE */
		return error("fakul:overflow no LONGINT available");
#endif /* LONGINTTRUE */
	}
	switch(S_I_I(n))
		{
		case 0:
		case 1: 	M_I_I(1L,d);break;
		case 2: 	M_I_I(2L,d);break;
		case 3: 	M_I_I(6L,d);break;
		case 4: 	M_I_I(24L,d);break;
		case 5: 	M_I_I(120L,d);break;
		case 6: 	M_I_I(720L,d);break;
		case 7: 	M_I_I(5040L,d);break;
		case 8: 	M_I_I(40320L,d);break;
		case 9: 	M_I_I(362880,d);break;
		case 10: 	M_I_I(3628800L,d);break;
		case 11: 	M_I_I(39916800L,d);break;
		case 12: 	M_I_I(479001600L,d);break;
		}
ende:
	ENDR("fakul");
}


#ifdef LONGINTTRUE
INT fakul_longint(n,res) OP n,res;
/* AK 180888 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140591 V1.2 */ /* AK 140891 V1.3 */
{
	OP i = callocobject();
	INT erg = OK;
	erg += m_i_longint(479001600L,res); /* 12! */
	erg += M_I_I(13L,i);
	while (S_I_I(i) <= S_I_I(n))
	{
		erg += mult_apply(i,res);
		erg += INC_INTEGER(i);
	}
	erg += SYMfreeall(i);
	return erg;
}
#endif /* LONGINTTRUE */

INT ggt_integer(a,b,c) OP a, b, c;
/* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140591 V1.2 */ /* AK 140891 V1.3 */
{
	return(M_I_I(ggt_i(S_I_I(a),S_I_I(b)),c));
}

INT ggt_i(i,j) INT i, j;
/* AK 031186 */ /* c = ggt(a,b) */ /* ok 5/12/86 */
/* AK 280689 V1.0 */ /* AK 061289 V1.1 */
/* AK 140591 V1.2 */ /* AK 140891 V1.3 */
{
	INT neg=1L;
	INT m=i;

	if (i<0L) i *= (-1L);
	if (j<0L) 	{
		j *= (-1L);
		if (m < 0L) neg=(-1L);
	};
	while ((i != 0L) && (j != 0L)) if (i > j) i=i%j;
	else j=j%i;

	if (i > 0L) {
		i *=neg;
		return(i);
	}
	if (j > 0L) {
		j *=neg;
		return(j);
	}
	return(error("ggt_i: both zero"));
}

INT ggt(a,b,c) OP a,b,c;
/* AK 190888 */ /* AK 280689 V1.0 */ /* AK 010290 V1.1 */
/* AK 140591 V1.2 */ /* AK 140891 V1.3 */
{
	OP d;
	OP i,j;
	INT erg=OK,comperg;
	CE3(a,b,c,ggt);
/*
	if (a==c) {
		d = callocobject();
		erg += copy(a,d);
		erg += ggt(d,b,c);
		erg += SYMfreeall(d);
		goto ggtende;
	};
	if (b==c) {
		d = callocobject();
		erg += copy(b,d);
		erg += ggt(a,d,c);
		erg += SYMfreeall(d);
		goto ggtende;
	};

	if (not EMPTYP(c))
		erg += freeself(c);
*/
	if (        (S_O_K(a) == INTEGER)
	    && 
	    (S_O_K(b) == INTEGER)
	    )
	{
		erg+=ggt_integer(a,b,c);
		goto ggtende;
	}

	i = callocobject();
	j = callocobject();
	erg += absolute(a,i);
	erg += absolute(b,j);

	while (posp(i) && posp(j))
	{

		comperg = comp(i,j);
		if (comperg > 0L)
			erg += mod(i,j,i);
		else	
			erg += mod(j,i,j);
	};

	if (posp(i))
		if (negp(a) && negp(b))
			erg += addinvers(i,c);
		else	
			erg += copy(i,c);
	else if (posp(j))
		if (negp(a) && negp(b))
			erg += addinvers(j,c);
		else	
			erg += copy(j,c);
	else	
		erg += error("ggt:two 0");

	erg += SYMfreeall(i);
	erg += SYMfreeall(j);
ggtende:
	ENDR("ggt");

}

INT hoch(basis,expon,ergeb)	OP basis, ergeb, expon;
/* AK 041186 ergeb = basis ** expon */ /* AK 031286  ok */
/* AK 280689 V1.0 */ /* AK 160190 V1.1 */
/* AK 061190 V1.1 hoch erlaubt als exponent auch LONGINT */
/* AK 090891 V1.3 */
{
	INT erg = OK;
	if ((expon == ergeb)&&(expon == basis)) /* AK 061191 */
	{
		OP c=callocobject();
		*c = *expon;
		C_O_K(ergeb,EMPTY);
		erg += hoch(c,c,ergeb);
		erg += SYMfreeall(c);
		goto he;
	};
	if (expon == ergeb)
	{
		OP c=callocobject();
		*c = *expon;
		C_O_K(ergeb,EMPTY); /* AK 071091 ohne copy */
		erg += hoch(basis,c,ergeb);
		erg += SYMfreeall(c);
		goto he;
	};
	if (basis == ergeb)
	{
		OP c=callocobject();
		*c = *basis;
		C_O_K(ergeb,EMPTY);
		erg += hoch(c,expon,ergeb);
		erg += SYMfreeall(c);
		goto he;
	};

	if (not EMPTYP(ergeb))
		freeself(ergeb);
	if ((S_O_K(expon) != INTEGER)&&(S_O_K(expon) != LONGINT))
	{
		printobjectkind(expon);
		return error("hoch:wrong type of expon");
	};
	if (negp(expon))
	{
		OP c=callocobject(), d=callocobject();
		erg += invers(basis,c);
		erg += addinvers(expon,d);
		erg += hoch(c,d,ergeb);
		erg += SYMfreeall(c);
		erg += SYMfreeall(d);
		goto he;
	}
	else if (nullp(expon))
		M_I_I(1L,ergeb);
	else if (einsp(expon))
		erg +=  copy(basis,ergeb);
	else	{
		OP n = callocobject();
		OP a = callocobject();
		erg += copy(expon,n);
		erg += copy(basis,a);
		erg += copy(basis,ergeb);  /* AK 290692 */
		erg += dec(n);  /* AK 290692 */
		while (not nullp(n)) {
			erg += mult_apply(a,ergeb);
			erg += dec(n);
		}
		erg += SYMfreeall(a);
		erg += SYMfreeall(n);
	};
he:
	ENDR("hoch");
}


INT invers(a,b) OP a,b;
/* AK 280689 V1.0 */ /* AK 070789 sonderfaelle 0 und 1 */
/* AK 081289 V1.1 */ /* AK 250391 V1.2 */ /* AK 140891 V1.3 */
{
	OP c;
	INT erg = OK;

	if (nullp(a)) /* AK 070789 */
	{
		debugprint(a);
		return error("invers:first is null");
	}

	if (check_equal_2(a,b,invers,&erg) == EQUAL)
		return erg;

	if (einsp(a)) /* AK 070789 */
		return copy(a,b);

	switch(S_O_K(a))
	{
#ifdef BRUCHTRUE
	case BRUCH : 
		erg += invers_bruch(a,b);
		break;
#endif /* BRUCHTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: 
		erg += invers_cyclo (a,b);
		break;
#endif /* CYCLOTRUE */
#ifdef FFTRUE
	case FF : erg += invers_ff(a,b); break;
#endif /* FFTRUE */
#ifdef LAURENTTRUE
	case LAURENT : erg += invers_laurent(a,b); break;
#endif /* LAURENTTRUE */
#ifdef MONOPOLYTRUE
	case MONOPOLY : erg += invers_monopoly(a,b); break;
#endif /* MONOPOLYTRUE */
#ifdef INTEGERTRUE
	case INTEGER :
	case LONGINT : 
		erg += invers_integer(a,b);
		break;
#endif /* INTEGERTRUE */	
#ifdef MATRIXTRUE
	case KRANZTYPUS:
	case KOSTKA :
	case MATRIX :
		erg += invers_matrix(a,b);
		break;
#endif /* MATRIXTRUE */
#ifdef PERMTRUE
	case PERMUTATION :
		erg += invers_permutation(a,b);
		break;
#endif /* PERMTRUE */
#ifdef POLYTRUE
        case POLYNOM : /* CC */
                erg += invers_POLYNOM(a,b);
                break;

#endif  /* POLYTRUE */

#ifdef	SQRADTRUE
	case SQ_RADICAL: 
		erg += invers_sqrad (a,b);
		break;
#endif /* SQRADTRUE */
	default: erg += WTO("invers",a); break;
	};
	ENDR("invers");
}


INT mult(a,b,d) OP a,b,d;
/* AK 280689 V1.0 */ /* AK 081289 V1.1 */ /* AK 140891 V1.3 */
{
	OP c;
	INT erg = OK;
	if (a == NULL || b == NULL || d == NULL)
		return error("mult: NULL object");

	if (EMPTYP(a))
		return error("mult: b empty object");
	if (EMPTYP(b))
		return error("mult: b empty object");

	/* sonderfaelle bei gleichen variablennamen */
	if	((a == d)&&(b==d))
	{
		c =callocobject(); 
		*c = *a; 
		C_O_K(d,EMPTY);
		erg += mult(c,c,d); 
		erg += SYMfreeall(c); 
		goto aaa;
	}
	else if	(a == d)
	{
		c =callocobject();
		*c = *a;
		C_O_K(d,EMPTY);
		erg += mult(c,b,d);
		erg += SYMfreeall(c);
		goto aaa;
	}
	else if (b == d)
	{
		c =callocobject();
		*c = *b ;
		C_O_K(d,EMPTY);
		erg += mult(a,c,d);
		erg += SYMfreeall(c);
		goto aaa;
	}

	/*freigabe des speichers belegt durch d */
	if (not EMPTYP(d)) 
			erg += freeself(d);


	/* MD */
	switch(S_O_K(b))
	{
#ifdef	MONOPOLYTRUE
	case MONOPOLY: 
		erg += mult_monopoly (b,a,d); goto aaa;
#endif /* MONOPOLYTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: 
		erg += mult_cyclo (b,a,d); goto aaa;
#endif /* CYCLOTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL: 
		erg += mult_sqrad (b,a,d);
		goto aaa;
#endif /* SQRADTRUE */
#ifdef SCHURTRUE
	case SCHUR:	
		erg+=mult_schur(b,a,d); 
		goto aaa;
	case MONOMIAL:
	case POW_SYM :
	case ELM_SYM :
	case HOM_SYM :  
		erg+=mult_symfunc(b,a,d);
		goto aaa;
#endif /* SCHURTRUE */
	}

	switch(S_O_K(a))
	{
#ifdef	MONOPOLYTRUE
	case MONOPOLY:  
		erg+=mult_monopoly (a,b,d);
		break;
#endif /* MONOPOLYTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC:  
		erg+=mult_cyclo (a,b,d);
		break;
#endif /* CYCLOTRUE */
#ifdef	REIHETRUE
	case REIHE:  
		erg+=mult_reihe(a,b,d);
		break;
#endif /* REIHETRUE */
#ifdef	FFTRUE
	case FF:  
		erg+=mult_ff(a,b,d);
		break;
#endif /* FFTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL:  
		erg+=mult_sqrad (a,b,d); break;
#endif /* SQRADTRUE */
#ifdef BRUCHTRUE
	case BRUCH : 	 
		erg+=mult_bruch(a,b,d); break;
#endif  /* BRUCHTRUE */
#ifdef INTEGERTRUE
	case INTEGER : 	 erg+=mult_integer(a,b,d); break;
#endif /* INTEGERTRUE */
#ifdef LAURENTTRUE
	case LAURENT : 	 erg+=mult_laurent(a,b,d); break;
#endif /* LAURENTTRUE */
#ifdef POLYTRUE
	case POLYNOM :  
		erg+=mult_polynom(a,b,d);
		break;
#endif /* POLYTRUE */
#ifdef SCHUBERTTRUE
	case SCHUBERT :
		switch(S_O_K(b))
		{
		case BRUCH:
		case LONGINT:
		case INTEGER:  
			erg+=mult_scalar_schubert(b, a, d);
			break;
		case POLYNOM:  
			erg+=mult_schubert_polynom(a,b,d);
			break;
		case SCHUBERT:  
			erg+=mult_schubert_schubert(a,b,d);
			break;
		};
		break;
#endif /* SCHUBERTTRUE */
#ifdef SCHURTRUE
	case SCHUR : 
		erg += mult_schur(a,b,d); 
		break;
	case MONOMIAL:
	case POW_SYM :
	case ELM_SYM :
	case HOM_SYM :  
		erg+=mult_symfunc(a,b,d);
		break;
#endif  /* SCHURTRUE */
#ifdef MATRIXTRUE
	case KRANZTYPUS:
	case KOSTKA :
	case MATRIX :
		erg+=mult_matrix(a,b,d);
		break;
#endif  /* MATRIXTRUE */
#ifdef LONGINTTRUE
	case LONGINT:    
		erg+=mult_longint(a,b,d);
		break;
#endif /* LONGINTTRUE */
#ifdef PERMTRUE
	case PERMUTATION:  
		erg+=mult_permutation(a,b,d);
		break;
#endif /* PERMTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR :
		switch(S_O_K(b))
		{
#ifdef BRUCHTRUE
		case BRUCH:
#endif /* BRUCHTRUE */
		case LONGINT:
		case INTEGER:   
			erg+=mult_scalar_vector(b,a,d);
			break;
		case VECTOR:    
		case INTEGERVECTOR:    
			erg+=mult_vector_vector(a,b,d);
			break;
#ifdef MATRIXTRUE
		case MATRIX:    
			erg+=mult_vector_matrix(a,b,d);
			break;
#endif /* MATRIXTRUE  */
		default:
			printobjectkind(b);
			error("mult_vector:wrong second type");
			return ERROR;
		};
		break;
#endif /* VECTORTRUE */
#ifdef CHARTRUE
	case SYMCHAR :
		switch(S_O_K(b))

		{
		case BRUCH:
		case LONGINT:
		case INTEGER:  
			erg+=mult_scalar_symchar(b,a,d);
			break;
		case SYMCHAR:  
			erg+=mult_symchar_symchar(a,b,d);
			break;
		};
		break;
#endif /* CHARTRUE */
	case GRAL:
		switch(S_O_K(b))
		{
		case GRAL: 
			erg += mult_gral_gral(a,b,d); 
			break;
		}
		break;

	default:   
		return WTT("mult",a,b);
	}
aaa:
	ENDR("mult");
}


INT scalarproduct(a,b,c) OP a,b,c;
/* AK 010888 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg=OK;
	if 	(a == c)
	{
		OP d =callocobject();
		erg += copy(a,d);
		erg += scalarproduct(d,b,c);
		erg += SYMfreeall(d);
		goto se;
	}
	if 	(b == c)
	{
		OP d =callocobject();
		erg += copy(b,d);
		erg += scalarproduct(a,d,c);
		erg += SYMfreeall(d);
		goto se;
	}

	if (not EMPTYP(c))
		erg += freeself(c);
	switch(S_O_K(a))
	{
#ifdef SCHUBERTTRUE
	case SCHUBERT: 
		erg += scalarproduct_schubert(a,b,c);
		break;
#endif /* SCHURTRUE */
#ifdef SCHURTRUE
	case SCHUR : 
		erg += scalarproduct_schur(a,b,c);
		break;
#endif /* SCHURTRUE */
#ifdef CHARTRUE
	case SYMCHAR : 
		erg += scalarproduct_symchar(a,b,c);
		break;
#endif /* CHARTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 
		erg += scalarproduct_vector(a,b,c);
		break;
#endif /* VECTORTRUE */
	default:
		erg += WTT("scalarproduct",a,b);
		break;
	};
se:
	ENDR("scalarproduct");
}


#ifdef POLYTRUE
INT vander(n,res) OP n,res;
/* AK 300588 */ /* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140891 V1.3 */
{
	INT i,j,erg = OK;
	OP a,b,c;

	if (check_equal_2(n,res,vander,&erg) == EQUAL)
		goto endr_ende;

	CTO(INTEGER,"vander",n);

	m_i_i(1L,res);

	a = callocobject();
	b = callocobject();
	c = callocobject();

	for (i=2L;i<=S_I_I(n);i++)
		for (j=1L;j<i;j++)
		{
			erg += m_iindex_monom(i-1,a);
			erg += m_iindex_monom(j-1,b);
			erg += sub(a,b,c);
			erg += mult(c,res,res);
		}

	erg += SYMfreeall(a); 
	erg += SYMfreeall(b); 
	erg += SYMfreeall(c); 
	ENDR("vander");
}
#endif  /* POLYTRUE */

INT weight(a,b) OP a,b;
/* AK 280689 V1.0 */ /* AK 050390 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg = OK;

	if (check_equal_2(a,b,weight,&erg) == EQUAL) goto endr_ende;

	switch(S_O_K(a))
	{
#ifdef PARTTRUE
	case AUG_PART : 
		erg+=weight_augpart(a,b);
		break;
	case PARTITION : 
		erg+=weight_partition(a,b);
		break;
#endif /* PARTTRUE */
#ifdef SKEWPARTTRUE
	case SKEWPARTITION : 
		erg+=weight_skewpartition(a,b);
		break;
#endif  /* SKEWPARTTRUE */
#ifdef TABLEAUXTRUE
	case TABLEAUX : 
		erg+=weight_tableaux(a,b); break;
#endif /* TABLEAUXTRUE */
	default:
		erg += WTO("weight",a); break;
	};
	ENDR("weight");
}

INT trace(a,b) OP a,b;
/* AK 131289 Spur berechnung */ /* AK 131289 V1.1 */
/* AK 140891 V1.3 */
{
	INT erg = OK;

	if (check_equal_2(a,b,trace,&erg) == EQUAL) goto endr_ende;
	
	switch (S_O_K(a)) {
#ifdef MATRIXTRUE
	case KRANZTYPUS:
	case KOSTKA:
	case MATRIX: 
		erg += trace_matrix(a,b); break;
#endif /* MATRIXTRUE */
	default:
		erg += WTO("trace",a); break;
	};
	ENDR("trace");
}

INT det(a,b) OP a,b;
/* AK 151289 Determinante berechnung */ /* AK 151289 V1.1 */
{
	INT erg = OK;

	if (check_equal_2(a,b,det,&erg) == EQUAL) goto endr_ende;
	

	switch (S_O_K(a)) {
#ifdef MATRIXTRUE
	case KRANZTYPUS:
	case KOSTKA:
	case MATRIX: 
		erg += det_matrix(a,b);
		break;
#endif /* MATRIXTRUE */
	default:
		erg += WTO("det",a); break;
	};
	ENDR("det");
}

INT invers_apply(a) OP a;
/* AK 140591 V1.2 */ /* AK 140891 V1.3 */
{
	INT erg = OK;
	if (EMPTYP(a)) goto endr_ende;
	switch(S_O_K(a))
	{
#ifdef INTEGERTRUE
	case INTEGER : 	  
		erg += invers_apply_integer(a);
		break;
#endif /* INTEGERTRUE */
	default: 
		{
			OP c = callocobject();
			erg += copy(a,c);
			erg += invers(c,a);
			erg += SYMfreeall(c);
		}
	}
	ENDR("invers_apply");
}

INT addinvers_apply(a) OP a;
/* addinvers am platz */ /* AK 201289 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg = OK;
	if (EMPTYP(a))
		return(OK);
	switch(S_O_K(a))
	{
#ifdef BRUCHTRUE
	case BRUCH : 	
		erg+=addinvers_apply_bruch(a);
		break;
#endif /* BRUCHTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: 
		erg+=addinvers_apply_cyclo(a);
		break;
#endif /* CYCLOTRUE */
#ifdef	FFTRUE
	case FF: erg+=addinvers_apply_ff(a); break;
#endif /* FFTRUE */
#ifdef	LAURENTTRUE
	case LAURENT: erg+=addinvers_apply_laurent(a); break;
#endif /* LAURENTTRUE */
#ifdef INTEGERTRUE
	case INTEGER : 	 
		erg+=addinvers_apply_integer(a);
		break;
#endif /* INTEGERTRUE */
#ifdef LONGINTTRUE
	case LONGINT : 	
		erg+=addinvers_apply_longint(a);
		break;
#endif /* LONGINTTRUE */
#ifdef MONOMTRUE
	case MONOM : 
		erg+=addinvers_apply_monom(a);
		break;
#endif /* MONOMTRUE */
#ifdef	MONOPOLYTRUE
	case MONOPOLY: 
		erg+=addinvers_apply_monopoly (a);
		break;
#endif /* MONOPOLYTRUE */
#ifdef POLYTRUE
	case GRAL:
	case MONOMIAL:
	case ELM_SYM:
	case HOM_SYM:
	case POW_SYM:
	case SCHUR:
	case SCHUBERT:
	case POLYNOM : 	
		erg+=addinvers_apply_polynom(a);
		break;
#endif /* POLYTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL: 
		erg+=addinvers_apply_sqrad (a);
		break;
#endif /* SQRADTRUE */
#ifdef CHARTRUE
	case SYMCHAR : 	
		erg+=addinvers_apply_symchar(a);
		break;
#endif /* CHARTRUE */
#ifdef VECTORTRUE
	case INTEGERVECTOR:
	case VECTOR : 	 
		erg+=addinvers_apply_vector(a);
		break;
#endif /* VECTORTRUE */
	default: 
		erg += WTO("addinvers_apply",a); break;
	};
	ENDR("addinvers_apply");
}

static INT mult_apply_co (a,b) OP a,b;
/* hilfsroutine tut normales mult aufrufen */
/* AK 091092 */
{
	OP c = callocobject();
	INT erg;
	*c = *b;
	C_O_K(b,EMPTY);
	erg = mult(a,c,b);
	erg += SYMfreeall(c);
	return erg;
}

INT mult_apply(a,b) OP a,b;
/* b = a * b */ /* AK 201289 V1.1 */ /* AK 190291 V1.2 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	if (a == b) {
		OP c;
		switch S_O_K(a) {
		case INTEGER: 
			if (S_I_I(a) < 10000L) return
			M_I_I(S_I_I(a)*S_I_I(a),a);
		};
		c = callocobject();
		erg += copy(a,c);
		erg += mult_apply(c,b);
		erg += SYMfreeall(c);
		goto me;
	}
	if (EMPTYP(b))
		return OK;
	if (EMPTYP(a))
		return(freeself(b));
maa:
	switch(S_O_K(a)) {
#ifdef BRUCHTRUE
	case BRUCH: 
		erg += mult_apply_bruch(a,b);
		break;
#endif /* BRUCHTRUE */
#ifdef FFTRUE
	case FF: 
		erg += mult_apply_ff(a,b);
		break;
#endif /* FFTRUE */
#ifdef GRALTRUE
	case GRAL: 
		erg += mult_apply_gral(a,b);
		break;
#endif /* GRALTRUE */
	case INTEGER: erg += mult_apply_integer(a,b); break;
#ifdef LONGINTTRUE
	case LONGINT: erg += mult_apply_longint(a,b); break;
#endif /* LONGINTTRUE */
#ifdef MATRIXTRUE
	case MATRIX: erg += mult_apply_matrix(a,b); break;
#endif /* MATRIXTRUE */
#ifdef POLYTRUE
	case POLYNOM: erg += mult_apply_polynom(a,b); break;
#endif /* POLYTRUE */
#ifdef REIHETRUE
	case REIHE: erg += mult_apply_reihe(a,b); break;
#endif /* REIHETRUE */
#ifdef SCHUBERTTRUE
	case SCHUBERT: erg += mult_apply_co(a,b); break;
#endif /* SCHUBERTTRUE */
#ifdef SCHURTRUE
	case HOM_SYM:
	case POW_SYM:
	case ELM_SYM:
	case MONOMIAL:
	case SCHUR: erg += mult_apply_co(a,b); break;
#endif /* SCHURTRUE */
#ifdef CHARTRUE
	case SYMCHAR: erg += mult_apply_symchar(a,b); break;
#endif /* CHARTRUE */
#ifdef	MONOPOLYTRUE
	case MONOPOLY: erg +=  mult_apply_monopoly (a,b); break;
#endif /* MONOPOLYTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: erg +=  mult_apply_cyclo (a,b); break;
#endif /* CYCLOTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL: erg +=  mult_apply_sqrad (a,b); break;
#endif /* SQRADTRUE */
#ifdef VECTORTRUE
	case VECTOR: 
	case INTEGERVECTOR:    
		erg += mult_apply_vector(a,b);
		break;
#endif /* VECTORTRUE */
	default: 
		return WTT("mult_apply",a,b);
	}
me:
	ENDR("mult_apply");
}

INT half_apply(a) OP a;
/* AK 021294 */
{
	OP c;
	INT erg = OK;
	switch S_O_K(a) {
		case INTEGER: M_I_I(S_I_I(a)/(INT)2, a);
			goto ende;
		case LONGINT: half_apply_longint(a);
			goto ende;
		}
	c = callocobject();
	erg += copy(a,c);
	erg += ganzdiv(c,cons_zwei,a);
	erg += SYMfreeall(c);
ende:
	ENDR("half_apply");
}

INT double_apply(a) OP a;
/* AK 010692 */
{
	OP c;
	INT erg = OK;
	switch S_O_K(a) {
	case INTEGER: 
		if (S_I_I(a) > -10000000L)
			if (S_I_I(a) < 10000000L) return
				M_I_I(S_I_I(a)+S_I_I(a),a);
		break;
	case BRUCH: 
		return double_apply(S_B_O(a));
	}
	c = callocobject();
	erg += copy(a,c);
	erg += add_apply(c,a);
	erg += SYMfreeall(c);
	return erg;
}

INT add_apply(a,b) OP a,b;
/* b = a + b */ /* AK 120390 V1.1 */ /* AK 140591 V1.2 */
/* AK 140891 V1.3 */
{
	INT erg = OK;
	OP c;
	if (a == b) 
		return double_apply(a);
	if (EMPTYP(a)) return OK;
	if (EMPTYP(b)) {
		erg += copy(a,b);
		goto add_apply_ende;
	}
	if (nullp(a)) 
		return OK;
	if (nullp(b)) {
		erg += copy(a,b);
		goto add_apply_ende;
	}

	switch(S_O_K(a)) {
#ifdef BRUCHTRUE
	case BRUCH: 
		erg += add_apply_bruch(a,b);
		break;
#endif /* BRUCHTRUE */
#ifdef FFTRUE
	case FF: 
		erg += add_apply_ff(a,b);
		break;
#endif /* FFTRUE */
#ifdef POLYTRUE
	case GRAL: 
		erg += add_apply_gral(a,b) ; 
		break;
#endif /* POLYTRUE */
	case INTEGER: 
		erg += add_apply_integer(a,b);
		break;
#ifdef LONGINTTRUE
	case LONGINT: 
		erg += add_apply_longint(a,b);
		break;
#endif /* LONGINTTRUE */
	case KRANZTYPUS:
#ifdef MATRIXTRUE
	case MATRIX: 
		erg += add_apply_matrix(a,b);
		break;
#endif /* MATRIXTRUE */
#ifdef REIHETRUE
	case REIHE: /* AK 020893 */
		erg += add_apply_reihe(a,b);
		break;
#endif /* REIHETRUE */
#ifdef SCHUBERTTRUE
	case SCHUBERT:  
		erg += add_apply_schubert(a,b);
		break;
#endif /* SCHUBERTTRUE */
#ifdef SCHURTRUE
	case POW_SYM:
	case MONOMIAL:
	case HOM_SYM:
	case ELM_SYM:
	case SCHUR:  
		erg += add_apply_symfunc(a,b);
		break;
#endif /* SCHURTRUE */
#ifdef CHARTRUE
	case SYMCHAR:  
		erg += add_apply_symchar(a,b);
		break;
#endif /* CHARTRUE */
#ifdef POLYTRUE
	case POLYNOM: 
		erg += add_apply_polynom(a,b);
		break;
#endif /* POLYTRUE */
	case VECTOR: 
		erg += add_apply_vector(a,b);
		break;
	case INTEGERVECTOR:    
		erg += add_apply_integervector(a,b);
		break;
#ifdef	MONOPOLYTRUE
	case MONOPOLY: 
		erg += add_apply_monopoly (a,b);
		break;
#endif /* MONOPOLYTRUE */
#ifdef	CYCLOTRUE
	case CYCLOTOMIC: 
		erg += add_apply_cyclo (a,b);
		break;
#endif /* CYCLOTRUE */
#ifdef	SQRADTRUE
	case SQ_RADICAL: 
		erg += add_apply_sqrad (a,b);
		break;
#endif /* SQRADTRUE */
	default:  
		c = callocobject();
		erg += copy(b,c);
		erg += add(a,c,b);
		erg += SYMfreeall(c);
		break;
	}
add_apply_ende:
	ENDR("add_apply");
}


INT multinom(a,b,c) OP a,b,c;
/* AK  040892 */
{
	OP d;
	INT i,erg = OK;
	if (
	    (S_O_K(a) != INTEGER) ||
	    (S_O_K(b) != VECTOR)
	    )
		return WTT(a,b,"multinom");

	for (i=0L;i<S_V_LI(b);i++)
		if (S_O_K(S_V_I(b,i)) != INTEGER)
			return error("multinom:no integer vector");

	erg += m_i_i(1L,c);
	d = callocobject();
	for (i=0L;i<S_V_LI(b);i++)
	{
		erg += fakul(S_V_I(b,i),d);
		erg += mult_apply(d,c);
	}
	erg += invers_apply(c);
	erg += fakul(a,d);
	erg += mult_apply(d,c);
	erg += SYMfreeall(d);
	ENDR("multinom");
}


static INT moebius_rekurs(n) OP n;
/* DL 030593 */
{
	INT erg;
	OP i, h;

	if (nullp(n))
		return 0L;

	if (einsp(n))
		return 1L;

	i = callocobject();
	h = callocobject();
	for (m_i_i(2L, i); mod(n, i, h), !nullp(h); inc(i));
	/* Koennte evtl. durch schnellere Version ersetzt werden, die
	nur Primzahlen durchlaeuft! */

	if (eq(i, n))
	{
		erg = -1L;
		goto fertig;
	}

	mult(i, i, h);
	mod(n, h, h);
	if (nullp(h))
	{
		erg = 0L;
		goto fertig;
	}

	div3(n, i, h);
	erg = -moebius_rekurs(h);

fertig:
	SYMfreeall(h);
	SYMfreeall(i);
	return erg;
}


INT moebius(n, my) OP n, my;
/* DL 030593 */
{
	INT erg = OK;
	if (n == NULL)
		{
		erg += error("moebius: input parameter == NULL");
		goto endr_ende;
		}

	if (my == NULL)
		{
		erg += error("moebius: output parameter == NULL");
		goto endr_ende;
		}

	if (S_O_K(n) != INTEGER && S_O_K(n) != LONGINT)
		{
		WTO("moebius", n);
		goto endr_ende;
		}

	if (negp(n))
		{
		erg += error("moebius: input parameter negative");
		goto endr_ende;
		}

	erg += m_i_i(moebius_rekurs(n), my);
	ENDR("moebius");
}

INT bin_ggt(a,b,c) OP a,b,c;
/* Knuth band 2 2. aufl. p.321 */
{
	OP k,u,v,t;
	INT erg = OK;
	k = callocobject();
	u = callocobject();
	v = callocobject();
	t = callocobject();
	erg += copy(a,u); 
	erg += copy(b,v);
	if (negp(u)) 
		erg += addinvers_apply(u);
	if (negp(v)) 
		erg += addinvers_apply(v);
	erg += m_i_i(0L,k);
	b1:
	if (odd(u)) goto b2;
	if (odd(v)) goto b2;
	erg += half_apply(u);
	erg += half_apply(v);
	erg += inc(k);
	goto b1;
	b2:
	if (odd(u)) { 
		erg += addinvers(v,t); 
		goto b4;}
	else 
		erg += copy(u,t);
	b3:
	erg += half_apply(t);
	b4:
	if (even(t)) goto b3;
	b5:
	if (gt(t,cons_null)) 
		{
		erg += freeself(u);
		erg += swap(t,u);
		erg += sub(u,v,t);
		}
	else 	{
		erg += addinvers(t,v);
		erg += addinvers_apply(t);
		erg += add_apply(u,t);
		}
	/* b6: */
	if (neq(t,cons_null)) goto b3;

	ende:
	erg += hoch(cons_zwei,k,c);
	erg += mult_apply(u,c);
	erg += SYMfreeall(u);
	erg += SYMfreeall(t);
	erg += SYMfreeall(v);
	erg += SYMfreeall(k);
	ENDR("bin_ggt");
}

INT extended_ggt(a,b,c,d,e) OP a,b,c,d,e;
/* c = ggt = da + eb */
/* AK 051294 */
/* Kn Bd2 p.325 */
{
	INT erg = OK;
	OP v,u,t;
	OP q;
x1:
	u = callocobject();
	v = callocobject();
	t = callocobject();
	q = callocobject();
	erg += m_il_v(3L,v);
	erg += m_il_v(3L,t);
	erg += m_il_v(3L,u);
	erg += m_i_i(1L,S_V_I(u,0L)); 
	erg += m_i_i(0L,S_V_I(u,1L));
	erg += copy(a,S_V_I(u,2L));
	erg += m_i_i(0L,S_V_I(v,0L));
	erg += m_i_i(1L,S_V_I(v,1L));
	erg += copy(b,S_V_I(v,2L));
x2:
	if (nullp(S_V_I(v,2L)))
		goto ende;
x3:
	erg += ganzdiv(S_V_I(u,2L),S_V_I(v,2L),q);
	erg += mult(q,v,q);
	erg += sub(u,q,t);
	erg += copy(v,u);
	erg += copy(t,v);
	
	goto x2;
ende:
	erg += copy(S_V_I(u,0L),d);
	erg += copy(S_V_I(u,1L),e);
	erg += copy(S_V_I(u,2L),c);
	erg += SYMfreeall(q);
	erg += SYMfreeall(v);
	erg += SYMfreeall(t);
	erg += SYMfreeall(u);
	ENDR("extended_ggt");
}

#define callocobject callocobject_trace
#undef callocobject
