/* * Add -a * r to b */ void arith_buffer_sub_mono(arith_buffer_t *b, rational_t *a, pprod_t *r) { mlist_t *p, *aux; mlist_t **q; if (q_is_zero(a)) return; q = &b->list; p = *q; assert(p == b->list); while (pprod_precedes(p->prod, r)) { q = &p->next; p = *q; } // p points to a monomial with p->prod >= r // q is &b->list if p is first in the list // q is &p0->next where p0 = predecessor of p otherwise. if (p->prod == r) { q_sub(&p->coeff, a); } else { assert(pprod_precedes(r, p->prod)); aux = alloc_list_elem(b->store); aux->next = p; q_set_neg(&aux->coeff, a); aux->prod = r; *q = aux; b->nterms ++; } }
/* * Check whether b is of the form a * X - a * Y * for a non-zero rational a and two products X and Y. * If so return X in *r1 and Y in *r2 */ bool arith_buffer_is_equality(arith_buffer_t *b, pprod_t **r1, pprod_t **r2) { mlist_t *p, *q; pprod_t *x, *y; rational_t a; bool is_eq; is_eq = false; if (b->nterms == 2) { p = b->list; q = p->next; x = p->prod; y = p->prod; if (x != empty_pp) { *r1 = x; *r2 = y; q_init(&a); q_set(&a, &p->coeff); q_add(&a, &q->coeff); is_eq = q_is_zero(&a); q_clear(&a); } } return is_eq; }
/* * Store gcd(a, b) into a * - if a is zero, copy b's absolute value into a * - a and b must be integer * - b must be non zero */ static void aux_gcd(rational_t *a, rational_t *b) { assert(q_is_integer(a) && q_is_integer(b)); if (q_is_zero(a)) { q_set_abs(a, b); } else { q_gcd(a, b); } }
void q_div ( Q a, Q x, Q y ) { Q inv; /* Doesn't seem to work. Will need to better understand inversion */ if ( q_is_zero(y) ) { return; } q_inv(inv,y); q_mul(a,x,inv); }
/* * Normalize: remove the zero monomials from b */ void arith_buffer_normalize(arith_buffer_t *b) { mlist_t *p; mlist_t **q; q = &b->list; p = *q; assert(p == b->list); while (p->next != NULL) { // p == *q and p is not the end marker assert(p == *q && p->prod != end_pp); if (q_is_zero(&p->coeff)) { // remove p *q = p->next; free_list_elem(b->store, p); b->nterms --; } else { q = &p->next; } p = *q; } }