// // ( n ) ( n ) (n+1)-k // return ( ) == ( ) ------- // ( k ) (k-1) k // void binomialCoefficient(mpz_t b, long n, long k) { mpz_set_ui(b,0); if(k>n || k<0) return; mpz_set_si(b,n); mpz_bin_ui(b,b,k); }
/* Function finds binomial coefficient for all (N,m) between Nini, Nend and mini mend. Wrties to mpz variables. */ void tabulate_bins_z(mpz_t bcs[], int Nini, int Nend, int mini, int mend) { int N; int m; int done=mend-mini+1; mpz_t bc; mpz_init(bc); mpz_t Nz; mpz_init(Nz); for(N=Nini;N<=Nend;N++) { mpz_set_ui(Nz,N); for(m=mini;m<=mend;m++) { if(N<1) { mpz_set_ui(bcs[(N-Nini)*done+(m-mini)],0); } else { mpz_bin_ui(bc,Nz,m); mpz_set(bcs[(N-Nini)*done+(m-mini)],bc); } } } mpz_clear(bc); mpz_clear(Nz); }
// Binomial Coefficient RCP<const Integer> binomial(const Integer &n, unsigned long k) { mpz_class f; mpz_bin_ui(f.get_mpz_t(), n.as_mpz().get_mpz_t(), k); return integer(f); }
//------------------------------------------------------------------------------ // Name: bin //------------------------------------------------------------------------------ knumber_base *knumber_integer::bin(knumber_base *rhs) { if(knumber_integer *const p = dynamic_cast<knumber_integer *>(rhs)) { mpz_bin_ui(mpz_, mpz_, mpz_get_ui(p->mpz_)); return this; } else if(knumber_float *const p = dynamic_cast<knumber_float *>(rhs)) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } else if(knumber_fraction *const p = dynamic_cast<knumber_fraction *>(rhs)) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } else if(knumber_error *const p = dynamic_cast<knumber_error *>(rhs)) { delete this; return new knumber_error(knumber_error::ERROR_UNDEFINED); } Q_ASSERT(0); return 0; }
/*Function to precompute all binomial coefficients inpdf: mpz_bin_ui(bcnum,n,i); hypergeometricpdf: mpz_bin_ui(bc_beta_active_inputs,beta,ai_cnt); mpz_bin_ui(bc_sub,mu_sub_beta,di-ai_cnt); mpz_bin_ui(bc_mu_d,mu,di); uniquecodes: mpz_bin_ui(bcnum,n,i); scjoint: mpz_bin_ui(bc_gamma_sy,gamp,(unsigned long int)sy); 1) mu,sx; 2) gamma,sy; 3) mu,d; (always subset of 1) 4) mu_sub_beta,di-ai_cnt; (for all mu, find all coeffs for less than or equal to d draws) 5) beta,ai_cnt; (always a subset of 2) Function finds binomial coefficient for all (N,m) between Nini, Nend and mini mend. Wrties to mpfr variables. */ void tabulate_bins_fr(mpfr_t *bcs, int Nini, int Nend, int mini, int mend, mpfr_prec_t prec) { int N; int m; int done=mend-mini+1; mpz_t bc; mpz_init(bc); mpz_t Nz; mpz_init(Nz); for(N=Nini;N<=Nend;N++) { mpz_set_ui(Nz,N); for(m=mini;m<=mend;m++) { mpz_bin_ui(bc,Nz,m); mpfr_set_z(*(bcs+(N-Nini)*done+(m-mini)),bc,MPFR_RNDN); } } mpz_clear(bc); mpz_clear(Nz); }
static PyObject * GMPy_MPZ_Function_Bincoef(PyObject *self, PyObject *args) { MPZ_Object *result = NULL, *tempx; unsigned long n, k; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("bincoef() requires two integer arguments"); return NULL; } if (!(result = GMPy_MPZ_New(NULL))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } k = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 1)); if (k == (unsigned long)(-1) && PyErr_Occurred()) { Py_DECREF((PyObject*)result); return NULL; } n = c_ulong_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!(n == (unsigned long)(-1) && PyErr_Occurred())) { /* Use mpz_bin_uiui which should be faster. */ mpz_bin_uiui(result->z, n, k); return (PyObject*)result; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) { Py_DECREF((PyObject*)result); return NULL; } mpz_bin_ui(result->z, tempx->z, k); Py_DECREF((PyObject*)tempx); return (PyObject*)result; }
void PaillierAdapter::dec( paillier_pubkey* pub, paillier_prvkey* prv, mpz_t c, unsigned int s, mpz_t res) { int i,j,k; mpz_t cprime, temp, tempDivisor, i_jCur, i_jPrev; mpz_init(cprime); //cprime = c^key mod n^{s+1} mpz_powm(cprime,c,prv->d,*pub->getnj(s+1)); //the algorithm from extracting i from (1+n)^i described in the paper. //the algorithm iteratively extracts i mod n, i mod n^2, etc. i mod n starts us off, and is just input - 1 / n. mpz_init(temp); mpz_init(tempDivisor); mpz_init(i_jCur); mpz_init_set(i_jPrev,cprime); mpz_sub_ui(i_jPrev,i_jPrev,1); mpz_divexact(i_jPrev,i_jPrev,*pub->getnj(1)); mpz_mod(i_jPrev,i_jPrev,*pub->getnj(2)); //just in case s=1; in that case we need this line to actually set i_jcur if(s==1) mpz_set(i_jCur,i_jPrev); //extract i_j = i mod n^j given i_{j-1}. this is done by taking (input - 1 mod n^{j+1}) / n , and subtracting //from that: (( (i_{j-1} choose 2)*n + (i_{j-1} choose 3)*n^2 + ... + (i_{j-1} choose j)*n^{j-1} )) mod n^j for(j=2;j<=s;j++) { //L((1+n)^i) as they call it mpz_mod(i_jCur,cprime,*pub->getnj(j+1)); mpz_sub_ui(i_jCur,i_jCur,1); mpz_divexact(i_jCur,i_jCur,*pub->getnj(1)); mpz_mod(i_jCur,i_jCur,*pub->getnj(j)); //subtract each of the binomial things for(k=2;k<=j;k++) { mpz_bin_ui(temp,i_jPrev,k); mpz_mul(temp,temp,*pub->getnj(k-1)); mpz_mod(temp,temp,*pub->getnj(j)); mpz_sub(i_jCur,i_jCur,temp); mpz_mod(i_jCur,i_jCur,*pub->getnj(j)); } mpz_set(i_jPrev,i_jCur); } //i_jCur is currently the message times the private key. mpz_invert(temp, prv->d, *pub->getnj(s)); mpz_mul(res, i_jCur, temp); mpz_mod(res, res, *pub->getnj(s)); //cleanup and return mpz_clear(cprime); mpz_clear(i_jPrev); mpz_clear(i_jCur); mpz_clear(temp); mpz_clear(tempDivisor); // unsigned int kfac, k; // mpz_t t1, t2, t3, a, id ; // std::cout << "dec called with s="<<s<<std::endl; // mpz_inits(t1, t2, t3, a, NULL); // mpz_init_set_ui(id, 0); // // mpz_powm(a, c, prv->d, *pub->getnj(s+1)); // // for(unsigned int j = 1 ; j <= s; j++) // { // mpz_set(t1, a); // mpz_mod(t1, t1, *pub->getnj(j+1)); // mpz_sub_ui(t1, t1, 1); // mpz_div(t1, t1, *pub->getnj(1)); // mpz_set(t2, id); // kfac = 1; // // for (k = 2; k <= j; k++) // { // kfac *= k; // mpz_sub_ui(id, id, 1); // mpz_mul(t2, t2, id); // mpz_mod(t2, t2, *pub->getnj(j)); // mpz_set_ui(t3, kfac); // // mpz_invert(t3, t3, *pub->getnj(j)); // // mpz_mul(t3, t3, t2); // mpz_mod(t3, t3, *pub->getnj(j)); // mpz_mul(t3, t3, *pub->getnj(k-1)); // mpz_mod(t3, t3, *pub->getnj(j)); // mpz_sub(t1, t1, t3); // mpz_mod(t1, t1, *pub->getnj(j)); // } // mpz_set(id, t1); // } // // mpz_mul(rop, id, prv->inv_d); // // mpz_mod(rop, rop, *pub->getnj(s)); // // mpz_clears(t1, t2, t3, a, id, NULL); }
/* Evaluate the expression E and put the result in R. */ void mpz_eval_expr (mpz_ptr r, expr_t e) { mpz_t lhs, rhs; switch (e->op) { case LIT: mpz_set (r, e->operands.val); return; case PLUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_add (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MINUS: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_sub (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MULT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_mul (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case DIV: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_q (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case MOD: mpz_init (rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_abs (rhs, rhs); mpz_eval_mod_expr (r, e->operands.ops.lhs, rhs); mpz_clear (rhs); return; case REM: /* Check if lhs operand is POW expression and optimize for that case. */ if (e->operands.ops.lhs->op == POW) { mpz_t powlhs, powrhs; mpz_init (powlhs); mpz_init (powrhs); mpz_init (rhs); mpz_eval_expr (powlhs, e->operands.ops.lhs->operands.ops.lhs); mpz_eval_expr (powrhs, e->operands.ops.lhs->operands.ops.rhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_powm (r, powlhs, powrhs, rhs); if (mpz_cmp_si (rhs, 0L) < 0) mpz_neg (r, r); mpz_clear (powlhs); mpz_clear (powrhs); mpz_clear (rhs); return; } mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_fdiv_r (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION >= 2 case INVMOD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_invert (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case POW: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmpabs_ui (lhs, 1) <= 0) { /* For 0^rhs and 1^rhs, we just need to verify that rhs is well-defined. For (-1)^rhs we need to determine (rhs mod 2). For simplicity, compute (rhs mod 2) for all three cases. */ expr_t two, et; two = malloc (sizeof (struct expr)); two -> op = LIT; mpz_init_set_ui (two->operands.val, 2L); makeexp (&et, MOD, e->operands.ops.rhs, two); e->operands.ops.rhs = et; } mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_cmp_si (rhs, 0L) == 0) /* x^0 is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, 0L) == 0) /* 0^y (where y != 0) is 0 */ mpz_set_ui (r, 0L); else if (mpz_cmp_ui (lhs, 1L) == 0) /* 1^y is 1 */ mpz_set_ui (r, 1L); else if (mpz_cmp_si (lhs, -1L) == 0) /* (-1)^y just depends on whether y is even or odd */ mpz_set_si (r, (mpz_get_ui (rhs) & 1) ? -1L : 1L); else if (mpz_cmp_si (rhs, 0L) < 0) /* x^(-n) is 0 */ mpz_set_ui (r, 0L); else { unsigned long int cnt; unsigned long int y; /* error if exponent does not fit into an unsigned long int. */ if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) goto pow_err; y = mpz_get_ui (rhs); /* x^y == (x/(2^c))^y * 2^(c*y) */ #if __GNU_MP_VERSION >= 2 cnt = mpz_scan1 (lhs, 0); #else cnt = 0; #endif if (cnt != 0) { if (y * cnt / cnt != y) goto pow_err; mpz_tdiv_q_2exp (lhs, lhs, cnt); mpz_pow_ui (r, lhs, y); mpz_mul_2exp (r, r, y * cnt); } else mpz_pow_ui (r, lhs, y); } mpz_clear (lhs); mpz_clear (rhs); return; pow_err: error = "result of `pow' operator too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); case GCD: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_gcd (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case LCM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_lcm (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case AND: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_and (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; case IOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_ior (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case XOR: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); mpz_xor (r, lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); return; #endif case NEG: mpz_eval_expr (r, e->operands.ops.lhs); mpz_neg (r, r); return; case NOT: mpz_eval_expr (r, e->operands.ops.lhs); mpz_com (r, r); return; case SQRT: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) < 0) { error = "cannot take square root of negative numbers"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_sqrt (r, lhs); return; #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 case ROOT: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (rhs) <= 0) { error = "cannot take non-positive root orders"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_sgn (lhs) < 0 && (mpz_get_ui (rhs) & 1) == 0) { error = "cannot take even root orders of negative numbers"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } { unsigned long int nth = mpz_get_ui (rhs); if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { /* If we are asked to take an awfully large root order, cheat and ask for the largest order we can pass to mpz_root. This saves some error prone special cases. */ nth = ~(unsigned long int) 0; } mpz_root (r, lhs, nth); } mpz_clear (lhs); mpz_clear (rhs); return; #endif case FAC: mpz_eval_expr (r, e->operands.ops.lhs); if (mpz_size (r) > 1) { error = "result of `!' operator too large"; longjmp (errjmpbuf, 1); } mpz_fac_ui (r, mpz_get_ui (r)); return; #if __GNU_MP_VERSION >= 2 case POPCNT: mpz_eval_expr (r, e->operands.ops.lhs); { long int cnt; cnt = mpz_popcount (r); mpz_set_si (r, cnt); } return; case HAMDIST: { long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); cnt = mpz_hamdist (lhs, rhs); mpz_clear (lhs); mpz_clear (rhs); mpz_set_si (r, cnt); } return; #endif case LOG2: mpz_eval_expr (r, e->operands.ops.lhs); { unsigned long int cnt; if (mpz_sgn (r) <= 0) { error = "logarithm of non-positive number"; longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (r, 2); mpz_set_ui (r, cnt - 1); } return; case LOG: { unsigned long int cnt; mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); if (mpz_sgn (lhs) <= 0) { error = "logarithm of non-positive number"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } if (mpz_cmp_ui (rhs, 256) >= 0) { error = "logarithm base too large"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } cnt = mpz_sizeinbase (lhs, mpz_get_ui (rhs)); mpz_set_ui (r, cnt - 1); mpz_clear (lhs); mpz_clear (rhs); } return; case FERMAT: { unsigned long int t; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); t = (unsigned long int) 1 << mpz_get_ui (lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0 || t == 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, t); mpz_add_ui (r, r, 1); mpz_clear (lhs); } return; case MERSENNE: mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_cmp_ui (lhs, ~(unsigned long int) 0) > 0) { error = "too large Mersenne number index"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } mpz_set_ui (r, 1); mpz_mul_2exp (r, r, mpz_get_ui (lhs)); mpz_sub_ui (r, r, 1); mpz_clear (lhs); return; case FIBONACCI: { mpz_t t; unsigned long int n, i; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "Fibonacci index out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); #if __GNU_MP_VERSION > 2 || __GNU_MP_VERSION_MINOR >= 1 mpz_fib_ui (r, n); #else mpz_init_set_ui (t, 1); mpz_set_ui (r, 1); if (n <= 2) mpz_set_ui (r, 1); else { for (i = 3; i <= n; i++) { mpz_add (t, t, r); mpz_swap (t, r); } } mpz_clear (t); #endif } return; case RANDOM: { unsigned long int n; mpz_init (lhs); mpz_eval_expr (lhs, e->operands.ops.lhs); if (mpz_sgn (lhs) <= 0 || mpz_cmp_si (lhs, 1000000000) > 0) { error = "random number size out of range"; mpz_clear (lhs); longjmp (errjmpbuf, 1); } n = mpz_get_ui (lhs); mpz_clear (lhs); mpz_urandomb (r, rstate, n); } return; case NEXTPRIME: { mpz_eval_expr (r, e->operands.ops.lhs); mpz_nextprime (r, r); } return; case BINOM: mpz_init (lhs); mpz_init (rhs); mpz_eval_expr (lhs, e->operands.ops.lhs); mpz_eval_expr (rhs, e->operands.ops.rhs); { unsigned long int k; if (mpz_cmp_ui (rhs, ~(unsigned long int) 0) > 0) { error = "k too large in (n over k) expression"; mpz_clear (lhs); mpz_clear (rhs); longjmp (errjmpbuf, 1); } k = mpz_get_ui (rhs); mpz_bin_ui (r, lhs, k); } mpz_clear (lhs); mpz_clear (rhs); return; case TIMING: { int t0; t0 = cputime (); mpz_eval_expr (r, e->operands.ops.lhs); printf ("time: %d\n", cputime () - t0); } return; default: abort (); } }
/* Function to calculate the expected number of unique codes within each input success class */ void uniquecodes(mpfr_t *ucodes, int psiz, mpz_t n, unsigned long int mu, mpz_t ncodes ,mpfr_t *pdf,mpfr_prec_t prec) { //200 bits precision gives log[2^200] around 60 digits decimal precision mpfr_t unity; mpfr_init2(unity,prec); mpfr_set_ui(unity,(unsigned long int) 1,MPFR_RNDN); mpfr_t nunity; mpfr_init2(nunity,prec); mpfr_set_si(nunity,(signed long int) -1,MPFR_RNDN); mpz_t bcnum; mpz_init(bcnum); mpfr_t bcnumf; mpfr_init2(bcnumf,prec); mpq_t cfrac; mpq_init(cfrac); mpfr_t cfracf; mpfr_init2(cfracf,prec); mpfr_t expargr; mpfr_init2(expargr,prec); mpfr_t r1; mpfr_init2(r1,prec); mpfr_t r2; mpfr_init2(r2,prec); // mpfr_t pdf[mu]; unsigned long int i; int pdex; int addr; // for(i=0;i<=mu;i++) // mpfr_init2(pdf[i],prec); // inpdf(pdf,n,pin,mu,bcs,prec); for(pdex=0;pdex<=psiz-1;pdex++) { for(i=0;i<=mu;i++) { addr=pdex*(mu+1)+i; mpz_bin_ui(bcnum,n,i); mpq_set_num(cfrac,ncodes); mpq_set_den(cfrac,bcnum); mpq_canonicalize(cfrac); mpfr_set_q(cfracf,cfrac,MPFR_RNDN); mpfr_mul(expargr,cfracf,*(pdf+addr),MPFR_RNDN); mpfr_mul(expargr,expargr,nunity,MPFR_RNDN); mpfr_exp(r1,expargr,MPFR_RNDN); mpfr_sub(r1,unity,r1,MPFR_RNDN); mpfr_set_z(bcnumf,bcnum,MPFR_RNDN); mpfr_mul(r2,bcnumf,r1,MPFR_RNDN); mpfr_set((*ucodes+addr),r2,MPFR_RNDN); mpfr_round((*ucodes+addr),(*ucodes+addr)); } } mpfr_clear(unity); mpfr_clear(nunity); mpz_clear(bcnum); mpfr_clear(bcnumf); mpq_clear(cfrac); mpfr_clear(cfracf); mpfr_clear(expargr); mpfr_clear(r1); mpfr_clear(r2); // for(i=0;i<=mu;i++) // mpfr_clear(pdf[i]); }
/************************************************************ * We used the GMP library's unsigned long long binomial * coefficient function whose data will be used in the aks.cpp * file. This is where most of the program's optimizations will * be needed as we could use dynamic programming for this * portion of our program's tasks. This would greatly speed * up our program and is really the bottleneck that makes * our program take so long for large numbers. However, we * must marvel at the fact that while it takes a long time, * our program can handle transcendentally large numbers and * determine whether they are prime or composite in puesdo- * polynomial time! The dynamic programming optimization will * have to wait for another day! But we hope to make time * for it in the near future! *************************************************************/ void binomial (mpz_t retVal, mpz_t topNum, mpz_t bottomNum) { unsigned long long temp = mpz_get_ull(bottomNum); mpz_bin_ui(retVal, topNum, temp); }
/*------------------------------------------------------------------------*/ int my_mpfr_beta (mpfr_t R, mpfr_t a, mpfr_t b, mpfr_rnd_t RND) { mpfr_prec_t p_a = mpfr_get_prec(a), p_b = mpfr_get_prec(b); if(p_a < p_b) p_a = p_b;// p_a := max(p_a, p_b) if(mpfr_get_prec(R) < p_a) mpfr_prec_round(R, p_a, RND);// so prec(R) = max( prec(a), prec(b) ) int ans; mpfr_t s; mpfr_init2(s, p_a); #ifdef DEBUG_Rmpfr R_CheckUserInterrupt(); int cc = 0; #endif /* "FIXME": check each 'ans' below, and return when not ok ... */ ans = mpfr_add(s, a, b, RND); if(mpfr_integer_p(s) && mpfr_sgn(s) <= 0) { // (a + b) is integer <= 0 if(!mpfr_integer_p(a) && !mpfr_integer_p(b)) { // but a,b not integer ==> R = finite / +-Inf = 0 : mpfr_set_zero (R, +1); mpfr_clear (s); return ans; }// else: sum is integer; at least one {a,b} integer ==> both integer int sX = mpfr_sgn(a), sY = mpfr_sgn(b); if(sX * sY < 0) { // one negative, one positive integer // ==> special treatment here : if(sY < 0) // ==> sX > 0; swap the two mpfr_swap(a, b); // now have --- a < 0 < b <= |a| integer ------------------ /* ================ and in this case: B(a,b) = (-1)^b B(1-a-b, b) = (-1)^b B(1-s, b) = (1*2*..*b) / (-s-1)*(-s-2)*...*(-s-b) */ /* where in the 2nd form, both numerator and denominator have exactly * b integer factors. This is attractive {numerically & speed wise} * for 'small' b */ #define b_large 100 #ifdef DEBUG_Rmpfr Rprintf(" my_mpfr_beta(<neg int>): s = a+b= "); R_PRT(s); Rprintf("\n a = "); R_PRT(a); Rprintf("\n b = "); R_PRT(b); Rprintf("\n"); if(cc++ > 999) { mpfr_set_zero (R, +1); mpfr_clear (s); return ans; } #endif unsigned long b_ = 0;// -Wall Rboolean b_fits_ulong = mpfr_fits_ulong_p(b, RND), small_b = b_fits_ulong && (b_ = mpfr_get_ui(b, RND)) < b_large; if(small_b) { #ifdef DEBUG_Rmpfr Rprintf(" b <= b_large = %d...\n", b_large); #endif //----------------- small b ------------------ // use GMP big integer arithmetic: mpz_t S; mpz_init(S); mpfr_get_z(S, s, RND); // S := s mpz_sub_ui (S, S, (unsigned long) 1); // S = s - 1 = (a+b-1) /* binomial coefficient choose(N, k) requires k a 'long int'; * here, b must fit into a long: */ mpz_bin_ui (S, S, b_); // S = choose(S, b) = choose(a+b-1, b) mpz_mul_ui (S, S, b_); // S = S*b = b * choose(a+b-1, b) // back to mpfr: R = 1 / S = 1 / (b * choose(a+b-1, b)) mpfr_set_ui(s, (unsigned long) 1, RND); mpfr_div_z(R, s, S, RND); mpz_clear(S); } else { // b is "large", use direct B(.,.) formula #ifdef DEBUG_Rmpfr Rprintf(" b > b_large = %d...\n", b_large); #endif // a := (-1)^b : // there is no mpfr_si_pow(a, -1, b, RND); int neg; // := 1 ("TRUE") if (-1)^b = -1, i.e. iff b is odd if(b_fits_ulong) { // (i.e. not very large) neg = (b_ % 2); // 1 iff b_ is odd, 0 otherwise } else { // really large b; as we know it is integer, can still.. // b2 := b / 2 mpfr_t b2; mpfr_init2(b2, p_a); mpfr_div_2ui(b2, b, 1, RND); neg = !mpfr_integer_p(b2); // b is odd, if b/2 is *not* integer #ifdef DEBUG_Rmpfr Rprintf(" really large b; neg = ('b is odd') = %d\n", neg); #endif } // s' := 1-s = 1-a-b mpfr_ui_sub(s, 1, s, RND); #ifdef DEBUG_Rmpfr Rprintf(" neg = %d\n", neg); Rprintf(" s' = 1-a-b = "); R_PRT(s); Rprintf("\n -> calling B(s',b)\n"); #endif // R := B(1-a-b, b) = B(s', b) if(small_b) { my_mpfr_beta (R, s, b, RND); } else { my_mpfr_lbeta (R, s, b, RND); mpfr_exp(R, R, RND); // correct *if* beta() >= 0 } #ifdef DEBUG_Rmpfr Rprintf(" R' = beta(s',b) = "); R_PRT(R); Rprintf("\n"); #endif // Result = (-1)^b B(1-a-b, b) = +/- s' if(neg) mpfr_neg(R, R, RND); } mpfr_clear(s); return ans; } } ans = mpfr_gamma(s, s, RND); /* s = gamma(a + b) */ #ifdef DEBUG_Rmpfr Rprintf("my_mpfr_beta(): s = gamma(a+b)= "); R_PRT(s); Rprintf("\n a = "); R_PRT(a); Rprintf("\n b = "); R_PRT(b); #endif ans = mpfr_gamma(a, a, RND); ans = mpfr_gamma(b, b, RND); ans = mpfr_mul(b, b, a, RND); /* b' = gamma(a) * gamma(b) */ #ifdef DEBUG_Rmpfr Rprintf("\n G(a) * G(b) = "); R_PRT(b); Rprintf("\n"); #endif ans = mpfr_div(R, b, s, RND); mpfr_clear (s); /* mpfr_free_cache() must be called in the caller !*/ return ans; }
int my_mpfr_lbeta(mpfr_t R, mpfr_t a, mpfr_t b, mpfr_rnd_t RND) { mpfr_prec_t p_a = mpfr_get_prec(a), p_b = mpfr_get_prec(b); if(p_a < p_b) p_a = p_b;// p_a := max(p_a, p_b) if(mpfr_get_prec(R) < p_a) mpfr_prec_round(R, p_a, RND);// so prec(R) = max( prec(a), prec(b) ) int ans; mpfr_t s; mpfr_init2(s, p_a); /* "FIXME": check each 'ans' below, and return when not ok ... */ ans = mpfr_add(s, a, b, RND); if(mpfr_integer_p(s) && mpfr_sgn(s) <= 0) { // (a + b) is integer <= 0 if(!mpfr_integer_p(a) && !mpfr_integer_p(b)) { // but a,b not integer ==> R = ln(finite / +-Inf) = ln(0) = -Inf : mpfr_set_inf (R, -1); mpfr_clear (s); return ans; }// else: sum is integer; at least one integer ==> both integer int sX = mpfr_sgn(a), sY = mpfr_sgn(b); if(sX * sY < 0) { // one negative, one positive integer // ==> special treatment here : if(sY < 0) // ==> sX > 0; swap the two mpfr_swap(a, b); /* now have --- a < 0 < b <= |a| integer ------------------ * ================ * --> see my_mpfr_beta() above */ unsigned long b_ = 0;// -Wall Rboolean b_fits_ulong = mpfr_fits_ulong_p(b, RND), small_b = b_fits_ulong && (b_ = mpfr_get_ui(b, RND)) < b_large; if(small_b) { //----------------- small b ------------------ // use GMP big integer arithmetic: mpz_t S; mpz_init(S); mpfr_get_z(S, s, RND); // S := s mpz_sub_ui (S, S, (unsigned long) 1); // S = s - 1 = (a+b-1) /* binomial coefficient choose(N, k) requires k a 'long int'; * here, b must fit into a long: */ mpz_bin_ui (S, S, b_); // S = choose(S, b) = choose(a+b-1, b) mpz_mul_ui (S, S, b_); // S = S*b = b * choose(a+b-1, b) // back to mpfr: R = log(|1 / S|) = - log(|S|) mpz_abs(S, S); mpfr_set_z(s, S, RND); // <mpfr> s := |S| mpfr_log(R, s, RND); // R := log(s) = log(|S|) mpfr_neg(R, R, RND); // R = -R = -log(|S|) mpz_clear(S); } else { // b is "large", use direct B(.,.) formula // a := (-1)^b -- not needed here, neither 'neg': want log( |.| ) // s' := 1-s = 1-a-b mpfr_ui_sub(s, 1, s, RND); // R := log(|B(1-a-b, b)|) = log(|B(s', b)|) my_mpfr_lbeta (R, s, b, RND); } mpfr_clear(s); return ans; } } ans = mpfr_lngamma(s, s, RND); // s = lngamma(a + b) ans = mpfr_lngamma(a, a, RND); ans = mpfr_lngamma(b, b, RND); ans = mpfr_add (b, b, a, RND); // b' = lngamma(a) + lngamma(b) ans = mpfr_sub (R, b, s, RND); mpfr_clear (s); return ans; }