bool arith_buffer_is_nonneg(arith_buffer_t *b) { return b->nterms == 1 && b->list->prod == empty_pp && q_is_nonneg(&b->list->coeff); }
/* * 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); } } }