void mag_rfac_ui(mag_t z, ulong n) { if (n < MAG_FAC_TABLE_NUM) { _fmpz_demote(MAG_EXPREF(z)); MAG_EXP(z) = mag_rfac_tab[n * 2]; MAG_MAN(z) = mag_rfac_tab[n * 2 + 1]; } else { double x = n; x = ceil((((x+0.5)*mag_d_log_lower_bound(x) - x) * 1.4426950408889634074) * -0.9999999); /* x + 1 could round down for huge x, but this doesn't matter as long as the value was perturbed up above */ fmpz_set_d(MAG_EXPREF(z), x + 1); MAG_MAN(z) = MAG_ONE_HALF; } }
void mag_polylog_tail(mag_t u, const mag_t z, long sigma, ulong d, ulong N) { mag_t TN, UN, t; if (N < 2) { mag_inf(u); return; } mag_init(TN); mag_init(UN); mag_init(t); if (mag_cmp_2exp_si(z, 0) >= 0) { mag_inf(u); } else { /* Bound T(N) */ mag_pow_ui(TN, z, N); /* multiply by log(N)^d */ if (d > 0) { mag_log_ui(t, N); mag_pow_ui(t, t, d); mag_mul(TN, TN, t); } /* multiply by 1/k^s */ if (sigma > 0) { mag_set_ui_lower(t, N); mag_pow_ui_lower(t, t, sigma); mag_div(TN, TN, t); } else if (sigma < 0) { mag_set_ui(t, N); mag_pow_ui(t, t, -sigma); mag_mul(TN, TN, t); } /* Bound U(N) */ mag_set(UN, z); /* multiply by (1 + 1/N)**S */ if (sigma < 0) { mag_binpow_uiui(t, N, -sigma); mag_mul(UN, UN, t); } /* multiply by (1 + 1/(N log(N)))^d */ if (d > 0) { ulong nl; /* rounds down */ nl = mag_d_log_lower_bound(N) * N * (1 - 1e-13); mag_binpow_uiui(t, nl, d); mag_mul(UN, UN, t); } /* T(N) / (1 - U(N)) */ if (mag_cmp_2exp_si(UN, 0) >= 0) { mag_inf(u); } else { mag_one(t); mag_sub_lower(t, t, UN); mag_div(u, TN, t); } } mag_clear(TN); mag_clear(UN); mag_clear(t); }
int main() { slong iter; flint_rand_t state; flint_printf("d_log_lower_bound...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000; iter++) { mpfr_t t; double x, y, z; mpfr_init2(t, 53); x = d_randtest2(state); x = ldexp(x, 100 - n_randint(state, 200)); switch (n_randint(state, 10)) { case 0: x = 1.0 + x; break; case 1: x = 1.0 - x; break; case 2: x = D_INF; break; case 3: x = 0.0; break; case 4: x = D_NAN; break; default: break; } y = mag_d_log_lower_bound(x); mpfr_set_d(t, x, MPFR_RNDD); mpfr_log(t, t, MPFR_RNDD); z = mpfr_get_d(t, MPFR_RNDD); if (y > z || fabs(y-z) > 0.000001 * fabs(z)) { flint_printf("FAIL\n"); flint_printf("x = %.20g\n", x); flint_printf("y = %.20g\n", y); flint_printf("z = %.20g\n", z); abort(); } mpfr_clear(t); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }