static PyObject * GMPy_MPZ_c_div_2exp(PyObject *self, PyObject *args) { mp_bitcnt_t nbits; MPZ_Object *result, *tempx; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments"); return NULL; } nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == (mp_bitcnt_t)(-1) && PyErr_Occurred()) { return NULL; } tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); result = GMPy_MPZ_New(NULL); if (!tempx || !result) { Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)tempx); return NULL; } mpz_cdiv_q_2exp(result->z, tempx->z, nbits); Py_DECREF((PyObject*)tempx); return (PyObject*)result; }
/*-----------------------------------------------------------------------------*/ void node_red(tree_t tree) { if(mpz_tstbit(tree->M, 0)) { mpz_set(tree->M_red, tree->M); tree->shift = 0; } else { tree->shift = mpz_scan1(tree->M,0); mpz_cdiv_q_2exp(tree->M_red, tree->M, tree->shift); } }
void hex_random_bit_op (enum hex_random_op op, unsigned long maxbits, char **ap, unsigned long *b, char **rp) { mpz_t a, r; unsigned long abits, bbits; unsigned signs; mpz_init (a); mpz_init (r); abits = gmp_urandomb_ui (state, 32) % maxbits; bbits = gmp_urandomb_ui (state, 32) % (maxbits + 100); mpz_rrandomb (a, state, abits); signs = gmp_urandomb_ui (state, 1); if (signs & 1) mpz_neg (a, a); switch (op) { default: abort (); case OP_SETBIT: mpz_set (r, a); mpz_setbit (r, bbits); break; case OP_CLRBIT: mpz_set (r, a); mpz_clrbit (r, bbits); break; case OP_COMBIT: mpz_set (r, a); mpz_combit (r, bbits); break; case OP_CDIV_Q_2: mpz_cdiv_q_2exp (r, a, bbits); break; case OP_CDIV_R_2: mpz_cdiv_r_2exp (r, a, bbits); break; case OP_FDIV_Q_2: mpz_fdiv_q_2exp (r, a, bbits); break; case OP_FDIV_R_2: mpz_fdiv_r_2exp (r, a, bbits); break; case OP_TDIV_Q_2: mpz_tdiv_q_2exp (r, a, bbits); break; case OP_TDIV_R_2: mpz_tdiv_r_2exp (r, a, bbits); break; } gmp_asprintf (ap, "%Zx", a); *b = bbits; gmp_asprintf (rp, "%Zx", r); mpz_clear (a); mpz_clear (r); }
static PyObject * Pympz_mpmath_normalize(PyObject *self, PyObject *args) { long sign = 0; mpir_si bc = 0, prec = 0, shift, zbits, carry = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0; PympzObject *man = 0, *upper = 0, *lower = 0; char rnd = 0; if (PyTuple_GET_SIZE(args) == 6) { /* Need better error-checking here. Under Python 3.0, overflow into C-long is possible. */ sign = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); man = (PympzObject *)PyTuple_GET_ITEM(args, 1); exp = PyTuple_GET_ITEM(args, 2); bc = SI_From_Integer(PyTuple_GET_ITEM(args, 3)); prec = SI_From_Integer(PyTuple_GET_ITEM(args, 4)); rndstr = PyTuple_GET_ITEM(args, 5); if (PyErr_Occurred()) { TYPE_ERROR("arguments long, PympzObject*, PyObject*, long, long, char needed"); return NULL; } } else { TYPE_ERROR("6 arguments required"); return NULL; } if (!Pympz_Check(man)) { TYPE_ERROR("argument is not an mpz"); return NULL; } /* If rndstr really is a string, extract the first character. */ if (Py2or3String_Check(rndstr)) { rnd = Py2or3String_AsString(rndstr)[0]; } else { VALUE_ERROR("invalid rounding mode specified"); return NULL; } /* If the mantissa is 0, return the normalized representation. */ if (!mpz_sgn(man->z)) { Py_INCREF((PyObject*)man); return mpmath_build_mpf(0, man, 0, 0); } /* if bc <= prec and the number is odd return it */ if ((bc <= prec) && mpz_odd_p(man->z)) { Py_INCREF((PyObject*)man); Py_INCREF((PyObject*)exp); return mpmath_build_mpf(sign, man, exp, bc); } if (!(upper = (PympzObject*)Pympz_new()) || !(lower = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)upper); Py_XDECREF((PyObject*)lower); } shift = bc - prec; if (shift>0) { switch (rnd) { case 'f': if(sign) { mpz_cdiv_q_2exp(upper->z, man->z, shift); } else { mpz_fdiv_q_2exp(upper->z, man->z, shift); } break; case 'c': if(sign) { mpz_fdiv_q_2exp(upper->z, man->z, shift); } else { mpz_cdiv_q_2exp(upper->z, man->z, shift); } break; case 'd': mpz_fdiv_q_2exp(upper->z, man->z, shift); break; case 'u': mpz_cdiv_q_2exp(upper->z, man->z, shift); break; case 'n': default: mpz_tdiv_r_2exp(lower->z, man->z, shift); mpz_tdiv_q_2exp(upper->z, man->z, shift); if (mpz_sgn(lower->z)) { /* lower is not 0 so it must have at least 1 bit set */ if (mpz_sizeinbase(lower->z, 2) == shift) { /* lower is >= 1/2 */ if (mpz_scan1(lower->z, 0) == shift-1) { /* lower is exactly 1/2 */ if (mpz_odd_p(upper->z)) carry = 1; } else { carry = 1; } } } if (carry) mpz_add_ui(upper->z, upper->z, 1); } if (!(tmp = PyIntOrLong_FromSI(shift))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); return NULL; } if (!(newexp = PyNumber_Add(exp, tmp))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); return NULL; } Py_DECREF(tmp); bc = prec; } else { mpz_set(upper->z, man->z); newexp = exp; Py_INCREF(newexp); } /* Strip trailing 0 bits. */ if ((zbits = mpz_scan1(upper->z, 0))) mpz_tdiv_q_2exp(upper->z, upper->z, zbits); if (!(tmp = PyIntOrLong_FromSI(zbits))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(newexp); return NULL; } if (!(newexp2 = PyNumber_Add(newexp, tmp))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); Py_DECREF(newexp); return NULL; } Py_DECREF(newexp); Py_DECREF(tmp); bc -= zbits; /* Check if one less than a power of 2 was rounded up. */ if (!mpz_cmp_ui(upper->z, 1)) bc = 1; Py_DECREF((PyObject*)lower); return mpmath_build_mpf(sign, upper, newexp2, bc); }
static PyObject * Pympz_mpmath_create(PyObject *self, PyObject *args) { long sign; mpir_si bc, shift, zbits, carry = 0, prec = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0; PympzObject *man = 0, *upper = 0, *lower = 0; const char *rnd = "f"; if (PyTuple_GET_SIZE(args) < 2) { TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments"); return NULL; } switch (PyTuple_GET_SIZE(args)) { case 4: rnd = Py2or3String_AsString(PyTuple_GET_ITEM(args, 3)); case 3: prec = SI_From_Integer(PyTuple_GET_ITEM(args, 2)); if (prec == -1 && PyErr_Occurred()) return NULL; prec = ABS(prec); case 2: exp = PyTuple_GET_ITEM(args, 1); case 1: man = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); if (!man) { TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments"); return NULL; } } /* If the mantissa is 0, return the normalized representation. */ if (!mpz_sgn(man->z)) { return mpmath_build_mpf(0, man, 0, 0); } upper = (PympzObject*)Pympz_new(); lower = (PympzObject*)Pympz_new(); if (!upper || !lower) { Py_DECREF((PyObject*)man); Py_XDECREF((PyObject*)upper); Py_XDECREF((PyObject*)lower); return NULL; } /* Extract sign, make man positive, and set bit count */ sign = (mpz_sgn(man->z) == -1); mpz_abs(upper->z, man->z); bc = mpz_sizeinbase(upper->z, 2); if (!prec) prec = bc; shift = bc - prec; if (shift > 0) { switch (rnd[0]) { case 'f': if(sign) { mpz_cdiv_q_2exp(upper->z, upper->z, shift); } else { mpz_fdiv_q_2exp(upper->z, upper->z, shift); } break; case 'c': if(sign) { mpz_fdiv_q_2exp(upper->z, upper->z, shift); } else { mpz_cdiv_q_2exp(upper->z, upper->z, shift); } break; case 'd': mpz_fdiv_q_2exp(upper->z, upper->z, shift); break; case 'u': mpz_cdiv_q_2exp(upper->z, upper->z, shift); break; case 'n': default: mpz_tdiv_r_2exp(lower->z, upper->z, shift); mpz_tdiv_q_2exp(upper->z, upper->z, shift); if (mpz_sgn(lower->z)) { /* lower is not 0 so it must have at least 1 bit set */ if (mpz_sizeinbase(lower->z, 2)==shift) { /* lower is >= 1/2 */ if (mpz_scan1(lower->z, 0)==shift-1) { /* lower is exactly 1/2 */ if (mpz_odd_p(upper->z)) carry = 1; } else { carry = 1; } } } if (carry) mpz_add_ui(upper->z, upper->z, 1); } if (!(tmp = PyIntOrLong_FromSI(shift))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); return NULL; } if (!(newexp = PyNumber_Add(exp, tmp))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); return NULL; } Py_DECREF(tmp); bc = prec; } else { newexp = exp; Py_INCREF(newexp); } /* Strip trailing 0 bits. */ if ((zbits = mpz_scan1(upper->z, 0))) mpz_tdiv_q_2exp(upper->z, upper->z, zbits); if (!(tmp = PyIntOrLong_FromSI(zbits))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(newexp); return NULL; } if (!(newexp2 = PyNumber_Add(newexp, tmp))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); Py_DECREF(newexp); return NULL; } Py_DECREF(newexp); Py_DECREF(tmp); bc -= zbits; /* Check if one less than a power of 2 was rounded up. */ if (!mpz_cmp_ui(upper->z, 1)) bc = 1; Py_DECREF((PyObject*)lower); Py_DECREF((PyObject*)man); return mpmath_build_mpf(sign, upper, newexp2, bc); }
int main( int argc, char * argv[] ) { if ( argc != 3 && argc != 4 ) { printf("\n"); printf("For a^2 + b^2 = c^2 :\n"); printf("\n"); printf("Usage: ptriples [-p] c_min c_max\n\n\n"); printf("Options:\n\n"); printf(" -p -- primitive triples only\n\n"); return 1; } int DoOnlyPrimitives = 0; if ( argc == 4 && strcmp( argv[1], "-p" ) == 0 ) DoOnlyPrimitives = 1; mpz_t user_c_min; mpz_init_set_str( user_c_min, argv[argc == 3 ? 1 : 2], 10 ); mpz_t user_c_max; mpz_init_set_str( user_c_max, argv[argc == 3 ? 2 : 3], 10 ); if ( mpz_cmp_ui( user_c_min, 1 ) < 0 ) { printf("\nc_min must be >= 1. Aborting.\n\n"); mpz_clear( user_c_max ); mpz_clear( user_c_min ); return 1; } if ( mpz_cmp( user_c_min, user_c_max ) > 0 ) { printf("\nc_min must be <= c_max. Aborting.\n\n"); mpz_clear( user_c_max ); mpz_clear( user_c_min ); return 1; } mpz_t working_c_min; if ( DoOnlyPrimitives ) mpz_init_set( working_c_min, user_c_min ); else mpz_init_set_ui( working_c_min, 1 ); // We are going to use Euclid's formula: // For arbitrary positive integers m and n, and m > n, // a = m^2 - n^2, b = 2mn, c = m^2 + n^2 // In addition, we will restrict GCD(m,n) = 1 and m-n be // an odd number to guarantee that the triple is primitive. struct ttable triples; triples.count = 0; triples.triples = NULL; mpz_t a; mpz_init( a ); mpz_t b; mpz_init( b ); mpz_t c; mpz_init( c ); mpz_t n; mpz_init( n ); mpz_t m; mpz_init( m ); // n can vary from 1 to no more than (c_max/2)^(1/2) mpz_t n_max; mpz_init_set( n_max, user_c_max ); mpz_cdiv_q_2exp( n_max, n_max, 1 ); mpz_sqrt( n_max, n_max ); mpz_t m_min; mpz_init( m_min ); mpz_t m_max; mpz_init( m_max ); mpz_t n_squared; mpz_init( n_squared ); mpz_t m_squared; mpz_init( m_squared ); mpz_t gcd; mpz_init( gcd ); mpz_t tempZ; mpz_init( tempZ ); mpz_t k; mpz_init( k ); mpz_t ka; mpz_init( ka ); mpz_t kb; mpz_init( kb ); mpz_t kc; mpz_init( kc ); // iterate through n for ( mpz_set_ui( n, 1 ); mpz_cmp( n, n_max ) <= 0; mpz_add_ui( n, n, 1 ) ) { mpz_mul( n_squared, n, n ); // compute m_min mpz_sub( m_min, working_c_min, n_squared ); if ( mpz_cmp_ui( m_min, 1 ) < 0 ) // make sure mpz_sqrt() has a legal value mpz_set_ui( m_min, 1 ); mpz_sqrt( m_min, m_min ); mpz_sub_ui( m_min, m_min, 1 ); // subtract 1 just to be on the safe side // compute m_max mpz_sub( m_max, user_c_max, n_squared ); if ( mpz_cmp_ui( m_max, 1 ) < 0 ) // make sure mpz_sqrt() has a legal value mpz_set_ui( m_max, 1 ); mpz_sqrt( m_max, m_max ); // calc first value of m if ( mpz_cmp( n, m_min ) < 0 ) { mpz_set( m, m_min ); mpz_sub( tempZ, m, n ); if ( mpz_divisible_ui_p( tempZ, 2 ) ) mpz_add_ui( m, m, 1 ); } else { mpz_set( m, n ); mpz_add_ui( m, m, 1 ); } // iterate through m for ( ; mpz_cmp( m, m_max ) <= 0; mpz_add_ui( m, m, 2 ) ) { // generate a primitive (a,b,c) mpz_gcd( gcd, m, n ); if ( mpz_cmp_ui( gcd, 1 ) != 0 ) continue; mpz_mul( m_squared, m, m ); mpz_sub( a, m_squared, n_squared ); mpz_mul( b, m, n ); mpz_mul_ui( b, b, 2 ); mpz_add( c, m_squared, n_squared ); // check if primitive is outside our working range if ( mpz_cmp( c, working_c_min ) < 0 ) continue; if ( mpz_cmp( c, user_c_max ) > 0 ) continue; if ( DoOnlyPrimitives ) AddPTriple( &triples, a, b, c ); else { // iterate through k in: (k*a)^2 + (k*b)^2 = (k*c)^2 mpz_fdiv_q( k, user_c_min, c ); for ( mpz_mul( kc, c, k ); mpz_cmp( kc, user_c_max ) <= 0; mpz_add_ui( k, k, 1 ), mpz_mul( kc, c, k ) ) { if ( mpz_cmp( kc, user_c_min ) < 0 ) continue; mpz_mul( ka, a, k ); mpz_mul( kb, b, k ); AddPTriple( &triples, ka, kb, kc ); } } } } mpz_clear( kc ); mpz_clear( kb ); mpz_clear( ka ); mpz_clear( k ); qsort( triples.triples, triples.count, sizeof(struct tentry), ttable_entry_cmpfunc ); // print long i; for ( i = 0; i < triples.count; i++ ) gmp_printf("(%Zd,%Zd,%Zd)\n", triples.triples[i].a, triples.triples[i].b, triples.triples[i].c ); mpz_clear( tempZ ); mpz_clear( gcd ); mpz_clear( m_squared ); mpz_clear( n_squared ); mpz_clear( m_max ); mpz_clear( m_min ); mpz_clear( n_max ); mpz_clear( m ); mpz_clear( n ); mpz_clear( c ); mpz_clear( b ); mpz_clear( a ); Cleanup_ttable( &triples ); mpz_clear( working_c_min ); mpz_clear( user_c_max ); mpz_clear( user_c_min ); return 0; }
int main() { const int urfd = open("/dev/urandom", O_RDONLY); mpz_t p, q, n; fprintf(stderr, "Generating group...\n"); init_random_prime(p, urfd, 512, 3); init_random_prime(q, urfd, 512, 7); print(" p:", p); print(" q:", q); mpz_init(n); mpz_mul(n, p, q); print(" n:", n); fprintf(stderr, "Performing extended Euclid...\n"); mpz_t u, v; xgcd(u, v, p, q); mpz_mul(u, u, p); mpz_mul(v, v, q); print (" u:", u); print (" v:", v); fprintf(stderr, "Picking random element...\n"); mpz_t e; random_element(e, urfd, 1024, n); print(" e:", e); fprintf(stderr, "Tweaking...\n"); int a = is_quadratic_residue(e, p); int b = is_quadratic_residue(e, q); fprintf(stderr, " residue state: [%d, %d]\n", a, b); int mul_2 = 0, negate = 0; if (a ^ b) { mul_2 = 1; a ^= 1; } if (!a) { negate = 1; a ^= 1; b ^= 1; } fprintf(stderr, " tweaks: 2:%d -:%d\n", mul_2, negate); if (negate) { mpz_neg(e, e); } if (mul_2) { mpz_mul_ui(e, e, 2); } if (negate || mul_2) mpz_mod(e, e, n); print(" tweaked e:", e); uint8_t root; read(urfd, &root, 1); root &= 3; fprintf(stderr, "Calculating root %d...\n", root); mpz_t pp1over4, qp1over4; mpz_init_set(pp1over4, p); mpz_add_ui(pp1over4, pp1over4, 1); mpz_cdiv_q_2exp(pp1over4, pp1over4, 2); mpz_init_set(qp1over4, q); mpz_add_ui(qp1over4, qp1over4, 1); mpz_cdiv_q_2exp(qp1over4, qp1over4, 2); mpz_t proot, qroot; mpz_init_set(proot, e); mpz_powm(proot, e, pp1over4, p); mpz_init_set(qroot, e); mpz_powm(qroot, e, qp1over4, q); if (root & 1) mpz_neg(proot, proot); if (root & 2) mpz_neg(qroot, qroot); mpz_mul(proot, proot, v); mpz_mul(qroot, qroot, u); mpz_add(proot, proot, qroot); mpz_mod(proot, proot, n); print(" sig:", proot); fprintf(stderr, "Compressing signature...\n"); mpz_t zsig; mpz_t ncopy; mpz_init_set(ncopy, n); signature_compress(zsig, proot, ncopy); print(" zsig:", zsig); mpz_t zsigcopy, t, t2; mpz_init(t); mpz_init(t2); mpz_init(zsigcopy); fprintf(stderr, "Performing 1000000 verifications\n"); const uint64_t start_time = time_now(); unsigned i; for (i = 0; i < 1000000; ++i) { mpz_set(zsigcopy, zsig); mpz_mul(zsigcopy, zsigcopy, zsigcopy); mpz_mul(zsigcopy, zsigcopy, e); mpz_mod(zsigcopy, zsigcopy, n); if (0 == mpz_sgn(zsigcopy)) abort(); mpz_sqrtrem(t, t2, zsigcopy); if (mpz_sgn(t2)) abort(); } const uint64_t end_time = time_now(); fprintf(stderr, "verify time: %f\n", ((double) (end_time - start_time)) / 1000000); return 0; }