void partitions_fmpz_fmpz_hrr(fmpz_t p, const fmpz_t n, int use_doubles) { arb_t x; arf_t bound; slong N; arb_init(x); arf_init(bound); N = partitions_hrr_needed_terms(fmpz_get_d(n)); if (fmpz_cmp_ui(n, 4e8) >= 0 && flint_get_num_threads() > 1) { hrr_sum_threaded(x, n, N, use_doubles); } else { partitions_hrr_sum_arb(x, n, 1, N, use_doubles); } partitions_rademacher_bound(bound, n, N); arb_add_error_arf(x, bound); if (!arb_get_unique_fmpz(p, x)) { flint_printf("not unique!\n"); arb_printd(x, 50); flint_printf("\n"); abort(); } arb_clear(x); arf_clear(bound); }
/* The floor+vec method *requires* n <= 1498 for floor(p(n)/2^64) to be equal to floor(T/2^64). It is faster up to n ~= 1200. With doubles, it is faster up to n ~= 500. */ void _partitions_fmpz_ui(fmpz_t res, ulong n, int use_doubles) { if (n < NUMBER_OF_SMALL_PARTITIONS) { fmpz_set_ui(res, partitions_lookup[n]); } else if (FLINT_BITS == 64 && (n < 500 || (!use_doubles && n < 1200))) { mp_ptr tmp = flint_malloc((n + 1) * sizeof(mp_limb_t)); if (n < 417) /* p(n) < 2^64 */ { partitions_vec(tmp, n + 1); fmpz_set_ui(res, tmp[n]); } else { arb_t x; arb_init(x); fmpz_set_ui(res, n); partitions_leading_fmpz(x, res, 4 * sqrt(n) - 50); arb_mul_2exp_si(x, x, -64); arb_floor(x, x, 4 * sqrt(n) - 50); if (arb_get_unique_fmpz(res, x)) { fmpz_mul_2exp(res, res, 64); partitions_vec(tmp, n + 1); fmpz_add_ui(res, res, tmp[n]); } else { flint_printf("warning: failed at %wu\n", n); fmpz_set_ui(res, n); partitions_fmpz_fmpz_hrr(res, res, use_doubles); } arb_clear(x); } flint_free(tmp); } else { fmpz_set_ui(res, n); partitions_fmpz_fmpz_hrr(res, res, use_doubles); } }
int main() { slong iter; flint_rand_t state; flint_printf("isolate_roots...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 40; iter++) { slong m, r, a, b, maxdepth, maxeval, maxfound, prec, i, j, num; arf_interval_ptr blocks; int * info; arf_interval_t interval; arb_t t; fmpz_t nn; prec = 2 + n_randint(state, 50); m = n_randint(state, 80); r = 1 + n_randint(state, 80); a = m - r; b = m + r; maxdepth = 1 + n_randint(state, 60); maxeval = 1 + n_randint(state, 5000); maxfound = 1 + n_randint(state, 100); arf_interval_init(interval); arb_init(t); fmpz_init(nn); arf_set_si(&interval->a, a); arf_set_si(&interval->b, b); num = arb_calc_isolate_roots(&blocks, &info, sin_pi2_x, NULL, interval, maxdepth, maxeval, maxfound, prec); /* check that all roots are accounted for */ for (i = a; i <= b; i++) { if (i % 2 == 0) { int found = 0; for (j = 0; j < num; j++) { arf_interval_get_arb(t, blocks + j, ARF_PREC_EXACT); if (arb_contains_si(t, i)) { found = 1; break; } } if (!found) { flint_printf("FAIL: missing root %wd\n", i); flint_printf("a = %wd, b = %wd, maxdepth = %wd, maxeval = %wd, maxfound = %wd, prec = %wd\n", a, b, maxdepth, maxeval, maxfound, prec); for (j = 0; j < num; j++) { arf_interval_printd(blocks + j, 15); flint_printf(" %d \n", info[i]); } abort(); } } } /* check that all reported single roots are good */ for (i = 0; i < num; i++) { if (info[i] == 1) { /* b contains unique 2n -> b/2 contains unique n */ arf_interval_get_arb(t, blocks + i, ARF_PREC_EXACT); arb_mul_2exp_si(t, t, -1); if (!arb_get_unique_fmpz(nn, t)) { flint_printf("FAIL: bad root %wd\n", i); flint_printf("a = %wd, b = %wd, maxdepth = %wd, maxeval = %wd, maxfound = %wd, prec = %wd\n", a, b, maxdepth, maxeval, maxfound, prec); for (j = 0; j < num; j++) { arf_interval_printd(blocks + j, 15); flint_printf(" %d \n", info[i]); } abort(); } } } _arf_interval_vec_clear(blocks, num); flint_free(info); arf_interval_clear(interval); arb_clear(t); fmpz_clear(nn); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }
/* corrects branch cut of sum_{k=0}^{r-1} log(z+k), given the logarithm of the product */ void _acb_log_rising_correct_branch(acb_t t, const acb_t t_wrong, const acb_t z, ulong r, long prec) { acb_t f; arb_t pi, u, v; fmpz_t pi_mult; long i, argprec; acb_init(f); arb_init(u); arb_init(pi); arb_init(v); fmpz_init(pi_mult); argprec = FLINT_MIN(prec, 40); arb_zero(u); for (i = 0; i < r; i++) { acb_add_ui(f, z, i, argprec); acb_arg(v, f, argprec); arb_add(u, u, v, argprec); } if (argprec == prec) { arb_set(acb_imagref(t), u); } else { arb_sub(v, u, acb_imagref(t), argprec); arb_const_pi(pi, argprec); arb_div(v, v, pi, argprec); if (arb_get_unique_fmpz(pi_mult, v)) { arb_const_pi(v, prec); arb_mul_fmpz(v, v, pi_mult, prec); arb_add(acb_imagref(t), acb_imagref(t), v, prec); } else { arb_zero(u); for (i = 0; i < r; i++) { acb_add_ui(f, z, i, prec); acb_arg(v, f, prec); arb_add(u, u, v, prec); } arb_set(acb_imagref(t), u); } } acb_clear(f); arb_clear(u); arb_clear(v); arb_clear(pi); fmpz_clear(pi_mult); }