/* * Multiply b by -1 */ void arith_buffer_negate(arith_buffer_t *b) { mlist_t *p; p = b->list; while (p->next != NULL) { q_neg(&p->coeff); p = p->next; } }
/* * Negate all coefficients * - p must be terminated by max_idx. */ void in_place_negate_monarray(monomial_t *p) { int32_t v; v = p->var; while (v != max_idx) { q_neg(&p->coeff); p ++ ; v = p->var; } }
/* * Multiply b by (- r) */ void arith_buffer_mul_negpp(arith_buffer_t *b, pprod_t *r) { pprod_table_t *tbl; mlist_t *p; tbl = b->ptbl; p = b->list; while (p->next != NULL) { assert(p->prod != end_pp); p->prod = pprod_mul(tbl, p->prod, r); q_neg(&p->coeff); p = p->next; } }
/* * Get a value of of variable k that satisfies the constraints. * - the constraint is (a * var[k] + other vars + fixed sum) is an integer * - so a possible solution is to set all non-fixed vars to (z - fixed_sum)/a */ static void get_solution_for_var(int_constraint_t *cnstr, uint32_t k, rational_t *val, int32_t z) { rational_t qz; assert(k < cnstr->sum_nterms); q_init(&qz); q_set32(&qz, z); sum_of_fixed_terms(cnstr, val); q_neg(val); q_add(val, &qz); q_div(val, &cnstr->sum[k].coeff); q_clear(&qz); }
/* * 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); } } }