void nmod_poly_xgcd_hgcd(nmod_poly_t G, nmod_poly_t S, nmod_poly_t T, const nmod_poly_t A, const nmod_poly_t B) { if (A->length < B->length) { nmod_poly_xgcd_hgcd(G, T, S, B, A); } else /* lenA >= lenB >= 0 */ { const slong lenA = A->length, lenB = B->length; mp_limb_t inv; if (lenA == 0) /* lenA = lenB = 0 */ { nmod_poly_zero(G); nmod_poly_zero(S); nmod_poly_zero(T); } else if (lenB == 0) /* lenA > lenB = 0 */ { inv = n_invmod(A->coeffs[lenA - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, A, inv); nmod_poly_zero(T); nmod_poly_set_coeff_ui(S, 0, inv); S->length = 1; } else if (lenB == 1) /* lenA >= lenB = 1 */ { nmod_poly_fit_length(T, 1); T->length = 1; T->coeffs[0] = n_invmod(B->coeffs[0], A->mod.n); nmod_poly_one(G); nmod_poly_zero(S); } else /* lenA >= lenB >= 2 */ { mp_ptr g, s, t; slong lenG; if (G == A || G == B) { g = _nmod_vec_init(FLINT_MIN(lenA, lenB)); } else { nmod_poly_fit_length(G, FLINT_MIN(lenA, lenB)); g = G->coeffs; } if (S == A || S == B) { s = _nmod_vec_init(FLINT_MAX(lenB - 1, 2)); } else { nmod_poly_fit_length(S, FLINT_MAX(lenB - 1, 2)); s = S->coeffs; } if (T == A || T == B) { t = _nmod_vec_init(FLINT_MAX(lenA - 1, 2)); } else { nmod_poly_fit_length(T, FLINT_MAX(lenA - 1, 2)); t = T->coeffs; } if (lenA >= lenB) lenG = _nmod_poly_xgcd_hgcd(g, s, t, A->coeffs, lenA, B->coeffs, lenB, A->mod); else lenG = _nmod_poly_xgcd_hgcd(g, t, s, B->coeffs, lenB, A->coeffs, lenA, A->mod); if (G == A || G == B) { flint_free(G->coeffs); G->coeffs = g; G->alloc = FLINT_MIN(lenA, lenB); } if (S == A || S == B) { flint_free(S->coeffs); S->coeffs = s; S->alloc = FLINT_MAX(lenB - 1, 2); } if (T == A || T == B) { flint_free(T->coeffs); T->coeffs = t; T->alloc = FLINT_MAX(lenA - 1, 2); } G->length = lenG; S->length = FLINT_MAX(lenB - lenG, 1); T->length = FLINT_MAX(lenA - lenG, 1); MPN_NORM(S->coeffs, S->length); MPN_NORM(T->coeffs, T->length); if (G->coeffs[lenG - 1] != 1) { inv = n_invmod(G->coeffs[lenG - 1], A->mod.n); nmod_poly_scalar_mul_nmod(G, G, inv); nmod_poly_scalar_mul_nmod(S, S, inv); nmod_poly_scalar_mul_nmod(T, T, inv); } } } }
int main(void) { int i, result; flint_rand_t state; flint_randinit(state); printf("xgcd_hgcd...."); fflush(stdout); /* Compare with result from gcd and check a*s + b*t = g */ for (i = 0; i < 1000; i++) { nmod_poly_t a, b, c, g1, g2, s, t, sum, temp; mp_limb_t n; do n = n_randtest_not_zero(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(c, n); nmod_poly_init(g1, n); nmod_poly_init(g2, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_init(sum, n); nmod_poly_init(temp, n); nmod_poly_randtest(a, state, n_randint(state, 600)); nmod_poly_randtest(b, state, n_randint(state, 600)); nmod_poly_randtest(c, state, n_randint(state, 400)); nmod_poly_mul(a, a, c); nmod_poly_mul(b, b, c); nmod_poly_gcd(g1, a, b); nmod_poly_xgcd_hgcd(g2, s, t, a, b); nmod_poly_mul(sum, s, a); nmod_poly_mul(temp, t, b); nmod_poly_add(sum, sum, temp); result = (nmod_poly_equal(g1, g2) && nmod_poly_equal(g1, sum) && (g1->length == 0 || g1->coeffs[g1->length - 1] == 1)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(c), printf("\n\n"); nmod_poly_print(g1), printf("\n\n"); nmod_poly_print(g2), printf("\n\n"); nmod_poly_print(sum), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(c); nmod_poly_clear(g1); nmod_poly_clear(g2); nmod_poly_clear(s); nmod_poly_clear(t); nmod_poly_clear(sum); nmod_poly_clear(temp); } /* Check aliasing of a and g */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(a, s, t, a, b); result = (nmod_poly_equal(a, g)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(g), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of b and g */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(b, s, t, a, b); result = (nmod_poly_equal(b, g)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(g), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and a */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, a, t, a, b); result = (nmod_poly_equal(s, a)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of s and b */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, b, t, a, b); result = (nmod_poly_equal(s, b)); if (!result) { printf("FAIL:\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(s), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and a */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, s, a, a, b); result = (nmod_poly_equal(t, a)); if (!result) { printf("FAIL:\n"); nmod_poly_print(a), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } /* Check aliasing of t and b */ for (i = 0; i < 200; i++) { nmod_poly_t a, b, g, s, t; mp_limb_t n; do n = n_randtest(state); while (!n_is_probabprime(n)); nmod_poly_init(a, n); nmod_poly_init(b, n); nmod_poly_init(g, n); nmod_poly_init(s, n); nmod_poly_init(t, n); nmod_poly_randtest(a, state, n_randint(state, 200)); nmod_poly_randtest(b, state, n_randint(state, 200)); nmod_poly_xgcd_hgcd(g, s, t, a, b); nmod_poly_xgcd_hgcd(g, s, b, a, b); result = (nmod_poly_equal(t, b)); if (!result) { printf("FAIL:\n"); nmod_poly_print(b), printf("\n\n"); nmod_poly_print(t), printf("\n\n"); printf("n = %ld\n", n); abort(); } nmod_poly_clear(a); nmod_poly_clear(b); nmod_poly_clear(g); nmod_poly_clear(s); nmod_poly_clear(t); } flint_randclear(state); printf("PASS\n"); return 0; }