static Matrix_t *makekernel(const Poly_t *pol) { Matrix_t *materg; PTR rowptr; FEL *xbuf, *pbuf = pol->Data; long pdeg = pol->Degree; int k, xshift; long fl = pol->Field; materg = MatAlloc(fl,pdeg,pdeg); rowptr = materg->Data; xbuf = NALLOC(FEL,pdeg+1); for (k = 0; k <= pdeg; ++k) xbuf[k] = FF_ZERO; xbuf[0] = FF_ONE; for (k = 0; k < pdeg; ++k) { int l; for (l = 0; l < pdeg; ++l) FfInsert(rowptr,l,xbuf[l]); FfInsert(rowptr,k,FfSub(xbuf[k],FF_ONE)); FfStepPtr(&rowptr); for (xshift = (int) fl; xshift > 0; ) { FEL f; int d; /* Find leading pos */ for (l = pdeg-1; xbuf[l] == FF_ZERO && l >= 0; --l); /* Shift left as much as possible */ if ((d = pdeg - l) > xshift) d = xshift; for (; l >= 0; l--) xbuf[l+d] = xbuf[l]; for (l = d-1; l >= 0; --l) xbuf[l] = FF_ZERO; xshift -= d; if (xbuf[pdeg] == FF_ZERO) continue; /* Reduce with pol */ f = FfNeg(FfDiv(xbuf[pdeg],pbuf[pdeg])); for (l = pdeg-1; l >= 0; --l) xbuf[l] = FfAdd(xbuf[l],FfMul(pbuf[l],f)); xbuf[pdeg] = FF_ZERO; } } SysFree(xbuf); return MatNullSpace__(materg); }
int FfSetField(int field) { static char filename[50]; FILE *fd; unsigned short info[5]; if (field != FfOrder) { Ff1MakeTables(field); sprintf(filename,"p%5.5d.zzz",field); if ((fd = SysFopen(filename,FM_READ|FM_LIB)) == NULL || fread((char *)info,sizeof(short),5,fd) != 5) { perror(filename); MTX_ERROR("Error opening table file"); return -1; } P = info[1]; Q = info[2]; N = info[3]; Q1 = Q - 1; Gen = info[4]; FfOrder = (long) Q; FfChar = (long) P; if (Q == 2) FfGen = 0; else FfGen = 1; if ((info[0]) != ZZZVERSION || N >= MAXPWR || Q < 2 || P < 2 || P > Q || Q % P != 0) { MTX_ERROR("ERROR IN TABLE FILE HEADER"); return -1; } if (inc != NULL) free(inc); inc = NALLOC(FEL,Q-1); if ( fread(poly,sizeof(short),(size_t) N+1,fd) != (size_t)N+1 || fread(ppwr,sizeof(short),(size_t) N,fd) != (size_t)N || fread(ppindex,sizeof(short),(size_t) N,fd) != (size_t)N || fread(&minusone,sizeof(short),1,fd) != 1 || fread(inc,sizeof(short),(size_t)(Q-1),fd) != (int) Q-1 ) { perror(filename); exit(EXIT_ERR); } if (poly[N] != 1) MTX_ERROR("ERROR IN TABLE FILE"); fclose(fd); } return 0; }
static factor_t *factorsquarefree(const Poly_t *pol) { long int e,j,k,ltmp,tdeg,exp; Poly_t *t0, *t, *w, *v; FEL *tbuf, *t0buf; factor_t *list; int nfactors = 0; /* Initialize variables -------------------- */ FfSetField(pol->Field); for (exp = 0, ltmp = FfOrder; ltmp % FfChar == 0; ++exp, ltmp /= FfChar); t0 = PolDup(pol); e = 1; /* Allocate the list of factors. The can be at most <pol->Degree> factors, but we need one extra entry to terminate the list. ----------------------------------------------------------- */ list = NALLOC(factor_t,pol->Degree + 1); /* Main loop --------- */ while (t0->Degree > 0) { Poly_t *der = PolDerive(PolDup(t0)); t = PolGcd(t0,der); PolFree(der); v = PolDivMod(t0,t); PolFree(t0); for (k = 0; v->Degree > 0; ) { Poly_t *tmp; if ( ++k % FfChar == 0 ) { tmp = PolDivMod(t,v); PolFree(t); t = tmp; k++; } w = PolGcd(t,v); list[nfactors].p = PolDivMod(v,w); list[nfactors].n = e * k; if (list[nfactors].p->Degree > 0) ++nfactors; /* add to output */ else PolFree(list[nfactors].p); /* discard const. */ PolFree(v); v = w; tmp = PolDivMod(t,v); PolFree(t); t = tmp; } PolFree(v); /* shrink the polynomial */ tdeg = t->Degree; e *= FfChar; if ( tdeg % FfChar != 0 ) printf("error in t, degree not div. by prime \n"); t0 = PolAlloc(FfOrder,tdeg/FfChar); t0buf = t0->Data; tbuf = t->Data; for (j = t0->Degree; j >= 0; --j) { FEL el, el1; long lexp; el = *tbuf; tbuf += FfChar; el1 = el; /* this is a bug, it should apply the e-1 power of the frobenius K. Lux 16th 11 1996 */ /* replace el1 by el1^(FfChar^(exp-1)) */ for ( lexp = 0; lexp < exp-1; lexp++ ) { long n; /* replace el1 by el1^FfChar */ el = el1; for ( n = FfChar-1; 0 < n; n-- ) { el1 = FfMul(el1,el); } } *t0buf = el1; ++t0buf; } PolFree(t); } PolFree(t0); /* Terminate the list ------------------ */ list[nfactors].p = NULL; list[nfactors].n = 0; return list; }
TNPtr* tn_detachmany (TNPtr n, int len) { /* Detaches the node n and its 'len -1' right siblings from the tree * by removing them from their parent node. In toto 'len' nodes are * removed. The sibling relationships are squashed as well, and the * index information for all right siblings is adjusted. The nodes * retain their children. After this function is called thes node * and their children are ready for tn_delete'. Or reinsertion in a * different place. * * The operation fails with a panic if there are less children we * can cut than requested. It also panics when trying to cut * nothing. * * Note: This function does not reset the parent reference in the * cut nodes. */ TNPtr* ch; TNPtr p = n->parent; int at = n->index; int end = at + len; ASSERT (end <= p->nchildren, "tn_detachmany - tried to cut too many children"); ASSERT (len > 0, "tn_detachmany - tried to cut nothing"); if ((at == 0) && (end == p->nchildren)) { /* All children are taken. There is no need to copy anything, we * can use the whole array, and reset the other information in the * parent. Note that the condition above implies 'at == 0'. The * parent node becomes a leaf again. */ ch = p->child; p->child = NULL; p->maxchildren = 0; p->nchildren = 0; tn_leaf (p); } else { /* Copies the cut nodes into a result array. Shifts the right * siblings down, if there are any. */ int i, k; ch = NALLOC (len, TNPtr); /* Examples. We always have nchildren = 10. * * _______________________________ * at = 2, len = 3. * * 01 234 56789 i = 0, k = 2 * 012 i = 3, k = 5 * * 01 234 56789 i = 2, k = 5 * 01 567 89 i = 7, k = 10 * * _______________________________ * at = 7, len = 3. * * 0123456 789 i = 0, k = 7 * 012 i = 3, k = 10 * * 0123456 789 i = 7, k = 10 * 0123456 nothing * * _______________________________ * at = 6, len = 3. * * 012345 678 9 i = 0, k = 6 * 012 i = 3, k = 9 * * 012345 678 9 i = 6, k = 9 * 012345 9 i = 7, k = 10 * * _______________________________ * at = 6, len = 1. * * 012345 6 789 i = 0, k = 6 * 0 i = 1, k = 7 * * 012345 6 789 i = 6, k = 7 * 012345 7 89 i = 9, k = 10 */ for (i = 0, k = at; i < len; i++, k++) { ASSERT_BOUNDS (k, p->nchildren); ASSERT_BOUNDS (i, len); ch [i] = p->child [k]; } for (i = at, k = end; k < p->nchildren; i++, k++) { ASSERT_BOUNDS (k, p->nchildren); ASSERT_BOUNDS (i, p->nchildren); p->child [i] = p->child [k]; p->child [i]->index -= len; } p->nchildren -= len; if (ch [0]->left) { ch [0]->left->right = ch [len-1]->right; } if (ch [len-1]->right) { ch [len-1]->right->left = ch [0]->left; } ch [0]->left = NULL; ch [len-1]->right = NULL; } n->tree->structure = 0; return ch; }