void frob(const mpoly_t P, const ctx_t ctxFracQt, const qadic_t t1, const qadic_ctx_t Qq, prec_t *prec, const prec_t *prec_in, int verbose) { const padic_ctx_struct *Qp = &Qq->pctx; const fmpz *p = Qp->p; const long a = qadic_ctx_degree(Qq); const long n = P->n - 1; const long d = mpoly_degree(P, -1, ctxFracQt); const long b = gmc_basis_size(n, d); long i, j, k; /* Diagonal fibre */ padic_mat_t F0; /* Gauss--Manin Connection */ mat_t M; mon_t *bR, *bC; fmpz_poly_t r; /* Local solution */ fmpz_poly_mat_t C, Cinv; long vC, vCinv; /* Frobenius */ fmpz_poly_mat_t F; long vF; fmpz_poly_mat_t F1; long vF1; fmpz_poly_t cp; clock_t c0, c1; double c; if (verbose) { printf("Input:\n"); printf(" P = "), mpoly_print(P, ctxFracQt), printf("\n"); printf(" p = "), fmpz_print(p), printf("\n"); printf(" t1 = "), qadic_print_pretty(t1, Qq), printf("\n"); printf("\n"); fflush(stdout); } /* Step 1 {M, r} *********************************************************/ c0 = clock(); mat_init(M, b, b, ctxFracQt); fmpz_poly_init(r); gmc_compute(M, &bR, &bC, P, ctxFracQt); { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_set_ui(r, 1); for (i = 0; i < M->m; i++) for (j = 0; j < M->n; j++) { fmpz_poly_lcm(t, r, fmpz_poly_q_denref( (fmpz_poly_q_struct *) mat_entry(M, i, j, ctxFracQt))); fmpz_poly_swap(r, t); } fmpz_poly_clear(t); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Gauss-Manin connection:\n"); printf(" r(t) = "), fmpz_poly_print_pretty(r, "t"), printf("\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } { qadic_t t; qadic_init2(t, 1); fmpz_poly_evaluate_qadic(t, r, t1, Qq); if (qadic_is_zero(t)) { printf("Exception (deformation_frob).\n"); printf("The resultant r evaluates to zero (mod p) at t1.\n"); abort(); } qadic_clear(t); } /* Precisions ************************************************************/ if (prec_in != NULL) { *prec = *prec_in; } else { deformation_precisions(prec, p, a, n, d, fmpz_poly_degree(r)); } if (verbose) { printf("Precisions:\n"); printf(" N0 = %ld\n", prec->N0); printf(" N1 = %ld\n", prec->N1); printf(" N2 = %ld\n", prec->N2); printf(" N3 = %ld\n", prec->N3); printf(" N3i = %ld\n", prec->N3i); printf(" N3w = %ld\n", prec->N3w); printf(" N3iw = %ld\n", prec->N3iw); printf(" N4 = %ld\n", prec->N4); printf(" m = %ld\n", prec->m); printf(" K = %ld\n", prec->K); printf(" r = %ld\n", prec->r); printf(" s = %ld\n", prec->s); printf("\n"); fflush(stdout); } /* Initialisation ********************************************************/ padic_mat_init2(F0, b, b, prec->N4); fmpz_poly_mat_init(C, b, b); fmpz_poly_mat_init(Cinv, b, b); fmpz_poly_mat_init(F, b, b); vF = 0; fmpz_poly_mat_init(F1, b, b); vF1 = 0; fmpz_poly_init(cp); /* Step 2 {F0} ***********************************************************/ { padic_ctx_t pctx_F0; fmpz *t; padic_ctx_init(pctx_F0, p, FLINT_MIN(prec->N4 - 10, 0), prec->N4, PADIC_VAL_UNIT); t = _fmpz_vec_init(n + 1); c0 = clock(); mpoly_diagonal_fibre(t, P, ctxFracQt); diagfrob(F0, t, n, d, prec->N4, pctx_F0, 0); padic_mat_transpose(F0, F0); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Diagonal fibre:\n"); printf(" P(0) = {"), _fmpz_vec_print(t, n + 1), printf("}\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } _fmpz_vec_clear(t, n + 1); padic_ctx_clear(pctx_F0); } /* Step 3 {C, Cinv} ******************************************************/ /* Compute C as a matrix over Z_p[[t]]. A is the same but as a series of matrices over Z_p. Mt is the matrix -M^t, and Cinv is C^{-1}^t, the local solution of the differential equation replacing M by Mt. */ c0 = clock(); { const long K = prec->K; padic_mat_struct *A; gmde_solve(&A, K, p, prec->N3, prec->N3w, M, ctxFracQt); gmde_convert_soln(C, &vC, A, K, p); for(i = 0; i < K; i++) padic_mat_clear(A + i); free(A); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Local solution:\n"); printf(" Time for C = %f\n", c); fflush(stdout); } c0 = clock(); { const long K = (prec->K + (*p) - 1) / (*p); mat_t Mt; padic_mat_struct *Ainv; mat_init(Mt, b, b, ctxFracQt); mat_transpose(Mt, M, ctxFracQt); mat_neg(Mt, Mt, ctxFracQt); gmde_solve(&Ainv, K, p, prec->N3i, prec->N3iw, Mt, ctxFracQt); gmde_convert_soln(Cinv, &vCinv, Ainv, K, p); fmpz_poly_mat_transpose(Cinv, Cinv); fmpz_poly_mat_compose_pow(Cinv, Cinv, *p); for(i = 0; i < K; i++) padic_mat_clear(Ainv + i); free(Ainv); mat_clear(Mt, ctxFracQt); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf(" Time for C^{-1} = %f\n", c); printf("\n"); fflush(stdout); } /* Step 4 {F(t) := C(t) F(0) C(t^p)^{-1}} ********************************/ /* Computes the product C(t) F(0) C(t^p)^{-1} modulo (p^{N_2}, t^K). This is done by first computing the unit part of the product exactly over the integers modulo t^K. */ c0 = clock(); { fmpz_t pN; fmpz_poly_mat_t T; fmpz_init(pN); fmpz_poly_mat_init(T, b, b); for (i = 0; i < b; i++) { /* Find the unique k s.t. F0(i,k) is non-zero */ for (k = 0; k < b; k++) if (!fmpz_is_zero(padic_mat_entry(F0, i, k))) break; if (k == b) { printf("Exception (frob). F0 is singular.\n\n"); abort(); } for (j = 0; j < b; j++) { fmpz_poly_scalar_mul_fmpz(fmpz_poly_mat_entry(T, i, j), fmpz_poly_mat_entry(Cinv, k, j), padic_mat_entry(F0, i, k)); } } fmpz_poly_mat_mul(F, C, T); fmpz_poly_mat_truncate(F, prec->K); vF = vC + padic_mat_val(F0) + vCinv; /* Canonicalise (F, vF) */ { long v = fmpz_poly_mat_ord_p(F, p); if (v == LONG_MAX) { printf("ERROR (deformation_frob). F(t) == 0.\n"); abort(); } else if (v > 0) { fmpz_pow_ui(pN, p, v); fmpz_poly_mat_scalar_divexact_fmpz(F, F, pN); vF = vF + v; } } /* Reduce (F, vF) modulo p^{N2} */ fmpz_pow_ui(pN, p, prec->N2 - vF); fmpz_poly_mat_scalar_mod_fmpz(F, F, pN); fmpz_clear(pN); fmpz_poly_mat_clear(T); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Matrix for F(t):\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } /* Step 5 {G = r(t)^m F(t)} **********************************************/ c0 = clock(); { fmpz_t pN; fmpz_poly_t t; fmpz_init(pN); fmpz_poly_init(t); fmpz_pow_ui(pN, p, prec->N2 - vF); /* Compute r(t)^m mod p^{N2-vF} */ if (prec->denR == NULL) { fmpz_mod_poly_t _t; fmpz_mod_poly_init(_t, pN); fmpz_mod_poly_set_fmpz_poly(_t, r); fmpz_mod_poly_pow(_t, _t, prec->m); fmpz_mod_poly_get_fmpz_poly(t, _t); fmpz_mod_poly_clear(_t); } else { /* TODO: We don't really need a copy */ fmpz_poly_set(t, prec->denR); } fmpz_poly_mat_scalar_mul_fmpz_poly(F, F, t); fmpz_poly_mat_scalar_mod_fmpz(F, F, pN); /* TODO: This should not be necessary? */ fmpz_poly_mat_truncate(F, prec->K); fmpz_clear(pN); fmpz_poly_clear(t); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Analytic continuation:\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } /* Steps 6 and 7 *********************************************************/ if (a == 1) { /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/ c0 = clock(); { const long N = prec->N2 - vF; fmpz_t f, g, t, pN; fmpz_init(f); fmpz_init(g); fmpz_init(t); fmpz_init(pN); fmpz_pow_ui(pN, p, N); /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */ _padic_teichmuller(f, t1->coeffs + 0, p, N); if (prec->denR == NULL) { _fmpz_mod_poly_evaluate_fmpz(g, r->coeffs, r->length, f, pN); fmpz_powm_ui(t, g, prec->m, pN); } else { _fmpz_mod_poly_evaluate_fmpz(t, prec->denR->coeffs, prec->denR->length, f, pN); } _padic_inv(g, t, p, N); /* F1 := g G(\hat{t_1}) */ for (i = 0; i < b; i++) for (j = 0; j < b; j++) { const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j); const long len = poly->length; if (len == 0) { fmpz_poly_zero(fmpz_poly_mat_entry(F1, i, j)); } else { fmpz_poly_fit_length(fmpz_poly_mat_entry(F1, i, j), 1); _fmpz_mod_poly_evaluate_fmpz(t, poly->coeffs, len, f, pN); fmpz_mul(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, g, t); fmpz_mod(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, pN); _fmpz_poly_set_length(fmpz_poly_mat_entry(F1, i, j), 1); _fmpz_poly_normalise(fmpz_poly_mat_entry(F1, i, j)); } } vF1 = vF; fmpz_poly_mat_canonicalise(F1, &vF1, p); fmpz_clear(f); fmpz_clear(g); fmpz_clear(t); fmpz_clear(pN); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Evaluation:\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } } else { /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/ c0 = clock(); { const long N = prec->N2 - vF; fmpz_t pN; fmpz *f, *g, *t; fmpz_init(pN); f = _fmpz_vec_init(a); g = _fmpz_vec_init(2 * a - 1); t = _fmpz_vec_init(2 * a - 1); fmpz_pow_ui(pN, p, N); /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */ _qadic_teichmuller(f, t1->coeffs, t1->length, Qq->a, Qq->j, Qq->len, p, N); if (prec->denR == NULL) { fmpz_t e; fmpz_init_set_ui(e, prec->m); _fmpz_mod_poly_compose_smod(g, r->coeffs, r->length, f, a, Qq->a, Qq->j, Qq->len, pN); _qadic_pow(t, g, a, e, Qq->a, Qq->j, Qq->len, pN); fmpz_clear(e); } else { _fmpz_mod_poly_reduce(prec->denR->coeffs, prec->denR->length, Qq->a, Qq->j, Qq->len, pN); _fmpz_poly_normalise(prec->denR); _fmpz_mod_poly_compose_smod(t, prec->denR->coeffs, prec->denR->length, f, a, Qq->a, Qq->j, Qq->len, pN); } _qadic_inv(g, t, a, Qq->a, Qq->j, Qq->len, p, N); /* F1 := g G(\hat{t_1}) */ for (i = 0; i < b; i++) for (j = 0; j < b; j++) { const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j); const long len = poly->length; fmpz_poly_struct *poly2 = fmpz_poly_mat_entry(F1, i, j); if (len == 0) { fmpz_poly_zero(poly2); } else { _fmpz_mod_poly_compose_smod(t, poly->coeffs, len, f, a, Qq->a, Qq->j, Qq->len, pN); fmpz_poly_fit_length(poly2, 2 * a - 1); _fmpz_poly_mul(poly2->coeffs, g, a, t, a); _fmpz_mod_poly_reduce(poly2->coeffs, 2 * a - 1, Qq->a, Qq->j, Qq->len, pN); _fmpz_poly_set_length(poly2, a); _fmpz_poly_normalise(poly2); } } /* Now the matrix for p^{-1} F_p at t=t_1 is (F1, vF1). */ vF1 = vF; fmpz_poly_mat_canonicalise(F1, &vF1, p); fmpz_clear(pN); _fmpz_vec_clear(f, a); _fmpz_vec_clear(g, 2 * a - 1); _fmpz_vec_clear(t, 2 * a - 1); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Evaluation:\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } /* Step 7 {Norm} *****************************************************/ /* Computes the matrix for $q^{-1} F_q$ at $t = t_1$ as the product $F \sigma(F) \dotsm \sigma^{a-1}(F)$ up appropriate transpositions because our convention of columns vs rows is the opposite of that used by Gerkmann. Note that, in any case, transpositions do not affect the characteristic polynomial. */ c0 = clock(); { const long N = prec->N1 - a * vF1; fmpz_t pN; fmpz_poly_mat_t T; fmpz_init(pN); fmpz_poly_mat_init(T, b, b); fmpz_pow_ui(pN, p, N); fmpz_poly_mat_frobenius(T, F1, 1, p, N, Qq); _qadic_mat_mul(F1, F1, T, pN, Qq); for (i = 2; i < a; i++) { fmpz_poly_mat_frobenius(T, T, 1, p, N, Qq); _qadic_mat_mul(F1, F1, T, pN, Qq); } vF1 = a * vF1; fmpz_poly_mat_canonicalise(F1, &vF1, p); fmpz_clear(pN); fmpz_poly_mat_clear(T); } c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Norm:\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } } /* Step 8 {Reverse characteristic polynomial} ****************************/ c0 = clock(); deformation_revcharpoly(cp, F1, vF1, n, d, prec->N0, prec->r, prec->s, Qq); c1 = clock(); c = (double) (c1 - c0) / CLOCKS_PER_SEC; if (verbose) { printf("Reverse characteristic polynomial:\n"); printf(" p(T) = "), fmpz_poly_print_pretty(cp, "T"), printf("\n"); printf(" Time = %f\n", c); printf("\n"); fflush(stdout); } /* Clean up **************************************************************/ padic_mat_clear(F0); mat_clear(M, ctxFracQt); free(bR); free(bC); fmpz_poly_clear(r); fmpz_poly_mat_clear(C); fmpz_poly_mat_clear(Cinv); fmpz_poly_mat_clear(F); fmpz_poly_mat_clear(F1); fmpz_poly_clear(cp); }
int main(int argc, char *argv[]) { int ans; char *str, *strout; fmpz_poly_t zpoly; fmpz_poly_q_t qpoly1; mpz_t mpzzero, mpzone, mpztwo; mpq_t mpqzero, mpqone, mpqtwo, mpqtwoinv; FLINT_TEST_INIT(state); flint_printf("all... "); fflush(stdout); /* Accessing numerator and denominator ***********************************/ fmpz_poly_q_init(qpoly1); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); str = "2 -1 1"; strout = fmpz_poly_get_str(fmpz_poly_q_numref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_numref: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); flint_printf(" qpoly1 = \""), fmpz_poly_q_print(qpoly1), flint_printf("\"\n"); abort(); } fmpz_poly_q_clear(qpoly1); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); str = "2 0 1"; strout = fmpz_poly_get_str(fmpz_poly_q_denref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_denref: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } fmpz_poly_q_clear(qpoly1); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); fmpz_poly_set(zpoly, fmpz_poly_q_numref(qpoly1)); str = "2 -1 1"; strout = fmpz_poly_get_str(zpoly); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_get_num: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "2 -1 1/2 0 1"); fmpz_poly_set(zpoly, fmpz_poly_q_denref(qpoly1)); str = "2 0 1"; strout = fmpz_poly_get_str(zpoly); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_get_den: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "1 1/1 1"); fmpz_poly_set_str(zpoly, "2 0 1"); fmpz_poly_set(fmpz_poly_q_numref(qpoly1), zpoly); str = "2 0 1"; strout = fmpz_poly_get_str(fmpz_poly_q_numref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_set_num: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); fmpz_poly_q_init(qpoly1); fmpz_poly_init(zpoly); fmpz_poly_q_set_str(qpoly1, "1 1/1 1"); fmpz_poly_set_str(zpoly, "2 0 1"); fmpz_poly_set(fmpz_poly_q_denref(qpoly1), zpoly); str = "2 0 1"; strout = fmpz_poly_get_str(fmpz_poly_q_denref(qpoly1)); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_set_den: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_clear(zpoly); flint_free(strout); /* Canonicalise **********************************************************/ fmpz_poly_q_init(qpoly1); str = "2 -1 1/2 0 1"; fmpz_poly_q_set_str(qpoly1, str); strout = fmpz_poly_q_get_str(qpoly1); ans = !strcmp(str, strout); if (!ans) { flint_printf("test_canonicalize: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } fmpz_poly_q_clear(qpoly1); flint_free(strout); fmpz_poly_q_init(qpoly1); str = "2 -1 -1/2 0 1"; fmpz_poly_q_set_str(qpoly1, "2 1 1/2 0 -1"); strout = fmpz_poly_q_get_str(qpoly1); ans = !strcmp("2 -1 -1/2 0 1", strout); if (!ans) { flint_printf("test_canonicalize: failed\n"); flint_printf(" Expected \"%s\", got \"%s\"\n", str, strout); abort(); } flint_free(strout); fmpz_poly_q_clear(qpoly1); /* Initialization, memory management and basic operations ****************/ test_set("0", "0"); test_set("0/1 1", "0"); test_set("3 -1 0 1/2 0 1", "3 -1 0 1/2 0 1"); test_set("3 -1 0 1/2 1 1", "2 -1 1"); test_set_si(-1, "1 -1"); test_set_si(13, "1 13"); test_set_si(0, "0"); test_swap("3 -1 0 1/2 0 1", "1 2/1 3", "1 2/1 3", "3 -1 0 1/2 0 1"); test_zero("0", "0"); test_zero("0/1 1", "0"); test_zero("3 -1 0 1/2 0 1", "0"); test_neg("0", "0"); test_neg("1 1/1 2", "1 -1/1 2"); test_neg("3 -1 0 1/2 0 1", "3 1 0 -1/2 0 1"); test_inv("1 1/1 2", "1 2"); test_inv("3 -1 0 1/2 0 1", "2 0 1/3 -1 0 1"); test_inv("3 -1 0 -1/2 0 1", "2 0 -1/3 1 0 1"); test_inv_inplace("1 1/1 2", "1 2"); test_inv_inplace("3 -1 0 1/2 0 1", "2 0 1/3 -1 0 1"); test_inv_inplace("3 -1 0 -1/2 0 1", "2 0 -1/3 1 0 1"); test_is_zero("0", 1); test_is_zero("0/1 1", 1); test_is_zero("3 -1 0 1/2 0 1", 0); test_is_zero("3 -1 0 1/2 1 1", 0); test_is_one("0", 0); test_is_one("0/1 1", 0); test_is_one("1 1/1 1", 1); test_is_one("2 1 1/2 1 1", 1); test_is_one("3 -1 0 1/2 0 1", 0); test_equal("1 1/1 2", "1 1/1 2", 1); test_equal("1 1/1 2", "1 1/1 2", 1); test_equal("3 -1 0 1/2 1 1", "2 -1 1", 1); test_equal("3 -1 0 1/2 -1 1", "2 -1 1", 0); /* Addition and subtraction **********************************************/ test_add("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 1 0 1/4 0 1 0 1"); test_add("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 3 -2 1/2 -1 1"); test_add("0/2 1 1", "1 2/1 1", "1 2"); test_add("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_add("2 1 1/1 1", "2 -1 1/1 1", "2 0 2"); test_add("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 -1 2 2/3 0 -1 1"); test_add("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 7 12 7 1/3 2 3 1"); test_add("2 1 1/2 -1 1", "2 1 1", "3 0 1 1/2 -1 1"); test_add("1 1/2 1 1", "2 0 1/2 1 1", "1 1"); test_add("2 1 1/3 4 -4 1", "1 1/2 -2 1", "2 -1 2/3 4 -4 1"); test_add("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "0"); test_add("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2"); test_add("1 1/3 3 5 2", "1 1/3 6 7 2", "1 1/3 2 3 1"); test_add_in_place1("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 1 0 1/4 0 1 0 1"); test_add_in_place1("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 3 -2 1/2 -1 1"); test_add_in_place1("0/2 1 1", "1 2/1 1", "1 2"); test_add_in_place1("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_add_in_place1("2 1 1/1 1", "2 -1 1/1 1", "2 0 2"); test_add_in_place1("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 -1 2 2/3 0 -1 1"); test_add_in_place1("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 7 12 7 1/3 2 3 1"); test_add_in_place1("2 1 1/2 -1 1", "2 1 1", "3 0 1 1/2 -1 1"); test_add_in_place1("1 1/2 1 1", "2 0 1/2 1 1", "1 1"); test_add_in_place1("2 1 1/3 4 -4 1", "1 1/2 -2 1", "2 -1 2/3 4 -4 1"); test_add_in_place1("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "0"); test_add_in_place1("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2"); test_add_in_place2("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 1 0 1/4 0 1 0 1"); test_add_in_place2("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 3 -2 1/2 -1 1"); test_add_in_place2("0/2 1 1", "1 2/1 1", "1 2"); test_add_in_place2("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_add_in_place2("2 1 1/1 1", "2 -1 1/1 1", "2 0 2"); test_add_in_place2("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 -1 2 2/3 0 -1 1"); test_add_in_place2("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 7 12 7 1/3 2 3 1"); test_add_in_place2("2 1 1/2 -1 1", "2 1 1", "3 0 1 1/2 -1 1"); test_add_in_place2("1 1/2 1 1", "2 0 1/2 1 1", "1 1"); test_add_in_place2("2 1 1/3 4 -4 1", "1 1/2 -2 1", "2 -1 2/3 4 -4 1"); test_add_in_place2("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "0"); test_add_in_place2("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2"); test_add_in_place3("2 1 1", "2 2 2"); test_add_in_place3("2 1 1/1 2", "2 1 1"); test_sub("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub("0/2 1 1", "1 2/1 1", "1 -2"); test_sub("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub("2 -1 1/2 0 1", "1 1", "1 -1/2 0 1"); test_sub("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub("0/2 1 1", "1 2/1 1", "1 -2"); test_sub("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub("2 1 1/2 -1 1", "2 1 1", "3 2 1 -1/2 -1 1"); test_sub("1 1/2 1 1", "2 0 1/2 1 1", "2 1 -1/2 1 1"); test_sub("2 1 1/3 4 -4 1", "1 1/2 -2 1", "1 3/3 4 -4 1"); test_sub("3 0 1 1/3 1 2 1", "2 0 -1/2 1 1", "2 0 2/2 1 1"); test_sub("2 1 1/2 0 1", "2 -1 1/2 0 1", "1 2/2 0 1"); test_sub("1 1/3 3 5 2", "1 1/3 6 7 2", "1 1/4 6 13 9 2"); test_sub("2 1 1/2 0 2", "2 1 1/2 0 2", "0"); test_sub("2 -1 2/2 0 1", "2 -1 1/2 0 1", "1 1"); test_sub_in_place1("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub_in_place1("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub_in_place1("0/2 1 1", "1 2/1 1", "1 -2"); test_sub_in_place1("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub_in_place1("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub_in_place1("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub_in_place1("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub_in_place2("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "5 1 0 3 0 1/4 0 1 0 1"); test_sub_in_place2("3 -1 0 1/2 1 1", "1 2/2 -1 1", "3 -1 -2 1/2 -1 1"); test_sub_in_place2("0/2 1 1", "1 2/1 1", "1 -2"); test_sub_in_place2("1 -3/1 4", "0/3 1 0 1", "1 -3/1 4"); test_sub_in_place2("2 1 1/1 1", "2 -1 1/1 1", "1 2"); test_sub_in_place2("2 1 1/2 0 1", "2 2 1/2 -1 1", "2 -1 -2/3 0 -1 1"); test_sub_in_place2("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "4 -9 -12 -5 -1/3 2 3 1"); test_sub_in_place3("2 -1 1/2 2 1", "0"); test_addmul("1 1/2 0 2", "2 3 1/1 4", "3 1 0 1/4 -2 0 0 1", "5 -4 3 1 5 1/5 0 -8 0 0 4"); test_submul("1 1/2 0 2", "2 3 1/1 4", "3 1 0 1/4 -2 0 0 1", "5 -4 -3 -1 -1 -1/5 0 -8 0 0 4"); /* Scalar multiplication and devision ************************************/ flint_mpz_init_set_si(mpzzero, 0); flint_mpz_init_set_si(mpzone, 1); flint_mpz_init_set_si(mpztwo, 2); mpq_init(mpqzero); flint_mpq_set_si(mpqzero, 0, 1); mpq_init(mpqone); flint_mpq_set_si(mpqone, 1, 1); mpq_init(mpqtwo); flint_mpq_set_si(mpqtwo, 2, 1); mpq_init(mpqtwoinv); flint_mpq_set_si(mpqtwoinv, 1, 2); test_scalar_mul_si("0", 1, "0"); test_scalar_mul_si("0", 0, "0"); test_scalar_mul_si("1 2", 0, "0"); test_scalar_mul_si("1 1/1 2", -2, "1 -1"); test_scalar_mul_si("2 1 1/2 -2 3", 5, "2 5 5/2 -2 3"); test_scalar_mul_si("2 1 1/2 -2 2", 3, "2 3 3/2 -2 2"); test_scalar_mul_mpz("0", mpzone, "0"); test_scalar_mul_mpz("0", mpzzero, "0"); test_scalar_mul_mpz("1 2", mpzzero, "0"); test_scalar_mul_mpz("1 1/1 2", mpztwo, "1 1"); test_scalar_mul_mpq("0", mpqone, "0"); test_scalar_mul_mpq("0", mpqzero, "0"); test_scalar_mul_mpq("1 2", mpqzero, "0"); test_scalar_mul_mpq("1 1/1 2", mpqtwo, "1 1"); test_scalar_mul_mpq("1 -2/1 1", mpqtwoinv, "1 -1"); test_scalar_div_si("0", 1, "0"); test_scalar_div_si("1 2", 2, "1 1"); test_scalar_div_si("1 1/1 2", -2, "1 -1/1 4"); test_scalar_div_si("3 -5 0 3/2 1 1", 2, "3 -5 0 3/2 2 2"); test_scalar_div_si("3 2 8 4/2 0 1", 3, "3 2 8 4/2 0 3"); test_scalar_div_si("3 2 8 4/2 0 1", -3, "3 -2 -8 -4/2 0 3"); test_scalar_div_si("3 -27 0 9/2 0 1", -3, "3 9 0 -3/2 0 1"); test_scalar_div_mpz("0", mpzone, "0"); test_scalar_div_mpz("1 2", mpztwo, "1 1"); test_scalar_div_mpz("1 1/1 2", mpztwo, "1 1/1 4"); test_scalar_div_mpq("0", mpqone, "0"); test_scalar_div_mpq("1 2", mpqone, "1 2"); test_scalar_div_mpq("1 1/1 2", mpqtwo, "1 1/1 4"); test_scalar_div_mpq("1 -2/1 1", mpqtwoinv, "1 -4"); mpz_clear(mpzzero); mpz_clear(mpzone); mpz_clear(mpztwo); mpq_clear(mpqzero); mpq_clear(mpqone); mpq_clear(mpqtwo); mpq_clear(mpqtwoinv); /* Multiplication, division and powing *********************************/ test_mul("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "1 -1"); test_mul("3 -1 0 1/2 1 1", "1 2/2 -1 1", "1 2"); test_mul("0/2 1 1", "1 2/1 1", "0"); test_mul("1 -3/1 4", "0/3 1 0 1", "0"); test_mul("2 1 1/1 1", "2 -1 1/1 1", "3 -1 0 1"); test_mul("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 2 3 1/3 0 -1 1"); test_mul("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "3 -2 1 1/2 1 1"); test_mul_in_place1("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "1 -1"); test_mul_in_place1("3 -1 0 1/2 1 1", "1 2/2 -1 1", "1 2"); test_mul_in_place1("0/2 1 1", "1 2/1 1", "0"); test_mul_in_place1("1 -3/1 4", "0/3 1 0 1", "0"); test_mul_in_place1("2 1 1/1 1", "2 -1 1/1 1", "3 -1 0 1"); test_mul_in_place1("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 2 3 1/3 0 -1 1"); test_mul_in_place1("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "3 -2 1 1/2 1 1"); test_mul_in_place2("3 1 0 1/2 0 1", "2 0 -1/3 1 0 1", "1 -1"); test_mul_in_place2("3 -1 0 1/2 1 1", "1 2/2 -1 1", "1 2"); test_mul_in_place2("0/2 1 1", "1 2/1 1", "0"); test_mul_in_place2("1 -3/1 4", "0/3 1 0 1", "0"); test_mul_in_place2("2 1 1/1 1", "2 -1 1/1 1", "3 -1 0 1"); test_mul_in_place2("2 1 1/2 0 1", "2 2 1/2 -1 1", "3 2 3 1/3 0 -1 1"); test_mul_in_place2("2 -1 1/2 2 1", "3 4 4 1/2 1 1", "3 -2 1 1/2 1 1"); test_mul_in_place3("2 0 1/2 1 1", "3 0 0 1/3 1 2 1"); test_div("3 -1 0 1/1 2", "2 1 1/1 1", "2 -1 1/1 2"); test_div("0/2 1 1", "2 1 1/1 1", "0"); test_div("3 -1 0 1/1 4", "2 -1 -1/1 2", "2 1 -1/1 2"); test_div("2 1 1", "2 1 -1/2 1 -1", "2 1 1"); test_div("2 1 1/3 4 4 1", "2 -1 1/3 6 5 1", "3 3 4 1/3 -2 1 1"); test_div_in_place1("3 -1 0 1/1 2", "2 1 1/1 1", "2 -1 1/1 2"); test_div_in_place1("0/2 1 1", "2 1 1/1 1", "0"); test_div_in_place1("3 -1 0 1/1 4", "2 -1 -1/1 2", "2 1 -1/1 2"); test_div_in_place1("2 1 1", "2 1 -1/2 1 -1", "2 1 1"); test_div_in_place1("2 1 1/3 4 4 1", "2 -1 1/3 6 5 1", "3 3 4 1/3 -2 1 1"); test_div_in_place1("0", "1 2/2 3 5", "0"); test_div_in_place2("3 -1 0 1/1 2", "2 1 1/1 1", "2 -1 1/1 2"); test_div_in_place2("0/2 1 1", "2 1 1/1 1", "0"); test_div_in_place2("3 -1 0 1/1 4", "2 -1 -1/1 2", "2 1 -1/1 2"); test_div_in_place2("2 1 1", "2 1 -1/2 1 -1", "2 1 1"); test_div_in_place2("2 1 1/3 4 4 1", "2 -1 1/3 6 5 1", "3 3 4 1/3 -2 1 1"); test_div_in_place3("3 -1 0 1/1 2", "1 1"); test_pow("2 0 -1/1 2", 3, "4 0 0 0 -1/1 8"); test_pow("0", 0, "1 1"); test_pow("2 1 -1", 0, "1 1"); test_pow("2 1 1/2 0 1", 0, "1 1"); /* Derivative ************************************************************/ test_derivative("0", "0"); test_derivative("1 2", "0"); test_derivative("1 -1/1 2", "0"); test_derivative("2 0 1", "1 1"); test_derivative("3 1 0 1", "2 0 2"); test_derivative("1 1/2 0 1", "1 -1/3 0 0 1"); test_derivative("2 2 1/2 -1 1", "1 -3/3 1 -2 1"); test_derivative("2 0 1/3 1 2 1", "2 1 -1/4 1 3 3 1"); /* Bug which allowed constant factors */ test_derivative("3 5 1 -2/2 10 2", "3 0 -10 -1/3 25 10 1"); /* Evaluation ************************************************************/ test_evaluate("1 1/1 2", -2, 3, "1/2"); test_evaluate("3 1 0 1/2 0 1", -1, 2, "-5/2"); test_evaluate("2 3 1/2 -1 1", 1, 1, "P"); test_evaluate("2 3 1/2 -1 1", 2, 3, "-11"); test_evaluate("2 3 1/2 -1 2", 1, 2, "P"); test_evaluate("2 1 1/2 -1 1", 2, 1, "3"); /* String methods ********************************************************/ fmpz_poly_q_init(qpoly1); ans = fmpz_poly_q_set_str(qpoly1, "1 3/xyz"); if ((ans == 0) || !fmpz_poly_q_is_zero(qpoly1)) { flint_printf("test_set_str: failed\n"); abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_q_init(qpoly1); ans = fmpz_poly_q_set_str(qpoly1, "abc/1 3"); if ((ans == 0) || !fmpz_poly_q_is_zero(qpoly1)) { flint_printf("test_set_str: failed\n"); abort(); } fmpz_poly_q_clear(qpoly1); fmpz_poly_q_init(qpoly1); ans = fmpz_poly_q_set_str(qpoly1, "abc/xyz"); if ((ans == 0) || !fmpz_poly_q_is_zero(qpoly1)) { flint_printf("test_set_str: failed\n"); abort(); } fmpz_poly_q_clear(qpoly1); test_get_str_pretty("1 -3", "-3"); test_get_str_pretty("3 1 2 1", "t^2+2*t+1"); test_get_str_pretty("1 -2/2 1 1", "-2/(t+1)"); test_get_str_pretty("2 1 1/2 -1 1", "(t+1)/(t-1)"); test_get_str_pretty("2 1 1/1 2", "(t+1)/2"); test_get_str_pretty("1 1/1 2", "1/2"); FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return EXIT_SUCCESS; }