/* file: poly.c */
#include "def.h"
#include "macro.h"

static struct monom * callocmonom();
#define callocobject callocobject_trace
#undef callocobject
#ifdef MEMCHECK
static INT mem_counter_monom;
#endif /* MEMCHECK */
/* static OP young_ls, young_ps, char_ls, char_ps;*/ /* AK 170893 */
static int tex_poly_var = LETTERS;
static int tex_poly_first_var_index = (INT)0;

#ifdef POLYTRUE
INT get_tex_polynom_parameter(a) INT a; /* AK 090395 */
{
	switch(a)
	{
	case VARTYP: return tex_poly_var;
	case FIRSTVARINDEX: return tex_poly_first_var_index;
       	default:
                        error("get_tex_polynom:wrong parameter");
	}
}

INT set_tex_polynom_parameter(i,a) INT i,a; /* AK 090395 */
{
	switch(i)
	{
	case FIRSTVARINDEX:
		tex_poly_first_var_index = a;
		break;
	case VARTYP:
		if (a == LETTERS)
			tex_poly_var = LETTERS;
		else if (a == NUMERICAL)
			tex_poly_var = NUMERICAL;
		else
			error("set_tex_polynom:VARTYP:wrong parameter");
		break;
	default:
			error("set_tex_polynom:wrong parameter");
	}
}

INT monom_anfang()
/* AK 100893 */
	{
	/* young_ps = char_ls = char_ps = young_ls = NULL; */
#ifdef MEMCHECK
	mem_counter_monom=(INT)0;
#endif /* MEMCHECK */
	return OK;
	}

INT monom_release()
/* AK 100893 */
	{
	INT erg = OK;
/*
	if (char_ls != NULL)
		{ SYMfreeall(char_ls); char_ls = NULL; }
	if (young_ls != NULL)
		{ SYMfreeall(young_ls); young_ls = NULL; }
	if (young_ps != NULL)
		{ SYMfreeall(young_ps); young_ps = NULL; }
	if (char_ps != NULL)
		{ SYMfreeall(char_ps); char_ps = NULL; }
*/
	return erg;
	}


INT monom_ende()
/* AK 100893 */
	{
	INT erg = OK;
#ifdef MEMCHECK 
	if (mem_counter_monom != (INT)0)
		{
		fprintf(stderr,"mem_counter_monom = %ld\n",mem_counter_monom);
		erg += error("monom memory not freed");
		}
#endif /* MEMCHECK */
	return erg;
	}


INT eval_polynom(poly,vec,res) OP poly,vec,res;
/* AK 310588 */
/* ein polynom wird ausgewertet indem der vector
vec eingesetzt wird
bsp 	poly:= 2 [3,0,1]
	vec:= [4,4,5]
	res = 2 * 4^3 * 5 = 640 [0,0,0] */
/* AK 110789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	OP zeiger = poly,monom,c;
	INT i;
	INT erg=OK;

	if ( ( not VECTORP(vec) )|| (S_O_K(poly) != POLYNOM))
		return WTT("eval_polynom",poly,vec);

	if (not EMPTYP(res)) 
		erg += freeself(res); 
	c = callocobject();

	while (zeiger != NULL)
	{
		monom = callocobject(); 
		erg += m_skn_po(S_PO_S(zeiger),S_PO_K(zeiger),NULL,monom);
		if (not VECTORP(S_PO_S(zeiger)))
		{ 
			printobjectkind(S_PO_S(zeiger));
			return error("eval_polynom:self != VECTOR "); 
		}
		for (i=(INT)0;i<S_PO_SLI(zeiger); i++)
		{
			if (i >= S_V_LI(vec)) goto evalpoly3;
			/* i ist < S_V_LI(vec) */
			if (not EMPTYP(S_V_I(vec,i)))
			if (S_PO_SII(zeiger,i) != (INT)0)
				{ 
			if (S_PO_SII(zeiger,i) != 1L)
					{
				erg += hoch(S_V_I(vec,i),S_PO_SI(zeiger,i),c);
				erg += mult_apply(c,S_PO_K(monom)); 
					}
			else /* AK 040892 */
				erg += mult_apply(S_V_I(vec,i),S_PO_K(monom)); 
				}
			M_I_I((INT)0,S_PO_SI(monom,i)); 
		};
evalpoly3:
		insert(monom,res,add_koeff,comp_monomvector_monomvector); 
		zeiger = S_PO_N(zeiger);
	}
	if (nullp(res))
		erg += m_i_i((INT)0,res);
	else if (S_PO_N(res) == NULL) /* AK 311091 */
		if (nullp(S_PO_S(res)))
			{
			if (not EMPTYP(c))
				erg += freeself(c);
			*c = *S_PO_K(res);
			C_O_K(S_PO_K(res),EMPTY);
			erg += freeself(res);
			*res = *c;
			C_O_K(c,EMPTY);
			}
	erg += SYMfreeall(c); 
	ENDR("eval_polynom");
}
#endif /* POLYTRUE */




#ifdef MONOMTRUE
static struct monom * callocmonom()
/* AK 230688 */ /* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	struct monom *c = 
	(struct monom *) SYM_calloc(1,sizeof(struct monom));
	if (c == NULL) 
		error("callocmonom:no mem");
#ifdef MEMCHECK 
	mem_counter_monom++; /* AK 100893 */
#endif /* MEMCHECK */
	return(c);
}

INT m_sk_mo(self,koeff,c) OP self,koeff,c;
/* AK 070690 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	erg += b_sk_mo(callocobject(),callocobject(),c);
	erg += copy(self,S_MO_S(c));  
	erg += copy(koeff,S_MO_K(c));
	ENDR("m_sk_mo");
}
#endif /*  MONOMTRUE */

#ifdef MONOMTRUE
INT b_sk_mo(self,koeff,c) OP self,koeff,c;
/* build_self koeff_monom AK 230688 */
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	OBJECTSELF d;
	INT erg = OK;

	d.ob_monom = callocmonom(); /* AK 161189 */

	erg += b_ks_o(MONOM,d,c);
	C_MO_S(c,self);
	C_MO_K(c,koeff);
	ENDR("b_sk_mo");
}
#endif	 /* MONOMTRUE */

#ifdef MONOMTRUE
INT objectwrite_monom(f,a) FILE *f; OP a;
/* AK 210690 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	fprintf(f,"%ld ",(INT)MONOM);
	erg += objectwrite(f,S_MO_K(a)); 
	erg += objectwrite(f,S_MO_S(a)); 
	ENDR("objectwrite_monom");
}
#endif /* MONOMTRUE */

#ifdef MONOMTRUE
INT objectread_monom(f,a) FILE *f; OP a;
/* AK 210690 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	erg += b_sk_mo(callocobject(),callocobject(),a);
	erg += objectread(f,S_MO_K(a)); 
	erg += objectread(f,S_MO_S(a)); 
	if (erg != OK)
		EDC("objectread_monom");
	return erg;
}
#endif /* MONOMTRUE */

#ifdef MONOMTRUE
INT scan_monom(c) OP c;
/* AK 230688 */ /* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	OBJECTKIND kind;

	b_sk_mo(callocobject(),callocobject(),c);
	printeingabe("what kind of monom");
	kind = scanobjectkind();

	scan(kind,S_MO_S(c));
	printeingabe("what kind of coefficent");
	kind = scanobjectkind();
	scan(kind,S_MO_K(c));
	return(OK);
}
#endif	 /* MONOMTRUE */



#ifdef MONOMTRUE
INT fprint_monom(f,monom) FILE *f; OP monom;
/* AK 230688 */ /* AK 100789 V1.0 */ /* AK 071289 V1.1 */
/* AK 040391 V1.2 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	if (dynamicp(S_MO_K(monom))) /* AK zum unterscheiden */
		fprintf(f,"(");
	erg += fprint(f,S_MO_K(monom)); 
	if (dynamicp(S_MO_K(monom))) /* AK 240795 */
		fprintf(f,")");
	if (f==stdout)
	{
		if (zeilenposition > (INT)70) {
			zeilenposition = (INT)0; fprintf(stdout,"\n"); }
		else zeilenposition++;
	}
	fprintf(f," "); 
	erg += fprint(f,S_MO_S(monom));
	if (f==stdout)
	{
		if (zeilenposition > (INT)70) {
			zeilenposition = (INT)0; 
			fprintf(stdout,"\n"); 
			}
	}
	ENDR("fprint_monom");
}
#endif	/* MONOMTRUE */

#ifdef MONOMTRUE
INT tex_monom(monom) OP monom;
/* AK 230688 */ /* AK 100789 V1.0 */ /* AK 191289 V1.1 */
/* AK 070291 V1.2 tex to texout */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	if (POLYNOMP(S_MO_K(monom)))
		  fprintf(texout,"(");
	erg += tex(S_MO_K(monom)); 
	fprintf(texout,"\\ ");
	texposition += (INT)2; 
	if (POLYNOMP(S_MO_K(monom))) /* AK 240795 */
		  fprintf(texout,")");
	erg += tex(S_MO_S(monom)); 
	ENDR("tex_monom");
}
#endif	/* MONOMTRUE */

#ifdef POLYTRUE
INT m_s_po(self,poly) OP self,poly;
/* AK 120790 V1.1 */ /* AK 200891 V1.3 */
	{
	INT erg = OK;
	OP s = callocobject();
	erg += copy(self,s);
	erg += b_s_po(s,poly);
	ENDR("m_s_po");
	}



INT b_s_po(self,poly) OP self,poly;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	erg += b_sn_l(callocobject(),NULL,poly);
	C_O_K(poly,POLYNOM);
	erg += b_sk_mo(self,callocobject(),S_L_S(poly));
	M_I_I(1L,S_PO_K(poly));
	ENDR("b_s_po");
}
#endif	 /* POLYTRUE */

#ifdef MONOMTRUE
INT freeself_monom(a) OP a;
/* AK 100789 V1.0 */ /* AK 211189 V1.1 */ /* AK 140891 V1.3 */
{
	OBJECTSELF d; 
	INT erg = OK;
	d = S_O_S(a); 

	erg += SYMfreeall(S_MO_S(a)); 
	erg += SYMfreeall(S_MO_K(a)); 
#ifdef MEMCHECK
	mem_counter_monom--; /* AK 100893 */
#endif /* MEMCHECK */
	SYM_free(d.ob_monom); 
	C_O_K(a,EMPTY); 
	ENDR("freeself_monom");
}



INT comp_monom(a,b) OP a,b;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */
/* AK 080390 bei gleichheit von self wird koeff verglichen */ 
/* AK 200891 V1.3 */
{
	INT erg;
	erg = comp(S_MO_S(a), S_MO_S(b));
	if (erg != (INT)0) 
		return(erg);
	return(comp(S_MO_K(a),S_MO_K(b)));
}



INT copy_monom(a,b) OP a,b;
/* AK 100789 V1.0 */ /* AK 071289 V1.1 */ /* AK 140891 V1.3 */
{
	INT erg = OK;
	if (S_O_K(S_MO_S(a)) != INTEGERVECTOR)
		erg += m_sk_mo(S_MO_S(a), S_MO_K(a), b);
	else {
		erg += b_sk_mo(callocobject(),callocobject(),b);
		erg += copy(S_MO_K(a), S_MO_K(b));
		erg += copy_integervector(S_MO_S(a), S_MO_S(b));
		}
	ENDR("copy_monom");
}



OP s_mo_s(a) OP a;
/* select_monom_self */ /* AK 100789 V1.0 */ /* AK 191289 V1.1 */
/* AK 200891 V1.3 */
{
	OBJECTSELF c;
	if (a == NULL) 
		return error("s_mo_s:a == NULL"),(OP)NULL;
	if (S_O_K(a) != MONOM) 
		return error("s_mo_s:a  != MONOM"),(OP)NULL;
	c = s_o_s(a);
	return(c.ob_monom->mo_self);
}

OP s_mo_k(a) OP a;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	OBJECTSELF c;
	if (a == NULL) 
		return error("s_mo_k:a == NULL"),(OP)NULL;
	if (S_O_K(a) != MONOM) 
		return error("s_mo_k:a  != MONOM"),(OP)NULL;
	c = s_o_s(a);
	return(c.ob_monom->mo_koeff);
}

/* the following routines only work with self part which are VECTORobjects */
OP s_mo_sl(a) OP a; 
/* AK 200891 V1.3 */
{
	return s_v_l(s_mo_s(a)); 
}
INT s_mo_sli(a) OP a; 
/* AK 200891 V1.3 */
{
	return s_v_li(s_mo_s(a)); 
}
OP s_mo_si(a,i) OP a;INT i; 
/* AK 200891 V1.3 */
{
	return s_v_i(s_mo_s(a),i); 
}
INT s_mo_sii(a,i) OP a;INT i; 
/* AK 200891 V1.3 */
{
	return s_v_ii(s_mo_s(a),i); 
}


INT s_mo_ki(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(s_i_i(s_mo_k(a))); 
}

INT c_mo_s(a,b) OP a,b; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	OBJECTSELF c; 
	c = s_o_s(a); 
	c.ob_monom->mo_self = b; 
	return(OK); 
}

INT c_mo_k(a,b) OP a,b; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	OBJECTSELF c; 
	c = s_o_s(a); 
	c.ob_monom->mo_koeff = b; 
	return(OK); 
}

#endif /* MONOMTRUE */

#ifdef MONOMTRUE
INT mult_scalar_monom(a,b,c) OP a,b,c;
/* AK 111188 */
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	if (not EMPTYP(c)) 
		freeself(c);
	b_sk_mo(callocobject(),callocobject(),c);
	copy(S_MO_S(b),S_MO_S(c)); 
	return mult(S_MO_K(b),a,S_MO_K(c));
}
#endif	/* MONOMTRUE */

#ifdef POLYTRUE 
INT mult_polynom(a,b,d) OP a,b,d;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 150591 V1.2 */
/* AK 080891 V1.3 */
/* CC 210595 fuer die rationnellen Funktionen*/

{
	INT erg = OK;
	OP tp1, tp2;
	if (nullp(a))
		return m_i_i((INT)0,d); /* AK 110991 */

	switch(S_O_K(b)) {
	case INTEGER:
	case LONGINT:
		erg+=mult_scalar_polynom(b,a,d);
		break;
#ifdef BRUCHTRUE
	case BRUCH: 
               if((!scalarp(S_B_O(b))) ||(!scalarp(S_B_U(b))))
                {
                        tp1=callocobject();tp2=callocobject();
                        M_I_I(1L,tp1);m_ou_b(a,tp1,tp2);
                        copy(tp2,a);
                        SYMfreeall(tp1);SYMfreeall(tp2);
                        erg += mult_bruch_bruch(a,b,d);
                }
                else
                        erg+=mult_scalar_polynom(b,a,d);
                break;
#endif /* BRUCHTRUE */
	case POLYNOM: erg+=mult_polynom_polynom(a,b,d);
		break;
#ifdef SCHUBERTTRUE
	case SCHUBERT: erg+=mult_schubert_polynom(b,a,d); /* AK 190690 */
		break;
#endif /* SCHUBERTTRUE */
#ifdef GRALTRUE
	case GRAL:	erg += mult_scalar_gral(a,b,d); 
		break; /* AK 170693 */
#endif /* GRALTRUE */
#ifdef SCHURTRUE
	case HOM_SYM:
	case MONOMIAL:
	case POW_SYM:
	case ELM_SYM:
	case SCHUR: erg += mult_scalar_schur(a,b,d); 
		break; /* AK 110692 */
#endif /* SCHURTRUE */
#ifdef MATRIXTRUE
	case MATRIX: erg+=mult_scalar_matrix(a,b,d);
		break;
#endif /* MATRIXTRUE */
#ifdef MONOMTRUE
	case MONOM: erg += mult_scalar_monom(a,b,d); 
		break; /* AK 110692 */
#endif /* MONOMTRUE */
	default: 
		erg += WTO("mult_polynom",b);
	}
	ENDR("mult_polynom");
}

INT mult_scalar_polynom(a,poly,res) OP a,poly,res;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 150591 V1.2 */ 
/* AK 200891 V1.3 */
{
	INT erg = OK;
	if (check_equal_3(a,poly,res,mult_scalar_polynom,&erg) == EQUAL)
                goto ee;
	if ((nullp(a))|| (nullp(poly)))
		{
		erg +=  m_i_i((INT)0,res); /* AK 110991 */
		goto ee;
		}
	erg += trans2formlist(a,poly,res,mult);
ee:
	ENDR("mult_scalar_polynom");
}

INT mult_polynom_polynom(eins,zwei,c) OP eins, zwei, c;
/* AK 100789 V1.0 */ /* AK 081289 V1.1 */ /* AK 150591 V1.2 */
/* AK 140891 V1.3 */
{
	OP z, ez, zz;
	INT erg = OK;

	if ((eins == c)||(zwei ==c))
		return ERROR;

	if (nullp(zwei)) /* AK 260494 */
		return OK;

	zz = zwei;
	while (zz != NULL)
	{
		z = callocobject();
		erg += copy_list(eins,z); /* eins ist polynom */

		ez = z;
		while (ez != NULL)
		{
			erg += add_apply(  S_PO_S(zz), S_PO_S(ez));
			erg += mult_apply( S_PO_K(zz), S_PO_K(ez));
			ez = S_PO_N(ez);
		};
		insert(z,c,add_koeff,comp_monomvector_monomvector);
		zz = S_PO_N(zz);
	};
	ENDR("mult_polynom_polynom");
}



INT numberofvariables(a,n) OP a,n;
/* AK 250692 */
/* n becomes the number of variables of the POLYNOM a */
{
	INT i,erg = OK;
	OP z;

	CTO(POLYNOM,"numberofvariables",a);

	erg += m_i_i((INT)0,n); /* frees the result automaticaly */
	if (S_L_S(a) == NULL)
		goto ne;
	z = a;
	while (z != NULL)
		{
		i = S_PO_SLI(z)-1L;
		while (S_PO_SII(z,i) == (INT)0) 
			i--;
		if (i+1L > S_I_I(n)) 
			erg += M_I_I(i+1L,n);
		z = S_PO_N(z);
		}
ne:
	ENDR("numberofvariables");
}
#endif /* POLYTRUE */
#ifdef POLYTRUE
INT mult_disjunkt_polynom_polynom(a,b,c) OP a, b, c;
/* AK 300889 */
/* die beiden polynome haben disjunkte alphabete */
/* beim c werden die alphabete hintereinandergehaengt */
/* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	OP z, ap, bp;
	OP n,l;
	INT i;

	if (S_O_K(a) != POLYNOM) 
		return error("mult_disjunkt_polynom_polynom:a != POLYNOM");
	if (S_O_K(b) != POLYNOM) 
		return error("mult_disjunkt_polynom_polynom:b != POLYNOM");
	if (not EMPTYP(c)) 
		freeself(c);
/* first check the number of variables of a */ /* AK 250692 */
	n = callocobject();
	numberofvariables(a,n);

	bp = b;
	l = callocobject();
	while (bp != NULL)
	{
		z = callocobject();
		copy(a,z);

		ap = z;
		while (ap != NULL)
		{
			if (S_PO_SLI(ap) < S_I_I(n))   /* AK 250692 */
				{
				m_il_nv(S_I_I(n),l);
				for (i=(INT)0;i<S_PO_SLI(ap);i++)
					M_I_I(S_PO_SII(ap,i),S_V_I(l,i));
				append(l,S_PO_S(bp),S_PO_S(ap));
				}
			else
				append(	S_PO_S(ap), S_PO_S(bp), S_PO_S(ap));
			mult(	S_PO_K(ap), S_PO_K(bp), S_PO_K(ap));
			ap = S_PO_N(ap);
		};

		add_apply(z,c);
		SYMfreeall(z);

		bp = S_PO_N(bp);
	};
	SYMfreeall(n);
	SYMfreeall(l);
	return(OK);
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT mult_apply_polynom_scalar(a,b) OP a,b;
/* AK 160290 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	OP c;
	c = callocobject();
	*c = *b;
	C_O_K(b,EMPTY);
	erg += copy_polynom(a,b);
	erg += mult_apply_scalar_polynom(c,b);
	erg += SYMfreeall(c);
	ENDR("mult_apply_polynom_scalar");
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT mult_apply_polynom(a,b) OP a,b;
/* AK 140290 V1.1 */ /* AK 140591 V1.2 */ /* AK 220791 V1.3 */
{
	INT erg = OK; /* zuweisung AK091091 */
mapa:
	if (nullp(b))
		return m_i_i((INT)0,b); /* AK 120991 */
	if (S_L_S(a) == NULL) /* AK 110394 */
		return m_i_i((INT)0,b); 
	switch(S_O_K(b)) {
		case BRUCH:
		case LONGINT:
		case INTEGER:  /* a ist scalar, b ist poly */
			erg+= mult_apply_polynom_scalar(a,b); 
			goto map_ende;
		case POLYNOM: 
			erg+= mult_apply_polynom_polynom(a,b); 
			goto map_ende;
		default:
			{
			OP c = callocobject();
			*c = *b; C_O_K(b,EMPTY);
			erg = mult(a,c,b);
			if (erg == ERROR) {
				printobjectkind(c);
				error("mult_apply_polynom:wrong second type");
				}
			SYMfreeall(c); return erg;
			}
		}
map_ende:
	ENDR("mult_apply_polynom");
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT mult_apply_polynom_polynom(a,b) OP a,b;
/* AK 140290 V1.1 */ /* AK 170591 V1.2 */ /* AK 200891 V1.3 */
{
	OP c;
	INT erg=OK,i;
	if (S_PO_N(a) == NULL) /* AK 100394 */
		{
		c = b;
		while (c != NULL)
			{
			erg += mult_apply(S_PO_K(a),S_PO_K(c));
			erg += add_apply(S_PO_S(a),S_PO_S(c)); 
			c = S_PO_N(c);
			}
		goto mape;
		}

	c = callocobject();
	*c = *b;
	C_O_K(b,EMPTY);
	erg += mult_polynom_polynom(a,c,b); 
	erg += SYMfreeall(c);
mape:
	ENDR("mult_apply_polynom_polynom");
}
#endif /* POLYTRUE */

INT mult_apply_scalar_monom(a,b) OP a,b; 
/* AK 150290 V1.1 */ /* AK 200891 V1.3 */
{
	return(mult_apply(a,S_MO_K(b)));
}

#ifdef POLYTRUE
INT mult_apply_scalar_polynom(a,b) OP a,b;
/* AK 201289 V1.1 */ /* AK 200891 V1.3 */
{
	OP z = b;
	INT erg = OK;
maspa:
	if (nullp(a))
		return m_i_i((INT)0,b); /* AK 110991 */
	while (z != NULL)
		{
		erg += mult_apply(a,S_L_S(z));
		z = S_L_N(z);
		}
	ENDR("mult_apply_scalar_polynom");
}
#endif /* POLYTRUE */


#ifdef POLYTRUE
INT scan_polynom(poly) OP poly;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
/* AK 201093: with add_apply */
{
	char antwort[2];
	INT erg = OK;
	OP d;


	erg += 
	printeingabe("input of a POLYNOM object as a sum of MONOM objects");
	erg += init(POLYNOM,poly);
	d = callocobject();
spa:
	erg += b_sn_l(callocobject(),NULL,d);
	C_O_K(d,POLYNOM);
	erg += scan(MONOM,S_L_S(d));
	erg += add_apply(d,poly);
spe:
	erg += printeingabe("one more monom  y/n");
	skip_comment(); /* AK 210395 */
	scanf("%s",antwort);
	if (antwort[0]  == 'y')
		goto spa;
	if (antwort[0]  == 'j')
		goto spa;
	if (antwort[0]  != 'n')
		goto spe;
	erg += SYMfreeall(d);
	ENDR("scan_polynom");
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT scan_fastpolynom(poly) OP poly;
/* AK 211093 */
{
	char antwort[2];
	INT erg = OK;
	OBJECTKIND kind;
	OP d;


	erg += 
	printeingabe("input of a POLYNOM object as a sum of MONOM objects");
	printeingabe("what kind of coefficent");
	kind = scanobjectkind();
	erg += init(POLYNOM,poly);
	d = callocobject();
spa:
	erg += b_skn_po(callocobject(),callocobject(),NULL,d);
	printeingabe("enter the exponent vector of the polynom");
	erg += scan(INTEGERVECTOR,S_PO_S(d));
	printeingabe("enter the coefficent of the polynom");
	scan(kind,S_PO_K(d));
	erg += add_apply(d,poly);
spe:
	erg += printeingabe("one more monom  y/n");
	skip_comment(); /* AK 210395 */
	scanf("%s",antwort);
	if (antwort[0]  == 'y')
		goto spa;
	if (antwort[0]  == 'j')
		goto spa;
	if (antwort[0]  != 'n')
		goto spe;
	erg += SYMfreeall(d);
	ENDR("scan_fastpolynom");
}
#endif /* POLYTRUE */


INT add_monom(a,b,c) OP a,b,c;
/* AK 201289 V1.1 */ /* AK 050891 V1.3 */
{
#ifdef MONOMTRUE
	INT erg = OK;
	switch (S_O_K(b)) {
#ifdef HOMSYMTRUE
		case HOM_SYM: erg += add_monom_homsym(a,b,c);break;
#endif /* HOMSYMTRUE */
#ifdef SCHURTRUE
		case SCHUR: erg += add_monom_schur(a,b,c);break;
#endif /* SCHURTRUE */
		default: return(error("add_monom:"));
		}
	ENDR("add_monom");
#endif /* MONOMTRUE */
}

#ifdef SCHURTRUE
INT add_monom_schur(a,b,d) OP a,b,d;
/* for all partition typ polynomials */
/* AK 201289 V1.1 */ /* AK 050891 V1.3 */
{ 
	INT erg = OK;
	OP c = callocobject(); 
	erg += init(S_O_K(b),c);
	erg += copy_monom(a,S_L_S(c)); 
	erg += add(c,b,d);
	erg += SYMfreeall(c);
	ENDR("add_monom_schur");
}
#endif /* SCHURTRUE */

#ifdef MONOMTRUE
INT add_koeff(a,b) OP a,b;
/* eqhandle bei insert bei polynomen, monopoly
addiert die beiden koeffizienten der monome a und b
nach dem monom b */
/* AK 100789 V1.0 */ /* AK 231189 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg = OK;
	CTO(MONOM,"add_koeff",a);
	CTO(MONOM,"add_koeff",b);
	erg += add_apply(S_MO_K(a), S_MO_K(b));
	erg += freeself_monom(a);
	if (nullp(S_MO_K(b))) 
		erg += freeself_monom(b);
	ENDR("add_koeff");
}
#endif	/* MONOMTRUE */

#ifdef POLYTRUE
INT add_scalar_polynom(a,b,c) OP a,b,c;
/* a scalar, b polynom, c empty */
/* AK 060891 V1.3 */
{
	INT erg = OK;
	OP d;
	if (S_O_K(b) != POLYNOM)
		return WTO("add_scalar_polynom",b);

	if (nullp(a))
		return copy(b,c);

	d = callocobject();
	erg += m_scalar_polynom(a,d);
	erg += add_polynom_polynom(d,b,c);
	erg += SYMfreeall(d);
	ENDR("add_scalar_polynom");
}

INT add_polynom(a,b,c) OP a,b,c;
/* AK 110789 V1.0 */ /* AK 191289 V1.1 */ /* AK 290591 V1.2 */
/* AK 060891 V1.3 */
/*CC 210595 Fuer die rationnellen Funktionen*/

{
	INT erg = OK;
	OP tp1,tp2;
	if (nullp(a))
		return copy(b,c);
	if (nullp(b))
		return copy(a,c);

	switch (S_O_K(b))
	{
	case INTEGER:
	case LONGINT:
		 erg += add_scalar_polynom(b,a,c); break; /* AK 060891 */
	case BRUCH:
                if((!scalarp(S_B_O(b)))
                ||(!scalarp(S_B_U(b))))
                {
                        tp1=callocobject();tp2=callocobject();
                        M_I_I(1L,tp1);m_ou_b(a,tp1,tp2);
                        copy(tp2,a);
                        SYMfreeall(tp1);SYMfreeall(tp2);
                        erg += add_bruch_bruch(a,b,c);
                }
                else
                        erg += add_scalar_polynom(b,a,c); break; /* AK 060891 */
                break;

	case GRAL:
	case POLYNOM: erg+= add_polynom_polynom(a,b,c);break;
	default: 
		{
			printobjectkind(b);
			return error("add_polynom:wrong second type");
		}
	}
	ENDR("add_polynom");
}
#endif /* POLYTRUE */


#ifdef POLYTRUE
INT add_polynom_polynom(a,b,c) OP a,b,c;
/* works for all types */
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 290591 V1.2 */
/* AK 050891 V1.3 */
{
	INT erg=OK;
	OP d;
/*
	if ( not (
		((S_O_K(a) == POLYNOM) && (S_O_K(b) == POLYNOM))
		||
		((S_O_K(a) == GRAL) && (S_O_K(b) == GRAL))
	))
		erg+= WTT("add_polynom_polynom",a,b);
*/
	if (
		(not LISTP(a)) 
		||
		(not LISTP(b)) 
	   )
		erg+= WTT("add_polynom_polynom",a,b);
	d = callocobject();
	if (not EMPTYP(c)) 
		erg += freeself(c);
	erg += copy_list(a,d); 
	erg += copy_list(b,c);
	

	insert(d,c,add_koeff,comp_monomvector_monomvector);

	ENDR("add_polynom_polynom");
}
#endif /* POLYTRUE */
 
#ifdef POLYTRUE
INT comp_polynom(a,b) OP a,b;
{
	return comp_list_co(a,b,comp_monomvector_monomvector);
}

INT comp_monomvector_monomvector(a,b) OP a,b;
/* vergleicht zwei monome von vectorform */
/* wenn keine vectorform dann der normale vergleich */
/* AK 100789 V1.0 */ /* AK 081289 V1.1 */ /* vergleich bei polynomen */
/* AK 120391 V1.2 */ /* AK 200891 V1.3 */
{
	INT i,j,erg=OK;
	OP as,bs;



	CTO(MONOM,"comp_monomvector_monomvector",a);
	CTO(MONOM,"comp_monomvector_monomvector",b);
		
	as = S_MO_S(a); 
	bs = S_MO_S(b);

	if (	(S_O_K(as) == PERMUTATION)
		&&
		(S_O_K(bs)==PERMUTATION)		)
		/* AK 210690 if schubert polynom */
		{
		erg=1L;
		if (S_P_LI(bs) > S_P_LI(as)) {
			a=bs;
			bs=as;
			as=a;
			erg= -1L;
		}
		/* as ist laenger als bs */
		for (i=(INT)0; i<S_P_LI(as); i++)
			{
			if (i < S_P_LI(bs))
				{
				if (S_P_II(as,i) > S_P_II(bs,i)) return erg*1L;
				if (S_P_II(as,i) < S_P_II(bs,i)) return erg*-1L;
				}
			else {
				if (S_P_II(as,i) < i+1L) return erg*-1L;
				if (S_P_II(as,i) > i+1L) return erg*1L;
				}
			}
		return (INT)0;
		}
	if (	(S_O_K(as) == MATRIX)
		&&
		(S_O_K(bs)==MATRIX)		)
		{
		INT h,l;
		h = (S_M_HI(as) > S_M_HI(bs) ? S_M_HI(as) : S_M_HI(bs));
		l = (S_M_LI(as) > S_M_LI(bs) ? S_M_LI(as) : S_M_LI(bs));
		for (i=(INT)0; i<h; i++)
		for (j=(INT)0; j<l; j++)
			{
			if (
				( i<S_M_HI(as) )  &&
				( i<S_M_HI(bs) )  &&
				( j<S_M_LI(as) )  &&
				( j<S_M_LI(bs) ) 
			   ) 
				if ((erg = comp(S_M_IJ(as,i,j),S_M_IJ(bs,i,j)))
					!= (INT)0) return erg;
			if (
				( i>=S_M_HI(as) )  &&
				( j<S_M_LI(bs) )
			   )
				if (not nullp(S_M_IJ(bs,i,j)))
					return -1L;
			if (
				( i>=S_M_HI(bs) )  &&
				( j<S_M_LI(as) )
			   )
				if (not nullp(S_M_IJ(as,i,j)))
					return 1L;
			if (
				( i<S_M_HI(as) )  &&
				( j>=S_M_LI(bs) )
			   )
				if (not nullp(S_M_IJ(as,i,j)))
					return 1L;
			if (
				( i<S_M_HI(bs) )  &&
				( j>=S_M_LI(as) )
			   )
				if (not nullp(S_M_IJ(bs,i,j)))
					return -1L;
			}
		return (INT)0;
		}
	if (
		((S_O_K(as) != VECTOR)&&(S_O_K(as) != INTEGERVECTOR))
		|| 
		((S_O_K(bs) != VECTOR)&&(S_O_K(bs) != INTEGERVECTOR))
	    )
			return comp(as,bs);


	for (i=(INT)0;i<S_V_LI(as);i++)
		{
		if (S_O_K(S_V_I(as,i)) != INTEGER)
		{
		if (S_O_K(S_V_I(as,i)) == LONGINT) {
			C_O_K(as,VECTOR);
			goto ccc;
			}
		fprintln(stderr,as);
		error("comp_monomvector_monomvector:as no INTEGERVECTOR");
		}
		else if (i >= S_V_LI(bs))
			{
			if (S_V_II(as,i) != (INT)0)
				return 1L; 
			}
		else if (S_O_K(S_V_I(bs,i)) != INTEGER)
		{
		if (S_O_K(S_V_I(bs,i)) == LONGINT) {
			C_O_K(bs,VECTOR);
			goto ccc;
			}
		fprintln(stderr,bs);
		error("comp_monomvector_monomvector:bs no INTEGERVECTOR");
		}
		else if ( S_V_II(as,i) > S_V_II(bs,i) )
			return 1L;
		else if ( S_V_II(as,i) < S_V_II(bs,i) )
			return -1L;
		}

	for (j=i;j<S_V_LI(bs);j++)
		{
		/* if (S_O_K(S_V_I(bs,i)) != INTEGER)  error AK 311091 */
		if (S_O_K(S_V_I(bs,j)) != INTEGER) 
		{
		if (S_O_K(S_V_I(bs,j)) == LONGINT) 
			{
			C_O_K(bs,VECTOR);
			goto ccc;
			}
		fprintln(stderr,bs);
		error("comp_monomvector_monomvector:bs no INTEGERVECTOR");
		}
		/* else if (S_V_II(bs,i) != (INT)0 )  error AK 311091 */
		else if (S_V_II(bs,j) != (INT)0 ) 
                        return -1L; 
		}


	return (INT)0;
ccc: /* AK 300195 */ /* vergleich mit longint -- slow */
	for (i=(INT)0;i<S_V_LI(as);i++)
		{
		if (i >= S_V_LI(bs))
			{
			if (not nullp(S_V_I(as,i)))
				return 1L; 
			}
		else if ( gt(S_V_I(as,i),S_V_I(bs,i)) )
			return 1L;
		else if ( lt(S_V_I(as,i),S_V_I(bs,i)) )
			return -1L;
		}

	for (j=i;j<S_V_LI(bs);j++)
		{
		if (not nullp(S_V_I(bs,j)))
                        return -1L; 
		}
	return (INT)0;
	ENDR("comp_monomvector_monomvector");
}
#endif /* POLYTRUE */


#ifdef MONOMTRUE
INT addinvers_monom(a,b) OP a,b;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	INT erg=OK;
	erg += b_sk_mo(callocobject(),callocobject(),b);
	erg += copy(S_MO_S(a),S_MO_S(b));
	erg += addinvers(S_MO_K(a),S_MO_K(b));
	return erg;
}

INT addinvers_apply_monom(a) OP a;
/* AK 201289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(addinvers_apply(S_MO_K(a))); 
}
#endif /* MONOMTRUE */

#ifdef POLYTRUE
INT addinvers_polynom(a,b) OP a,b;
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(transformlist(a,b,addinvers)); 
}

INT addinvers_apply_polynom(a) OP a;
/* AK 201289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(transform_apply_list(a,addinvers_apply)); 
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT m_skn_po(a,b,c,d) OP a,b,c,d;
/* make_self.koeff.next_polynom */
/* AK 290590 V1.1 */ /* AK 200891 V1.3 */
{
	OP s=NULL,k=NULL,n=NULL;
	INT erg = OK;
	if (c != NULL) { 
		n = callocobject(); 
		erg += copy(c,n); 
		}
	if (a != NULL) { 
		s = callocobject(); 
		erg += copy(a,s); 
		}
	if (b != NULL) { 
		k = callocobject(); 
		erg += copy(b,k); 
		}
	erg += b_skn_po(s,k,n,d);
	ENDR("m_skn_po");
}

INT b_skn_po(a,b,c,d) OP a,b,c,d;
/* AK 100789 V1.0 */ /* AK 241189 V1.1 */ /* AK 130891 V1.3 */
{
	INT erg = OK;
	erg += b_sn_l(callocobject(),c,d); 
	erg += C_O_K(d,POLYNOM);
	erg += b_sk_mo(a,b,S_L_S(d)); 
	ENDR("b_skn_po");
}


OP s_po_s(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	if (a == NULL) return  
		error("s_po_s: a == NULL"),(OP)NULL;
	if (s_o_k(a) != POLYNOM) return  
		error("s_po_s: not POLYNOM"),(OP)NULL;
	return(s_mo_s(s_l_s(a))); 
}

OP s_po_k(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	if (a == NULL) return  
		error("s_po_k: a == NULL"),(OP)NULL;
	if (s_o_k(a) != POLYNOM) return  
		error("s_po_k: not POLYNOM"),(OP)NULL;
	return s_mo_k(s_l_s(a));
}

OP s_po_n(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	if (a == NULL) return  
		error("s_po_n: a == NULL"),(OP)NULL;
	if (s_o_k(a) != POLYNOM) return  
		error("s_po_n: not POLYNOM"),(OP)NULL;
	return s_l_n(a); 
}

OP s_po_si(a,i) OP a; INT i; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	if (a == NULL) return  
		error("s_po_si: a == NULL"),(OP)NULL;
	if (s_o_k(a) != POLYNOM) return  
		error("s_po_si: not POLYNOM"),(OP)NULL;
	return s_v_i(s_mo_s(s_l_s(a)),i); 
}

OP s_po_sl(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	if (a == NULL) return  
		error("s_po_sl: a == NULL"),(OP)NULL;
	if (s_o_k(a) != POLYNOM) return  
		error("s_po_sl: not POLYNOM"),(OP)NULL;
	return s_v_l(s_mo_s(s_l_s(a))); 
}

INT s_po_ki(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(s_mo_ki(s_l_s(a))); 
}

INT s_po_sii(a,i) OP a; INT i; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(s_v_ii(s_mo_s(s_l_s(a)),i)); 
}


INT s_po_sli(a) OP a; 
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{ 
	return(s_v_li(s_mo_s(s_l_s(a)))); 
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT test_poly()
/* AK 191289 V1.1 */ /* AK 190291 V1.2 */ /* AK 200891 V1.3 */
{
	OP a = callocobject();
	OP b = callocobject();
	OP c = callocobject();

	printf("test_poly:scan(a)"); 
	scan(POLYNOM,a);
	println(a);
	printf("test_poly:copy(a,b)"); 
	copy(a,b); 
	println(b);
	printf("test_poly:mult(a,b,b)"); 
	mult(a,b,b); 
	println(b);
	printf("test_poly:tex(b)"); 
	tex(b); 
	printf("test_poly:add(b,a,a)"); 
	add(b,a,a); 
	println(a);
	printf("test_poly:hoch(b,2L,a)"); 
	hoch(b,cons_zwei,a); 
	println(a);
	printf("test_poly:eval_polynom(a,b,c)");
	m_il_v(2L,b); 
	M_I_I(3L,s_v_i(b,(INT)0)); 
	M_I_I(5L,s_v_i(b,1L));
	printf("b=");
	println(b);
	eval_polynom(a,b,c); 
	println(c);
	printf("test_poly:vander(4L,c)"); 
	M_I_I(4L,b);
	vander(b,c);
	println(c);
	printf("test_poly:numberofvariables(c,b)"); 
	numberofvariables(c,b); 
	println(b);

#ifdef BRUCHTRUE
	freeself(a); freeself(b); freeself(c);
	printf("test_poly:lagrange_polynom([1,7],[5,7],c)"); 
	m_il_v(2L,a);
	m_i_i(1L, s_v_i(a,(INT)0));
	m_i_i(7L, s_v_i(a,1L));

	m_il_v(2L,b);
	m_i_i(5L, s_v_i(b,(INT)0));
	m_i_i(7L, s_v_i(b,1L));

	lagrange_polynom(a,b,c);println(c);
#endif /* BRUCHTRUE */
	printf("test_poly:mult_disjunkt_polynom_polynom(c,c,a)"); 
	mult_disjunkt_polynom_polynom(c,c,a); 
	println(a);


	m_i_i(1L,a); 
	m_scalar_polynom(a,b); 
	if (not einsp(b)) 
		printf("test_poly:ERROR!!:einsp test not successful\n");
	else
		printf("test_poly:einsp test successful\n");

	m_i_i((INT)0,a); 
	m_scalar_polynom(a,b); 
	if (not nullp(b)) 
		printf("test_poly:ERROR!!:nullp test not successful\n");
	else
		printf("test_poly:nullp test successful\n");

	SYMfreeall(a);
	SYMfreeall(b);
	SYMfreeall(c);
	return(OK);
}
#endif /* POLYTRUE */


#ifdef POLYTRUE
INT tex_polynom(poly) OP poly;
/* AK 101187 */ /* zur TeXausgabe eines polynoms */
/* AK 100789 V1.0 */ /* AK 191289 V1.1 */
/* AK 070291 V1.2 tex to texout */ /* AK 200891 V1.3 */
{
	OP zeiger = poly;
	OP z;
	INT i,j;
	INT hbool=1L;
	INT ts = texmath_yn; /* AK 260892 */

	if (ts == (INT)0) 
		{
		texmath_yn = 1L;
		fprintf(texout,"\\ $ ");
		}
	else
		fprintf(texout,"\\ ");
	texposition += 3L;
	if (EMPTYP(poly)) 
		return(OK);
	while (zeiger != NULL)
	{
		hbool = 1L;
		if (not einsp(S_PO_K(zeiger))) 
			{
			if (negeinsp(S_PO_K(zeiger))) /* AK 100892 */
			{
			fprintf(texout," - "); 
			texposition += 3L; 
			}
			else
				{
				if (POLYNOMP(S_PO_K(zeiger)))
					fprintf(texout,"(");
				if (negp(S_PO_K(zeiger)))
					{
					fprintf(texout," - "); 
					addinvers_apply(S_PO_K(zeiger));
					tex(S_PO_K(zeiger)); 
					addinvers_apply(S_PO_K(zeiger));
					}
				else
					tex(S_PO_K(zeiger)); 
				hbool=(INT)0; 
				if (POLYNOMP(S_PO_K(zeiger)))
					fprintf(texout,")");
				}
			}
		/* der koeffizient wird nur geschrieben wenn er ungleich 1 ist*/
		fprintf(texout,"\\ ");
		texposition += 3L;
		if (S_O_K(S_PO_S(zeiger)) == MATRIX) /* AK 031291 */
			{
			z = S_PO_S(zeiger);
			for (i=(INT)0;i<S_M_HI(z);i++)
			for (j=(INT)0;j<S_M_LI(z);j++)
				if (S_M_IJI(z,i,j) >(INT)0)
				{
				hbool=(INT)0;
				if (S_M_IJI(z,i,j) >1L)
					fprintf(texout," x_{%ld,%ld}^{%ld} ",
						i,j,S_M_IJI(z,i,j));
				else 
					fprintf(texout," x_{%ld,%ld} ", i,j);
				texposition += 15L;
				}
			}
		else 	{
		for (i= (INT)0 ;i < S_PO_SLI(zeiger); i++)
			if (S_PO_SII(zeiger,i) > (INT)0)
			{
				hbool=(INT)0;
				if (tex_poly_var == NUMERICAL) /* AK 090395 */
			fprintf(texout,"x_{%d}",i+tex_poly_first_var_index);
				else
			fprintf(texout,"%c",'a'+i+tex_poly_first_var_index);
				texposition ++;
				if (S_PO_SII(zeiger,i) != 1L)
				{
					fprintf(texout,"^{%d}",S_PO_SII(zeiger,i));
					texposition += 10L;
				};
			};
			}
		if (hbool == 1L) 
			fprintf(texout,"1");
		fprintf(texout,"\\ ");
		texposition += 3L;
		if (texposition > 60L)
		{ 
			fprintf(texout,"\n");
			texposition = (INT)0; 
		}

		zeiger = S_PO_N(zeiger);
		if (zeiger != NULL)
		if (not negp(S_PO_K(zeiger))) /* AK 100892 */
		{ 
			fprintf(texout," + "); 
			texposition += 5L; 
		}
	};
	if (ts == (INT)0)
		{
		fprintf(texout,"$ \\ ");
		texmath_yn = (INT)0;
		}
	else 
		fprintf(texout,"\\ ");
	texposition += 2L;
	return(OK);
}



INT copy_polynom(a,b) OP a,b; 
/* AK 091190 V1.1 */ /* AK 190291 V1.2 */ /* AK 200891 V1.3 */
	{
	return(copy_list(a,b));
	}



INT add_apply_polynom_polynom(a,b) OP a,b;
/* AK 091190 V1.1 */ /* AK 190291 V1.2 */ /* AK 200891 V1.3 */
	{
	INT erg = OK;
	OP c;
	c = callocobject();
	erg += copy_polynom(a,c);
	insert(c,b,add_koeff,comp_monomvector_monomvector);
	ENDR("add_apply_polynom_polynom");
	}


INT add_apply_polynom_scalar(a,b) OP a,b;
/* AK 130891 V1.3 */
{
	OP c = callocobject();
	INT erg = OK;
	erg += copy(a,c);
	erg += add(b,c,b); /* error AK 211194 */
	erg += SYMfreeall(c);
	ENDR("add_apply_polynom_scalar");
}
#endif /* POLYTRUE */

INT add_apply_polynom(a,b) OP a,b;
/* AK 220390 V1.1 */ /* AK 190291 V1.2 */
/* AK 130891 V1.3 */
{
#ifdef POLYTRUE
	INT erg = OK;
	OP d;
	if ((EMPTYP(b)) 
		||  nullp(b) )
		return(copy_polynom(a,b));
	switch(S_O_K(b)) {
		case BRUCH:
		case LONGINT:
		case CYCLOTOMIC:
		case SQ_RADICAL:
		case INTEGER: erg += add_apply_polynom_scalar(a,b);break;
/*CC 28/09/95*/
                case MONOPOLY: d=callocobject();
                                erg += t_POLYNOM_MONOPOLY(a,d);
                                erg += add_apply_monopoly(d,b);
                                erg += SYMfreeall(d);
                                break;


		case POLYNOM:  erg += add_apply_polynom_polynom(a,b);break;
#ifdef SCHUBERTTRUE
		case SCHUBERT:  erg += add_apply_polynom_schubert(a,b);break;
#endif /* SCHUBERTTRUE */
		default:
			printobjectkind(b);
			return error("add_apply_polynom:wrong second type");
		}
	ENDR("add_apply_polynom");
#endif /* POLYTRUE */
}

#ifdef SCHUBERTTRUE
INT add_apply_polynom_schubert(a,b) OP a,b;
/* AK 190291 V1.2 */ /* AK 200891 V1.3 */
{
	OP c = callocobject();
	INT erg = OK;
	erg += t_POLYNOM_SCHUBERT(a,c);
	erg += add_apply(c,b);
	erg += SYMfreeall(c);
	ENDR("add_apply_polynom_schubert");
}
#endif /* SCHUBERTTRUE */

#ifdef SCHUBERTTRUE
INT gauss_schubert_polynom(a,b,c) OP a,b,c;
/* AK 040190 gausspolynom [a+b \atop b] */
/* mittels schubertpolynome */
/* AK 040190 V1.1 */ /* AK 200891 V1.3 */
{
	INT i,m;
	OP vec = callocobject();
	OP perm = callocobject();
	INT erg = OK;

	erg += m_il_v(S_I_I(a)+S_I_I(b)+1L,vec);
	for (i=(INT)0,m=(INT)0;i<S_I_I(b);i++,m++)
		M_I_I((INT)0,S_V_I(vec,m));
	M_I_I(S_I_I(a),S_V_I(vec,m)); m++;
	for (i=(INT)0;i<S_I_I(a);i++,m++)
		M_I_I((INT)0,S_V_I(vec,m));
	/* dies ist der lehmercode */
	erg += lehmercode(vec,perm);
	erg += m_perm_schubert_qpolynom(perm,c);
	erg += SYMfreeall(perm);
	erg += SYMfreeall(vec);
	ENDR("gauss_schubert_polynom");
}
#endif /* SCHUBERTTRUE */

INT polya_sub(a,c,b) OP a,b,c;
/* einsetzung */ /* a ist polynom */ /* c ist length of alphabet */
/* b wird ergebnis x_i ----> 1 + q^i */
/* AK 080190 */ /* AK 091190 V1.1 */ /* AK 200891 V1.3 */
{
#ifdef POLYTRUE
	OP d=callocobject();
	OP e=callocobject();
	OP f=callocobject();
	OP g=callocobject();
	OP z;
	INT i;
	INT erg = OK;

	erg += m_il_v(S_I_I(c),d);
	erg += b_skn_po(callocobject(),callocobject(),NULL,e);
	erg += m_il_v(1L,S_PO_S(e));
	M_I_I(0L,S_PO_SI(e,0L));
	M_I_I(1L,S_PO_K(e));
	erg += copy(e,f); 
	M_I_I(1L,S_PO_SI(f,0L));
	erg += insert(f,e,add_koeff,comp_monomvector_monomvector);
	for (i=0L;i<S_V_LI(d);i++)
		{
		erg += copy(e,S_V_I(d,i));
		z = S_V_I(d,i);
		while (z != NULL)
			{
			M_I_I(S_PO_SII(z,0L)*(i+1L),S_PO_SI(z,0L));
			z = S_L_N(z);
			}
		}
	erg += eval_polynom(a,d,b); 
	/* erg += copy(S_PO_K(g),b); nicht mehr noetig AK 031291 */
	erg += SYMfreeall(d);
	erg += SYMfreeall(e);
	erg += SYMfreeall(g);
	ENDR("polya_sub");
#endif /* POLYTRUE */
}

INT unimodalp(a) OP a;
/* AK 080190 */ /* AK 091190 V1.1 */ /* AK 200891 V1.3 */
{
	OP z,k;
	if (EMPTYP(a)) return(FALSE);
	if (S_O_K(a) != POLYNOM) return(FALSE);
	z = S_PO_N(a);
	k = S_PO_K(a);
	while (z != NULL)
		{
		if (lt(S_PO_K(z),k)) break;
		k = S_PO_K(z);
		z = S_PO_N(z);
		}
	if (z == NULL) return(TRUE);
	k = S_PO_K(z);
	z = S_PO_N(z);
	while (z != NULL)
		{
		if (gr(S_PO_K(z),k)) return(FALSE);
		k = S_PO_K(z);
		z = S_PO_N(z);
		}
	return(TRUE);
}

INT degree_polynom(a,b) OP a,b;
/* b becomes the degree, but only if in one variable */
/* AK 300590 V1.1 */ /* AK 190291 V1.2 */ /* AK 200891 V1.3 */
{
	OP z,za;
	INT erg = OK;
	if (not EMPTYP(b)) 
		erg += freeself(b);
	z = a;
	while (z != NULL)
		{
		za = z;
                if( (S_O_K(S_PO_S(z)) != VECTOR) &&
			(S_O_K(S_PO_S(z)) != INTEGERVECTOR))         /*CC*/
                {
                        printobjectkind(S_PO_S(z));
                        return error("degree_polynom: not VECTOR");
                }

		if (S_PO_SLI(z) != 1L) 
		return error("degree_polynom: not single variable");
	z = S_PO_N(z);
		}
	/* za has now maximail degree */
	erg += copy (S_PO_SI(za,0L),b);
	ENDR("degree_polynom");
}

#ifdef POLYTRUE
INT lagrange_polynom(a,b,c) OP a,b,c;
/* a sind die stuetzpunkte VECTOR
   b die werte VECTOR
   c wird das polynom */
/* AK 060690 V1.1 */ /* AK 200891 V1.3 */
{
	INT i,j;
	OP zw,h;
	if (not EMPTYP(c)) freeself(c);
	if ( (S_O_K(a) != VECTOR) || (S_O_K(b) != VECTOR) )
		return error("lagrange_polynom: no vector arguments");
	if (S_V_LI(a) != S_V_LI(b))
		return error("lagrange_polynom: different vector length");
	zw = callocobject();
	h = callocobject();
	for (i=0L; i< S_V_LI(a) ; i++ )
		{
		copy (S_V_I(b,i), zw);
		for (j = 0L; j < S_V_LI(a); j++)
		if (i != j) {
			sub (S_V_I(a,i),S_V_I(a,j),h);
			div3(zw,h,zw); 
			freeself(h);
			b_skn_po(
			callocobject(),callocobject(),callocobject(),h);
			b_skn_po(
			callocobject(),callocobject(),NULL,S_PO_N(h));
			m_il_v(1L,S_PO_S(h));
			m_il_v(1L,S_PO_S(S_PO_N(h)));
			M_I_I(0L,S_PO_SI(h,0L));
			M_I_I(1L,S_PO_SI(S_PO_N(h),0L));
			addinvers(S_V_I(a,j), S_PO_K(h));
			M_I_I(1L, S_PO_K(S_PO_N(h)));
			mult(h,zw,zw);
			}
		add(zw,c,c); freeself(zw);
		}
	SYMfreeall(zw);SYMfreeall(h);
	return OK;
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT m_index_monom(i,res) OP i; OP res; 
{
	INT erg = OK;
	if (i==res) /* OK */ ;
	CTO(INTEGER,"m_index_monom",i);
	erg += m_iindex_monom(S_I_I(i),res);
	ENDR("m_index_monom");
}

INT m_iindex_monom(i,erg) INT i; OP erg; 
/* AK 200891 V1.3 */
{
return
 m_iindex_iexponent_monom(i,(INT)1,erg);
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT m_iindex_iexponent_monom(i,ex,res) INT i,ex; OP res;
/* AK 300588 */ /* macht aus i das Monom x_i */
/* AK 030789 V1.0 */ /* AK 060390 V1.1 */ /* AK 200891 V1.3 */
	{
	INT j;
	INT erg = OK;

	if (i<(INT)0)  
		return error("m_iindex_iexponent_monom:index < 0 ");
	erg += b_skn_po(callocobject(),callocobject(),NULL,res);
	erg += m_il_nv(i+1L,S_PO_S(res));
	C_O_K(S_PO_S(res),INTEGERVECTOR);
	M_I_I(1L,S_PO_K(res));
	M_I_I(ex,S_PO_SI(res,i));
	ENDR("m_iindex_iexponent_monom");
	}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT nullp_polynom(a) OP a;
/* AK 180291 V1.2 */ /* AK 200891 V1.3 */
{
	OP z = a;
	if (empty_listp(a)) 
		return TRUE;
	while (z != NULL)
		{
		if (not nullp(S_PO_K(z)) ) 
			return FALSE;
		z = S_PO_N(z);
		}
	return TRUE;
}
#endif /* POLYTRUE */


#ifdef POLYTRUE
INT einsp_polynom(a) OP a;
/* AK 180291 V1.2 */ /* AK 200891 V1.3 */
{
	OP z = a;
	INT i;
	if (empty_listp(a)) return FALSE;
	if (not einsp(S_PO_K(z)) ) return FALSE;
	/* now check whether self == 000000 */
	for (i=(INT)0; i<S_PO_SLI(z); i++)
		if (S_PO_SII(z,i) != (INT)0) return FALSE;
	z = S_PO_N(z);
	if (z != NULL) return FALSE;
	return TRUE;
}
#endif /* POLYTRUE */


#ifdef POLYTRUE
INT m_scalar_polynom(a,b) OP a,b;
/* AK 180291 V1.2 */ /* AK 060891 V1.3 */
{
	INT erg = OK;
	if (check_equal_2(a,b,m_scalar_polynom,&erg) == EQUAL)
                goto ee;
	erg += b_skn_po(callocobject(),callocobject(),NULL,b);
	erg += copy(a,S_PO_K(b));
	erg += m_il_v(1L,S_PO_S(b));
	erg += m_i_i((INT)0,S_PO_SI(b,(INT)0));
	C_O_K(S_PO_S(b),INTEGERVECTOR);
ee:
	ENDR("m_scalar_polynom");
}
#endif /* POLYTRUE */

#ifdef POLYTRUE
INT character_polynom(a,b) OP a,b;
/* AK 040892 */
{
	INT erg = OK;
	INT i,wi;
	OP l,lp,p,res,v;
	if (EMPTYP(a))
		{
		erg += m_scalar_polynom(cons_eins,b);
		goto endr_ende;
		}
	CTO(PARTITION,"character_polynom",a);
	C1R(a,"character_polynom",b);

/* cpa: */
	if (EMPTYP(a))
		return m_scalar_polynom(cons_eins,b);
/*
	if (char_ls == NULL)  {
		char_ls = callocobject();
		char_ps = callocobject();
		erg += m_il_v((INT)0,char_ls);
		erg += m_il_v((INT)0,char_ps);
		}
	else	{
		for (i=(INT)0;i<S_V_LI(char_ls);i++)
			if (EQ(S_V_I(char_ls,i),a))
				{
				erg +=  copy(S_V_I(char_ps,i),b);
				goto cpende;
				}
		}
*/

	l = callocobject();
	lp = callocobject();
	p = callocobject();
	v = callocobject();
	erg += copy(S_PA_L(a),l); 
	erg += inc(l);
	erg += copy(a,lp);
	erg += first_permutation(l,p);
	erg += young_polynom(a,b);
	while (next(p,p))
		{
		erg += copy(S_PA_S(a),v);
		for (i=1L;i<S_P_LI(p);i++)
			{
			wi=S_V_II(v,S_V_LI(v)-i)+S_P_II(p,i)-i-1L;
			if (wi<(INT)0) break;
			erg += m_i_i(	wi,
				S_V_I(v,S_V_LI(v)-i)
			     );
			}
		if (wi<(INT)0) continue;
		erg += m_v_pa(v,lp);
		res = callocobject();
		erg += young_polynom(lp,res);
		if (oddp(p)) 
			erg += addinvers_apply(res);
		insert(res,b,NULL,NULL);

		}
	erg += SYMfreeall(l); 
	erg += SYMfreeall(lp);
	erg += SYMfreeall(p);
	erg += SYMfreeall(v); /* AK 190893 */
/*
	erg += inc(char_ls);
	erg += inc(char_ps);
	erg += copy(a,S_V_I(char_ls,S_V_LI(char_ls)-1L));
	erg += copy(b,S_V_I(char_ps,S_V_LI(char_ls)-1L));
cpende:
*/
	S1R(a,"character_polynom",b);
	ENDR("character_polynom");
}
#endif /* POLYTRUE */

#ifdef  POLYTRUE 
INT young_polynom(a,l) OP a,l;
/* AK 040892 */
{	
	OP b , c ,e , d , n,m ,f;
	INT i,j,k,wi,ii;
	INT erg = OK;
ypa:
	if (S_O_K(a) == EMPTY)
		{
		erg +=  m_scalar_polynom(cons_eins,l);
		goto endr_ende;
		}
	CTO(PARTITION,"young_polynom",a);
	C1R(a,"young_polynom",l);

/*
	if (young_ls == NULL)  {
		young_ls = callocobject();
		young_ps = callocobject();
		erg += m_il_v((INT)0,young_ls);
		erg += m_il_v((INT)0,young_ps);
		}
	else	{
		for (i=(INT)0;i<S_V_LI(young_ls);i++)
			if (EQ(S_V_I(young_ls,i),a))
				{
				erg +=  copy(S_V_I(young_ps,i),l);
				goto youngende;
				}
		}
*/
	b = callocobject(); c = callocobject();
	d = callocobject(); e = callocobject();
	f = callocobject(); m = callocobject();
	n = callocobject();

 	erg += weight(a,b); wi = S_I_I(b);
	erg += m_il_v(S_PA_LI(a),b);
	erg += m_i_i((INT)0,l);
	for (i=(INT)0;i<S_V_LI(b);i++)
		erg += first_part_EXPONENT(S_PA_I(a,i),S_V_I(b,i));
	do {
	   erg += m_i_i(1L,n);
	   for (i=(INT)0;i<wi;i++)
		{
		erg += m_il_nv(S_PA_LI(a),c);
		k=(INT)0;
		for (ii=(INT)0;ii<S_PA_LI(a);ii++)
			{
			if (i<S_PA_II(a,ii)) 
				m_i_i(S_PA_II(S_V_I(b,ii),i),S_V_I(c,ii));
			if (i<S_PA_II(a,ii)) 
				k+=S_PA_II(S_V_I(b,ii),i);
			}
		if (k>(INT)0) 
			{
			erg += m_i_i(k,d);
			erg += multinom(d,c,e);
			erg += m_iindex_monom(i,f);
			erg += binom(f,d,m); 
			erg += mult_apply(e,m); 
			erg += mult_apply(m,n); 
			}
		}
	   erg += add(n,l,l); 
	   j=(INT)0;
	   while (not next(S_V_I(b,j),S_V_I(b,j))) 
			{
			j++;
			if (j==S_V_LI(b)) break;
			}
	   if (j == S_V_LI(b)) break;
   /* links von der stelle wo erhoeht wurd muss auf null gesetzt werden */
	   for (j--;j>=(INT)0;j--)
		erg += first_part_EXPONENT(S_PA_I(a,j),S_V_I(b,j));
	   } while(1);
	/* alle partitionen durchlaufen */

	erg += SYMfreeall(b); erg += SYMfreeall(e);
	erg += SYMfreeall(m); erg += SYMfreeall(n);
	erg += SYMfreeall(f); erg += SYMfreeall(d); 
	erg += SYMfreeall(c);

/*
	erg += inc(young_ls);
	erg += inc(young_ps);
	erg += copy(a,S_V_I(young_ls,S_V_LI(young_ls)-1L));
	erg += copy(l,S_V_I(young_ps,S_V_LI(young_ls)-1L));

youngende:
*/
	S1R(a,"young_polynom",l);
	ENDR("young_polynom");
}
#endif /* POLYTRUE */

#ifdef  POLYTRUE 

INT eval_char_polynom(poly,vec,res) OP poly,vec,res;
/* AK 310588 */
/* ein polynom wird ausgewertet indem der vector
vec eingesetzt wird
bsp 	poly:= 2 [3,0,1]
	vec:= [4,4,5]
	res = 2 * 4^3 * 5 = 640 [0,0,0] */
/* AK 110789 V1.0 */ /* AK 191289 V1.1 */ /* AK 200891 V1.3 */
{
	OP zeiger = poly,monom,c;
	INT i;
	INT erg=OK;

	if (
		(S_O_K(vec) != VECTOR) &&
		(S_O_K(vec) != INTEGERVECTOR)
	   )
	{ 
		printobjectkind(vec); 
		return error("eval_char_polynom:vec != VECTOR "); 
	}

	m_i_i((INT)0,res);
	c = callocobject();
	monom = callocobject(); 

	while (zeiger != NULL)
	{
		erg += copy(S_PO_K(zeiger),monom);
		if (
			(S_O_K(S_PO_S(zeiger)) != VECTOR) &&
			(S_O_K(S_PO_S(zeiger)) != INTEGERVECTOR)
		   )
		{ 
			printobjectkind(S_PO_S(zeiger));
			return error("eval_char_polynom:self != VECTOR "); 
		}
		for (i=(INT)0;i<S_PO_SLI(zeiger); i++)
		{
			if (i >= S_V_LI(vec)) goto evalpoly3;
			/* i ist < S_V_LI(vec) */
			if (not EMPTYP(S_V_I(vec,i)))
			/* if (not nullp (S_PO_SI(zeiger,i))) AK 040892 */
			if (S_PO_SII(zeiger,i) != (INT)0)
				{ 
				if (S_PO_SII(zeiger,i) == 1L)
					mult_apply_integer(S_V_I(vec,i),monom); 
				else if (S_PO_SII(zeiger,i) == 2L)
					{
					m_i_i(S_V_II(vec,i)*S_V_II(vec,i),c);
					mult_apply_integer(c,monom); 
					}
				else if (S_PO_SII(zeiger,i) == 3L)
					{
			m_i_i(S_V_II(vec,i)*S_V_II(vec,i)*S_V_II(vec,i),c);
			erg += mult_apply_integer(c,monom); 
					}
				else if (S_PO_SII(zeiger,i) == 4L)
					{
	m_i_i(S_V_II(vec,i)*S_V_II(vec,i)*S_V_II(vec,i)*S_V_II(vec,i),c);
	erg += mult_apply_integer(c,monom); 
					}
				else /* AK 040892 */
					{
					erg += hoch(S_V_I(vec,i),S_PO_SI(zeiger,i),c);
					erg += mult_apply(c,monom); 
					}
				}
		};
evalpoly3:
	if ( (S_O_K(monom) == INTEGER)
		&& (S_O_K(res) == INTEGER) )
		erg += add_apply_integer_integer(monom,res);
	else if (S_O_K(monom) == BRUCH)
		erg += add_apply_bruch(monom,res);
	else
		erg += add_apply(monom,res);
		zeiger = S_PO_N(zeiger);
	}
	erg += SYMfreeall(c); 
	erg += SYMfreeall(monom); 
	return erg;
}



INT m_vec_vec_poly(a,b,c) OP a,b,c;
/* AK 310892 */
/* input two integer vectors a,b of same length */
/* output polynom c= ... a_i ^ b_i ... with coeff 1 */
{
	INT erg = OK;
	INT i,maxvar;
	if (S_O_K(a) != VECTOR)
		return ERROR;
	if (S_O_K(b) != VECTOR)
		return ERROR;
	if (S_V_LI(a) != S_V_LI(b)) 
		return ERROR;
	maxvar = (INT)0;
	for (i=(INT)0;i<S_V_LI(a);i++)
		{
		if (S_O_K(S_V_I(a,i)) != INTEGER)
			return ERROR;
		if (S_O_K(S_V_I(b,i)) != INTEGER)
			return ERROR;
		if (S_V_II(b,i) < (INT)0)
			return ERROR;
		if (S_V_II(a,i) < (INT)0)
			return ERROR;
		if (S_V_II(a,i) > maxvar) 
			maxvar = S_V_II(a,i);
		}
	/* now the input is OK */
	b_skn_po(callocobject(),callocobject(),NULL,c);
	m_i_i(1L,S_PO_K(c));
	m_il_nv(maxvar+1L,S_PO_S(c));
	for (i=(INT)0;i<S_V_LI(a);i++)
		{
		M_I_I(S_V_II(b,i)+S_PO_SII(c,S_V_II(a,i)),
			S_PO_SI(c,S_V_II(a,i)));
		}
	return erg;
}



INT is_scalar_polynom(a) OP a;
/* AK 290793 */
{
	if (scalarp(a) ) 
		return TRUE;
	if (nullp(S_PO_S(a)) && S_PO_N(a) == NULL)
		return TRUE;
	else
		return FALSE;
}




INT select_coeff_polynom(a,b,c) OP a,b,c;
/* AK 020893 */
/* c becomes the coeff of the exponent vector b in the polynomial a */
{
	OP z;
	INT erg = OK;
	if ((S_O_K(a) != POLYNOM) ||
		(S_O_K(b) != VECTOR))
			return WTT("select_coeff_polynom",a,b);

	z = a;
	while (z != NULL)
		{
		if (comp_numeric_vector(S_PO_S(z), b) == (INT)0)
			{
			erg += copy(S_PO_K(z),c);
		 	goto s_p_c_ende;
			}
		z = S_L_N(z);
		}
	erg += m_i_i((INT)0,c);
s_p_c_ende:
	return erg;
}



INT random_monom(a) OP a;
/* AK 180893 */
{
	OP b,c;
	INT i,erg = OK;
rma:
	b = callocobject();
	c = callocobject();
	erg += random_integer(b,cons_eins,NULL);
	erg += m_l_v(b,c);
	for  (i=(INT)0;i<S_V_LI(c);i++)
		erg += random_integer(S_V_I(c,i),NULL,NULL);
		
	erg += b_skn_po(c,callocobject(),NULL,a);
	erg += random_integer(b,NULL,NULL);
	if ((S_I_I(b) % 3L) == (INT)0)
		erg += random_integer(S_PO_K(a),NULL,NULL);
	if ((S_I_I(b) % 3L) == 1L)
		erg += random_longint(S_PO_K(a),NULL);
	if ((S_I_I(b) % 3L) == 2L)
		{
		erg += b_ou_b(callocobject(),callocobject(),S_PO_K(a));
		erg += random_integer(S_B_O(S_PO_K(a)),NULL,NULL);
		erg += random_integer(S_B_U(S_PO_K(a)),NULL,NULL);
		erg += kuerzen(S_PO_K(a));
		}
	erg += SYMfreeall(b);
	return erg;
}


INT random_polynom(a) OP a;
/* AK 180893 */
{
	OP b,c;
	INT i,erg = OK;
rpa:
	b = callocobject();
	c = callocobject();
	erg += random_integer(b,NULL,NULL);
	init(POLYNOM,a);
	for (i=(INT)0;i<=S_I_I(b);i++)
		{
		erg += random_monom(c);
		erg += add_apply(c,a);
		}
	erg += SYMfreeall(b);
	erg += SYMfreeall(c);
	ENDR("random_polynom");
}



INT symmetricp_i(a,i) OP a; INT i;
/* AK 141293 */
/* true if the POLYNOM object a ist the symmetric in a_i and a_{i+1} */
{
	OP d,c;
	INT erg = OK, res;

	if (i<(INT)0) 
		return error("symmetricp_i: index < 0");
	CTO(POLYNOM,"symmetricp_i",a);

	d = callocobject();
	c = callocobject();
	M_I_I(i+1,c);
	erg += divdiff(c,a,d);
	if (nullp(d))
		res = TRUE;
	else 
		res = FALSE;
	erg += SYMfreeall(d);
	erg += SYMfreeall(c);
	ENDR("symmetricp_i");
}

INT symmetricp(a) OP a;
{
	OP n;
	INT i,res;
	if (MATRIXP(a)) return symmetricp_matrix(a);
	n=callocobject();
	numberofvariables(a,n);
	for (i=(INT)0;i<S_I_I(n)-1L;i++)
		if (symmetricp_i(a,i) == FALSE)
			{ res =FALSE; goto se; }
		
	res = TRUE;
	se:
	SYMfreeall(n);
	return res;
}

INT cast_apply_monom(a) OP a;
/* AK 010394 */
{
	INT erg = OK;
	switch(S_O_K(a))
		{
		}
	return erg;
}


static INT GaussRec(po, m, n, res) INT po, m, n; OP res;
{ if (n==0L || m==n) inc(S_V_I(res,po));
  else { GaussRec(po,m-1,n-1,res); GaussRec(po+n,m-1,n,res); }
}

INT gauss_polynom(m, n, pol) OP m,n,pol;
/* SV&AL */
{
        INT i;
	INT erg = OK;
        OP d,res;

        res = callocobject();
        erg += m_il_nv(S_I_I(n)* ( S_I_I(m)-S_I_I(n)  ) + (INT ) 1 ,res);
	GaussRec((INT)0,S_I_I(m),S_I_I(n),res);
        erg += m_iindex_iexponent_monom((INT)0,(INT)0,pol);
        for (i=(INT)1;i<S_V_LI(res);i++)
                {
                C_PO_N(pol,callocobject());
                erg += m_iindex_iexponent_monom((INT)0,i,S_PO_N(pol));
                pol = S_PO_N(pol);
                erg += m_i_i(S_V_II(res,i),S_PO_K(pol));
                }
	erg += SYMfreeall(res);
	return OK;
}


INT t_LIST_POLYNOM(a,b) OP a,b;
/* AK 250195 */
{
	INT erg = OK;
	OP z,zb;
	CE2(a,b,t_LIST_POLYNOM);
                
	z = a;
	erg +=  init(POLYNOM,b);
	zb = b;
	if (S_L_S(z) == NULL)
		goto endr_ende;
	C_L_S(zb,callocobject());
again:
	erg += m_sk_mo(S_L_S(z),cons_eins,S_L_S(zb));
	C_O_K(zb,POLYNOM);
	if (S_L_N(z) != NULL)
		{
		C_L_N(zb,callocobject());
		erg += b_sn_l(callocobject(),NULL,S_L_N(zb));
		zb = S_L_N(zb);
		z = S_L_N(z);
		goto again;
		}

	ENDR("t_LIST_POLYNOM");
}

INT invers_POLYNOM(a,b) OP a ,b;
/* CC */
{
	INT erg = OK;
        if(not emptyp(b)) 
		erg += freeself(b);
        erg += m_ou_b(cons_eins,a,b);
        ENDR("invers_POLYNOM");
}

#endif /* POLYTRUE */


#undef callocobject
