int bu_mulmod (uint32 *c, unsigned int cn, uint32 const *a, unsigned int an, uint32 const *b, unsigned int bn, uint32 const *m, unsigned int mn) { unsigned int alen = bu_len(a, an) ; unsigned int blen = bu_len(b, bn) ; uint32 x[alen+blen] ; if (!bu_mul(x, alen+blen, a, alen, b, blen)) return 0 ; if (!bu_mod(x, alen+blen, m, mn)) return 0 ; return bu_copy(c, cn, x, mn) ; }
int bu_divmod (uint32 *q, unsigned int qn, uint32 const *y, unsigned int yn, uint32 const *x, unsigned int xn, uint32 const *m, unsigned int mn) { unsigned int ylen = bu_len(y, yn) ; unsigned int xlen = bu_len(x, xn) ; unsigned int mlen = bu_len(m, mn) ; unsigned int n = ylen ; if (n < xlen) n = xlen ; if (n < mlen) n = mlen ; if (!n) return (errno = EDOM, 0) ; { uint32 yy[n] ; uint32 xx[n] ; uint32 mm[n] ; bu_gcd(xx, n, x, xlen, m, mlen) ; if ((xx[0] != 1) || (bu_len(xx, n) != 1)) return (errno = EDOM, 0) ; bu_copy_internal(yy, y, ylen) ; bu_zero(yy+ylen, n-ylen) ; bu_copy_internal(xx, x, xlen) ; bu_zero(xx+xlen, n-xlen) ; bu_copy_internal(mm, m, mlen) ; bu_zero(mm+mlen, n-mlen) ; bu_divmod_internal(yy, xx, mm, n) ; return bu_copy(q, qn, yy, n) ; } }
void bu_div_internal (uint32 *a, unsigned int an, uint32 const *b, unsigned int bn, uint32 *q, unsigned int qn) { unsigned int alen = bu_len(a, an) ; unsigned int blen = bu_len(b, bn) ; bu_zero(q, qn) ; if (alen < blen) return ; { uint32 bb[alen + 1] ; unsigned int i = 1 + ((alen - blen) << 5) ; bu_zero(bb, alen - blen) ; bu_copy_internal(bb + alen - blen, b, blen) ; bb[alen] = 0 ; while (bu_cmp(a, alen, bb, alen+1) >= 0) { bu_slb(bb + alen - blen, blen + 1) ; i++ ; } while (i && (bu_cmp(a, alen, bb, alen+1) < 0)) { bu_srb(bb, alen + 1) ; i-- ; } while (i--) { bu_slb(q, alen - blen + 1) ; if (bu_cmp(a, alen, bb, alen) >= 0) { bu_sub(a, alen, a, alen, bb, alen) ; q[0] |= 1 ; } bu_srb(bb, alen) ; } } }