/* computes R(n) = exp(-n)/n * sum(k!/(-n)^k, k=0..n-2) with error at most 4*ulp(x). Assumes n>=2. Since x <= exp(-n)/n <= 1/8, then 4*ulp(x) <= ulp(1). */ static void mpfr_const_euler_R (mpfr_t x, unsigned long n) { unsigned long k, m; mpz_t a, s; mpfr_t y; MPFR_ASSERTN (n >= 2); /* ensures sum(k!/(-n)^k, k=0..n-2) >= 2/3 */ /* as we multiply the sum by exp(-n), we need only PREC(x) - n/LOG2 bits */ m = MPFR_PREC(x) - (unsigned long) ((double) n / LOG2); mpz_init_set_ui (a, 1); mpz_mul_2exp (a, a, m); mpz_init_set (s, a); for (k = 1; k <= n; k++) { mpz_mul_ui (a, a, k); mpz_fdiv_q_ui (a, a, n); /* the error e(k) on a is e(k) <= 1 + k/n*e(k-1) with e(0)=0, i.e. e(k) <= k */ if (k % 2) mpz_sub (s, s, a); else mpz_add (s, s, a); } /* the error on s is at most 1+2+...+n = n*(n+1)/2 */ mpz_fdiv_q_ui (s, s, n); /* err <= 1 + (n+1)/2 */ MPFR_ASSERTN (MPFR_PREC(x) >= mpz_sizeinbase(s, 2)); mpfr_set_z (x, s, MPFR_RNDD); /* exact */ mpfr_div_2ui (x, x, m, MPFR_RNDD); /* now x = 1/n * sum(k!/(-n)^k, k=0..n-2) <= 1/n */ /* err(x) <= (n+1)/2^m <= (n+1)*exp(n)/2^PREC(x) */ mpfr_init2 (y, m); mpfr_set_si (y, -(long)n, MPFR_RNDD); /* assumed exact */ mpfr_exp (y, y, MPFR_RNDD); /* err <= ulp(y) <= exp(-n)*2^(1-m) */ mpfr_mul (x, x, y, MPFR_RNDD); /* err <= ulp(x) + (n + 1 + 2/n) / 2^prec(x) <= ulp(x) + (n + 1 + 2/n) ulp(x)/x since x*2^(-prec(x)) < ulp(x) <= ulp(x) + (n + 1 + 2/n) 3/(2n) ulp(x) since x >= 2/3*n for n >= 2 <= 4 * ulp(x) for n >= 2 */ mpfr_clear (y); mpz_clear (a); mpz_clear (s); }
int main( void ) { mpz_t num, digit; unsigned long long sum; mpz_init( num ); mpz_init( digit ); sum = 0; /****************************************************** * void mpz_fac_ui (mpz_t rop, unsigned long int op) * * -> Sets 'rop' to 'op!' * ******************************************************/ mpz_fac_ui( num, 100 ); while( mpz_sgn( num ) ) // while num > 0 { sum += mpz_mod_ui( digit, num, 10 ); mpz_fdiv_q_ui( num, num, 10 ); } printf( "Answer: %llu\n", sum ); mpz_clear( num ); return 0; }
int main(void) { mpz_t base; mpz_t exponent; mpz_t arrows; mpz_t result; mpz_init(base); mpz_init(exponent); mpz_init(arrows); mpz_init(result); mpz_set_ui(base, 2L); mpz_set_ui(arrows, 2L); mpz_set_ui(exponent, 5L); arrow(result, base, exponent, arrows); gmp_printf("%Zd\n", result); int digit = 0; while (mpz_cmp_ui(result, 1L) >= 0) { digit++; mpz_fdiv_q_ui(result, result, 10UL); } gmp_printf("%d digits\n%", digit); return 0; }
void decode_all(int* array, header h, int level) { if(!level) { return finish(array); } int* new_array = malloc(sizeof(int)*headers[level-1].size); int index = 0; mpz_t number, spill; mpz_init(number); mpz_init(spill); for(int i = 0; i < h.size; i++) { mpz_ui_pow_ui(spill, 2, M); mpz_set(number, remainders[level-1][i]); mpz_addmul_ui(number, spill, array[i]); int min = headers[level-1].chunksize > (headers[level-1].size - index)?(headers[level-1].size - index):headers[level-1].chunksize; for(int j = 0; j < min; j++) { new_array[index + min - j - 1] = mpz_fdiv_q_ui(number, number, headers[level-1].K); } index += min; } return decode_all(new_array, headers[level - 1], level - 1); }
void calcterm(int n,mpz_t r) { int i; mpz_set_ui(r,0); for(i=1;(long long)i*i<=n;i++) if(n%i==0) { calc(i,n,r); if(i!=n/i) calc(n/i,n,r); } mpz_fdiv_q_ui(r,r,2*n); }
/* assuming b[0]...b[2(n-1)] are computed, computes and stores B[2n]*(2n+1)! t/(exp(t)-1) = sum(B[j]*t^j/j!, j=0..infinity) thus t = (exp(t)-1) * sum(B[j]*t^j/j!, n=0..infinity). Taking the coefficient of degree n+1 > 1, we get: 0 = sum(1/(n+1-k)!*B[k]/k!, k=0..n) which gives: B[n] = -sum(binomial(n+1,k)*B[k], k=0..n-1)/(n+1). Let C[n] = B[n]*(n+1)!. Then C[n] = -sum(binomial(n+1,k)*C[k]*n!/(k+1)!, k=0..n-1), which proves that the C[n] are integers. */ mpz_t* mpfr_bernoulli_internal (mpz_t *b, unsigned long n) { if (n == 0) { b = (mpz_t *) (*__gmp_allocate_func) (sizeof (mpz_t)); mpz_init_set_ui (b[0], 1); } else { mpz_t t; unsigned long k; b = (mpz_t *) (*__gmp_reallocate_func) (b, n * sizeof (mpz_t), (n + 1) * sizeof (mpz_t)); mpz_init (b[n]); /* b[n] = -sum(binomial(2n+1,2k)*C[k]*(2n)!/(2k+1)!, k=0..n-1) */ mpz_init_set_ui (t, 2 * n + 1); mpz_mul_ui (t, t, 2 * n - 1); mpz_mul_ui (t, t, 2 * n); mpz_mul_ui (t, t, n); mpz_fdiv_q_ui (t, t, 3); /* exact: t=binomial(2*n+1,2*k)*(2*n)!/(2*k+1)! for k=n-1 */ mpz_mul (b[n], t, b[n-1]); for (k = n - 1; k-- > 0;) { mpz_mul_ui (t, t, 2 * k + 1); mpz_mul_ui (t, t, 2 * k + 2); mpz_mul_ui (t, t, 2 * k + 2); mpz_mul_ui (t, t, 2 * k + 3); mpz_fdiv_q_ui (t, t, 2 * (n - k) + 1); mpz_fdiv_q_ui (t, t, 2 * (n - k)); mpz_addmul (b[n], t, b[k]); } /* take into account C[1] */ mpz_mul_ui (t, t, 2 * n + 1); mpz_fdiv_q_2exp (t, t, 1); mpz_sub (b[n], b[n], t); mpz_neg (b[n], b[n]); mpz_clear (t); } return b; }
void fmpz_fdiv_q(fmpz_t f, const fmpz_t g, const fmpz_t h) { fmpz c1 = *g; fmpz c2 = *h; if (fmpz_is_zero(h)) { printf("Exception: division by zero in fmpz_fdiv_q\n"); abort(); } if (!COEFF_IS_MPZ(c1)) /* g is small */ { if (!COEFF_IS_MPZ(c2)) /* h is also small */ { fmpz q = c1 / c2; /* compute C quotient */ fmpz r = c1 - c2 * q; /* compute remainder */ if (r && (c2 ^ r) < 0L) --q; fmpz_set_si(f, q); } else /* h is large and g is small */ { if ((c1 > 0L && fmpz_sgn(h) < 0) || (c1 < 0L && fmpz_sgn(h) > 0)) /* signs are the same */ fmpz_set_si(f, -1L); /* quotient is negative, round down to minus one */ else fmpz_zero(f); } } else /* g is large */ { __mpz_struct *mpz_ptr = _fmpz_promote(f); if (!COEFF_IS_MPZ(c2)) /* h is small */ { if (c2 > 0) /* h > 0 */ { mpz_fdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), c2); } else { mpz_cdiv_q_ui(mpz_ptr, COEFF_TO_PTR(c1), -c2); mpz_neg(mpz_ptr, mpz_ptr); } } else /* both are large */ { mpz_fdiv_q(mpz_ptr, COEFF_TO_PTR(c1), COEFF_TO_PTR(c2)); } _fmpz_demote_val(f); /* division by h may result in small value */ } }
void C_BigInt::divideInPlace (const uint32_t inDivisor, uint32_t & outRemainder) { mpz_t quotient ; mpz_init (quotient) ; if (mpz_sgn (mGMPint) >= 0) { outRemainder = (uint32_t) mpz_fdiv_q_ui (quotient, mGMPint, inDivisor) ; }else{ outRemainder = (uint32_t) mpz_cdiv_q_ui (quotient, mGMPint, inDivisor) ; } mpz_swap (quotient, mGMPint) ; mpz_clear (quotient) ; }
static char generator_rule_PAIR(Generator *gen) { GeneratorState *state = gen->tip; unsigned long val; /* * PAIR ::= basic TYPE */ val = mpz_fdiv_q_ui(state->seed, state->seed, _GENERATOR_BASIC_N); state->rule = GENERATOR_RULE_TYPE; return generator_map_basic(val); }
static PyObject * GMPy_MPZ_IFloorDiv_Slot(PyObject *self, PyObject *other) { MPZ_Object *rz; if (!(rz = GMPy_MPZ_New(NULL))) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(MPZ(other)) == 0) { ZERO_ERROR("mpz division by zero"); return NULL; } mpz_fdiv_q(rz->z, MPZ(self), MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if (!error) { if (temp == 0) { ZERO_ERROR("mpz division by zero"); return NULL; } else if(temp > 0) { mpz_fdiv_q_ui(rz->z, MPZ(self), temp); } else { mpz_cdiv_q_ui(rz->z, MPZ(self), -temp); mpz_neg(rz->z, rz->z); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_fdiv_q(rz->z, MPZ(self), tempz); mpz_cloc(tempz); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; }
void SchurRing::dimension(const int *exp, mpz_t result) const // exp: 0..nvars_ // Return in 'result' the dimension of the irreducible // GL(nvars_) representation having highest weight // 'exp' { int i,j; mpz_set_ui(result, 1); for (i=1; i<nvars_; i++) for (j=i+1; j<=nvars_; j++) if (exp[i] != exp[j]) mpz_mul_ui(result, result, exp[i] - exp[j] + j - i); for (i=1; i<nvars_; i++) for (j=i+1; j<=nvars_; j++) if (exp[i] != exp[j]) mpz_fdiv_q_ui(result, result, j - i); }
static PyObject * Pyxmpz_inplace_floordiv(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_q(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } else if(temp_si > 0) { mpz_fdiv_q_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { mpz_cdiv_q_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); mpz_neg(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a)); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pyxmpz_AS_MPZ(b)) == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } mpz_fdiv_q(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; }
void calcterm2(int n,mpz_t r) { mpz_t z; calcterm(n,r); mpz_init(z); if(n&1) { mpz_ui_pow_ui(z,2,n/2); mpz_add(r,r,z); } else { mpz_ui_pow_ui(z,2,n/2-1); mpz_add(r,r,z); if(n>=4) { mpz_ui_pow_ui(z,2,n/2-2); mpz_add(r,r,z); } mpz_set_ui(z,0); calcterm(n/2,z); mpz_fdiv_q_ui(z,z,2); mpz_sub(r,r,z); } mpz_clear(z); }
/* * fun introot n = * if n = 0 * then 0 * else increase (2 * introot (n div 4), n) */ void introot (mpz_t r, const mpz_t n) { unsigned long int i = 0; unsigned long int size = mpz_sizeinbase (n, 4); mpz_t *stack = malloc (size * sizeof (mpz_t)); mpz_set (r, n); for (i = 1; i <= size; i++) { mpz_init_set (*(stack + size - i), r); mpz_fdiv_q_ui (r, r, 4); } for (i = 0; i < size; i++) { mpz_mul_ui (r, r, 2); increase (r, *(stack + i)); mpz_clear (*(stack + i)); } free (stack); }
/* * === FUNCTION ====================================================================== * Name: convertToChar * Description: * ===================================================================================== */ char *convertToChar(mpz_t *arr, int arr_size, int block_size, int *ret_size) { char *result; int res_size = arr_size * block_size + 1, i, j; result = (char *) malloc (sizeof(char) * res_size); mpz_t tmp; mpz_init(tmp); for (i=0; i<arr_size; i++) { mpz_set(tmp, arr[i]); for (j=0; j<block_size; j++) { result[block_size - 1 - j + i *block_size] = (char) mpz_fdiv_ui(tmp, NB_CHAR); mpz_fdiv_q_ui(tmp, tmp, NB_CHAR); } } *ret_size = res_size; result[res_size - 1] = '\0'; return result; } /* ----- end of function convertToChar ----- */
static PyObject * GMPy_XMPZ_IFloorDiv_Slot(PyObject *self, PyObject *other) { if (PyIntOrLong_Check(other)) { int error; native_si temp = GMPy_Integer_AsNative_siAndError(other, &error); if (!error) { if (temp == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } else if(temp > 0) { mpz_fdiv_q_ui(MPZ(self), MPZ(self), temp); } else { mpz_cdiv_q_ui(MPZ(self), MPZ(self), -temp); mpz_neg(MPZ(self), MPZ(self)); } } else { mpz_set_PyIntOrLong(global.tempz, other); mpz_fdiv_q(MPZ(self), MPZ(self), global.tempz); } Py_INCREF(self); return self; } if (CHECK_MPZANY(other)) { if (mpz_sgn(MPZ(other)) == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } mpz_fdiv_q(MPZ(self), MPZ(self), MPZ(other)); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; }
/* Test all bin(n,k) cases, with 0 <= k <= n + 1 <= count. */ void bin_smallexaustive (unsigned int count) { mpz_t want; unsigned long n, k; mpz_init (want); for (n = 0; n < count; n++) { mpz_set_ui (want, 1); for (k = 0; k <= n; k++) { try_mpz_bin_uiui (want, n, k); mpz_mul_ui (want, want, n - k); mpz_fdiv_q_ui (want, want, k + 1); } try_mpz_bin_uiui (want, n, k); } mpz_clear (want); }
int main( void ) { unsigned int a, b; unsigned long long sum, max; max = 0; mpz_t num, curr, digit; mpz_init(num); mpz_init(curr); mpz_init(digit); for( a = 1; a < 100; a++ ) { for( b = 2; b < 100; b++ ) { mpz_ui_pow_ui(num, a, b); mpz_set( curr, num ); sum = 0; while( mpz_sgn(curr) ) { sum += mpz_mod_ui(digit, curr, 10); mpz_fdiv_q_ui(curr, curr, 10); } max = ( sum > max ) ? sum : max; } } printf("Answer: %llu\n", max); mpz_clear(digit); mpz_clear(num); mpz_clear(curr); return 0; }
static char generator_rule_TUPLE(Generator *gen) { GeneratorState *next, *state = gen->tip; unsigned long val; /* * TUPLE ::= TYPE | TYPE TUPLE */ val = mpz_fdiv_q_ui(state->seed, state->seed, 2); switch (val) { case 0: state->rule = GENERATOR_RULE_TYPE; return generator_rule_TYPE(gen); case 1: next = generator_push(gen); next->rule = GENERATOR_RULE_TYPE; generator_inverse_pi(gen, state->seed, next->seed, state->seed); return generator_rule_TYPE(gen); default: assert(0); return 0; } }
int main(long argc, char *argv[]) { if(argc != 4) { printf("three arguments required\n"); exit(1); } mpz_t n, buffer1, buffer2; mpz_init(n); mpz_init(buffer1); mpz_init(buffer2); mpz_ui_pow_ui(n, atol(argv[2]), atol(argv[3])); mpz_mul_ui(n, n, atol(argv[1])); uint64_t crn = lpow(n, 1, 3); uint64_t srn = lpow(n, 1, 2); uint64_t ttrn = lpow(n, 2, 3); uint64_t start_block = 1; uint64_t finish_block = ttrn/crn; size_t psize = (size_t)(((1.26*crn)/log(crn) + 1) * sizeof(uint64_t)); uint64_t* primes = (uint64_t*)malloc(psize); assert(primes!=NULL); uint64_t pi_crn = sieve(crn, primes); int8_t* mu = malloc(sizeof(int8_t) * (crn+1)); //mu will run from 1 to crn with s[0] not used assert(mu != NULL); memset(mu, 1, sizeof(int8_t) * (crn+1)); uint64_t* lpf = malloc(sizeof(uint64_t) * (crn+1)); //lpf will run from 1 to crn with s[0] not used assert(lpf != NULL); memset(lpf, 0, sizeof(uint64_t) * (crn+1)); uint64_t i, j; for(i=1; i<=pi_crn; i++) for(j=primes[i]; j<=crn; j+=primes[i]) { mu[j] = -mu[j]; if(lpf[j] == 0) lpf[j] = primes[i]; } for(i=1; i<=pi_crn; i++) for(j=sqr(primes[i]); j<=crn; j+=sqr(primes[i])) mu[j]=0; //remove numbers that are not squarefree uint64_t blocksize = crn; uint64_t num_blocks = ttrn/blocksize; assert(start_block <= finish_block); assert(finish_block <= num_blocks); mpz_t S2_result; mpz_init(S2_result); uint64_t* s = malloc((crn/64+2)*sizeof(uint64_t)); assert(s != NULL); uint64_t* phi = malloc((pi_crn+1)*sizeof(uint64_t)); memset(phi, 0, (pi_crn+1)*sizeof(uint64_t)); uint64_t p, f, m, k, start, q, block_id, first_m, last_m, L, U, first_f; for(block_id = start_block; block_id <= finish_block; block_id++) { memset(s, ~0, sizeof(uint64_t) * (crn/64+2)); L = (block_id -1)*blocksize + 1; U = L + blocksize; for(i=1; i<=pi_crn; i++) { p = primes[i]; mpz_fdiv_q_ui(buffer1, n, L*p); mpz_fdiv_q_ui(buffer2, n, U*p); first_m = mpz_get_ui(buffer1); last_m = mpz_get_ui(buffer2); if(first_m > crn) first_m = crn; if(last_m > first_m) last_m = first_m; if(p > first_m) break; start = L; for(m = first_m; m > last_m && p*m > crn ; m--) { if(mu[m] != 0 && p < lpf[m] && p*m > crn && m <= crn) { mpz_fdiv_q_ui(buffer1, n, p*m); q = mpz_get_ui(buffer1); assert(q>=L); assert(q<=U); phi[i] += count_bits(s, start - L, q - L); start = q+1; if(mu[m] > 0) mpz_sub_ui(S2_result, S2_result, mu[m] * phi[i]); else mpz_add_ui(S2_result, S2_result, -mu[m] * phi[i]); } } phi[i] += count_bits(s, start - L, U -1 - L); sieve_step(start, U, phi,s, L, p); } } uint64_t short_block_length = ttrn % blocksize; if(short_block_length>0) { //short block L = L + blocksize; U = L + short_block_length; memset(s, ~0, sizeof(uint64_t) * (crn/64+2)); for(i=1; i<=pi_crn; i++) { start = L; p = primes[i]; mpz_fdiv_q_ui(buffer1, n, L*p); mpz_fdiv_q_ui(buffer2, n, U*p); first_m = mpz_get_ui(buffer1); last_m = mpz_get_ui(buffer2); if(first_m > crn) first_m = crn; if(last_m > first_m) last_m = first_m; if(p > first_m) break; for(m=first_m; m>last_m && p*m>crn ; m--) { if(mu[m]!=0 && p<lpf[m] && p*m>crn && m<=crn) { mpz_fdiv_q_ui(buffer1, n, p*m); q = mpz_get_ui(buffer1); assert(q>=L); assert(q<=U); phi[i] += count_bits(s, start - L, q - L); start = q+1; if(mu[m] > 0) mpz_sub_ui(S2_result, S2_result, mu[m]*phi[i]); else mpz_add_ui(S2_result, S2_result, -mu[m]*phi[i]); } } sieve_step(start, U, phi,s, L, p); } } mpz_out_str (stdout, 10, S2_result); printf("\n"); mpz_clears(buffer1, buffer2, n, S2_result, NULL); free(s); free(phi); free(primes); free(mu); free(lpf); return(0); }
/*------------------------------------------------------------------------*/ static void search_coeffs(msieve_obj *obj, poly_search_t *poly, bounds_t *bounds, uint32 deadline) { mpz_t curr_high_coeff; double dn = mpz_get_d(poly->N); uint32 digits = mpz_sizeinbase(poly->N, 10); double start_time = get_cpu_time(); uint32 deadline_per_coeff = 800; uint32 batch_size = (poly->degree == 5) ? POLY_BATCH_SIZE : 1; if (digits <= 100) deadline_per_coeff = 5; else if (digits <= 105) deadline_per_coeff = 20; else if (digits <= 110) deadline_per_coeff = 30; else if (digits <= 120) deadline_per_coeff = 50; else if (digits <= 130) deadline_per_coeff = 100; else if (digits <= 140) deadline_per_coeff = 200; else if (digits <= 150) deadline_per_coeff = 400; printf("deadline: %u seconds per coefficient\n", deadline_per_coeff); mpz_init(curr_high_coeff); mpz_fdiv_q_ui(curr_high_coeff, bounds->gmp_high_coeff_begin, (mp_limb_t)MULTIPLIER); mpz_mul_ui(curr_high_coeff, curr_high_coeff, (mp_limb_t)MULTIPLIER); if (mpz_cmp(curr_high_coeff, bounds->gmp_high_coeff_begin) < 0) { mpz_add_ui(curr_high_coeff, curr_high_coeff, (mp_limb_t)MULTIPLIER); } poly->num_poly = 0; while (1) { curr_poly_t *c = poly->batch + poly->num_poly; if (mpz_cmp(curr_high_coeff, bounds->gmp_high_coeff_end) > 0) { if (poly->num_poly > 0) { search_coeffs_core(obj, poly, deadline_per_coeff); } break; } stage1_bounds_update(bounds, dn, mpz_get_d(curr_high_coeff), poly->degree); mpz_set(c->high_coeff, curr_high_coeff); c->p_size_max = bounds->p_size_max; c->coeff_max = bounds->coeff_max; if (++poly->num_poly == batch_size) { search_coeffs_core(obj, poly, deadline_per_coeff); if (obj->flags & MSIEVE_FLAG_STOP_SIEVING) break; if (deadline) { double curr_time = get_cpu_time(); double elapsed = curr_time - start_time; if (elapsed > deadline) break; } poly->num_poly = 0; } mpz_add_ui(curr_high_coeff, curr_high_coeff, (mp_limb_t)MULTIPLIER); } mpz_clear(curr_high_coeff); }
/*------------------------------------------------------------------------*/ static void search_coeffs(msieve_obj *obj, poly_search_t *poly, uint32 deadline) { uint32 digits = mpz_sizeinbase(poly->N, 10); double deadline_per_coeff; double cumulative_time = 0; sieve_t ad_sieve; poly_coeff_t *c = poly_coeff_init(); #ifdef HAVE_CUDA void *gpu_data = gpu_data_init(obj, poly); #endif /* determine the CPU time limit; I have no idea if the following is appropriate */ if (digits <= 100) deadline_per_coeff = 5; else if (digits <= 105) deadline_per_coeff = 20; else if (digits <= 110) deadline_per_coeff = 30; else if (digits <= 120) deadline_per_coeff = 50; else if (digits <= 130) deadline_per_coeff = 100; else if (digits <= 140) deadline_per_coeff = 200; else if (digits <= 150) deadline_per_coeff = 400; else if (digits <= 175) deadline_per_coeff = 800; else if (digits <= 200) deadline_per_coeff = 1600; else deadline_per_coeff = 3200; printf("deadline: %.0lf CPU-seconds per coefficient\n", deadline_per_coeff); /* set up lower limit on a_d */ mpz_sub_ui(poly->tmp1, poly->gmp_high_coeff_begin, 1); mpz_fdiv_q_ui(poly->tmp1, poly->tmp1, HIGH_COEFF_MULTIPLIER); mpz_add_ui(poly->tmp1, poly->tmp1, 1); mpz_mul_ui(poly->gmp_high_coeff_begin, poly->tmp1, HIGH_COEFF_MULTIPLIER); init_ad_sieve(&ad_sieve, poly); while (1) { double elapsed; /* we only use a_d which are composed of many small prime factors, in order to have lots of projective roots going into stage 2 */ if (find_next_ad(&ad_sieve, poly, c->high_coeff)) break; /* recalculate internal parameters used for search */ stage1_bounds_update(poly, c); /* finally, sieve for polynomials using Kleinjung's improved algorithm */ #ifdef HAVE_CUDA cumulative_time = sieve_lattice_gpu(obj, poly, c, gpu_data, deadline_per_coeff); #else elapsed = sieve_lattice_cpu(obj, poly, c, deadline_per_coeff); cumulative_time += elapsed; #endif if (obj->flags & MSIEVE_FLAG_STOP_SIEVING) break; if (deadline && cumulative_time > deadline) break; } free_ad_sieve(&ad_sieve); #ifdef HAVE_CUDA gpu_data_free(gpu_data); #endif poly_coeff_free(c); }
static int generator_rule_TYPE(Generator *gen) { GeneratorState *next, *state = gen->tip; unsigned long val; int res; /* * TYPE ::= basic * | 'v' * | '(' ')' * | 'm' TYPE * | 'a' TYPE * | '(' TUPLE ')' * | '{' PAIR '}' */ res = mpz_cmp_ui(state->seed, _GENERATOR_BASIC_N + 2); if (res < 0) { /* * TYPE ::= basic | 'v' | '(' ')' */ val = mpz_get_ui(state->seed); switch (val) { case _GENERATOR_BASIC_N + 0: /* * TYPE ::= 'v' */ generator_pop(gen); return 'v'; case _GENERATOR_BASIC_N + 1: /* * TYPE ::= '(' ')' */ state->rule = GENERATOR_RULE_TUPLE_CLOSE; return '('; default: /* * TYPE ::= basic */ generator_pop(gen); return generator_map_basic(val); } } else { /* * TYPE ::= 'm' TYPE | 'a' TYPE | '(' TUPLE ')' | '{' PAIR '}' */ mpz_sub_ui(state->seed, state->seed, _GENERATOR_BASIC_N + 2); val = mpz_fdiv_q_ui(state->seed, state->seed, _GENERATOR_COMPOUND_N); switch (val) { case GENERATOR_COMPOUND_m: /* * TYPE ::= 'm' TYPE */ state->rule = GENERATOR_RULE_TYPE; return 'm'; case GENERATOR_COMPOUND_a: /* * TYPE ::= 'a' TYPE */ state->rule = GENERATOR_RULE_TYPE; return 'a'; case GENERATOR_COMPOUND_r: /* * TYPE ::= '(' TUPLE ')' */ state->rule = GENERATOR_RULE_TUPLE_CLOSE; next = generator_push(gen); next->rule = GENERATOR_RULE_TUPLE; mpz_set(next->seed, state->seed); return '('; case GENERATOR_COMPOUND_e: /* * TYPE ::= '{' PAIR '}' */ state->rule = GENERATOR_RULE_PAIR_CLOSE; next = generator_push(gen); next->rule = GENERATOR_RULE_PAIR; mpz_set(next->seed, state->seed); return '{'; default: assert(0); return 0; } } }
static PyObject * GMPy_Integer_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result; if (!(result = GMPy_MPZ_New(context))) return NULL; if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { int error; native_si temp = GMPy_Integer_AsNative_siAndError(y, &error); if (!error) { if (temp > 0) { mpz_fdiv_q_ui(result->z, MPZ(x), temp); } else if (temp == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } else { mpz_cdiv_q_ui(result->z, MPZ(x), -temp); mpz_neg(result->z, result->z); } } else { mpz_set_PyIntOrLong(global.tempz, y); mpz_fdiv_q(result->z, MPZ(x), global.tempz); } return (PyObject*)result; } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_q(result->z, MPZ(x), MPZ(y)); return (PyObject*)result; } } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } if (PyIntOrLong_Check(x)) { mpz_set_PyIntOrLong(global.tempz, x); mpz_fdiv_q(result->z, global.tempz, MPZ(y)); return (PyObject*)result; } } if (IS_INTEGER(x) && IS_INTEGER(y)) { MPZ_Object *tempx, *tempy; tempx = GMPy_MPZ_From_Integer(x, context); tempy = GMPy_MPZ_From_Integer(y, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("division or modulo by zero"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_q(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; }
int main(int cnt, char** v) { if (cnt > 1) { mpz_t max, pmax, qmax, p, q, max_tmp, ans, gcd, tmp, a, b, c, k; mpz_inits(max, pmax, qmax, '\0'); mpz_inits(p, q, max_tmp, '\0'); mpz_inits(ans, gcd, tmp, '\0'); mpz_inits(a, b, c, k, '\0'); mpz_set_str(max, v[1], 10); mpz_root(qmax, max, 4); mpz_fdiv_q_ui(max_tmp, max, 4); mpz_root(pmax, max_tmp, 4); mpz_set_str(p, "1", 10); while (mpz_cmp(p, pmax) <= 0) { mpz_set(q, p); while (mpz_cmp(q, qmax) <= 0) { mpz_gcd(gcd, p, q); if (mpz_cmp_ui(gcd, 1) == 0) { // int g = mpz_get_ui(gcd); // if(g==1){ // uint64_t k=max/q/q/(p+q)/(p+q); // uint64_t a=p*p*(p+q)*(p+q); // uint64_t b=q*q*(p+q)*(p+q); // uint64_t c=p*p*q*q; mpz_set_str(tmp, "0", 10); mpz_set_str(max_tmp, "0", 10); //mpz_set_str(k,"1",10); mpz_set_str(a, "1", 10); mpz_set_str(b, "1", 10); mpz_set_str(c, "1", 10); mpz_add(max_tmp, p, q); mpz_fdiv_q(k, max, q); mpz_fdiv_q(k, k, q); mpz_fdiv_q(k, k, max_tmp); mpz_fdiv_q(k, k, max_tmp); mpz_mul(a, p, p); mpz_mul(a, a, max_tmp); mpz_mul(a, a, max_tmp); mpz_mul(b, q, q); mpz_mul(b, b, max_tmp); mpz_mul(b, b, max_tmp); mpz_mul(c, p, p); mpz_mul(c, c, q); mpz_mul(c, c, q); mpz_add(tmp, tmp, a); mpz_add(tmp, tmp, b); mpz_add(tmp, tmp, c); mpz_mul(tmp, tmp, k); mpz_add_ui(k, k, 1); mpz_mul(tmp, tmp, k); mpz_fdiv_q_ui(tmp, tmp, 2); mpz_add(ans, ans, tmp); // } } mpz_add_ui(q, q, 1); } mpz_add_ui(p, p, 1); } gmp_printf("%Zd\n", ans); mpz_clears(max, pmax, qmax, '\0'); mpz_clears(p, q, max_tmp,'\0'); mpz_clears(ans, gcd, tmp, '\0'); mpz_clears(a, b, c, k, '\0'); } }
/* f <- 1 - r/2! + r^2/4! + ... + (-1)^l r^l/(2l)! + ... Assumes |r| < 1/2, and f, r have the same precision. Returns e such that the error on f is bounded by 2^e ulps. */ static int mpfr_cos2_aux (mpfr_ptr f, mpfr_srcptr r) { mpz_t x, t, s; mpfr_exp_t ex, l, m; mpfr_prec_t p, q; unsigned long i, maxi, imax; MPFR_ASSERTD(mpfr_get_exp (r) <= -1); /* compute minimal i such that i*(i+1) does not fit in an unsigned long, assuming that there are no padding bits. */ maxi = 1UL << (CHAR_BIT * sizeof(unsigned long) / 2); if (maxi * (maxi / 2) == 0) /* test checked at compile time */ { /* can occur only when there are padding bits. */ /* maxi * (maxi-1) is representable iff maxi * (maxi / 2) != 0 */ do maxi /= 2; while (maxi * (maxi / 2) == 0); } mpz_init (x); mpz_init (s); mpz_init (t); ex = mpfr_get_z_2exp (x, r); /* r = x*2^ex */ /* remove trailing zeroes */ l = mpz_scan1 (x, 0); ex += l; mpz_fdiv_q_2exp (x, x, l); /* since |r| < 1, r = x*2^ex, and x is an integer, necessarily ex < 0 */ p = mpfr_get_prec (f); /* same than r */ /* bound for number of iterations */ imax = p / (-mpfr_get_exp (r)); imax += (imax == 0); q = 2 * MPFR_INT_CEIL_LOG2(imax) + 4; /* bound for (3l)^2 */ mpz_set_ui (s, 1); /* initialize sum with 1 */ mpz_mul_2exp (s, s, p + q); /* scale all values by 2^(p+q) */ mpz_set (t, s); /* invariant: t is previous term */ for (i = 1; (m = mpz_sizeinbase (t, 2)) >= q; i += 2) { /* adjust precision of x to that of t */ l = mpz_sizeinbase (x, 2); if (l > m) { l -= m; mpz_fdiv_q_2exp (x, x, l); ex += l; } /* multiply t by r */ mpz_mul (t, t, x); mpz_fdiv_q_2exp (t, t, -ex); /* divide t by i*(i+1) */ if (i < maxi) mpz_fdiv_q_ui (t, t, i * (i + 1)); else { mpz_fdiv_q_ui (t, t, i); mpz_fdiv_q_ui (t, t, i + 1); } /* if m is the (current) number of bits of t, we can consider that all operations on t so far had precision >= m, so we can prove by induction that the relative error on t is of the form (1+u)^(3l)-1, where |u| <= 2^(-m), and l=(i+1)/2 is the # of loops. Since |(1+x^2)^(1/x) - 1| <= 4x/3 for |x| <= 1/2, for |u| <= 1/(3l)^2, the absolute error is bounded by 4/3*(3l)*2^(-m)*t <= 4*l since |t| < 2^m. Therefore the error on s is bounded by 2*l*(l+1). */ /* add or subtract to s */ if (i % 4 == 1) mpz_sub (s, s, t); else mpz_add (s, s, t); } mpfr_set_z (f, s, MPFR_RNDN); mpfr_div_2ui (f, f, p + q, MPFR_RNDN); mpz_clear (x); mpz_clear (s); mpz_clear (t); l = (i - 1) / 2; /* number of iterations */ return 2 * MPFR_INT_CEIL_LOG2 (l + 1) + 1; /* bound is 2l(l+1) */ }
static PyObject * GMPy_MPZ_is_aprcl_prime(PyObject *self, PyObject *other) { mpz_t N; s64_t T, U; int i, j, H, I, J, K, P, Q, W, X; int IV, InvX, LEVELnow, NP, PK, PL, PM, SW, VK, TestedQs, TestingQs; int QQ, T1, T3, U1, U3, V1, V3; int break_this = 0; MPZ_Object *tempx; if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("is_aprcl_prime() requires 'mpz' argument"); return NULL; } mpz_init(N); mpz_set(N, tempx->z); Py_DECREF(tempx); /* make sure the input is >= 2 and odd */ if (mpz_cmp_ui(N, 2) < 0) Py_RETURN_FALSE; if (mpz_divisible_ui_p(N, 2)) { if (mpz_cmp_ui(N, 2) == 0) Py_RETURN_TRUE; else Py_RETURN_FALSE; } /* only three small exceptions for this implementation */ /* with this set of P and Q primes */ if (mpz_cmp_ui(N, 3) == 0) Py_RETURN_TRUE; if (mpz_cmp_ui(N, 7) == 0) Py_RETURN_TRUE; if (mpz_cmp_ui(N, 11) == 0) Py_RETURN_TRUE; /* If the input number is larger than 7000 decimal digits we will just return whether it is a BPSW (probable) prime */ NumberLength = mpz_sizeinbase(N, 10); if (NumberLength > 7000) { VALUE_ERROR("value too large to test"); return NULL; } allocate_vars(); mpz_set(TestNbr, N); mpz_set_si(biS, 0); j = PK = PL = PM = 0; for (J = 0; J < PWmax; J++) { /* aiJX[J] = 0; */ mpz_set_ui(aiJX[J], 0); } break_this = 0; /* GetPrimes2Test : */ for (i = 0; i < LEVELmax; i++) { /* biS[0] = 2; */ mpz_set_ui(biS, 2); for (j = 0; j < aiNQ[i]; j++) { Q = aiQ[j]; if (aiT[i]%(Q-1) != 0) continue; U = aiT[i] * Q; do { U /= Q; /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); } while (U % Q == 0); // Exit loop if S^2 > N. if (CompareSquare(biS, TestNbr) > 0) { /* break GetPrimes2Test; */ break_this = 1; break; } } /* End for j */ if (break_this) break; } /* End for i */ if (i == LEVELmax) { /* too big */ free_vars(); VALUE_ERROR("value too large to test"); return NULL; } LEVELnow = i; TestingQs = j; T = aiT[LEVELnow]; NP = aiNP[LEVELnow]; MainStart: for (;;) { for (i = 0; i < NP; i++) { P = aiP[i]; if (T%P != 0) continue; SW = TestedQs = 0; /* Q = W = (int) BigNbrModLong(TestNbr, P * P); */ Q = W = mpz_fdiv_ui(TestNbr, P * P); for (J = P - 2; J > 0; J--) { W = (W * Q) % (P * P); } if (P > 2 && W != 1) { SW = 1; } for (;;) { for (j = TestedQs; j <= TestingQs; j++) { Q = aiQ[j] - 1; /* G = aiG[j]; */ K = 0; while (Q % P == 0) { K++; Q /= P; } Q = aiQ[j]; if (K == 0) { continue; } PM = 1; for (I = 1; I < K; I++) { PM = PM * P; } PL = (P - 1) * PM; PK = P * PM; for (I = 0; I < PK; I++) { /* aiJ0[I] = aiJ1[I] = 0; */ mpz_set_ui(aiJ0[I], 0); mpz_set_ui(aiJ1[I], 0); } if (P > 2) { JacobiSum(0, P, PL, Q); } else { if (K != 1) { JacobiSum(0, P, PL, Q); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } if (K != 2) { for (I = 0; I < PM; I++) { /* aiJW[I] = aiJ0[I]; */ mpz_set(aiJW[I], aiJ0[I]); } JacobiSum(1, P, PL, Q); for (I = 0; I < PM; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } JS_JW(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ1[I] = aiJS[I]; */ mpz_set(aiJ1[I], aiJS[I]); } JacobiSum(2, P, PL, Q); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } for (I = 0; I < PM; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } JS_2(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ2[I] = aiJS[I]; */ mpz_set(aiJ2[I], aiJS[I]); } } } } /* aiJ00[0] = aiJ01[0] = 1; */ mpz_set_ui(aiJ00[0], 1); mpz_set_ui(aiJ01[0], 1); for (I = 1; I < PK; I++) { /* aiJ00[I] = aiJ01[I] = 0; */ mpz_set_ui(aiJ00[I], 0); mpz_set_ui(aiJ01[I], 0); } /* VK = (int) BigNbrModLong(TestNbr, PK); */ VK = mpz_fdiv_ui(TestNbr, PK); for (I = 1; I < PK; I++) { if (I % P != 0) { U1 = 1; U3 = I; V1 = 0; V3 = PK; while (V3 != 0) { QQ = U3 / V3; T1 = U1 - V1 * QQ; T3 = U3 - V3 * QQ; U1 = V1; U3 = V3; V1 = T1; V3 = T3; } aiInv[I] = (U1 + PK) % PK; } else { aiInv[I] = 0; } } if (P != 2) { for (IV = 0; IV <= 1; IV++) { for (X = 1; X < PK; X++) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ0[I]; */ mpz_set(aiJS[I], aiJ0[I]); } if (X % P == 0) { continue; } if (IV == 0) { /* LongToBigNbr(X, biExp, NumberLength); */ mpz_set_ui(biExp, X); } else { /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */ mpz_set_ui(biExp, (VK * X) / PK); if ((VK * X) / PK == 0) { continue; } } JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } InvX = aiInv[X]; for (I = 0; I < PK; I++) { J = (I * InvX) % PK; /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */ mpz_add(aiJW[J], aiJW[J], aiJS[I]); } NormalizeJW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } } else { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJS[I], aiJ01[I]); } } JS_JW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJ00[I] = aiJS[I]; */ mpz_set(aiJ00[I], aiJS[I]); } } else { for (I = 0; I < PK; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } } /* end for X */ } /* end for IV */ } else { if (K == 1) { /* MultBigNbrByLongModN(1, Q, aiJ00[0], TestNbr, NumberLength); */ mpz_set_ui(aiJ00[0], Q); /* aiJ01[0] = 1; */ mpz_set_ui(aiJ01[0], 1); } else { if (K == 2) { if (VK == 1) { /* aiJ01[0] = 1; */ mpz_set_ui(aiJ01[0], 1); } /* aiJS[0] = aiJ0[0]; */ /* aiJS[1] = aiJ0[1]; */ mpz_set(aiJS[0], aiJ0[0]); mpz_set(aiJS[1], aiJ0[1]); JS_2(PK, PL, PM, P); if (VK == 3) { /* aiJ01[0] = aiJS[0]; */ /* aiJ01[1] = aiJS[1]; */ mpz_set(aiJ01[0], aiJS[0]); mpz_set(aiJ01[1], aiJS[1]); } /* MultBigNbrByLongModN(aiJS[0], Q, aiJ00[0], TestNbr, NumberLength); */ mpz_mul_ui(aiJ00[0], aiJS[0], Q); /* MultBigNbrByLongModN(aiJS[1], Q, aiJ00[1], TestNbr, NumberLength); */ mpz_mul_ui(aiJ00[1], aiJS[1], Q); } else { for (IV = 0; IV <= 1; IV++) { for (X = 1; X < PK; X += 2) { for (I = 0; I <= PM; I++) { /* aiJS[I] = aiJ1[I]; */ mpz_set(aiJS[I], aiJ1[I]); } if (X % 8 == 5 || X % 8 == 7) { continue; } if (IV == 0) { /* LongToBigNbr(X, biExp, NumberLength); */ mpz_set_ui(biExp, X); } else { /* LongToBigNbr(VK * X / PK, biExp, NumberLength); */ mpz_set_ui(biExp, VK * X / PK); if (VK * X / PK == 0) { continue; } } JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } InvX = aiInv[X]; for (I = 0; I < PK; I++) { J = I * InvX % PK; /* AddBigNbrModN(aiJW[J], aiJS[I], aiJW[J], TestNbr, NumberLength); */ mpz_add(aiJW[J], aiJW[J], aiJS[I]); } NormalizeJW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } } else { for (I = 0; I < PK; I++) { /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJS[I], aiJ01[I]); } } NormalizeJS(PK, PL, PM, P); JS_JW(PK, PL, PM, P); if (IV == 0) { for (I = 0; I < PK; I++) { /* aiJ00[I] = aiJS[I]; */ mpz_set(aiJ00[I], aiJS[I]); } } else { for (I = 0; I < PK; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } } /* end for X */ if (IV == 0 || VK % 8 == 1 || VK % 8 == 3) { continue; } for (I = 0; I < PM; I++) { /* aiJW[I] = aiJ2[I]; */ /* aiJS[I] = aiJ01[I]; */ mpz_set(aiJW[I], aiJ2[I]); mpz_set(aiJS[I], aiJ01[I]); } for (; I < PK; I++) { /* aiJW[I] = aiJS[I] = 0; */ mpz_set_ui(aiJW[I], 0); mpz_set_ui(aiJS[I], 0); } JS_JW(PK, PL, PM, P); for (I = 0; I < PM; I++) { /* aiJ01[I] = aiJS[I]; */ mpz_set(aiJ01[I], aiJS[I]); } } /* end for IV */ } } } for (I = 0; I < PL; I++) { /* aiJS[I] = aiJ00[I]; */ mpz_set(aiJS[I], aiJ00[I]); } for (; I < PK; I++) { /* aiJS[I] = 0; */ mpz_set_ui(aiJS[I], 0); } /* DivBigNbrByLong(TestNbr, PK, biExp, NumberLength); */ mpz_fdiv_q_ui(biExp, TestNbr, PK); JS_E(PK, PL, PM, P); for (I = 0; I < PK; I++) { /* aiJW[I] = 0; */ mpz_set_ui(aiJW[I], 0); } for (I = 0; I < PL; I++) { for (J = 0; J < PL; J++) { /* MontgomeryMult(aiJS[I], aiJ01[J], biTmp); */ /* AddBigNbrModN(biTmp, aiJW[(I + J) % PK], aiJW[(I + J) % PK], TestNbr, NumberLength); */ mpz_mul(biTmp, aiJS[I], aiJ01[J]); mpz_add(aiJW[(I + J) % PK], biTmp, aiJW[(I + J) % PK]); } } NormalizeJW(PK, PL, PM, P); /* MatchingRoot : */ do { H = -1; W = 0; for (I = 0; I < PL; I++) { if (mpz_cmp_ui(aiJW[I], 0) != 0)/* (!BigNbrIsZero(aiJW[I])) */ { /* if (H == -1 && BigNbrAreEqual(aiJW[I], 1)) */ if (H == -1 && (mpz_cmp_ui(aiJW[I], 1) == 0)) { H = I; } else { H = -2; /* AddBigNbrModN(aiJW[I], MontgomeryMultR1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */ { W++; } } } } if (H >= 0) { /* break MatchingRoot; */ break; } if (W != P - 1) { /* Not prime */ free_vars(); Py_RETURN_FALSE; } for (I = 0; I < PM; I++) { /* AddBigNbrModN(aiJW[I], 1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) == 0) /* (BigNbrIsZero(biTmp)) */ { break; } } if (I == PM) { /* Not prime */ free_vars(); Py_RETURN_FALSE; } for (J = 1; J <= P - 2; J++) { /* AddBigNbrModN(aiJW[I + J * PM], 1, biTmp, TestNbr, NumberLength); */ mpz_add_ui(biTmp, aiJW[I + J * PM], 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */ { /* Not prime */ free_vars(); Py_RETURN_FALSE; } } H = I + PL; } while (0); if (SW == 1 || H % P == 0) { continue; } if (P != 2) { SW = 1; continue; } if (K == 1) { if ((mpz_get_ui(TestNbr) & 3) == 1) { SW = 1; } continue; } // if (Q^((N-1)/2) mod N != N-1), N is not prime. /* MultBigNbrByLongModN(1, Q, biTmp, TestNbr, NumberLength); */ mpz_set_ui(biTmp, Q); mpz_mod(biTmp, biTmp, TestNbr); mpz_sub_ui(biT, TestNbr, 1); /* biT = n-1 */ mpz_divexact_ui(biT, biT, 2); /* biT = (n-1)/2 */ mpz_powm(biR, biTmp, biT, TestNbr); /* biR = Q^((n-1)/2) mod n */ mpz_add_ui(biTmp, biR, 1); mpz_mod(biTmp, biTmp, TestNbr); if (mpz_cmp_ui(biTmp, 0) != 0)/* (!BigNbrIsZero(biTmp)) */ { /* Not prime */ free_vars(); Py_RETURN_FALSE; } SW = 1; } /* end for j */ if (SW == 0) { TestedQs = TestingQs + 1; if (TestingQs < aiNQ[LEVELnow] - 1) { TestingQs++; Q = aiQ[TestingQs]; U = T * Q; do { /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); U /= Q; } while (U % Q == 0); continue; /* Retry */ } LEVELnow++; if (LEVELnow == LEVELmax) { free_vars(); // return mpz_bpsw_prp(N); /* Cannot tell */ VALUE_ERROR("maximum levels reached"); return NULL; } T = aiT[LEVELnow]; NP = aiNP[LEVELnow]; /* biS = 2; */ mpz_set_ui(biS, 2); for (J = 0; J <= aiNQ[LEVELnow]; J++) { Q = aiQ[J]; if (T%(Q-1) != 0) continue; U = T * Q; do { /* MultBigNbrByLong(biS, Q, biS, NumberLength); */ mpz_mul_ui(biS, biS, Q); U /= Q; } while (U % Q == 0); if (CompareSquare(biS, TestNbr) > 0) { TestingQs = J; /* continue MainStart; */ /* Retry from the beginning */ goto MainStart; } } /* end for J */ free_vars(); VALUE_ERROR("internal failure"); return NULL; } /* end if */ break; } /* end for (;;) */ } /* end for i */ // Final Test /* biR = 1 */ mpz_set_ui(biR, 1); /* biN <- TestNbr mod biS */ /* Compute N mod S */ mpz_fdiv_r(biN, TestNbr, biS); for (U = 1; U <= T; U++) { /* biR <- (biN * biR) mod biS */ mpz_mul(biR, biN, biR); mpz_mod(biR, biR, biS); if (mpz_cmp_ui(biR, 1) == 0) /* biR == 1 */ { /* Number is prime */ free_vars(); Py_RETURN_TRUE; } if (mpz_divisible_p(TestNbr, biR) && mpz_cmp(biR, TestNbr) < 0) /* biR < N and biR | TestNbr */ { /* Number is composite */ free_vars(); Py_RETURN_FALSE; } } /* End for U */ /* This should never be reached. */ free_vars(); SYSTEM_ERROR("Internal error: APR-CL error with final test."); return NULL; } }
void C_BigInt::divideBy (const uint32_t inDivisor, C_BigInt & outQuotient, uint32_t & outRemainder) const { outRemainder = (uint32_t) mpz_fdiv_q_ui (outQuotient.mGMPint, mGMPint, inDivisor) ; }