mp_limb_t cramer_rule(const mpfr_t den_bound, mpz_square_mat_t A, mpfr_prec_t pr, slong k) // returns log2(Cramer bound on numerator) rounded up { mp_limb_t bI; const slong n=A->r; mpfr_t u,v,w; mpfr_init2(w,pr); mpfr_init2(u,pr); log2_L2_norm_4arg(u, A, k, n); //mpfr_printf("k=%d row norm=%10Rf\n",k,u); mpfr_sub(w, den_bound, u, MPFR_RNDU); // w=den_bound / min row norm mpfr_sub_ui(u, w, 1, MPFR_RNDU); // u=den_bound/2/min row norm // vector norm = square root of n mpfr_init(v); mpfr_set_ui(v, n, MPFR_RNDU); mpfr_log2(w, v, MPFR_RNDU); // w=b norm * 2 mpfr_clear(v); mpfr_div_ui(w, w, 2, MPFR_RNDU); // w=b norm mpfr_add(w, w, u, MPFR_RNDU); // w=b norm*(...) mpfr_clear(u); bI=mpfr_get_uj(w, MPFR_RNDU); mpfr_clear(w); if(bI<FLINT_BITS) bI=FLINT_BITS; return bI; }
static void test_get_uj_smallneg (void) { mpfr_t x; int i; mpfr_init2 (x, 64); for (i = 1; i <= 4; i++) { int r; mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN); RND_LOOP (r) { intmax_t s; uintmax_t u; mpfr_clear_erangeflag (); s = mpfr_get_sj (x, (mpfr_rnd_t) r); if (mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + small negative op" " for rnd = %s and x = -%d/4\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); exit (1); } u = mpfr_get_uj (x, (mpfr_rnd_t) r); if (u != 0) { printf ("ERROR for get_uj + ERANGE + small negative op" " for rnd = %s and x = -%d/4\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); printf ("Expected 0, got %ju\n", u); exit (1); } if ((s == 0) ^ !mpfr_erangeflag_p ()) { char *not = s == 0 ? "" : " not"; printf ("ERROR for get_uj + ERANGE + small negative op" " for rnd = %s and x = -%d/4\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); printf ("The rounding integer (%jd) is%s representable in " "unsigned long,\nbut the erange flag is%s set.\n", s, not, not); exit (1); } } } mpfr_clear (x); }
static void check_uj (uintmax_t u, mpfr_ptr x) { mpfr_t y; int i; mpfr_init2 (y, MPFR_PREC (x)); for (i = -1; i <= 1; i++) { int rnd; mpfr_set_si_2exp (y, i, -2, MPFR_RNDN); mpfr_add (y, y, x, MPFR_RNDN); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) { uintmax_t r; if (rnd == MPFR_RNDZ && i < 0) continue; if (rnd == MPFR_RNDD && i < 0) continue; if (rnd == MPFR_RNDU && i > 0) continue; if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) || (MPFR_IS_NEG(y) && i < 0))) continue; /* rint (y) == x == u */ r = mpfr_get_uj (y, (mpfr_rnd_t) rnd); if (r != u) { printf ("Error in check_uj for y = "); mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); printf (" in %s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) rnd)); printf ("Got %ju instead of %ju.\n", r, u); exit (1); } } } mpfr_clear (y); }
int main (void) { mpfr_t x; intmax_t j; tests_start_mpfr (); mpfr_init_set_ui (x, 1, MPFR_RNDN); j = mpfr_get_uj (x, MPFR_RNDN); mpfr_clear (x); if (j != 1) { #ifdef MPFR_PRINTF_MAXLM printf ("Error: got %" MPFR_PRINTF_MAXLM "d instead of 1.\n", j); #else printf ("Error: did not get 1.\n"); #endif exit (1); } tests_end_mpfr (); return 0; }
static void check_erange (void) { mpfr_t x; uintmax_t dl; intmax_t d; /* Test for ERANGE flag + correct behaviour if overflow */ mpfr_init2 (x, 256); mpfr_set_uj (x, MPFR_UINTMAX_MAX, MPFR_RNDN); mpfr_clear_erangeflag (); dl = mpfr_get_uj (x, MPFR_RNDN); if (dl != MPFR_UINTMAX_MAX || mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + ERANGE + UINTMAX_MAX (1)\n"); exit (1); } mpfr_add_ui (x, x, 1, MPFR_RNDN); dl = mpfr_get_uj (x, MPFR_RNDN); if (dl != MPFR_UINTMAX_MAX || !mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + ERANGE + UINTMAX_MAX (2)\n"); exit (1); } mpfr_set_sj (x, -1, MPFR_RNDN); mpfr_clear_erangeflag (); dl = mpfr_get_uj (x, MPFR_RNDN); if (dl != 0 || !mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + ERANGE + -1 \n"); exit (1); } mpfr_set_sj (x, MPFR_INTMAX_MAX, MPFR_RNDN); mpfr_clear_erangeflag (); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MAX || mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MAX (1)\n"); exit (1); } mpfr_add_ui (x, x, 1, MPFR_RNDN); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MAX || !mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MAX (2)\n"); exit (1); } mpfr_set_sj (x, MPFR_INTMAX_MIN, MPFR_RNDN); mpfr_clear_erangeflag (); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MIN || mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MIN (1)\n"); exit (1); } mpfr_sub_ui (x, x, 1, MPFR_RNDN); d = mpfr_get_sj (x, MPFR_RNDN); if (d != MPFR_INTMAX_MIN || !mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + ERANGE + INTMAX_MIN (2)\n"); exit (1); } mpfr_set_nan (x); mpfr_clear_erangeflag (); d = mpfr_get_uj (x, MPFR_RNDN); if (d != 0 || !mpfr_erangeflag_p ()) { printf ("ERROR for get_uj + NaN\n"); exit (1); } mpfr_clear_erangeflag (); d = mpfr_get_sj (x, MPFR_RNDN); if (d != 0 || !mpfr_erangeflag_p ()) { printf ("ERROR for get_sj + NaN\n"); exit (1); } mpfr_clear (x); }
void fmpz_mat_det_modular_given_divisor_8arg(mpz_t det, nmod_mat_t Amod, mpfr_t hadamard_log2, mpfr_prec_t pr, p_k_pk_t* pp, n_primes_rev_t iT, mp_limb_t xmod, const fmpz_mat_t A) /* act like fmpz_mat_det_modular_given_divisor_4block(), but * decrease primes using iT, rather than increase them * don't count H.B., use hadamard_log2 which is 1+log2(H.B.) * sum logarithms instead of multiplying together found primes * re-use found prime pp->p and xmod which is determinant of A modulo pp->p hadamard_log2 on entry is upper bound on log2(2*H.B) on exit, decreased to an unspecified value iT on entry just found prime pp->p possibly gets shifted */ { // loop bound = 2*H.B / known det divisor decrease_bound_mpz(hadamard_log2,pr,det); #if 0 flint_printf("det modulo %llX = %llX\n",pp->p_deg_k,xmod); #endif // re-use known det A modulo pp->p_deg_k mp_limb_t divisor_inv=invert_det_divisor_modulo_pk(det,pp,&Amod->mod); xmod=n_mulmod2_preinv(xmod,divisor_inv, Amod->mod.n,Amod->mod.ninv); fmpz_t xnew,x; fmpz_init(xnew); fmpz_init(x); fmpz_t prod; fmpz_init_set_ui(prod, UWORD(1) ); fmpz_CRT_ui(xnew, x, prod, xmod, pp->p_deg_k, 1); fmpz_set_ui(prod, pp->p_deg_k); fmpz_set(x, xnew); #if LOUD_DET_BOUND mpfr_printf("fmpz_mat_det_modular_given_divisor_8arg(): log2 bound=%Rf\n", hadamard_log2); slong primes_used=1; #endif // for orthogonal matrice the bound might be reached at this point. // Attempt to skip main loop if(comp_bound_ui(hadamard_log2,pp->p_deg_k)) { mp_limb_t* scratch=flint_malloc( 4*(A->r-4)*sizeof(mp_limb_t) ); mp_limb_t bound=mpfr_get_uj(hadamard_log2,MPFR_RNDU); for(;;) { divisor_inv=choose_prime_and_degree( pp, &Amod->mod, iT, det ); // TODO: optimize fmpz_mat_get_nmod_mat() fmpz_mat_get_nmod_mat(Amod, A); // TODO: call a faster subroutine instead of nmod_mat_det_mod_pk_4block() // when pp->p is 64 bit long xmod=nmod_mat_det_mod_pk_4block(Amod,pp[0],scratch); xmod=n_mulmod2_preinv(xmod,divisor_inv, Amod->mod.n,Amod->mod.ninv); // TODO: rewrite fmpz_CRT_ui() -> mpz_CRT_ui_5arg() fmpz_CRT_ui(xnew, x, prod, xmod, pp->p_deg_k, 1); fmpz_mul_ui(prod, prod, pp->p_deg_k); #if LOUD_DET_BOUND primes_used++; #endif if(cmp_positive_log2(prod,bound) >= 0) break; fmpz_set(x, xnew); } flint_free(scratch); } #if LOUD_DET_BOUND flint_printf("fmpz_mat_det_modular_given_divisor_8arg() primes used: %d\n\n\n", primes_used); #endif fmpz_clear(prod); mpz_fmpz_mul_det_2arg(det,xnew); fmpz_clear(prod); fmpz_clear(x); fmpz_clear(xnew); }