#include #include "datatype.h" #include "stackm.h" #include "extern.h" #include "extern2.h" static void printTag(coeffType t) { switch(t) { case UNKNOWN: fprintf(stderr," UNKNOWN "); break; case INTEGER: fprintf(stderr," INTEGER "); break; case MP_INTEGER: fprintf(stderr," MP_INTEGER "); break; case POLY_COEFF: fprintf(stderr," POLY_COEFF "); break; default: fprintf(stderr," Unknown tag of coeffType."); break; } } char *intToString(i) int i; { char work[80]; char *s; sprintf(work,"%d",i); s = (char *)sGC_malloc((strlen(work)+2)*sizeof(char)); if (s == (char *)NULL) errorCoeff("No more memory."); strcpy(s,work); return(s); } char *coeffToString(cp) struct coeff *cp; { char *s; switch(cp->tag) { case INTEGER: return(intToString((cp->val).i)); break; case MP_INTEGER: s = mpz_get_str((char *)NULL,10,(cp->val).bigp); return(s); break; case POLY_COEFF: s = POLYToString((cp->val).f,'*',1); return(s); break; default: warningCoeff("coeffToString: Unknown tag."); return(" Unknown-coeff "); break; } } /* constructors */ struct coeff *intToCoeff(i,ringp) int i; struct ring *ringp; { struct coeff *c; int p; c =newCoeff(); if (ringp->next != (struct ring *)NULL) { c->tag = POLY_COEFF; c->val.f = cxx(i,0,0,ringp->next); c->p = ringp->p; }else{ p = ringp->p; if (p) { c->tag = INTEGER; c->p = p; c->val.i = i % p; }else{ c->tag = MP_INTEGER; c->p = 0; c->val.bigp = newMP_INT(); mpz_set_si(c->val.bigp,(long) i); } } return(c); } struct coeff *mpintToCoeff(b,ringp) MP_INT *b; struct ring *ringp; { struct coeff *c; struct coeff *c2; int p; c =newCoeff(); p = ringp->p; if (ringp->next == (struct ring *)NULL) { if (p) { c->tag = INTEGER; c->p = p; c->val.i = ((int) mpz_get_si(b)) % p; }else{ c->tag = MP_INTEGER; c->p = 0; c->val.bigp = b; } return(c); }else{ c2 = mpintToCoeff(b,ringp->next); c->tag = POLY_COEFF; c->p = ringp->p; c->val.f = coeffToPoly(c2,ringp->next); return(c); /* errorCoeff("mpintToCoeff(): mpint --> poly_coeff has not yet be supported. Returns 0."); c->tag = POLY_COEFF; c->val.f = ZERO; */ } } struct coeff *polyToCoeff(f,ringp) POLY f; struct ring *ringp; { struct coeff *c; if (f ISZERO) { c =newCoeff(); c->tag = POLY_COEFF; c->p = ringp->p; c->val.f = f; return(c); } if (f->m->ringp != ringp->next) { errorCoeff("polyToCoeff(): f->m->ringp != ringp->next. Returns 0."); f = 0; } c =newCoeff(); c->tag = POLY_COEFF; c->p = ringp->p; c->val.f = f; return(c); } /* returns -c */ struct coeff *coeffNeg(c,ringp) struct coeff *c; struct ring *ringp; { struct coeff *r; r = intToCoeff(-1,ringp); Cmult(r,r,c); return(r); } int coeffToInt(cp) struct coeff *cp; { POLY f; switch(cp->tag) { case INTEGER: return(cp->val.i); break; case MP_INTEGER: return(mpz_get_si(cp->val.bigp)); break; case POLY_COEFF: f = cp->val.f; if (f == ZERO) return(0); else return(coeffToInt(f->coeffp)); break; default: errorCoeff("Unknown tag in coeffToInt().\n"); } } void Cadd(r,a,b) struct coeff *r; struct coeff *a; struct coeff *b; { int p; POLY f; if (a->tag == INTEGER && b->tag == INTEGER && r->tag == INTEGER) { r->p = p = a->p; r->val.i = ((a->val.i) + (b->val.i)) % p; }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER && r->tag == MP_INTEGER) { mpz_add(r->val.bigp,a->val.bigp,b->val.bigp); }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF && r->tag == POLY_COEFF) { f = ppAdd(a->val.f,b->val.f); r->val.f = f; }else { warningCoeff("Cadd(): The data type is not supported."); } } void Csub(r,a,b) struct coeff *r; struct coeff *a; struct coeff *b; { int p; if (a->tag == INTEGER && b->tag == INTEGER && r->tag == INTEGER) { r->p = p = a->p; r->val.i = ((a->val.i) - (b->val.i)) % p; }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER && r->tag == MP_INTEGER) { mpz_sub(r->val.bigp,a->val.bigp,b->val.bigp); }else { warningCoeff("Csub(): The data type is not supported."); } } void Cmult(r,a,b) struct coeff *r; struct coeff *a; struct coeff *b; { int p; POLY f; if (a->tag == INTEGER && b->tag == INTEGER && r->tag == INTEGER) { r->p = p = a->p; r->val.i = ((a->val.i) * (b->val.i)) % p; }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER && r->tag == MP_INTEGER) { mpz_mul(r->val.bigp,a->val.bigp,b->val.bigp); }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF && r->tag == POLY_COEFF) { f = ppMult(a->val.f,b->val.f); r->val.f = f; }else { warningCoeff("Cmult(): The data type is not supported."); printTag(a->tag); printTag(b->tag); printTag(r->tag); fprintf(stderr,"\n"); warningCoeff("Returns coeffCopy(a) ------------------"); printf("Type in return.\n");getchar(); getchar(); *r = *(coeffCopy(a)); } } int isZero(a) struct coeff *a; { int r; if (a->tag == INTEGER) { if (a->val.i) return(0); else return(1); }else if (a->tag == MP_INTEGER) { r = mpz_cmp_si(a->val.bigp,(long)0); if (r == 0) return(1); else return(0); }else if (a->tag == POLY_COEFF) { if (a->val.f ISZERO) return(1); else return(0); }else{ warningCoeff("CisZero(): The data type is not supported."); return(1); } } struct coeff *coeffCopy(c) struct coeff *c; /* Deep copy */ { struct coeff *r; r = newCoeff(); switch(c->tag) { case INTEGER: r->tag = INTEGER; r->p = c->p; r->val.i = c->val.i; break; case MP_INTEGER: r->tag = MP_INTEGER; r->p = 0; r->val.bigp = newMP_INT(); mpz_set(r->val.bigp,c->val.bigp); break; case POLY_COEFF: r->tag = POLY_COEFF; r->p = c->p; r->val.f = pcmCopy(c->val.f); /* The polynomial is deeply copied. */ break; default: warningCoeff("coeffCopy(): Unknown tag for the argument."); break; } return(r); } void CiiComb(r,p,q) struct coeff *r; int p,q; /* r->val.bigp is read only. */ { switch(r->tag) { case INTEGER: r->val.i = iiComb(p,q,r->p); break; case MP_INTEGER: r->val.bigp = BiiComb(p,q); break; default: warningCoeff("CiiComb(): Unknown tag."); break; } } MP_INT *BiiComb(p,q) int p,q; /* It returns {p \choose q} when p>=0, 0<=q<=p. The value is read only. DON'T CHANGE IT. p=0 0 1 p=1 1 2 1 1 p=2 3 4 5 1 2 1 q=0 q=1 q=2 [p(p+1)/2+q] */ { extern MP_INT *Mp_one; int i,j; MP_INT **newTable; static MP_INT **table; static int tableSize = 0; static int maxp = 0; /* You have {p \choose q} in the table when p=0 and 0<=q or p<0 and 0<=q. [p,q] = p*[p-1,q-1]. [p,0] = 1. The value is read only. DON'T CHANGE IT. When p>=0, p=0 0 1 p=1 1 2 1 1 p=2 3 4 5 1 2 2*1 p=3 6 7 8 9 1 3 3*2 3*2*1, if p=0) { if (q < 0) { warningCoeff("Negative argument to BiiPoch(). Returns zero."); return(Mp_zero); } if (q == 0) return(Mp_one); if (p=0 && p < k) return(0); r = 1; for (i=0;ival.bigp is read only. */ { switch(r->tag) { case INTEGER: r->val.i = iiPoch(p,q,r->p); break; case MP_INTEGER: r->val.bigp = BiiPoch(p,q); break; default: warningCoeff("CiiPoch(): Unknown tag."); break; } } MP_INT *BiiPower(p,q) int p,q; /* It returns p^q. q must be >=0. p^q = [p,q] = p*[p,q-1]. The value is read only. DON'T CHANGE IT. */ /* [p,q] is indexed by table2D[p+q,q]=table1D[(p+q)(p+q+1)/2 + q]. p+q = pq. q=3 0 1 8 27 q=2 0 1 4 9 q=1 0 1 2 3 q=0 1 1 1 1 -p=0 -p=1 -p=2 -p=3 */ { extern MP_INT *Mp_one; extern MP_INT *Mp_zero; MP_INT mp_work; int i,j; MP_INT **newTable; MP_INT **newTable2; static MP_INT **table; static int tableSize = 0; static int maxp = 0; static MP_INT **tableneg; int pq; if (q < 0) { warningCoeff("Negative argument to BiiPower(). Returns zero."); return(Mp_zero); } if (q == 0) return(Mp_one); if (p>=0) { pq = p+q; }else { pq = -p+q; } if (pq=0) return(table[(pq*(pq+1))/2+q]); if (pq=0) { return(table[(pq*(pq+1))/2 +q]); }else{ return(tableneg[(pq*(pq+1))/2 +q]); } } int iiPower(k,s,P) int k; int s; /* k^s , s>=0*/ int P; { int kk,r; r = 1; for (kk=0; kkval.bigp is read only. */ { switch(r->tag) { case INTEGER: r->val.i = iiPower(p,q,r->p); break; case MP_INTEGER: r->val.bigp = BiiPower(p,q); break; default: warningCoeff("CiiPower(): Unknown tag."); break; } } struct coeff *stringToUniversalNumber(s,flagp) char *s; int *flagp; { MP_INT *value; struct coeff * c; value =newMP_INT(); *flagp = mpz_set_str(value,s,10); c = newCoeff(); c->tag = MP_INTEGER; c->p = 0; c->val.bigp = value; return(c); } struct coeff *newUniversalNumber(i) int i; { extern struct ring *SmallRingp; struct coeff *c; c = intToCoeff(i,SmallRingp); return(c); } struct coeff *newUniversalNumber2(i) MP_INT *i; { extern struct ring *SmallRingp; struct coeff *c; c = mpintToCoeff(i,SmallRingp); return(c); } int coeffEqual(a,b) struct coeff *a; struct coeff *b; { if (a->tag == INTEGER && b->tag == INTEGER) { return((a->val.i) == (b->val.i)); }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER) { if (mpz_cmp(a->val.bigp,b->val.bigp)==0) return(1); else return(0); }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF) { return(ppSub(a->val.f,b->val.f) ISZERO); }else { warningCoeff("coeffEqual(): The data type is not supported."); } } int coeffGreater(a,b) struct coeff *a; struct coeff *b; { if (a->tag == INTEGER && b->tag == INTEGER) { return((a->val.i) - (b->val.i)); }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER) { return(mpz_cmp(a->val.bigp,b->val.bigp)); }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF) { warningCoeff("coeffGreater(POLY,POLY) always returns 0."); return(0); }else { warningCoeff("coeffGreater(): The data type is not supported."); } } void universalNumberDiv(r,a,b) struct coeff *r; struct coeff *a; struct coeff *b; { if (a->tag == MP_INTEGER && b->tag == MP_INTEGER && r->tag == MP_INTEGER) { mpz_div(r->val.bigp,a->val.bigp,b->val.bigp); }else { warningCoeff("universalNumberDiv(): The data type is not supported."); } } /* Note that it does not check if c is zero or not. cf isZero(). */ POLY coeffToPoly(c,ringp) struct coeff *c; struct ring *ringp; { int p; struct coeff *tc; if (c->tag == INTEGER) { tc = intToCoeff(c->val.i,ringp); return(newCell(tc,newMonomial(ringp))); }else if (c->tag == MP_INTEGER) { tc = mpintToCoeff(c->val.bigp,ringp); return(newCell(tc,newMonomial(ringp))); } else if (c->tag == POLY_COEFF) { return(newCell(c,newMonomial(ringp))); }else { warningCoeff("coeffToPoly(): The data type is not supported. Return 0."); return(ZERO); } } void errorCoeff(str) char *str; { fprintf(stderr,"Error(coeff.c): %s\n",str); fprintf(stderr,"Type in ctrl-\\");getchar(); exit(15); } void warningCoeff(str) char *str; { fprintf(stderr,"Warning(coeff.c): %s\n",str); }