/**************************************** * Computer Algebra System SINGULAR * ****************************************/ /* $Id$ */ /* * ABSTRACT - Hilbert series */ #include #include #include #include #include #include #include #include static int **Qpol; static int *Q0, *Ql; static int hLength; static int hMinModulweight(intvec *modulweight) { int i,j,k; if(modulweight==NULL) return 0; j=(*modulweight)[0]; for(i=modulweight->rows()-1;i!=0;i--) { k=(*modulweight)[i]; if(k0; i--) { x = 0; for (j = 0; j < Nstc; j++) { y = stc[j][var[i]]; if (y > x) x = y; } z += x; j = i - 1; if (z > Ql[j]) { if (z>(INT_MAX)/2) { Werror("interal arrays too big"); return; } p = (int *)omAlloc((unsigned long)z * sizeof(int)); if (Ql[j]!=0) { if (j==0) memcpy(p, Qpol[j], Ql[j] * sizeof(int)); omFreeSize((ADDRESS)Qpol[j], Ql[j] * sizeof(int)); } if (j==0) { for (x = Ql[j]; x < z; x++) p[x] = 0; } Ql[j] = z; Qpol[j] = p; } } } static int *hAddHilb(int Nv, int x, int *pol, int *lp) { int l = *lp, ln, i; int *pon; *lp = ln = l + x; pon = Qpol[Nv]; memcpy(pon, pol, l * sizeof(int)); if (l > x) { for (i = x; i < l; i++) pon[i] -= pol[i - x]; for (i = l; i < ln; i++) pon[i] = -pol[i - x]; } else { for (i = l; i < x; i++) pon[i] = 0; for (i = x; i < ln; i++) pon[i] = -pol[i - x]; } return pon; } static void hLastHilb(scmon pure, int Nv, varset var, int *pol, int lp) { int l = lp, x, i, j; int *p, *pl; p = pol; for (i = Nv; i>0; i--) { x = pure[var[i + 1]]; if (x!=0) p = hAddHilb(i, x, p, &l); } pl = *Qpol; j = Q0[Nv + 1]; for (i = 0; i < l; i++) pl[i + j] += p[i]; x = pure[var[1]]; if (x!=0) { j += x; for (i = 0; i < l; i++) pl[i + j] -= p[i]; } j += l; if (j > hLength) hLength = j; } static void hHilbStep(scmon pure, scfmon stc, int Nstc, varset var, int Nvar, int *pol, int Lpol) { int iv = Nvar -1, ln, a, a0, a1, b, i; int x, x0; scmon pn; scfmon sn; int *pon; if (Nstc==0) { hLastHilb(pure, iv, var, pol, Lpol); return; } x = a = 0; pn = hGetpure(pure); sn = hGetmem(Nstc, stc, stcmem[iv]); hStepS(sn, Nstc, var, Nvar, &a, &x); Q0[iv] = Q0[Nvar]; ln = Lpol; pon = pol; if (a == Nstc) { x = pure[var[Nvar]]; if (x!=0) pon = hAddHilb(iv, x, pon, &ln); hHilbStep(pn, sn, a, var, iv, pon, ln); return; } else { pon = hAddHilb(iv, x, pon, &ln); hHilbStep(pn, sn, a, var, iv, pon, ln); } b = a; x0 = 0; loop { Q0[iv] += (x - x0); a0 = a; x0 = x; hStepS(sn, Nstc, var, Nvar, &a, &x); hElimS(sn, &b, a0, a, var, iv); a1 = a; hPure(sn, a0, &a1, var, iv, pn, &i); hLex2S(sn, b, a0, a1, var, iv, hwork); b += (a1 - a0); ln = Lpol; if (a < Nstc) { pon = hAddHilb(iv, x - x0, pol, &ln); hHilbStep(pn, sn, b, var, iv, pon, ln); } else { x = pure[var[Nvar]]; if (x!=0) pon = hAddHilb(iv, x - x0, pol, &ln); else pon = pol; hHilbStep(pn, sn, b, var, iv, pon, ln); return; } } } /* *basic routines */ static void hWDegree(intvec *wdegree) { int i, k; int x; for (i=pVariables; i; i--) { x = (*wdegree)[i-1]; if (x != 1) { for (k=hNexist-1; k>=0; k--) { hexist[k][i] *= x; } } } } static intvec * hSeries(ideal S, intvec *modulweight, int notstc, intvec *wdegree, ideal Q, ring tailRing) { intvec *work, *hseries1=NULL; int mc; int p0; int i, j, k, l, ii, mw; hexist = hInit(S, Q, &hNexist, tailRing); if (hNexist==0) { hseries1=new intvec(2); (*hseries1)[0]=1; (*hseries1)[1]=0; return hseries1; } #if 0 if (wdegree == NULL) hWeight(); else hWDegree(wdegree); #else if (wdegree != NULL) hWDegree(wdegree); #endif p0 = 1; hwork = (scfmon)omAlloc(hNexist * sizeof(scmon)); hvar = (varset)omAlloc((pVariables + 1) * sizeof(int)); hpure = (scmon)omAlloc((1 + (pVariables * pVariables)) * sizeof(int)); stcmem = hCreate(pVariables - 1); Qpol = (int **)omAlloc((pVariables + 1) * sizeof(int *)); Ql = (int *)omAlloc0((pVariables + 1) * sizeof(int)); Q0 = (int *)omAlloc((pVariables + 1) * sizeof(int)); *Qpol = NULL; hLength = k = j = 0; mc = hisModule; if (mc!=0) { mw = hMinModulweight(modulweight); hstc = (scfmon)omAlloc(hNexist * sizeof(scmon)); } else { mw = 0; hstc = hexist; hNstc = hNexist; } loop { if (mc!=0) { hComp(hexist, hNexist, mc, hstc, &hNstc); if (modulweight != NULL) j = (*modulweight)[mc-1]-mw; } if (hNstc!=0) { hNvar = pVariables; for (i = hNvar; i>=0; i--) hvar[i] = i; //if (notstc) // TODO: no mon divides another hStaircase(hstc, &hNstc, hvar, hNvar); hSupp(hstc, hNstc, hvar, &hNvar); if (hNvar!=0) { if ((hNvar > 2) && (hNstc > 10)) hOrdSupp(hstc, hNstc, hvar, hNvar); hHilbEst(hstc, hNstc, hvar, hNvar); memset(hpure, 0, (pVariables + 1) * sizeof(int)); hPure(hstc, 0, &hNstc, hvar, hNvar, hpure, &hNpure); hLexS(hstc, hNstc, hvar, hNvar); Q0[hNvar] = 0; hHilbStep(hpure, hstc, hNstc, hvar, hNvar, &p0, 1); } } else { if(*Qpol!=NULL) (**Qpol)++; else { *Qpol = (int *)omAlloc(sizeof(int)); hLength = *Ql = **Qpol = 1; } } if (*Qpol!=NULL) { i = hLength; while ((i > 0) && ((*Qpol)[i - 1] == 0)) i--; if (i > 0) { l = i + j; if (l > k) { work = new intvec(l); for (ii=0; ii 0) { (*hseries1)[i + j - 1] += (*Qpol)[i - 1]; (*Qpol)[i - 1] = 0; i--; } } } mc--; if (mc <= 0) break; } if (k==0) { hseries1=new intvec(2); (*hseries1)[0]=0; (*hseries1)[1]=0; } else { l = k+1; while ((*hseries1)[l-2]==0) l--; if (l!=k) { work = new intvec(l); for (ii=l-2; ii>=0; ii--) (*work)[ii] = (*hseries1)[ii]; delete hseries1; hseries1 = work; } (*hseries1)[l-1] = mw; } for (i = 0; i <= pVariables; i++) { if (Ql[i]!=0) omFreeSize((ADDRESS)Qpol[i], Ql[i] * sizeof(int)); } omFreeSize((ADDRESS)Q0, (pVariables + 1) * sizeof(int)); omFreeSize((ADDRESS)Ql, (pVariables + 1) * sizeof(int)); omFreeSize((ADDRESS)Qpol, (pVariables + 1) * sizeof(int *)); hKill(stcmem, pVariables - 1); omFreeSize((ADDRESS)hpure, (1 + (pVariables * pVariables)) * sizeof(int)); omFreeSize((ADDRESS)hvar, (pVariables + 1) * sizeof(int)); omFreeSize((ADDRESS)hwork, hNexist * sizeof(scmon)); hDelete(hexist, hNexist); if (hisModule!=0) omFreeSize((ADDRESS)hstc, hNexist * sizeof(scmon)); return hseries1; } intvec * hHstdSeries(ideal S, intvec *modulweight, intvec *wdegree, ideal Q, ring tailRing) { return hSeries(S, modulweight, 0, wdegree, Q, tailRing); } intvec * hFirstSeries(ideal S, intvec *modulweight, ideal Q, intvec *wdegree, ring tailRing) { return hSeries(S, modulweight, 1, wdegree, Q, tailRing); } intvec * hSecondSeries(intvec *hseries1) { intvec *work, *hseries2; int i, j, k, s, t, l; if (hseries1 == NULL) return NULL; work = new intvec(hseries1); k = l = work->length()-1; s = 0; for (i = k-1; i >= 0; i--) s += (*work)[i]; loop { if ((s != 0) || (k == 1)) break; s = 0; t = (*work)[k-1]; k--; for (i = k-1; i >= 0; i--) { j = (*work)[i]; (*work)[i] = -t; s += t; t += j; } } hseries2 = new intvec(k+1); for (i = k-1; i >= 0; i--) (*hseries2)[i] = (*work)[i]; (*hseries2)[k] = (*work)[l]; delete work; return hseries2; } void hDegreeSeries(intvec *s1, intvec *s2, int *co, int *mu) { int m, i, j, k; *co = *mu = 0; if ((s1 == NULL) || (s2 == NULL)) return; i = s1->length(); j = s2->length(); if (j > i) return; m = 0; for(k=j-2; k>=0; k--) m += (*s2)[k]; *mu = m; *co = i - j; } static void hPrintHilb(intvec *hseries) { int i, j, l, k; if (hseries == NULL) return; l = hseries->length()-1; k = (*hseries)[l]; for (i = 0; i < l; i++) { j = (*hseries)[i]; if (j != 0) { Print("// %8d t^%d\n", j, i+k); } } } /* *caller */ void hLookSeries(ideal S, intvec *modulweight, ideal Q) { int co, mu, l; intvec *hseries2; intvec *hseries1 = hFirstSeries(S, modulweight, Q); hPrintHilb(hseries1); l = hseries1->length()-1; if (l > 1) hseries2 = hSecondSeries(hseries1); else hseries2 = hseries1; hDegreeSeries(hseries1, hseries2, &co, &mu); PrintLn(); hPrintHilb(hseries2); if ((l == 1) &&(mu == 0)) scPrintDegree(pVariables+1, 0); else scPrintDegree(co, mu); if (l>1) delete hseries1; delete hseries2; }