int main(void) { int i, result; flint_rand_t state; printf("xgcd...."); fflush(stdout); flint_randinit(state); for (i = 0; i < 100000; i++) { mp_limb_t a, b, c, g, bits1, bits2, bits3, ph, pl, qh, ql; mp_limb_t s, t; bits1 = n_randint(state, FLINT_BITS-1) + 1; bits2 = n_randint(state, bits1) + 1; bits3 = n_randint(state, FLINT_BITS - bits1) + 1; do { a = n_randbits(state, bits1); b = n_randbits(state, bits2); } while ((n_gcd(a, b) != 1UL) || (b > a)); c = n_randbits(state, bits3); g = n_xgcd(&s, &t, a*c, b*c); umul_ppmm(ph, pl, a*c, s); umul_ppmm(qh, ql, b*c, t); sub_ddmmss(ph, pl, ph, pl, qh, ql); result = ((g == c) && (ph == 0UL) && (pl == c)); if (!result) { printf("FAIL:\n"); printf("a = %lu, b = %lu, c = %lu, g = %lu, s = %lu, t = %lu\n", a, b, c, g, s, t); abort(); } } flint_randclear(state); printf("PASS\n"); return 0; }
int main(void) { int i, result; flint_rand_t state; flint_randinit(state); printf("sdiv_qrnnd...."); fflush(stdout); for (i = 0; i < 1000000; i++) { mp_limb_signed_t d, nh, nl, q, r, ph, pl; do { d = n_randtest_not_zero(state); nh = n_randtest(state); } while (FLINT_ABS(nh) >= FLINT_ABS(d)/2); nl = n_randtest(state); sdiv_qrnnd(q, r, nh, nl, d); smul_ppmm(ph, pl, d, q); if (r < 0L) sub_ddmmss(ph, pl, ph, pl, 0UL, -r); else add_ssaaaa(ph, pl, ph, pl, 0UL, r); result = ((ph == nh) && (pl == nl)); if (!result) { printf("FAIL:\n"); printf("nh = %lu, nl = %lu, d = %lu\n", nh, nl, d); printf("ph = %lu, pl = %lu\n", ph, pl); abort(); } } flint_randclear(state); printf("PASS\n"); return 0; }
static __inline__ long _fmpr_add_small(fmpr_t z, mp_limb_t x, int xsign, const fmpz_t xexp, mp_limb_t y, int ysign, const fmpz_t yexp, long shift, long prec, long rnd) { mp_limb_t hi, lo, t, u; int sign = ysign; t = x; u = y; lo = u << shift; hi = (shift == 0) ? 0 : (u >> (FLINT_BITS - shift)); if (xsign == ysign) { add_ssaaaa(hi, lo, hi, lo, 0, t); } else { if (hi == 0) { if (lo >= t) { lo = lo - t; } else { lo = t - lo; sign = !sign; } } else { sub_ddmmss(hi, lo, hi, lo, 0, t); } } if (hi == 0) return fmpr_set_round_ui_2exp_fmpz(z, lo, xexp, sign, prec, rnd); else return fmpr_set_round_uiui_2exp_fmpz(z, hi, lo, xexp, sign, prec, rnd); }
void check_data (void) { #define M MP_LIMB_T_MAX static const struct { mp_limb_t want_dh,want_dl, mh,ml, sh,sl; } data[] = { { 0,0, 0,0, 0,0 }, { 0,0, 0,1, 0,1 }, { 0,0, 1,2, 1,2 }, { 0,1, 0,2, 0,1 }, { 0,M, 1,0, 0,1 }, { M,M, 0,0, 0,1 }, { M,M, 0,M-1, 0,M }, { 0,0, 0,M-1, 0,M-1 }, { 0,1, 0,M-1, 0,M-2 }, }; int i; mp_limb_t got_dh, got_dl; for (i = 0; i < numberof (data); i++) { sub_ddmmss (got_dh,got_dl, data[i].mh,data[i].ml, data[i].sh,data[i].sl); if (got_dh != data[i].want_dh || got_dl != data[i].want_dl) { printf ("check_data wrong at data[%d]\n", i); mp_limb_trace (" mh", data[i].mh); mp_limb_trace (" ml", data[i].ml); mp_limb_trace (" sh", data[i].sh); mp_limb_trace (" sl", data[i].sl); mp_limb_trace (" want dh", data[i].want_dh); mp_limb_trace (" want dl", data[i].want_dl); mp_limb_trace (" got dh ", got_dh); mp_limb_trace (" got dl ", got_dl); abort (); } } }
int main(void) { int i, result; flint_rand_t state; printf("submod...."); fflush(stdout); flint_randinit(state); for (i = 0; i < 1000000; i++) { mp_limb_t a, b, d, r1, r2, s1; d = n_randtest(state); a = n_randint(state, d); b = n_randint(state, d); r1 = n_submod(a, b, d); add_ssaaaa(s1, r2, 0UL, a, 0UL, d); sub_ddmmss(s1, r2, s1, r2, 0UL, b); if ((s1) || (r2 >= d)) r2 -= d; result = (r1 == r2); if (!result) { printf("FAIL:\n"); printf("a = %lu, b = %lu, d = %lu\n", a, b, d); printf("r1 = %lu, r2 = %lu\n", r1, r2); abort(); } } flint_randclear(state); printf("PASS\n"); return 0; }
int main(void) { TIunion aa, bb, cc; TItype m = 0x1111111111111110ULL; TItype n = 0x1111111111111111ULL; TItype d; aa.s.high = m; aa.s.low = m; bb.s.high = n; bb.s.low = n; sub_ddmmss (&cc.s.high, &cc.s.low, aa.s.high, aa.s.low, bb.s.high, bb.s.low); d = aa.t - bb.t; if (d != cc.t) abort(); cc.t = aa.t -d; if (cc.t != bb.t) abort(); return 0; }
void check_random (void) { mp_limb_t want_dh,want_dl, got_dh,got_dl, mh,ml, sh,sl; int i; gmp_randstate_t rands; gmp_randinit_default(rands); for (i = 0; i < 20; i++) { mh = urandom (rands); ml = urandom (rands); sh = urandom (rands); sl = urandom (rands); refmpn_sub_ddmmss (&want_dh,&want_dl, mh,ml, sh,sl); sub_ddmmss (got_dh,got_dl, mh,ml, sh,sl); if (got_dh != want_dh || got_dl != want_dl) { printf ("check_data wrong at data[%d]\n", i); mp_limb_trace (" mh", mh); mp_limb_trace (" ml", ml); mp_limb_trace (" sh", sh); mp_limb_trace (" sl", sl); mp_limb_trace (" want dh", want_dh); mp_limb_trace (" want dl", want_dl); mp_limb_trace (" got dh ", got_dh); mp_limb_trace (" got dl ", got_dl); abort (); } } gmp_randclear(rands); }
void my_udiv_qr_3by2 ( mp_limb_t* p_q, mp_limb_t* p_r1, mp_limb_t* p_r0, mp_limb_t* p_n2, mp_limb_t* p_n1, mp_limb_t* p_n0, mp_limb_t* p_d1, mp_limb_t* p_d0, mp_limb_t* p_dinv, mp_limb_t* p__q0, mp_limb_t* p__t1, mp_limb_t* p__t0, mp_limb_t* p__mask) { /* mp_limb_t q = *p_q; mp_limb_t r0 = *p_r0; mp_limb_t r1 = *p_r1; mp_limb_t n0 = *p_n0; mp_limb_t n1 = *p_n1; mp_limb_t n2 = *p_n2; mp_limb_t dinv = *p_dinv; mp_limb_t d0 = *p_d0; mp_limb_t d1 = *p_d1; mp_limb_t _q0, _t1, _t0, _mask; _q0 = *p__q0; _t0 = *p__t0; _t1 = *p__t1; _mask = *p__mask; */ #define q (*p_q) #define r0 (*p_r0) #define r1 (*p_r1) #define n0 (*p_n0) #define n1 (*p_n1) #define n2 (*p_n2) #define dinv (*p_dinv) #define d0 (*p_d0) #define d1 (*p_d1) #define _q0 (*p__q0) #define _t0 (*p__t0) #define _t1 (*p__t1) #define _mask (*p__mask) printf("n0 %08lx\n", n0); printf("n1 %08lx\n", n1); printf("n2 %08lx\n", n2); printf("dinv %08lx\n", dinv); printf("d0 %08lx\n", d0); printf("d1 %08lx\n", d1); umul_ppmm ((q), _q0, (n2), (dinv)); printf("q %08lx\n", q); printf("_q0 %08lx\n", _q0); add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); printf("q %08lx\n", q); /* Compute the two most significant limbs of n - q'd */ (r1) = (n1) - (d1) * (q); printf("r1 %08lx\n", r1); (r0) = (n0); printf("r0 %08lx\n", r0); sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); umul_ppmm (_t1, _t0, (d0), (q)); printf("_t0 %08lx\n", _t0); printf("_t1 %08lx\n", _t1); sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); (q)++; /* Conditionally adjust q and the remainders */ _mask = - (mp_limb_t) ((r1) >= _q0); printf("_mask %08lx\n", _mask); (q) += _mask; printf("q %08lx\n", q); add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); if (UNLIKELY ((r1) >= (d1))) { if ((r1) > (d1) || (r0) >= (d0)) { (q)++; printf("q %08lx\n", q); sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); } } #undef q #undef r0 #undef r1 #undef n0 #undef n1 #undef n2 #undef dinv #undef d0 #undef d1 #undef _q0 #undef _t1 #undef _t0 #undef _mask }
mp_limb_t _ll_factor_SQUFOF(mp_limb_t n_hi, mp_limb_t n_lo, ulong max_iters) { mp_limb_t n[2]; mp_limb_t sqrt[2]; mp_limb_t rem[2]; mp_size_t num, sqroot, p, q; mp_limb_t l, l2, iq, pnext; mp_limb_t qarr[50]; mp_limb_t qupto, qlast, t, r = 0; ulong i, j; n[0] = n_lo; n[1] = n_hi; if (n_hi) num = mpn_sqrtrem(sqrt, rem, n, 2); else num = ((sqrt[0] = n_sqrtrem(rem, n_lo)) != 0UL); sqroot = sqrt[0]; p = sqroot; q = rem[0]; if ((q == 0) || (num == 0)) { return sqroot; } l = 1 + 2*n_sqrt(2*p); l2 = l/2; qupto = 0; qlast = 1; for (i = 0; i < max_iters; i++) { iq = (sqroot + p)/q; pnext = iq*q - p; if (q <= l) { if ((q & 1UL) == 0UL) { qarr[qupto] = q/2; qupto++; if (qupto >= 50UL) return 0UL; } else if (q <= l2) { qarr[qupto] = q; qupto++; if (qupto >= 50UL) return 0UL; } } t = qlast + iq*(p - pnext); qlast = q; q = t; p = pnext; if ((i & 1) == 1) continue; if (!n_is_square(q)) continue; r = n_sqrt(q); if (qupto == 0UL) break; for (j = 0; j < qupto; j++) if (r == qarr[j]) goto cont; break; cont: ; if (r == 1UL) return 0UL; } if (i == max_iters) return 0UL; /* taken too long, give up */ qlast = r; p = p + r*((sqroot - p)/r); umul_ppmm(rem[1], rem[0], p, p); sub_ddmmss(sqrt[1], sqrt[0], n[1], n[0], rem[1], rem[0]); if (sqrt[1]) { int norm; count_leading_zeros(norm, qlast); udiv_qrnnd(q, rem[0], (sqrt[1] << norm) + r_shift(sqrt[0], FLINT_BITS - norm), sqrt[0] << norm, qlast << norm); rem[0] >>= norm; } else {
mp_limb_t mpn_divrem (mp_ptr qp, mp_size_t qextra_limbs, mp_ptr np, mp_size_t nsize, mp_srcptr dp, mp_size_t dsize) { mp_limb_t most_significant_q_limb = 0; switch (dsize) { case 0: /* We are asked to divide by zero, so go ahead and do it! (To make the compiler not remove this statement, return the value.) */ return 1 / dsize; case 1: { mp_size_t i; mp_limb_t n1; mp_limb_t d; d = dp[0]; n1 = np[nsize - 1]; if (n1 >= d) { n1 -= d; most_significant_q_limb = 1; } qp += qextra_limbs; for (i = nsize - 2; i >= 0; i--) udiv_qrnnd (qp[i], n1, n1, np[i], d); qp -= qextra_limbs; for (i = qextra_limbs - 1; i >= 0; i--) udiv_qrnnd (qp[i], n1, n1, 0, d); np[0] = n1; } break; case 2: { mp_size_t i; mp_limb_t n1, n0, n2; mp_limb_t d1, d0; np += nsize - 2; d1 = dp[1]; d0 = dp[0]; n1 = np[1]; n0 = np[0]; if (n1 >= d1 && (n1 > d1 || n0 >= d0)) { sub_ddmmss (n1, n0, n1, n0, d1, d0); most_significant_q_limb = 1; } for (i = qextra_limbs + nsize - 2 - 1; i >= 0; i--) { mp_limb_t q; mp_limb_t r; if (i >= qextra_limbs) np--; else np[0] = 0; if (n1 == d1) { /* Q should be either 111..111 or 111..110. Need special treatment of this rare case as normal division would give overflow. */ q = ~(mp_limb_t) 0; r = n0 + d1; if (r < d1) /* Carry in the addition? */ { add_ssaaaa (n1, n0, r - d0, np[0], 0, d0); qp[i] = q; continue; } n1 = d0 - (d0 != 0); n0 = -d0; } else { udiv_qrnnd (q, r, n1, n0, d1); umul_ppmm (n1, n0, d0, q); } n2 = np[0]; q_test: if (n1 > r || (n1 == r && n0 > n2)) { /* The estimated Q was too large. */ q--; sub_ddmmss (n1, n0, n1, n0, 0, d0); r += d1; if (r >= d1) /* If not carry, test Q again. */ goto q_test; } qp[i] = q; sub_ddmmss (n1, n0, r, n2, n1, n0); } np[1] = n1; np[0] = n0; } break; default: { mp_size_t i; mp_limb_t dX, d1, n0; np += nsize - dsize; dX = dp[dsize - 1]; d1 = dp[dsize - 2]; n0 = np[dsize - 1]; if (n0 >= dX) { if (n0 > dX || mpn_cmp (np, dp, dsize - 1) >= 0) { mpn_sub_n (np, np, dp, dsize); n0 = np[dsize - 1]; most_significant_q_limb = 1; } } for (i = qextra_limbs + nsize - dsize - 1; i >= 0; i--) { mp_limb_t q; mp_limb_t n1, n2; mp_limb_t cy_limb; if (i >= qextra_limbs) { np--; n2 = np[dsize]; } else { n2 = np[dsize - 1]; MPN_COPY_DECR (np + 1, np, dsize); np[0] = 0; } if (n0 == dX) /* This might over-estimate q, but it's probably not worth the extra code here to find out. */ q = ~(mp_limb_t) 0; else { mp_limb_t r; udiv_qrnnd (q, r, n0, np[dsize - 1], dX); umul_ppmm (n1, n0, d1, q); while (n1 > r || (n1 == r && n0 > np[dsize - 2])) { q--; r += dX; if (r < dX) /* I.e. "carry in previous addition?" */ break; n1 -= n0 < d1; n0 -= d1; } } /* Possible optimization: We already have (q * n0) and (1 * n1) after the calculation of q. Taking advantage of that, we could make this loop make two iterations less. */ cy_limb = mpn_submul_1 (np, dp, dsize, q); if (n2 != cy_limb) { mpn_add_n (np, np, dp, dsize); q--; } qp[i] = q; n0 = np[dsize - 1]; } } } return most_significant_q_limb; }
mp_limb_t mpn_div_qr_1n_pi2 (mp_ptr qp, mp_srcptr up, mp_size_t un, struct precomp_div_1_pi2 *pd) { mp_limb_t most_significant_q_limb; mp_size_t i; mp_limb_t r, u2, u1, u0; mp_limb_t d0, di1, di0; mp_limb_t q3a, q2a, q2b, q1b, q2c, q1c, q1d, q0d; mp_limb_t cnd; ASSERT (un >= 2); ASSERT ((pd->d & GMP_NUMB_HIGHBIT) != 0); ASSERT (! MPN_OVERLAP_P (qp, un-2, up, un) || qp+2 >= up); ASSERT_MPN (up, un); #define q3 q3a #define q2 q2b #define q1 q1b up += un - 3; r = up[2]; d0 = pd->d; most_significant_q_limb = (r >= d0); r -= d0 & -most_significant_q_limb; qp += un - 3; qp[2] = most_significant_q_limb; di1 = pd->dip[1]; di0 = pd->dip[0]; for (i = un - 3; i >= 0; i -= 2) { u2 = r; u1 = up[1]; u0 = up[0]; /* Dividend in {r,u1,u0} */ umul_ppmm (q1d,q0d, u1, di0); umul_ppmm (q2b,q1b, u1, di1); q2b++; /* cannot spill */ add_sssaaaa (r,q2b,q1b, q2b,q1b, u1,u0); umul_ppmm (q2c,q1c, u2, di0); add_sssaaaa (r,q2b,q1b, q2b,q1b, q2c,q1c); umul_ppmm (q3a,q2a, u2, di1); add_sssaaaa (r,q2b,q1b, q2b,q1b, q2a,q1d); q3 += r; r = u0 - q2 * d0; cnd = (r >= q1); r += d0 & -cnd; sub_ddmmss (q3,q2, q3,q2, 0,cnd); if (UNLIKELY (r >= d0)) { r -= d0; add_ssaaaa (q3,q2, q3,q2, 0,1); } qp[0] = q2; qp[1] = q3; up -= 2; qp -= 2; } if ((un & 1) == 0) { u2 = r; u1 = up[1]; udiv_qrnnd_preinv (q3, r, u2, u1, d0, di1); qp[1] = q3; } return r; #undef q3 #undef q2 #undef q1 }