/** * This is a general function to count divisors. It will work * for any integer. * * We can optimise. If sqrt(num) is also a divisor, there are * an odd number of divisors. * All divisors have pairs so we only need to check half of them. * ie. up to sqrt(num) */ int mpz_count_divisors(const mpz_t num) { int count=0; mpz_t div; mpz_t sqt; mpz_init(sqt); mpz_init(div); mpz_sqrtrem(sqt,div,num); if(!mpz_cmp_ui(div,0)){ count--; if(/*div not num*/1) {} } mpz_set(div,sqt); do { if(mpz_divisible_p(num,div)){ count++;count++; } mpz_sub_ui(div,div,1); } while(mpz_cmp_ui(div,0)); mpz_clear(div); mpz_clear(sqt); return count; }
static Variant HHVM_FUNCTION(gmp_sqrtrem, const Variant& data) { mpz_t gmpData, gmpSquareRoot, gmpRemainder; if (!variantToGMPData(cs_GMP_FUNC_NAME_GMP_SQRTREM, gmpData, data)) { return false; } if (mpz_sgn(gmpData) < 0) { raise_warning(cs_GMP_INVALID_NUMBER_IS_NEGATIVE, cs_GMP_FUNC_NAME_GMP_SQRTREM); return false; } mpz_init(gmpSquareRoot); mpz_init(gmpRemainder); mpz_sqrtrem(gmpSquareRoot, gmpRemainder, gmpData); ArrayInit returnArray(2, ArrayInit::Map{}); returnArray.set(0, NEWOBJ(GMPResource)(gmpSquareRoot)); returnArray.set(1, NEWOBJ(GMPResource)(gmpRemainder)); mpz_clear(gmpData); mpz_clear(gmpSquareRoot); mpz_clear(gmpRemainder); return returnArray.toVariant(); }
static PyObject * GMPy_MPZ_Function_IsqrtRem(PyObject *self, PyObject *other) { MPZ_Object *root = NULL, *rem = NULL, *temp = NULL; PyObject *result; if (!(temp = GMPy_MPZ_From_Integer(other, NULL))) { TYPE_ERROR("isqrt_rem() requires 'mpz' argument"); return NULL; } if (mpz_sgn(temp->z) < 0) { VALUE_ERROR("isqrt_rem() of negative number"); Py_DECREF((PyObject*)temp); return NULL; } if (!(result = PyTuple_New(2)) || !(root = GMPy_MPZ_New(NULL)) || !(rem = GMPy_MPZ_New(NULL))) { /* LCOV_EXCL_START */ Py_DECREF((PyObject*)temp); Py_XDECREF(result); Py_XDECREF((PyObject*)root); Py_XDECREF((PyObject*)rem); return NULL; /* LCOV_EXCL_STOP */ } mpz_sqrtrem(root->z, rem->z, temp->z); Py_DECREF((PyObject*)temp); PyTuple_SET_ITEM(result, 0, (PyObject*)root); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; }
int executeSumCalculation(mpz_t num) { mpz_t sum, squareRoot, sqrtRem, st; mpz_t range, rem; int i; pthread_mutex_t mutex; pthread_cond_t cond; unsigned long long termCount; int err; SUM_THREAD_CONTEXT contexts[SUM_THREADS_PER_CALC]; mpz_init(squareRoot); mpz_init(sqrtRem); mpz_init(range); mpz_init(rem); pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); termCount = 0; //The sum starts at 1 because 1 is a factor of any number mpz_init_set_ui(sum, 1); //We know that exactly 1 factor of every pair of factors will //appear before the square root. mpz_sqrtrem(squareRoot, sqrtRem, num); //Check if the the number is a square if (mpz_cmp_ui(sqrtRem, 0) != 0) { //Emulate ceil mpz_add_ui(squareRoot, squareRoot, 1); } //Factor starts at 2 mpz_init_set_ui(st, 2); //Compute range mpz_mod_ui(rem, squareRoot, SUM_THREADS_PER_CALC); mpz_sub(squareRoot, squareRoot, rem); mpz_divexact_ui(range, squareRoot, SUM_THREADS_PER_CALC); for (i = 0; i < SUM_THREADS_PER_CALC; i++) { mpz_init_set(contexts[i].st, st); mpz_init_set(contexts[i].factor, st); mpz_init(contexts[i].otherfactor); mpz_add(st, st, range); if (i == 0) { mpz_sub_ui(st, st, 2); } mpz_init_set(contexts[i].end, st); if (i == 0) { mpz_add(contexts[i].end, contexts[i].end, rem); mpz_add(st, st, rem); } mpz_init_set(contexts[i].num, num); contexts[i].sum = ∑ contexts[i].termCount = &termCount; contexts[i].termMutex = &mutex; contexts[i].termVar = &cond; printf("Assigning work to sum thread %d\n", i); err = pthread_create(&contexts[i].id, NULL, SumThread, &contexts[i]); if (err != 0) return -1; } fflush(stdout); for (;;) { pthread_mutex_lock(&mutex); printf("%llu sum threads complete\n", termCount); fflush(stdout); if (termCount == SUM_THREADS_PER_CALC) { pthread_mutex_unlock(&mutex); break; } if (mpz_cmp(sum, num) > 0) { printf("sum is too large; terminating children\n"); fflush(stdout); pthread_mutex_unlock(&mutex); break; } pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); } for (i = 0; i < SUM_THREADS_PER_CALC; i++) { void *ret; pthread_cancel(contexts[i].id); pthread_join(contexts[i].id, &ret); mpz_clear(contexts[i].st); mpz_clear(contexts[i].num); mpz_clear(contexts[i].factor); mpz_clear(contexts[i].end); mpz_clear(contexts[i].otherfactor); } mpz_clear(squareRoot); mpz_clear(sqrtRem); mpz_clear(range); mpz_clear(rem); mpz_clear(st); if (mpz_cmp(sum, num) == 0) { mpz_clear(sum); return 1; } else { mpz_clear(sum); return 0; } }
int main(int argc, char **argv) { gettimeofday(&start_global, NULL); print_lib_version(); mpz_init(N); mpz_t B; mpz_init(B); unsigned long int uBase; int64_t nb_primes; modular_root_t *modular_roots; uint64_t i, j; if (mpz_init_set_str(N, argv[1], 10) == -1) { printf("Cannot load N %s\n", argv[1]); exit(2); } mpz_t sqrtN, rem; mpz_init(sqrtN); mpz_init(rem); mpz_sqrtrem(sqrtN, rem, N); if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */ mpz_add_ui(sqrtN, sqrtN, 1); else /* N is a perfect square, factored! */ { printf("\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN)); return 0; } if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */ { printf("N:%s is prime\n", mpz_get_str(NULL, 10, N)); exit(0); } OPEN_LOG_FILE("freq"); //-------------------------------------------------------- // calculate the smoothness base for the given N //-------------------------------------------------------- get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */ uBase = mpz_get_ui(B); printf("n: %s\tBase: %s\n", mpz_get_str(NULL, 10, N), mpz_get_str(NULL, 10, B)); //-------------------------------------------------------- // sieve primes that are less than the smoothness base using Eratosthenes sieve //-------------------------------------------------------- START_TIMER(); nb_primes = sieve_primes_up_to((int64_t) (uBase)); printf("\nPrimes found %" PRId64 " [Smoothness Base %lu]\n", nb_primes, uBase); STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done"); //-------------------------------------------------------- // fill the primes array with primes to which n is a quadratic residue //-------------------------------------------------------- START_TIMER(); primes = calloc(nb_primes, sizeof(int64_t)); nb_qr_primes = fill_primes_with_quadratic_residue(primes, N); /*for(i=0; i<nb_qr_primes; i++) printf("%" PRId64 "\n", primes[i]);*/ printf("\nN-Quadratic primes found %" PRId64 "\n", nb_qr_primes); STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done"); //-------------------------------------------------------- // calculate modular roots //-------------------------------------------------------- START_TIMER(); modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t)); mpz_t tmp, r1, r2; mpz_init(tmp); mpz_init(r1); mpz_init(r2); for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(tmp, (unsigned long) primes[i]); mpz_sqrtm(r1, N, tmp); /* calculate the modular root */ mpz_neg(r2, r1); /* -q mod n */ mpz_mod(r2, r2, tmp); modular_roots[i].root1 = mpz_get_ui(r1); modular_roots[i].root2 = mpz_get_ui(r2); } mpz_clear(tmp); mpz_clear(r1); mpz_clear(r2); STOP_TIMER_PRINT_TIME("\nModular roots calculation done"); /*for(i=0; i<nb_qr_primes; i++) { printf("[%10" PRId64 "-> roots: %10u - %10u]\n", primes[i], modular_roots[i].root1, modular_roots[i].root2); }*/ //-------------------------------------------------------- // ***** initialize the matrix ***** //-------------------------------------------------------- START_TIMER(); init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes); mpz_init2(tmp_matrix_row, nb_qr_primes); STOP_TIMER_PRINT_TIME("\nMatrix initialized"); //-------------------------------------------------------- // [Sieving] //-------------------------------------------------------- START_TIMER(); mpz_t x, sieving_index, next_sieving_index; unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */ uint64_t p_pow; smooth_number_t *x_squared; x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t)); smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET, sizeof(smooth_number_t)); mpz_init_set(x, sqrtN); mpz_init_set(sieving_index, x); mpz_init_set(next_sieving_index, x); mpz_t p; mpz_init(p); mpz_t str; mpz_init_set(str, sieving_index); printf("\nSieving ...\n"); //-------------------------------------------------------- // Init before sieving //-------------------------------------------------------- for (i = 0; i < SIEVING_STEP; i++) { mpz_init(x_squared[i].value_x); mpz_init(x_squared[i].value_x_squared); /* the factors_exp array is used to keep track of exponents */ //x_squared[i].factors_exp = calloc(nb_qr_primes, sizeof(uint64_t)); /* we use directly the exponents vector modulo 2 to preserve space */mpz_init2( x_squared[i].factors_vect, nb_qr_primes); mpz_add_ui(x, x, 1); } int nb_smooth_per_round = 0; char s[512]; //-------------------------------------------------------- // WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET //-------------------------------------------------------- while (nb_smooth_numbers_found < nb_qr_primes + NB_VECTORS_OFFSET) { nb_smooth_per_round = 0; mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */ mpz_set(sieving_index, next_sieving_index); printf("\r"); printf( "\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "", mpz_get_str(NULL, 10, sieving_index), nb_smooth_numbers_found, nb_qr_primes); fflush(stdout); for (i = 0; i < SIEVING_STEP; i++) { mpz_set(x_squared[i].value_x, x); mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */ mpz_sub(x_squared[i].value_x_squared, x_squared[i].value_x_squared, N); mpz_clear(x_squared[i].factors_vect); mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */ mpz_add_ui(x, x, 1); } mpz_set(next_sieving_index, x); //-------------------------------------------------------- // eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth //-------------------------------------------------------- for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(p, (unsigned long) primes[i]); mpz_set(x, sieving_index); /* get the first multiple of p that is directly larger that sieving_index * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2 * are also multiples of p */ get_sieving_start_index(x, x, p, modular_roots[i].root1); mpz_set(str, x); mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */ for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); /* eliminate all factors of p */ if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */ { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } /* sieve next element located p steps from here */ } /* same goes for root2 */ if (modular_roots[i].root2 == modular_roots[i].root1) continue; mpz_set(x, sieving_index); get_sieving_start_index(x, x, p, modular_roots[i].root2); mpz_set(str, x); mpz_sub(x, x, sieving_index); for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); if (p_pow & 1) { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } } } //printf("\tSmooth numbers found %" PRId64 "\n", nb_smooth_numbers_found); /*sprintf(s, "[start: %s - end: %s - step: %" PRId64 "] nb_smooth_per_round: %d", mpz_get_str(NULL, 10, sieving_index), mpz_get_str(NULL, 10, next_sieving_index), SIEVING_STEP, nb_smooth_per_round); APPEND_TO_LOG_FILE(s);*/ } STOP_TIMER_PRINT_TIME("\nSieving DONE"); uint64_t t = 0; //-------------------------------------------------------- //the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number() //-------------------------------------------------------- START_TIMER(); gauss_elimination(&matrix); STOP_TIMER_PRINT_TIME("\nGauss elimination done"); //print_matrix_matrix(&matrix); //print_matrix_identity(&matrix); uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */ int nb_linear_relations = 0; mpz_t linear_relation_z, solution_z; mpz_init(linear_relation_z); mpz_init(solution_z); get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/ while (mpz_cmp_ui(linear_relation_z, 0) == 0) { nb_linear_relations++; get_matrix_row(linear_relation_z, &matrix, row_index--); } printf("\tLinear dependent relations found : %d\n", nb_linear_relations); //-------------------------------------------------------- // Factor //-------------------------------------------------------- //We use the last linear relation to reconstruct our solution START_TIMER(); printf("\nFactorizing..\n"); mpz_t solution_X, solution_Y; mpz_init(solution_X); mpz_init(solution_Y); /* we start testing from the first linear relation encountered in the matrix */ for (j = nb_linear_relations; j > 0; j--) { printf("Trying %d..\n", nb_linear_relations - j + 1); mpz_set_ui(solution_X, 1); mpz_set_ui(solution_Y, 1); get_identity_row(solution_z, &matrix, nb_qr_primes + NB_VECTORS_OFFSET - j + 1); for (i = 0; i < nb_qr_primes; i++) { if (mpz_tstbit(solution_z, i)) { mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x); mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */ mpz_mul(solution_Y, solution_Y, smooth_numbers[i].value_x_squared); /*TODO: handling huge stuff here, there is no modulo N like in the solution_X case! * eliminate squares as long as you go*/ } } mpz_sqrt(solution_Y, solution_Y); mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */ mpz_sub(solution_X, solution_X, solution_Y); mpz_gcd(solution_X, solution_X, N); if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */ break; } mpz_cdiv_q(solution_Y, N, solution_X); printf("\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); printf("\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); /*sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); APPEND_TO_LOG_FILE(s); sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); APPEND_TO_LOG_FILE(s); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); sprintf(s, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); APPEND_TO_LOG_FILE(s);*/ STOP_TIMER_PRINT_TIME("\nFactorizing done"); printf("Cleaning memory..\n"); /********************** clear the x_squared array **********************/ for (i = 0; i < SIEVING_STEP; i++) { mpz_clear(x_squared[i].value_x); mpz_clear(x_squared[i].value_x_squared); //free(x_squared[i].factors_exp); mpz_clear(x_squared[i].factors_vect); } free(x_squared); /********************** clear the x_squared array **********************/ free(modular_roots); /********************** clear the smooth_numbers array **********************/ for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) { mpz_clear(smooth_numbers[i].value_x); mpz_clear(smooth_numbers[i].value_x_squared); //free(smooth_numbers[i].factors_exp); } free(smooth_numbers); /********************** clear the smooth_numbers array **********************/ free(primes); /********************** clear mpz _t **********************/mpz_clear(B); mpz_clear(N); sqrtN, rem; mpz_clear(x); mpz_clear(sieving_index); mpz_clear(next_sieving_index); mpz_clear(p); mpz_clear(str); /********************** clear mpz _t **********************/ free_matrix(&matrix); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); printf("****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); show_mem_usage(); return 0; }
int main (int argc, char **argv) { mpz_t x2; mpz_t x, rem; mpz_t temp, temp2; mp_size_t x2_size; int i; int reps = 1000; gmp_randstate_ptr rands; mpz_t bs; unsigned long size_range; tests_start (); TESTS_REPS (reps, argv, argc); rands = RANDS; mpz_init (bs); mpz_init (x2); mpz_init (x); mpz_init (rem); mpz_init (temp); mpz_init (temp2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 17 + 2; /* 0..262144 bit operands */ mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs); mpz_rrandomb (x2, rands, x2_size); /* printf ("%ld\n", SIZ (x2)); */ mpz_sqrtrem (x, rem, x2); MPZ_CHECK_FORMAT (x); MPZ_CHECK_FORMAT (rem); mpz_mul (temp, x, x); /* Is square of result > argument? */ if (mpz_cmp (temp, x2) > 0) dump_abort (x2, x, rem); mpz_add_ui (temp2, x, 1); mpz_mul (temp2, temp2, temp2); /* Is square of (result + 1) <= argument? */ if (mpz_cmp (temp2, x2) <= 0) dump_abort (x2, x, rem); mpz_add (temp2, temp, rem); /* Is the remainder wrong? */ if (mpz_cmp (x2, temp2) != 0) dump_abort (x2, x, rem); } mpz_clear (bs); mpz_clear (x2); mpz_clear (x); mpz_clear (rem); mpz_clear (temp); mpz_clear (temp2); tests_end (); exit (0); }
int main (int argc, char **argv) { mpz_t x2; mpz_t x, rem; mpz_t temp, temp2; mp_size_t x2_size; int i; int reps = 20000; gmp_randstate_t rands; mpz_t bs; unsigned long size_range; tests_start (); gmp_randinit_default(rands); mpz_init (bs); if (argc == 2) reps = atoi (argv[1]); mpz_init (x2); mpz_init (x); mpz_init (rem); mpz_init (temp); mpz_init (temp2); for (i = 0; i < reps; i++) { mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 12 + 2; /* 0..8191 bit operands */ mpz_urandomb (bs, rands, size_range); x2_size = mpz_get_ui (bs); mpz_rrandomb (x2, rands, x2_size); /* printf ("%ld\n", SIZ (x2)); */ mpz_sqrtrem (x, rem, x2); mpz_mul (temp, x, x); /* Is square of result > argument? */ if (mpz_cmp (temp, x2) > 0) dump_abort (x2, x, rem); mpz_add_ui (temp2, x, 1); mpz_mul (temp2, temp2, temp2); /* Is square of (result + 1) <= argument? */ if (mpz_cmp (temp2, x2) <= 0) dump_abort (x2, x, rem); mpz_add (temp2, temp, rem); /* Is the remainder wrong? */ if (mpz_cmp (x2, temp2) != 0) dump_abort (x2, x, rem); } mpz_clear (bs); mpz_clear (x2); mpz_clear (x); mpz_clear (rem); mpz_clear (temp); mpz_clear (temp2); gmp_randclear(rands); tests_end (); exit (0); }
/* assuming slaves (workers)) are all homogenous, let them all do the calculations regarding primes sieving, calculating the smoothness base and the modular roots */ int main(int argc, char **argv) { MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &mpi_group_size); int len; MPI_Get_processor_name(processor_name, &len); gettimeofday(&start_global, NULL); print_lib_version(); mpz_init(N); mpz_t B; mpz_init(B); unsigned long int uBase; int64_t nb_primes; modular_root_t *modular_roots; uint64_t i, j; if (argc < 2) { PRINT(my_rank, "usage: %s Number_to_factorize\n", argv[0]); exit(2); } if (mpz_init_set_str(N, argv[1], 10) == -1) { PRINT(my_rank, "Cannot load N %s\n", argv[1]); exit(2); } mpz_t sqrtN, rem; mpz_init(sqrtN); mpz_init(rem); mpz_sqrtrem(sqrtN, rem, N); if (mpz_cmp_ui(rem, 0) != 0) /* if not perfect square, calculate the ceiling */ mpz_add_ui(sqrtN, sqrtN, 1); else /* N is a perfect square, factored! */ { PRINT(my_rank, "\n<<<[FACTOR]>>> %s\n", mpz_get_str(NULL, 10, sqrtN)); return 0; } if (mpz_probab_prime_p(N, 10) > 0) /* don't bother factoring */ { PRINT(my_rank, "N:%s is prime\n", mpz_get_str(NULL, 10, N)); exit(0); } OPEN_LOG_FILE("freq"); //-------------------------------------------------------- // calculate the smoothness base for the given N //-------------------------------------------------------- get_smoothness_base(B, N); /* if N is too small, the program will surely fail, please consider a pen and paper instead */ uBase = mpz_get_ui(B); PRINT(my_rank, "n: %s\tBase: %s\n", mpz_get_str(NULL, 10, N), mpz_get_str(NULL, 10, B)); //-------------------------------------------------------- // sieve primes that are less than the smoothness base using Eratosthenes sieve //-------------------------------------------------------- START_TIMER(); nb_primes = sieve_primes_up_to((int64_t) (uBase)); PRINT(my_rank, "\tPrimes found %" PRId64 " [Smoothness Base %lu]\n", nb_primes, uBase); STOP_TIMER_PRINT_TIME("\tEratosthenes Sieving done"); //-------------------------------------------------------- // fill the primes array with primes to which n is a quadratic residue //-------------------------------------------------------- START_TIMER(); primes = calloc(nb_primes, sizeof(int64_t)); nb_qr_primes = fill_primes_with_quadratic_residue(primes, N); /*for(i=0; i<nb_qr_primes; i++) PRINT(my_rank, "%" PRId64 "\n", primes[i]);*/ PRINT(my_rank, "\tN-Quadratic primes found %" PRId64 "\n", nb_qr_primes); STOP_TIMER_PRINT_TIME("\tQuadratic prime filtering done"); //-------------------------------------------------------- // calculate modular roots //-------------------------------------------------------- START_TIMER(); modular_roots = calloc(nb_qr_primes, sizeof(modular_root_t)); mpz_t tmp, r1, r2; mpz_init(tmp); mpz_init(r1); mpz_init(r2); for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(tmp, (unsigned long) primes[i]); mpz_sqrtm(r1, N, tmp); /* calculate the modular root */ mpz_neg(r2, r1); /* -q mod n */ mpz_mod(r2, r2, tmp); modular_roots[i].root1 = mpz_get_ui(r1); modular_roots[i].root2 = mpz_get_ui(r2); } mpz_clear(tmp); mpz_clear(r1); mpz_clear(r2); STOP_TIMER_PRINT_TIME("Modular roots calculation done"); //-------------------------------------------------------- // ***** initialize the matrix ***** //-------------------------------------------------------- if (my_rank == 0) /* only the master have the matrix */ { START_TIMER(); init_matrix(&matrix, nb_qr_primes + NB_VECTORS_OFFSET, nb_qr_primes); mpz_init2(tmp_matrix_row, nb_qr_primes); STOP_TIMER_PRINT_TIME("Matrix initialized"); } //-------------------------------------------------------- // [Sieving] - everyones sieves including the master //-------------------------------------------------------- START_TIMER(); mpz_t x, sieving_index, next_sieving_index, relative_start, global_step; unsigned long ui_index, SIEVING_STEP = 50000; /* we sieve for 50000 elements at each loop */ int LOCAL_SIEVING_ROUNDS = 10; /* number of iterations a worker sieves before communicating results to the master */ unsigned long sieving_round = 0; unsigned long nb_big_rounds = 0; uint64_t p_pow; smooth_number_t *x_squared; x_squared = calloc(SIEVING_STEP, sizeof(smooth_number_t)); if (my_rank == 0) smooth_numbers = calloc(nb_qr_primes + NB_VECTORS_OFFSET, sizeof(smooth_number_t)); else temp_slaves_smooth_numbers = calloc(500, sizeof(smooth_number_t)); /* TODO: this is not properly correct, using a linkedlist is better to keep track of temporary * smooth numbers at the slaves nodes however it's pretty rare to find 500 smooth numbers in * 50000 * 10 interval. */ mpz_init_set(x, sqrtN); mpz_init(global_step); mpz_init(relative_start); mpz_init(sieving_index); mpz_init(next_sieving_index); mpz_t p; mpz_init(p); mpz_t str; mpz_init_set(str, sieving_index); PRINT(my_rank, "\n[%s] Sieving ...\n", processor_name); //-------------------------------------------------------- // Init before sieving //-------------------------------------------------------- for (i = 0; i < SIEVING_STEP; i++) { mpz_init(x_squared[i].value_x); mpz_init(x_squared[i].value_x_squared); mpz_init2(x_squared[i].factors_vect, nb_qr_primes); mpz_add_ui(x, x, 1); } int nb_smooth_per_round = 0; char s[512]; //-------------------------------------------------------- // WHILE smooth numbers found less than the primes in the smooth base + NB_VECTORS_OFFSET for master // Or master asked for more smooth numbers from slaves //-------------------------------------------------------- while (1) { mpz_set_ui(global_step, nb_big_rounds); /* calculates the coordinate where the workers start sieving from */ mpz_mul_ui(global_step, global_step, (unsigned long) mpi_group_size); mpz_mul_ui(global_step, global_step, SIEVING_STEP); mpz_mul_ui(global_step, global_step, LOCAL_SIEVING_ROUNDS); mpz_add(global_step, global_step, sqrtN); mpz_set_ui(relative_start, SIEVING_STEP); mpz_mul_ui(relative_start, relative_start, LOCAL_SIEVING_ROUNDS); mpz_mul_ui(relative_start, relative_start, (unsigned long) my_rank); mpz_add(relative_start, relative_start, global_step); mpz_set(sieving_index, relative_start); mpz_set(next_sieving_index, relative_start); for (sieving_round = 0; sieving_round < LOCAL_SIEVING_ROUNDS; /* each slave sieves for LOCAL_SIEVING_ROUNDS rounds */ sieving_round++) { nb_smooth_per_round = 0; mpz_set(x, next_sieving_index); /* sieve numbers from sieving_index to sieving_index + sieving_step */ mpz_set(sieving_index, next_sieving_index); if (my_rank == 0) { printf("\r"); printf( "\t\tSieving at: %s30 <--> Smooth numbers found: %" PRId64 "/%" PRId64 "", mpz_get_str(NULL, 10, sieving_index), nb_global_smooth_numbers_found, nb_qr_primes); fflush(stdout); } for (i = 0; i < SIEVING_STEP; i++) { mpz_set(x_squared[i].value_x, x); mpz_pow_ui(x_squared[i].value_x_squared, x, 2); /* calculate value_x_squared <- x²-n */ mpz_sub(x_squared[i].value_x_squared, x_squared[i].value_x_squared, N); mpz_clear(x_squared[i].factors_vect); mpz_init2(x_squared[i].factors_vect, nb_qr_primes); /* reconstruct a new fresh 0ed vector of size nb_qr_primes bits */ mpz_add_ui(x, x, 1); } mpz_set(next_sieving_index, x); //-------------------------------------------------------- // eliminate factors in the x_squared array, those who are 'destructed' to 1 are smooth //-------------------------------------------------------- for (i = 0; i < nb_qr_primes; i++) { mpz_set_ui(p, (unsigned long) primes[i]); mpz_set(x, sieving_index); /* get the first multiple of p that is directly larger that sieving_index * Quadratic SIEVING: all elements from this number and in positions multiples of root1 and root2 * are also multiples of p */ get_sieving_start_index(x, x, p, modular_roots[i].root1); mpz_set(str, x); mpz_sub(x, x, sieving_index); /* x contains index of first number that is divisible by p */ for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); /* eliminate all factors of p */ if (p_pow & 1) /* mark bit if odd power of p exists in this x_squared[j] */ { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } /* sieve next element located p steps from here */ } /* same goes for root2 */ if (modular_roots[i].root2 == modular_roots[i].root1) continue; mpz_set(x, sieving_index); get_sieving_start_index(x, x, p, modular_roots[i].root2); mpz_set(str, x); mpz_sub(x, x, sieving_index); for (j = mpz_get_ui(x); j < SIEVING_STEP; j += primes[i]) { p_pow = mpz_remove(x_squared[j].value_x_squared, x_squared[j].value_x_squared, p); if (p_pow & 1) { mpz_setbit(x_squared[j].factors_vect, i); } if (mpz_cmp_ui(x_squared[j].value_x_squared, 1) == 0) { save_smooth_number(x_squared[j]); nb_smooth_per_round++; } } } } if (my_rank == 0) /* master gathers smooth numbers from slaves */ { gather_smooth_numbers(); notify_slaves(); } else /* slaves send their smooth numbers to master */ { send_smooth_numbers_to_master(); nb_global_smooth_numbers_found = get_server_notification(); } if (nb_global_smooth_numbers_found >= nb_qr_primes + NB_VECTORS_OFFSET) break; nb_big_rounds++; } STOP_TIMER_PRINT_TIME("\nSieving DONE"); if (my_rank == 0) { uint64_t t = 0; //-------------------------------------------------------- //the matrix ready, start Gauss elimination. The Matrix is filled on the call of save_smooth_number() //-------------------------------------------------------- START_TIMER(); gauss_elimination(&matrix); STOP_TIMER_PRINT_TIME("\nGauss elimination done"); uint64_t row_index = nb_qr_primes + NB_VECTORS_OFFSET - 1; /* last row in the matrix */ int nb_linear_relations = 0; mpz_t linear_relation_z, solution_z; mpz_init(linear_relation_z); mpz_init(solution_z); get_matrix_row(linear_relation_z, &matrix, row_index--); /* get the last few rows in the Gauss eliminated matrix*/ while (mpz_cmp_ui(linear_relation_z, 0) == 0) { nb_linear_relations++; get_matrix_row(linear_relation_z, &matrix, row_index--); } PRINT(my_rank, "\tLinear dependent relations found : %d\n", nb_linear_relations); //-------------------------------------------------------- // Factor //-------------------------------------------------------- //We use the last linear relation to reconstruct our solution START_TIMER(); PRINT(my_rank, "%s", "\nFactorizing..\n"); mpz_t solution_X, solution_Y; mpz_init(solution_X); mpz_init(solution_Y); /* we start testing from the first linear relation encountered in the matrix */ for (j = nb_linear_relations; j > 0; j--) { PRINT(my_rank, "Trying %d..\n", nb_linear_relations - j + 1); mpz_set_ui(solution_X, 1); mpz_set_ui(solution_Y, 1); get_identity_row(solution_z, &matrix, nb_qr_primes + NB_VECTORS_OFFSET - j + 1); for (i = 0; i < nb_qr_primes; i++) { if (mpz_tstbit(solution_z, i)) { mpz_mul(solution_X, solution_X, smooth_numbers[i].value_x); mpz_mod(solution_X, solution_X, N); /* reduce x to modulo N */ mpz_mul(solution_Y, solution_Y, smooth_numbers[i].value_x_squared); /*TODO: handling huge stuff here, there is no modulo N like in the solution_X case! * eliminate squares as long as you go*/ } } mpz_sqrt(solution_Y, solution_Y); mpz_mod(solution_Y, solution_Y, N); /* y = sqrt(MUL(xi²-n)) mod N */ mpz_sub(solution_X, solution_X, solution_Y); mpz_gcd(solution_X, solution_X, N); if (mpz_cmp(solution_X, N) != 0 && mpz_cmp_ui(solution_X, 1) != 0) /* factor can be 1 or N, try another relation */ break; } mpz_cdiv_q(solution_Y, N, solution_X); PRINT(my_rank, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); PRINT( my_rank, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); sprintf(s, "\n>>>>>>>>>>> FACTORED %s =\n", mpz_get_str(NULL, 10, N)); APPEND_TO_LOG_FILE(s); sprintf(s, "\tFactor 1: %s \n\tFactor 2: %s", mpz_get_str(NULL, 10, solution_X), mpz_get_str(NULL, 10, solution_Y)); APPEND_TO_LOG_FILE(s); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); sprintf(s, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); APPEND_TO_LOG_FILE(s); STOP_TIMER_PRINT_TIME("\nFactorizing done"); } PRINT(my_rank, "%s", "\nCleaning memory..\n"); /********************** clear the x_squared array **********************/ for (i = 0; i < SIEVING_STEP; i++) { mpz_clear(x_squared[i].value_x); mpz_clear(x_squared[i].value_x_squared); //free(x_squared[i].factors_exp); mpz_clear(x_squared[i].factors_vect); } free(x_squared); /********************** clear the x_squared array **********************/ free(modular_roots); /********************** clear the smooth_numbers array **********************/ if (my_rank == 0) { for (i = 0; i < nb_qr_primes + NB_VECTORS_OFFSET; i++) { mpz_clear(smooth_numbers[i].value_x); mpz_clear(smooth_numbers[i].value_x_squared); mpz_clear(smooth_numbers[i].factors_vect); //free(smooth_numbers[i].factors_exp); } free(smooth_numbers); } else { for (i = 0; i < 500; i++) { mpz_clear(temp_slaves_smooth_numbers[i].value_x); mpz_clear(temp_slaves_smooth_numbers[i].value_x_squared); mpz_clear(temp_slaves_smooth_numbers[i].factors_vect); } free(temp_slaves_smooth_numbers); } /********************** clear the smooth_numbers array **********************/ free(primes); /********************** clear mpz _t **********************/mpz_clear(B); mpz_clear(N); sqrtN, rem; mpz_clear(x); mpz_clear(sieving_index); mpz_clear(next_sieving_index); mpz_clear(p); mpz_clear(str); /********************** clear mpz _t **********************/ free_matrix(&matrix); gettimeofday(&end_global, NULL); timersub(&end_global, &start_global, &elapsed); PRINT(my_rank, "****** TOTAL TIME: %.3f ms\n", elapsed.tv_sec * 1000 + elapsed.tv_usec / (double) 1000); show_mem_usage(); MPI_Finalize(); 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; }
int main (int argc, char **argv) { int i; int pass, reps = 400; mpz_t in1, in2, in3; unsigned long int in2i; mp_size_t size; mpz_t res1, res2, res3; mpz_t ref1, ref2, ref3; mpz_t t; unsigned long int r1, r2; gmp_randstate_ptr rands; mpz_t bs; unsigned long bsi, size_range; tests_start (); TESTS_REPS (reps, argv, argc); rands = RANDS; mpz_init (bs); mpz_init (in1); mpz_init (in2); mpz_init (in3); mpz_init (ref1); mpz_init (ref2); mpz_init (ref3); mpz_init (res1); mpz_init (res2); mpz_init (res3); mpz_init (t); for (pass = 1; pass <= reps; pass++) { if (isatty (fileno (stdout))) { printf ("\r%d/%d passes", pass, reps); fflush (stdout); } mpz_urandomb (bs, rands, 32); size_range = mpz_get_ui (bs) % 21 + 2; if ((pass & 1) == 0) { /* Make all input operands have quite different sizes */ mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in1, rands, size); mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in2, rands, size); mpz_urandomb (bs, rands, 32); size = mpz_get_ui (bs) % size_range; mpz_rrandomb (in3, rands, size); } else { /* Make all input operands have about the same size */ mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in1, rands, size); mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in2, rands, size); mpz_urandomb (bs, rands, size_range); size = mpz_get_ui (bs); mpz_rrandomb (in3, rands, size); } mpz_urandomb (bs, rands, 3); bsi = mpz_get_ui (bs); if ((bsi & 1) != 0) mpz_neg (in1, in1); if ((bsi & 2) != 0) mpz_neg (in2, in2); if ((bsi & 4) != 0) mpz_neg (in3, in3); for (i = 0; i < numberof (dss); i++) { if (dss[i].isdivision && mpz_sgn (in2) == 0) continue; if (dss[i].isslow && size_range > 19) continue; (dss[i].fptr) (ref1, in1, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RSS (dss[i], res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dss, i, in1, in2, NULL); mpz_set (res1, in2); INVOKE_RSS (dss[i], res1, in1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dss, i, in1, in2, NULL); } for (i = 0; i < numberof (ddss_div); i++) { if (mpz_sgn (in2) == 0) continue; (ddss_div[i].fptr) (ref1, ref2, in1, in2); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); INVOKE_RRSS (ddss_div[i], res1, res2, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res2, in1); INVOKE_RRSS (ddss_div[i], res1, res2, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res1, in2); INVOKE_RRSS (ddss_div[i], res1, res2, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); mpz_set (res2, in2); INVOKE_RRSS (ddss_div[i], res1, res2, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL (ddss_div, i, in1, in2, NULL); } for (i = 0; i < numberof (ds); i++) { if (ds[i].nonneg && mpz_sgn (in1) < 0) continue; (ds[i].fptr) (ref1, in1); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RS (ds[i], res1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (ds, i, in1, in2, NULL); } in2i = mpz_get_ui (in2); for (i = 0; i < numberof (dsi); i++) { if (dsi[i].mod != 0) in2i = mpz_get_ui (in2) % dsi[i].mod; (dsi[i].fptr) (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); INVOKE_RRS (dsi[i], res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL (dsi, i, in1, in2, NULL); } if (in2i != 0) /* Don't divide by 0. */ { for (i = 0; i < numberof (dsi_div); i++) { r1 = (dsi_div[i].fptr) (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = (dsi_div[i].fptr) (res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || r1 != r2) FAIL (dsi_div, i, in1, in2, NULL); } for (i = 0; i < numberof (ddsi_div); i++) { r1 = (ddsi_div[i].fptr) (ref1, ref2, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = (ddsi_div[i].fptr) (res1, res2, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2) FAIL (ddsi_div, i, in1, in2, NULL); mpz_set (res2, in1); (ddsi_div[i].fptr) (res1, res2, res2, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || r1 != r2) FAIL (ddsi_div, i, in1, in2, NULL); } } if (mpz_sgn (in1) >= 0) { mpz_sqrtrem (ref1, ref2, in1); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); mpz_sqrtrem (res1, res2, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); mpz_set (res2, in1); mpz_sqrtrem (res1, res2, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); mpz_set (res1, in1); mpz_sqrtrem (res1, res1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref2, res1) != 0) FAIL2 (mpz_sqrtrem, in1, NULL, NULL); } if (mpz_sgn (in1) >= 0) { mpz_root (ref1, in1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_root (res1, res1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_root, in1, in2, NULL); } if (mpz_sgn (in1) >= 0) { mpz_rootrem (ref1, ref2, in1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); mpz_set (res1, in1); mpz_rootrem (res1, res2, res1, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_rootrem, in1, in2, NULL); mpz_set (res2, in1); mpz_rootrem (res1, res2, res2, in2i % 0x100 + 1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0) FAIL2 (mpz_rootrem, in1, in2, NULL); } if (size_range < 18) /* run fewer tests since gcdext lots of time */ { mpz_gcdext (ref1, ref2, ref3, in1, in2); MPZ_CHECK_FORMAT (ref1); MPZ_CHECK_FORMAT (ref2); MPZ_CHECK_FORMAT (ref3); mpz_set (res1, in1); mpz_gcdext (res1, res2, res3, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in1); mpz_gcdext (res1, res2, res3, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res3, in1); mpz_gcdext (res1, res2, res3, res3, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in2); mpz_gcdext (res1, res2, res3, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in2); mpz_gcdext (res1, res2, res3, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res3, in2); mpz_gcdext (res1, res2, res3, in1, res3); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); MPZ_CHECK_FORMAT (res3); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in1); mpz_gcdext (res1, res2, NULL, res1, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in1); mpz_gcdext (res1, res2, NULL, res2, in2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res1, in2); mpz_gcdext (res1, res2, NULL, in1, res1); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); mpz_set (res2, in2); mpz_gcdext (res1, res2, NULL, in1, res2); MPZ_CHECK_FORMAT (res1); MPZ_CHECK_FORMAT (res2); if (mpz_cmp (ref1, res1) != 0 || mpz_cmp (ref2, res2) != 0 || mpz_cmp (ref3, res3) != 0) FAIL2 (mpz_gcdext, in1, in2, NULL); } /* Don't run mpz_powm for huge exponents or when undefined. */ if (size_range < 17 && mpz_sizeinbase (in2, 2) < 250 && mpz_sgn (in3) != 0 && (mpz_sgn (in2) >= 0 || mpz_invert (t, in1, in3))) { mpz_powm (ref1, in1, in2, in3); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_powm (res1, res1, in2, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); mpz_set (res1, in2); mpz_powm (res1, in1, res1, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); mpz_set (res1, in3); mpz_powm (res1, in1, in2, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm, in1, in2, in3); } /* Don't run mpz_powm_ui when undefined. */ if (size_range < 17 && mpz_sgn (in3) != 0) { mpz_powm_ui (ref1, in1, in2i, in3); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); mpz_powm_ui (res1, res1, in2i, in3); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm_ui, in1, in2, in3); mpz_set (res1, in3); mpz_powm_ui (res1, in1, in2i, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_powm_ui, in1, in2, in3); } { r1 = mpz_gcd_ui (ref1, in1, in2i); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); r2 = mpz_gcd_ui (res1, res1, in2i); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_gcd_ui, in1, in2, NULL); } if (mpz_sgn (in2) != 0) { /* Test mpz_remove */ mp_bitcnt_t refretval, retval; refretval = mpz_remove (ref1, in1, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, in1); retval = mpz_remove (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || refretval != retval) FAIL2 (mpz_remove, in1, in2, NULL); mpz_set (res1, in2); retval = mpz_remove (res1, in1, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0 || refretval != retval) FAIL2 (mpz_remove, in1, in2, NULL); } if (mpz_sgn (in2) != 0) { /* Test mpz_divexact */ mpz_mul (t, in1, in2); mpz_divexact (ref1, t, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, t); mpz_divexact (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact, t, in2, NULL); mpz_set (res1, in2); mpz_divexact (res1, t, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact, t, in2, NULL); } if (mpz_sgn (in2) > 0) { /* Test mpz_divexact_gcd, same as mpz_divexact */ mpz_mul (t, in1, in2); mpz_divexact_gcd (ref1, t, in2); MPZ_CHECK_FORMAT (ref1); mpz_set (res1, t); mpz_divexact_gcd (res1, res1, in2); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact_gcd, t, in2, NULL); mpz_set (res1, in2); mpz_divexact_gcd (res1, t, res1); MPZ_CHECK_FORMAT (res1); if (mpz_cmp (ref1, res1) != 0) FAIL2 (mpz_divexact_gcd, t, in2, NULL); } } if (isatty (fileno (stdout))) printf ("\r%20s", ""); mpz_clear (bs); mpz_clear (in1); mpz_clear (in2); mpz_clear (in3); mpz_clear (ref1); mpz_clear (ref2); mpz_clear (ref3); mpz_clear (res1); mpz_clear (res2); mpz_clear (res3); mpz_clear (t); if (isatty (fileno (stdout))) printf ("\r"); tests_end (); exit (0); }