Example #1
0
 void log10(const mpz_t n, mpz_t l, int prec) {
   mpf_t tmp, tmp2;
   mpf_inits(tmp, tmp2, NULL);
   mpf_set_z(tmp, n);
   log10(tmp, tmp2, prec);
   mpz_set_f(l, tmp2);
   mpf_clears(tmp, tmp2, NULL);    
 }
Example #2
0
 void log2(const mpz_t n, mpz_t l) {
   mpf_t tmp, tmp2;
   mpf_inits(tmp, tmp2, NULL);
   mpf_set_z(tmp, n);
   log2(tmp, tmp2);
   mpz_set_f(l, tmp2);
   mpf_clears(tmp, tmp2, NULL);        
 }
Example #3
0
 void log(const mpz_t n, mpz_t l, mpz_t b) {
   mpf_t tmp, tmp2, tmp3;
   mpf_inits(tmp, tmp2, tmp3, NULL);
   mpf_set_z(tmp, n);
   mpf_set_z(tmp3, b);    
   log(tmp, tmp2, tmp3);
   mpz_set_f(l, tmp2);
   mpf_clears(tmp, tmp2, tmp3, NULL);            
 }
Example #4
0
 void log(const mpf_t n, mpf_t l, mpf_t b) {
   // l = log10(n)/log10(b)
   mpf_t tmp, tmp2;
   mpf_inits(tmp, tmp2, NULL);
   log10(n, tmp);
   log10(b, tmp2);
   mpf_div(l, tmp, tmp2);
   mpf_clears(tmp, tmp2, NULL);            
 }  
Example #5
0
  void log10(const mpf_t n, mpf_t l, int prec) {
    // Approximate log10 to prec digits.
    // Ref.: http://www.brics.dk/RS/04/17/BRICS-RS-04-17.pdf
    mpf_t tmp, tmp2;
    mpf_inits(tmp, tmp2, NULL);
    mpf_set(tmp, n);

    stringstream res;
    for (int i = 0; i < prec + 1; i++) { 
      int d = digits(tmp);

      // m_(i+1) = (m_i / (10 ^ a_i)) ^ 10 
      mpf_set_ui(tmp2, 10);
      mpf_pow_ui(tmp2, tmp2, d);
      mpf_div(tmp2, tmp, tmp2);
      mpf_pow_ui(tmp, tmp2, 10);

      res << d;      
      if (i == 0) res << ".";
    }

    mpf_set_str(l, res.str().c_str(), 10);
    mpf_clears(tmp, tmp2, NULL);
  }
Example #6
0
//Le but de la fonction est de calculer le développement en fractions continue jusqu'à un certain rang de racine carrée de kN et de stocker les couples (A_n-1,Q_n) comme décrit dans la section (à venir)
cfrac expand(const mpz_t N, const long long unsigned int rang, const mpz_t k)
{
	cfrac res;	//Contient l'ensemble des A_n-1 et l'ensemble Q_n
	mpz_inits(res.N, res.k, res.g, NULL);

	//Initialisation des variables
	mpz_t* A = (mpz_t*)malloc((rang+1)*sizeof(mpz_t));		//Le tableau contenant les A_n-1
	mpz_t* Q = (mpz_t*)malloc((rang+2)*sizeof(mpz_t));		//Le tableau contenant les Q_n
	mpz_t* P = (mpz_t*)malloc((rang+1)*sizeof(mpz_t));		//Éléments reliés au Q_n
	mpz_t* r = (mpz_t*)malloc((rang+1)*sizeof(mpz_t));		//Interviennent dans le calcul des A_n-1 & Q_n
	mpz_t* q = (mpz_t*)malloc(rang*sizeof(mpz_t));			//Idem
	mpz_t g, tempz;											//Idem, tempz = variable à tout faire	
	mpf_t sqrtkN, tempf, tempf2;									//sqrtkN = sqrt(k*N), tempf = variable à tout faire

	

	//Valeurs d'initialisation de la boucle
	mpz_inits(g, A[0], Q[0], r[0], tempz, NULL);
	mpf_inits(tempf, sqrtkN, tempf2, NULL);

	//Initialisation des différentes valeurs "indépendantes"

	mpz_set(tempz, N);
	mpz_mul(tempz, tempz, k);
	mpf_set_z(sqrtkN, tempz);
	mpf_sqrt(sqrtkN, sqrtkN);
	mpf_floor(tempf, sqrtkN);
	mpz_set_f(g, tempf);				//g = [sqrt(kN)]

	mpz_set(Q[0], k);
	mpz_mul(Q[0], Q[0], N);				//Q_-1 = kN = Q[0]
	mpz_set(r[0], g);					//r_-1 = r[0]
	mpz_set_ui(A[0], 1);				//A_-1 = A[0]

	
	//Calcul de P_0 & Q_0
	mpz_init_set_ui(Q[1], 1);			//Q_0 = Q[1]
	mpz_init_set_ui(P[0], 0);			//P_0 = P[0]	

	for(long long int i = 0; i < rang; i++)
	{
		switch(i)
		{
			case 0:

				//Calcul de q_0
				mpz_init_set(q[0], g);				//q_0 = [(sqrt(kN) + P_0)/Q_0] avec P_0 = 0 et Q_0 = 1

				//Calcul de A_0
				mpz_init_set(A[1],A[0]);
				mpz_mul(A[1], A[1], q[0]);			//A_0 = q_0*A_-1
				mpz_mod(A[1], A[1], N);				//On réduit mod N

				//Calcul de r_0
				mpz_init_set_ui(r[1], 0);			//r_0 = P_0 + g - q_0.Q_0 = 0 + g - g.1 = 0

				//Calcul de P_1
				mpz_init_set(P[1], g);				//P_1 = g - r_0 = g - 0 = g

				//Calcul de Q_1 = Q[2]
				mpz_init_set(Q[2], r[1]);		
				mpz_sub(Q[2], Q[2], r[0]);
				mpz_mul(Q[2], Q[2], q[0]);
				mpz_add(Q[2], Q[2], Q[0]);
				
				break;
			default:
				//Calcul q_i
				mpz_init(q[i]);	
				mpf_set_z(tempf, P[i]);
				mpf_set_z(tempf2, Q[i+1]);
				mpf_add(tempf, tempf, sqrtkN);				//sqrt(kN) + P_i
				mpf_div(tempf, tempf, tempf2);		
				mpf_floor(tempf, tempf);					//floor((sqrt(kN) + P_i)/Q_i)
				mpz_set_f(q[i], tempf);

				//Calcul de r_n = r[n+1]	
				mpz_init(r[i+1]);
				mpz_submul(r[i+1], q[i], Q[i+1]);
				mpz_add(r[i+1], r[i+1], P[i]);
				mpz_add(r[i+1], r[i+1], g);

				//Calcul de A_n = A[n+1] 		
				mpz_init_set(A[i+1],A[i]);
				mpz_mul(A[i+1], A[i+1], q[i]);		//A_i-1*q_i
				mpz_add(A[i+1], A[i+1], A[i-1]);	//A_i-1*q_i + A_i-2
				mpz_mod(A[i+1], A[i+1], N);			//réduction modulo N

				//Calcul P_n+1 
				mpz_init_set(P[i+1], g);
				mpz_sub(P[i+1], P[i+1], r[i+1]);		//P[n+1] = g - r_n = g - r[n+1]

				//Calcul Q_n+1 = Q[n+2]
				mpz_init_set(Q[i+2], r[i+1]); 
				mpz_sub(Q[i+2],	Q[i+2], r[i]);		//(r_n - r_n-1)
				mpz_mul(Q[i+2], Q[i+2], q[i]);		//q_n(r_n - r_n-1)
				mpz_add(Q[i+2], Q[i+2], Q[i]);		//Q_n-1 + q_n(r_n - r_n-1)
				
				break;
		}

	}

	//Test de routine pour voir si le développement de la fraction continue s'est bien passé
	mpz_t tempsqrt;
	mpz_init(tempsqrt);
	mpz_set(tempsqrt, k);
	mpz_mul(tempsqrt, tempsqrt, N);
	mpz_sqrt(tempsqrt, tempsqrt);
	mpz_mul_ui(tempsqrt, tempsqrt, 2);

	for(int i = 1; i < rang; i++)				//Éviter de commencer à i = 0 puisque cela représente Q_-1 qui n'intervient uniquement dans l'algo et non dans le développement en fraction continue
	{
		if(mpz_cmp(Q[i], tempsqrt) >= 0)	//Si Q_n >= 2sqrt(kN)
		{
			res.rang = 0;

			mpz_clears(g, tempz, NULL);
			mpf_clears(sqrtkN, tempf, tempf2, NULL);
			return res;
		}
	}

	//Assignation des tableaux dans le résultat
	res.A = A;
	res.Q = Q;
	res.r = r;
	res.q = q;
	res.P = P;
	mpz_set(res.N, N);
	mpz_set(res.k, k);
	res.rang = rang;
	mpz_set(res.g, g);

	//Libération de mémoire
	mpz_clears(g, tempz, NULL);
	mpf_clears(sqrtkN, tempf, tempf2, NULL);

	return res;
}
Example #7
0
void
check_random (long reps)
{
  unsigned long test;
  gmp_randstate_ptr rands = RANDS;
  mpf_t a, b, x;
  mpz_t ds;
  int hibits, lshift1, lshift2;
  int xtra;

#define HIBITS 10
#define LSHIFT1 10
#define LSHIFT2 10

  mpf_set_default_prec ((1 << HIBITS) + (1 << LSHIFT1) + (1 << LSHIFT2));

  mpz_init (ds);
  mpf_inits (a, b, x, NULL);

  for (test = 0; test < reps; test++)
    {
      mpz_urandomb (ds, rands, HIBITS);
      hibits = mpz_get_ui (ds) + 1;
      mpz_urandomb (ds, rands, hibits);
      mpz_setbit (ds, hibits  - 1);	/* make sure msb is set */
      mpf_set_z (a, ds);
      mpf_set_z (b, ds);

      mpz_urandomb (ds, rands, LSHIFT1);
      lshift1 = mpz_get_ui (ds);
      mpf_mul_2exp (a, a, lshift1 + 1);
      mpf_mul_2exp (b, b, lshift1 + 1);
      mpf_add_ui (a, a, 1);	/* make a one-bit difference */

      mpz_urandomb (ds, rands, LSHIFT2);
      lshift2 = mpz_get_ui (ds);
      mpf_mul_2exp (a, a, lshift2);
      mpf_mul_2exp (b, b, lshift2);
      mpz_urandomb (ds, rands, lshift2);
      mpf_set_z (x, ds);
      mpf_add (a, a, x);
      mpf_add (b, b, x);

      insert_random_low_zero_limbs (a, rands);
      insert_random_low_zero_limbs (b, rands);

      if (mpf_eq (a, b, lshift1 + hibits) == 0 ||
	  mpf_eq (b, a, lshift1 + hibits) == 0)
	{
	  dump_abort (a, b, lshift1 + hibits, lshift1, lshift2, hibits, 1, test);
	}
      for (xtra = 1; xtra < 100; xtra++)
	if (mpf_eq (a, b, lshift1 + hibits + xtra) != 0 ||
	    mpf_eq (b, a, lshift1 + hibits + xtra) != 0)
	  {
	    dump_abort (a, b, lshift1 + hibits + xtra, lshift1, lshift2, hibits, 0, test);
	  }
    }

  mpf_clears (a, b, x, NULL);
  mpz_clear (ds);
}
Example #8
0
void *chudnovsky_chunk(void *arguments)
{
	unsigned long int k, threek, total_iterations;
	mpz_t a, b, c, d, e, rt, rb;
	mpf_t rtf, rbf, r;
	struct thread_args *args = (struct thread_args *)arguments;

	total_iterations = args->iter;

	/* Init libgmp variables */
	mpz_inits(a, b, c, d, e, rt, rb, NULL);
	mpf_inits(rtf, rbf, r, NULL);

	/* Main loop of a thread */
	while (1) {
		/* Check which k needs calculation */
		pthread_mutex_lock(&args->start_mutex);
		k = args->k;
		args->k++;
		pthread_mutex_unlock(&args->start_mutex);
		/* If all ks are done, say return */
		if (k > total_iterations) break;
		/* 3k */
		threek = k * 3;
		/* (6k!) */
		mpz_fac_ui(a, threek << 1);
		/* 545140134k */
		mpz_set_ui(b, BCONST1);
		mpz_mul_ui(b, b, k);
		/* 13591409 + 545140134k */
		mpz_add_ui(b, b, BCONST2);
		/* (3k)! */
		mpz_fac_ui(c, threek);
		/* (k!)^3 */
		mpz_fac_ui(d, k);
		mpz_pow_ui(d, d, DCONST1);
		/* (-640320)^3k */
		mpz_set_ui(e, ECONST1);
		mpz_pow_ui(e, e, threek);
		if ((threek & 1) == 1) mpz_neg(e, e);
		/* Get everything together */
		/* (6k)! (13591409 + 545140134k) */
		mpz_mul(rt, a, b);
		/* (3k)! (k!)^3 */
		mpz_mul(rb, c, d);
		mpz_mul(rb, rb, e);
		/* Switch to floats */
		mpf_set_z(rtf, rt);
		mpf_set_z(rbf, rb);
		/* divide top/bottom */
		mpf_div(r, rtf, rbf);
		/* add result to the sum */

		pthread_mutex_lock(&args->sum_mutex);
		mpf_add(args->sum, args->sum, r);
		pthread_mutex_unlock(&args->sum_mutex);
	}

	/* Deinit variables, result is passed via args->sum */
	mpz_clears(a, b, c, d, e, rt, rb, NULL);
	mpf_clears(rtf, rbf, r, NULL);
}
Example #9
0
int chudnovsky(int digits, int threads)
{
	int res = 0;
	unsigned long int i, iter, precision, rest, per_cpu, k;
	mpf_t ltf, sum, result;
	pthread_t *pthreads;
	struct thread_args targs;
        mp_exp_t exponent;
        char *pi;

	/* If threads is not specified, check how many CPUs are avail */
	if (threads == 0) {
		threads = get_cpu_count();
	}

	pthreads = malloc(threads * sizeof(pthread_t));
	if (pthreads == NULL) {
		res = -ENOMEM;
		goto chudnovsky_exit;
	}

	/* Calculate and set precision */
	precision = (digits * BPD) + 1;
	mpf_set_default_prec(precision);

	/* Calculate number of iterations */
	iter = digits/DPI + 1;

	/* Init all objects */
	mpf_inits(ltf, sum, result, targs.sum, NULL);
	mpf_set_ui(sum, 0);
	mpf_set_ui(targs.sum, 0);

	/* Set pthread specific stuff */
	targs.k = 0;
	targs.iter = iter;
	pthread_mutex_init(&targs.start_mutex, NULL);
	pthread_mutex_init(&targs.sum_mutex, NULL);

	/* Prepare the constant from the left side of the equation */
	mpf_sqrt_ui(ltf, LTFCON1);
	mpf_mul_ui(ltf, ltf, LTFCON2);

	printf("Starting summing, using:\n"
		"%d digits - %lu iterations - %d threads\n",
		digits, iter, threads);

	for (i = 0; i < threads; i++) {
		pthread_create(&pthreads[i], NULL, &chudnovsky_chunk, (void *) &targs);
	}

	/* Wait for threads to finish and take their sums */
	for (i = 0; i < threads; i++) {
		pthread_join(pthreads[i], NULL);
	}

	printf("Starting final steps\n");

	/* Invert sum */
	mpf_ui_div(sum, 1, targs.sum);
	mpf_mul(result, sum, ltf);

	/* Get one more char then needed and then trunc to avoid rounding */
	pi = mpf_get_str(NULL, &exponent, 10, digits + 2, result);
	pi[digits+1] = '\0';

	if (strlen(pi) < LAST_DIGITS_PRINT + 1) {
		printf("Calculated PI:\n");
		printf("\t%.*s.%s\n", (int)exponent, pi, pi + exponent);
	} else {
		printf("Last digits of Pi are:\n");
		printf("\t%s\n", pi+(digits-(LAST_DIGITS_PRINT-1)));
	}

	free(pi);

	mpf_clears(ltf, sum, result, NULL);
	pthread_mutex_destroy(&targs.start_mutex);
	pthread_mutex_destroy(&targs.sum_mutex);

	/* TODO: add verification here! */

chudnovsky_free_pthreads:
	free(pthreads);
chudnovsky_exit:
	return res;
}