[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

more fun with pi



counts off the numbers of pi.


you might like this:

// piextraction.c

#include <math.h>
#include "obviate.h"
#include "Utilitaire.h"
#include "piextraction.h"

#define NHX 16
#define eps 1e-17

/*
This function employs the recently discovered digit piextraction scheme
to produce hex digits of .  This code is valid up to ic = 2^24 on
systems with IEEE arithmetic.	(David H. Bailey     960429)
*/

void piextraction(void)
{
	double pid, s1, s2, s3, s4;
	int ic = 1000000; char chx[NHX];

/*  ic is the hex digit position -- output begins at position ic + 1. */

	s1 = series(1,ic); s2 = series(4,ic);
	s3 = series(5,ic); s4 = series(6,ic);
	pid = 4. * s1 - 2. * s2 - s3 - s4;
	pid = pid - (int) pid + 1.;
	ihex (pid,NHX,chx);

 printf ("Pi hex digit computation\n");
 printf ("position = %i + 1\n %20.15f\n %12.12s\n", ic, pid, chx);

}

/*
This returns, in chx, the first nhx hex
digits of the fraction of x.
*/

void ihex(double x,int nhx,char chx[])
{
	int i; double y;
	char hx[] = "0123456789ABCDEF";

	y = fabs (x);
	for (i = 0;i < nhx;i++){
		y = 16. * (y - floor(y));
		chx[i] = hx[(int)y];
	}
}

/*
This routine evaluates the series  sum_k 16^(ic-k)/(8*k+m)
using the modular exponentiation technique.
*/

double series(int m,int ic)
{
	int k; double ak,p,s,t;
	double expm(double x,double y);

 	s = 0.;

/*  Sum the series up to ic. */
	for(k = 0; k < ic;k++){
		ak = 8 * k + m;
		p = ic - k;
		t = expm (p, ak);
		s = s + t / ak;
		s = s - (int) s;
	}

/*  Compute a few terms where k >= ic. */
	for(k = ic; k <= ic + 100;k++){
		ak = 8 * k + m;
		t = pow (16.,(double)(ic - k))/ak;
		if (t < eps) break;
		s = s + t; s = s - (int) s;
	}
	return s;
}


/* expm = 16^p mod ak. This routine uses the left-to-right binary exponentiation scheme. It is valid for ak <= 2^24. */

double expm (double p,double ak)
{
	int i, j; double p1, pt, r;
	#define ntp 25
	static double tp[ntp];
	static int tp1 = 0;

/*  If this is the first call to expm,
fill the power of two table tp. */
	if(tp1 == 0) {
		tp1 = 1; tp[0] = 1.;
		for (i = 1;i < ntp;i++)
			tp[i] = 2. * tp[i-1];
	}
	if(ak == 1.) return 0.;

/*  Find the greatest power of two less than or equal to p. */
	for(i = 0;i < ntp;i++) if(tp[i] > p) break;
	pt = tp[i-1]; p1 = p; r = 1.;

/*  Perform binary exponentiation algorithm modulo ak. */
	for (j = 1;j <= i;j++){
		if (p1 >= pt){
			r = 16. * r;
			r = r - (int)(r/ak)*ak;
			p1 = p1 - pt;
		}
		pt = 0.5 * pt;
			if (pt >= 1.){
			r = r * r;
			r = r - (int) (r / ak) * ak;
		}
	}
	return r;
}





// eof



              Akira


_________________________________________________________________ Get your FREE download of MSN Explorer at http://explorer.msn.com