void fmpz_poly_mul_karatsuba(fmpz_poly_t res, const fmpz_poly_t poly1, const fmpz_poly_t poly2) { long len_out; if ((poly1->length == 0) || (poly2->length == 0)) { fmpz_poly_zero(res); return; } len_out = poly1->length + poly2->length - 1; fmpz_poly_fit_length(res, len_out); if (poly1->length >= poly2->length) _fmpz_poly_mul_karatsuba(res->coeffs, poly1->coeffs, poly1->length, poly2->coeffs, poly2->length); else _fmpz_poly_mul_karatsuba(res->coeffs, poly2->coeffs, poly2->length, poly1->coeffs, poly1->length); _fmpz_poly_set_length(res, len_out); }
void target(void* y, unsigned long count) { arg_t* arg = (arg_t*) y; mpz_t x; mpz_init(x); mpz_poly_t in1, in2, out; mpz_poly_init(in1); mpz_poly_init(in2); mpz_poly_init(out); fmpz_poly_t in1f, in2f, outf; fmpz_poly_init2(in1f, arg->length1, (arg->bits1-1)/FLINT_BITS+1); fmpz_poly_init2(in2f, arg->length2, (arg->bits2-1)/FLINT_BITS+1); _fmpz_poly_stack_init(outf, arg->length1 + arg->length2 - 1, in1f->limbs + in2f->limbs + 1); for (unsigned long i = 0; i < arg->length1; i++) { mpz_urandomb(x, randstate, arg->bits1); mpz_poly_set_coeff(in1, i, x); } mpz_poly_to_fmpz_poly(in1f, in1); for (unsigned long i = 0; i < arg->length2; i++) { mpz_urandomb(x, randstate, arg->bits2); mpz_poly_set_coeff(in2, i, x); } mpz_poly_to_fmpz_poly(in2f, in2); start_clock(0); if (arg->which) { for (unsigned long i = 0; i < count; i++) _fmpz_poly_mul_karatsuba(outf, in1f, in2f); } else { for (unsigned long i = 0; i < count; i++) mpz_poly_mul_karatsuba(out, in1, in2); } stop_clock(0); _fmpz_poly_stack_clear(outf); fmpz_poly_clear(in2f); fmpz_poly_clear(in1f); mpz_poly_clear(out); mpz_poly_clear(in2); mpz_poly_clear(in1); mpz_clear(x); }
int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("mul_karatsuba...."); fflush(stdout); /* Check aliasing of a and b */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_karatsuba(a, b, c); fmpz_poly_mul_karatsuba(b, b, c); result = (fmpz_poly_equal(a, b)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(b), flint_printf("\n\n"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Check aliasing of a and c */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_karatsuba(a, b, c); fmpz_poly_mul_karatsuba(c, b, c); result = (fmpz_poly_equal(a, c)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(c), flint_printf("\n\n"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); } /* Compare with mul_classical */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { fmpz_poly_t a, b, c, d; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(c); fmpz_poly_init(d); fmpz_poly_randtest(b, state, n_randint(state, 50), 200); fmpz_poly_randtest(c, state, n_randint(state, 50), 200); fmpz_poly_mul_karatsuba(a, b, c); fmpz_poly_mul_classical(d, b, c); result = (fmpz_poly_equal(a, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(a), flint_printf("\n\n"); fmpz_poly_print(d), flint_printf("\n\n"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(c); fmpz_poly_clear(d); } /* Check _fmpz_poly_mul_karatsuba directly */ for (i = 0; i < 200 * flint_test_multiplier(); i++) { slong len1, len2; fmpz_poly_t a, b, out1, out2; len1 = n_randint(state, 100) + 1; len2 = n_randint(state, 100) + 1; fmpz_poly_init(a); fmpz_poly_init(b); fmpz_poly_init(out1); fmpz_poly_init(out2); fmpz_poly_randtest(a, state, len1, 200); fmpz_poly_randtest(b, state, len2, 200); fmpz_poly_mul_karatsuba(out1, a, b); fmpz_poly_fit_length(a, a->alloc + n_randint(state, 10)); fmpz_poly_fit_length(b, b->alloc + n_randint(state, 10)); a->length = a->alloc; b->length = b->alloc; fmpz_poly_fit_length(out2, a->length + b->length - 1); if (a->length >= b->length) _fmpz_poly_mul_karatsuba(out2->coeffs, a->coeffs, a->length, b->coeffs, b->length); else _fmpz_poly_mul_karatsuba(out2->coeffs, b->coeffs, b->length, a->coeffs, a->length); _fmpz_poly_set_length(out2, a->length + b->length - 1); _fmpz_poly_normalise(out2); result = (fmpz_poly_equal(out1, out2)); if (!result) { flint_printf("FAIL:\n"); fmpz_poly_print(out1), flint_printf("\n\n"); fmpz_poly_print(out2), flint_printf("\n\n"); abort(); } fmpz_poly_clear(a); fmpz_poly_clear(b); fmpz_poly_clear(out1); fmpz_poly_clear(out2); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }