Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
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 << ')';
}
Пример #4
0
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;
}
Пример #5
0
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);
}
Пример #6
0
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];
}
Пример #7
0
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);
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
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());
    }
}
Пример #11
0
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;
}