/* w.b. hart */ void zz_gcd(zz_ptr g, zz_srcptr a, zz_srcptr b) { long asize = ABS(a->size); long bsize = ABS(b->size); long size; nn_t ta, tb; TMP_INIT; if (asize == 0) zz_copy(g, b); else if (bsize == 0) zz_copy(g, a); else { TMP_START; ZZ_ORDER(a, asize, b, bsize); ta = TMP_ALLOC(asize*sizeof(word_t)); tb = TMP_ALLOC(bsize*sizeof(word_t)); nn_copyi(ta, a->n, asize); nn_copyi(tb, b->n, bsize); zz_fit(g, bsize); size = nn_gcd(g->n, ta, asize, tb, bsize); g->size = (a->size & b->size) < 0 ? -size : size; TMP_END; } }
/* w.b. hart */ void zz_div(zz_ptr q, zz_srcptr a, zz_srcptr b) { long asize = ABS(a->size); long bsize = ABS(b->size); long rsize = bsize; long qsize = asize - bsize + 1; int qsign = (a->size ^ b->size); zz_t r; if (asize < bsize) q->size = 0; else { zz_init(r); zz_copy(r, a); zz_fit(q, qsize); if (qsign < 0) { nn_divrem(q->n, r->n, asize, b->n, bsize); rsize = nn_normalise(r->n, rsize); } else nn_div(q->n, r->n, asize, b->n, bsize); qsize -= q->n[qsize - 1] == 0; q->size = qsign >= 0 ? qsize : -qsize; if (q->size < 0 && rsize != 0) zz_sub_1(q, q, 1); zz_clear(r); } }
/* w.b. hart */ void zz_divrem(zz_ptr q, zz_t r, zz_srcptr a, zz_srcptr b) { long asize = ABS(a->size); long bsize = ABS(b->size); long rsize = bsize; long qsize = asize - bsize + 1; zz_copy(r, a); if (asize < bsize) q->size = 0; else { zz_fit(q, qsize); nn_divrem(q->n, r->n, asize, b->n, bsize); qsize -= q->n[qsize - 1] == 0; rsize = nn_normalise(r->n, rsize); q->size = (a->size ^ b->size) >= 0 ? qsize : -qsize; r->size = a->size >= 0 ? rsize : -rsize; if (q->size < 0 && r->size != 0) { zz_sub_1(q, q, 1); zz_add(r, r, b); } } }
struct zz_node * zz_copy_recursive(struct zz_tree * tree, struct zz_node * node) { struct zz_node *ret; struct zz_node *iter; ret = zz_copy(tree, node); if (ret == NULL) return ret; zz_foreach_child(iter, node) zz_append_child(ret, zz_copy_recursive(tree, iter)); return ret; }