Example #1
0
/*
 * Add -a * r * b1 to b
 */
void arith_buffer_sub_mono_times_buffer(arith_buffer_t *b, arith_buffer_t *b1, rational_t *a, pprod_t *r) {
  mlist_t *p, *aux, *p1;
  mlist_t **q;
  pprod_t *r1;

  q = &b->list;
  p = *q;

  p1 = b1->list;
  while (p1->next != NULL) {
    r1 = pprod_mul(b->ptbl, p1->prod, r);
    while (pprod_precedes(p->prod, r1)) {
      q = &p->next;
      p = *q;
    }

    if (p->prod == r1) {
      q_submul(&p->coeff, &p1->coeff, a);
      q = &p->next;
      p = *q;
    } else {
      assert(pprod_precedes(r1, p->prod));

      aux = alloc_list_elem(b->store);
      aux->next = p;
      q_submul(&aux->coeff, &p1->coeff, a); // since aux->coeff is 0 initially
      aux->prod = r1;

      *q = aux;
      q = &aux->next;
      b->nterms ++;
    }
    p1 = p1->next;
  }
}
Example #2
0
/*
 * Subtract a * poly from b
 */
void arith_buffer_sub_mono_times_monarray(arith_buffer_t *b, monomial_t *poly, pprod_t **pp, rational_t *a, pprod_t *r) {
  mlist_t *p, *aux;
  mlist_t **q;
  pprod_t *r1;

  assert(good_pprod_array(poly, pp));

  q = &b->list;
  p = *q;

  while (poly->var < max_idx) {
    // poly points to a pair (coeff, x_i)
    // r1 = r * power product for x_i
    r1 = pprod_mul(b->ptbl, *pp, r);
    while (pprod_precedes(p->prod, r1)) {
      q = &p->next;
      p = *q;
    }

    // p points to monomial whose prod is >= r1 in the deg-lex order
    // q points to the predecessor of p in the list
    if (p->prod == r1) {
      q_submul(&p->coeff, &poly->coeff, a);
      q = &p->next;
      p = *q;
    } else {
      assert(pprod_precedes(r1, p->prod));

      aux = alloc_list_elem(b->store);
      aux->next = p;
      q_submul(&aux->coeff, &poly->coeff, a); // aux->coeff is initialized to 0 in alloc_list_elem
      aux->prod = r1;

      *q = aux;
      q = &aux->next;
      b->nterms ++;
    }

    // move to the next monomial of poly
    poly ++;
    pp ++;
  }
}
Example #3
0
/*
 * Phase and period of p
 * - p is c + (a_1/b_1) x_1 + ... + (a_n/b_n) x_n where
 *   a_i/b_i is an irreducible fraction
 * - let D = gcd(a_1,..., a_n) and L = lcm(b_1,...,b_n)
 *   then period = D/L and phase = c - floor(c/period) * period
 */
void monarray_period_and_phase(monomial_t *p, rational_t *period, rational_t *phase) {
  rational_t aux;
  monomial_t *c;
  int32_t v;

  /*
   * c := the constant monomial of p or NULL if p's constant is zero
   */
  c = NULL;
  v = p->var;
  if (v == const_idx) {
    c = p;
    p ++;
    v = p->var;
  }

  if (v < max_idx) {
    /*
     * p is not a constant: compute D and L
     * we use period for D and phase for L
     */
    q_get_num(period, &p->coeff); // D := |a_1|
    if (q_is_neg(period)) {
      q_neg(period);
    }

    q_get_den(phase, &p->coeff);  // L := b_1
    q_init(&aux);

    for (;;) {
      p ++;
      v = p->var;
      if (v >= max_idx) break;
      q_get_num(&aux, &p->coeff);
      q_gcd(period, &aux);        // D := gcd(D, a_i)
      q_get_den(&aux, &p->coeff);
      q_lcm(phase, &aux);         // L := lcm(L, b_i)
    }

    assert(q_is_pos(period) && q_is_pos(phase));
    q_div(period, phase);        // period := D/L

    /*
     * Phase: constant modulo D/L
     */
    if (c == NULL) {
      q_clear(phase);  // no constant: phase = 0
    } else {
      q_set(&aux, &c->coeff);
      q_div(&aux, period);
      q_floor(&aux);             // aux = floor(c/period)
      q_set(phase, &c->coeff);
      q_submul(phase, &aux, period); // phase = c - aux * period

      assert(q_is_nonneg(phase) && q_lt(phase, period));
    }

    q_clear(&aux);

  } else {
    /*
     * p is constant: period := 0, phase = constant coeff
     */
    q_clear(period);
    if (c == NULL) {
      q_clear(phase);
    } else {
      q_set(phase, &c->coeff);
    }
  }

}