ring_elem SchurRing::mult_monomials(const int *m, const int *n) { int i; exponents a_part = ALLOCATE_EXPONENTS(sizeof(int) * (nvars_ + 1)); exponents b_part = ALLOCATE_EXPONENTS(sizeof(int) * (nvars_ + 1)); exponents lambda = ALLOCATE_EXPONENTS(2 * sizeof(int) * (nvars_ + 1)); exponents p = ALLOCATE_EXPONENTS(2 * sizeof(int) * (nvars_ + 1)); // First: obtain the partitions to_partition(m, a_part); to_partition(n, b_part); // Second: make the skew partition int a = b_part[1]; for (i=1; i <= nvars_ && a_part[i] != 0; i++) { p[i] = a + a_part[i]; lambda[i] = a; } int top = i-1; for (i=1; i <= nvars_ && b_part[i] != 0; i++) { p[top+i] = b_part[i]; lambda[top+i] = 0; } p[top+i] = 0; lambda[top+i] = 0; // Call the SM() algorithm return skew_schur(lambda, p); }
ring_elem SkewPolynomialRing::mult_by_term(const ring_elem f, const ring_elem c, const int *m) const // Computes c*m*f, BUT NOT doing normal form wrt a quotient ideal.. { Nterm head; Nterm *inresult = &head; exponents EXP1 = ALLOCATE_EXPONENTS(exp_size); exponents EXP2 = ALLOCATE_EXPONENTS(exp_size); M_->to_expvector(m, EXP1); for (Nterm *s = f; s != NULL; s = s->next) { M_->to_expvector(s->monom, EXP2); int sign = skew_.mult_sign(EXP1, EXP2); if (sign == 0) continue; Nterm *t = new_term(); t->next = 0; t->coeff = K_->mult(c, s->coeff); if (sign < 0) K_->negate_to(t->coeff); M_->mult(m, s->monom, t->monom); inresult->next = t; inresult = inresult->next; } inresult->next = 0; return head.next; }
void SchurRing::elem_text_out(buffer &o, const ring_elem f, bool p_one, bool p_plus, bool p_parens) const { exponents EXP = ALLOCATE_EXPONENTS(sizeof(int) * (nvars_ + 1)); int n = n_terms(f); bool needs_parens = p_parens && (n > 1); if (needs_parens) { if (p_plus) o << '+'; o << '('; p_plus = false; } p_one = false; for (Nterm *t = f; t != NULL; t = t->next) { int isone = M_->is_one(t->monom); p_parens = !isone; K_->elem_text_out(o,t->coeff, p_one,p_plus,p_parens); to_partition(t->monom, EXP); o << "{" << EXP[1]; for (int i=2; i<=nvars_ && EXP[i] != 0; i++) o << "," << EXP[i]; o << "}"; p_plus = true; } if (needs_parens) o << ')'; }
int res_comp::sort_value(res_pair *p, const int *sort_order) const { exponents REDUCE_exp = ALLOCATE_EXPONENTS(exp_size); M->to_expvector(p->base_monom, REDUCE_exp); int result = 0; for (int i = 0; i < P->n_vars(); i++) result += REDUCE_exp[i] * sort_order[i]; return result; }
void SchurRing::from_partition(const int *exp, int *m) const { exponents EXP1 = ALLOCATE_EXPONENTS(exp_size); // 0..nvars-1 EXP1[nvars_-1] = exp[nvars_]; for (int i=nvars_-1; i>0; i--) EXP1[i-1] = exp[i] - exp[i+1]; M_->from_expvector(EXP1, m); }
void SchurRing::to_partition(const int *m, int *exp) const // exp[1]..exp[nvars] are set { exponents EXP1 = ALLOCATE_EXPONENTS(exp_size); // 0..nvars-1 // remark: exp_size is defined in an ancestor class of SchurRing M_->to_expvector(m, EXP1); exp[nvars_] = EXP1[nvars_-1]; for (int i=nvars_-1; i>=1; i--) exp[i] = exp[i+1] + EXP1[i-1]; }
ring_elem SchurRing2::mult_terms(const_schur_partition a, const_schur_partition b) { int maxsize = (a[0] - 1 + b[0] - 1) + 1; // this is the max number of elements in the output partition, plus one schur_partition lambda = ALLOCATE_EXPONENTS(sizeof(schur_word) * maxsize); schur_partition p = ALLOCATE_EXPONENTS(sizeof(schur_word) * maxsize); // Second: make the skew partition (note: r,s>=1) // this is: if a = r+1 a1 a2 ... ar // b = s+1 b1 b2 ... bs // p is: // (r+s+1) b1+a1 b1+a2 ... b1+ar b1 b2 ... bs // lambda is: // (r+1) b1 b1 ... b1 0 0 ... 0 int r = a[0]-1; int s = b[0]-1; int c = b[1]; assert(r+s+1 == maxsize); for (int i=1; i<=r; i++) { assert(i < maxsize); p[i] = c + a[i]; lambda[i] = c; } for (int i=r+1; i<r+s+1; i++) { assert(i < maxsize); p[i] = b[i-r]; lambda[i] = 0; } p[0] = r+s+1; lambda[0] = r+1; return skew_schur(lambda, p); }
ring_elem SchurRing::dimension(const ring_elem f) const { exponents EXP = ALLOCATE_EXPONENTS(sizeof(int) * (nvars_ + 1)); ring_elem result = K_->from_int(0); mpz_t dim; mpz_init(dim); for (Nterm *t = f; t != NULL; t = t->next) { to_partition(t->monom, EXP); dimension(EXP, dim); ring_elem h = K_->from_int(dim); ring_elem h2 = K_->mult(t->coeff, h); K_->add_to(result, h2); K_->remove(h); } return result; }
int res_comp::compare_res_pairs(res_pair *f, res_pair *g) const { exponents EXP1, EXP2; int cmp, df, dg, i; // if (f->compare_num < g->compare_num) return 1; // if (f->compare_num > g->compare_num) return -1; // MES: what to do if we obtain equality? Here is one way: switch (compare_type) { case 1: // Compare using descending lexicographic order // on the usual set of variables EXP1 = ALLOCATE_EXPONENTS(exp_size); EXP2 = ALLOCATE_EXPONENTS(exp_size); M->to_expvector(f->base_monom, EXP1); M->to_expvector(g->base_monom, EXP2); for (i = 0; i < M->n_vars(); i++) { if (EXP1[i] < EXP2[i]) return -1; if (EXP1[i] > EXP2[i]) return 1; } return 0; case 2: // Compare using ascending lexicographic order // on the usual set of variables EXP1 = ALLOCATE_EXPONENTS(exp_size); EXP2 = ALLOCATE_EXPONENTS(exp_size); M->to_expvector(f->base_monom, EXP1); M->to_expvector(g->base_monom, EXP2); for (i = 0; i < M->n_vars(); i++) { if (EXP1[i] < EXP2[i]) return 1; if (EXP1[i] > EXP2[i]) return -1; } return 0; case 3: // Compare using descending lexicographic order // on the reversed set of variables EXP1 = ALLOCATE_EXPONENTS(exp_size); EXP2 = ALLOCATE_EXPONENTS(exp_size); M->to_expvector(f->base_monom, EXP1); M->to_expvector(g->base_monom, EXP2); for (i = M->n_vars() - 1; i >= 0; i--) { if (EXP1[i] < EXP2[i]) return -1; if (EXP1[i] > EXP2[i]) return 1; } return 0; case 4: // Compare using ascending lexicographic order // on the reversed set of variables EXP1 = ALLOCATE_EXPONENTS(exp_size); EXP2 = ALLOCATE_EXPONENTS(exp_size); M->to_expvector(f->base_monom, EXP1); M->to_expvector(g->base_monom, EXP2); for (i = M->n_vars() - 1; i >= 0; i--) { if (EXP1[i] < EXP2[i]) return 1; if (EXP1[i] > EXP2[i]) return -1; } return 0; case 5: // The original method, but with degree added, since // the new skeleton code doesn't just sort elements of // the same degree. df = degree(f); dg = degree(g); if (df > dg) return -1; if (df < dg) return 1; cmp = M->compare(f->base_monom, g->base_monom); if (cmp != 0) return cmp; cmp = f->first->compare_num - g->first->compare_num; if (cmp < 0) return 1; if (cmp > 0) return -1; return 0; default: cmp = M->compare(f->base_monom, g->base_monom); if (cmp != 0) return cmp; cmp = f->first->compare_num - g->first->compare_num; if (cmp < 0) return 1; if (cmp > 0) return -1; return 0; } return 0; }
void gbB::remainder(POLY &f, int degf, bool use_denom, ring_elem &denom) // find the remainder of f = [g,gsyz] wrt the GB, // i.e. replace f with h[h,hsyz], st // h = f - sum(a_i * g_i), in(f) not in in(G) // hsyz = fsyz - sum(a_i * gsyz_i) // denom is unchanged // (Here: G = (g_i) is the GB, and a_i are polynomials generated // during division). // c is an integer, and is returned as 'denom'. // Five issues: // (a) if gcd(c, coeffs(f)) becomes > 1, can we divide // c, f, by this gcd? If so, how often do we do this? // (b) do we reduce by any element of the GB, or only those whose // sugar degree is no greater than degf? // (c) can we exclude an element of the GB from the g_i? // (for use in auto reduction). // (d) can we reduce by the minimal GB instead of the original GB? // ANSWER: NO. Instead, use a routine to make a new GB. // (e) Special handling of quotient rings: none needed. { exponents EXP = ALLOCATE_EXPONENTS(exp_size); gbvector head; gbvector *frem = &head; frem->next = 0; int count = 0; POLY h = f; while (!R->gbvector_is_zero(h.f)) { int gap; R->gbvector_get_lead_exponents(F, h.f, EXP); int x = h.f->comp; int w = find_good_divisor(EXP,x,degf, gap); // replaced gap, g. if (w < 0 || gap > 0) { frem->next = h.f; frem = frem->next; h.f = h.f->next; frem->next = 0; } else { POLY g = gb[w]->g; R->gbvector_reduce_lead_term(F, Fsyz, head.next, h.f, h.fsyz, g.f, g.fsyz, use_denom, denom); count++; // stats_ntail++; if (M2_gbTrace >= 10) { buffer o; o << " tail reducing by "; R->gbvector_text_out(o,F,g.f, 2); o << "\n giving "; R->gbvector_text_out(o,F,h.f, 3); emit_line(o.str()); } } } h.f = head.next; R->gbvector_remove_content(h.f, h.fsyz, use_denom, denom); f.f = h.f; f.fsyz = h.fsyz; if ((M2_gbTrace & PRINT_SPAIR_TRACKING) != 0) { buffer o; o << "number of reduction steps was " << count; emit_line(o.str()); } else if (M2_gbTrace >= 4 && M2_gbTrace != 15) { buffer o; o << "," << count; emit_wrapped(o.str()); } }
bool gbB::reduceit(spair *p) { /* Returns false iff we defer computing this spair. */ /* If false is returned, this routine has grabbed the spair 'p'. */ exponents EXP = ALLOCATE_EXPONENTS(exp_size); int tmf, wt; int count = -1; if (M2_gbTrace == 15) { buffer o; o << "considering "; spair_text_out(o,p); o << " : "; emit_line(o.str()); } compute_s_pair(p); /* Changes the type, possibly */ while (!R->gbvector_is_zero(p->f())) { if (count++ > max_reduction_count) { spair_set_defer(p); return false; } if (M2_gbTrace >= 5) { if ((wt = weightInfo->gbvector_weight(p->f(), tmf)) > this_degree) { buffer o; o << "ERROR: degree of polynomial is too high: deg " << wt << " termwt " << tmf << " expectedeg " << this_degree << newline; emit(o.str()); } } int gap,w; R->gbvector_get_lead_exponents(F, p->f(), EXP); int x = p->f()->comp; w = find_good_divisor(EXP,x,this_degree, gap); // replaced gap, g. if (w < 0) break; if (false && gap > 0) { POLY h; h.f = R->gbvector_copy(p->x.f.f); h.fsyz = R->gbvector_copy(p->x.f.fsyz); insert_gb(h,(p->type == SPAIR_GEN ? ELEMB_MINGEN : 0)); } POLY g = gb[w]->g; R->gbvector_reduce_lead_term(F, Fsyz, 0, p->f(), p->fsyz(), /* modifies these */ g.f, g.fsyz); stats_nreductions++; if (M2_gbTrace == 15) { buffer o; o << " reducing by g" << w; o << ", yielding "; R->gbvector_text_out(o, F, p->f(), 3); emit_line(o.str()); } if (R->gbvector_is_zero(p->f())) break; if (gap > 0) { p->deg += gap; if (M2_gbTrace == 15) { buffer o; o << " deferring to degree " << p->deg; emit_line(o.str()); } spair_set_insert(p); return false; } } if (M2_gbTrace >= 4 && M2_gbTrace != 15) { buffer o; o << "." << count; emit_wrapped(o.str()); } return true; }