1 
/** Calculate pi at compile time 

2 
* 

3 
* Compile with dmd c pi.d 

4 
*/ 

5 
module calcpi; 

6 


7 
import meta.math; 

8 
import meta.conv; 

9 


10 
/** real evaluateSeries!(real x, real metafunction!(real y, int n) term) 

11 
* 

12 
* Evaluate a power series at compile time. 

13 
* 

14 
* Given a metafunction of the form 

15 
* real term!(real y, int n), 

16 
* which gives the nth term of a convergent series at the point y 

17 
* (where the first term is n==1), and a real number x, 

18 
* this metafunction calculates the infinite sum at the point x 

19 
* by adding terms until the sum doesn't change any more. 

20 
*/ 

21 
template evaluateSeries(real x, alias term, int n=1, real sumsofar=0.0) 

22 
{ 

23 
static if (n>1 && sumsofar == sumsofar + term!(x, n+1)) { 

24 
const real evaluateSeries = sumsofar; 

25 
} else { 

26 
const real evaluateSeries = evaluateSeries!(x, term, n+1, sumsofar + term!(x, n)); 

27 
} 

28 
} 

29 


30 
/*** Calculate atan(x) at compile time. 

31 
* 

32 
* Uses the Maclaurin formula 

33 
* atan(z) = z  z^3/3 + Z^5/5  Z^7/7 + ... 

34 
*/ 

35 
template atan(real z) 

36 
{ 

37 
const real atan = evaluateSeries!(z, atanTerm); 

38 
} 

39 


40 
template atanTerm(real x, int n) 

41 
{ 

42 
const real atanTerm = (n & 1 ? 1 : 1) * pow!(x, 2*n1)/(2*n1); 

43 
} 

44 


45 
/// Machin's formula for pi 

46 
/// pi/4 = 4 atan(1/5)  atan(1/239). 

47 
pragma(msg, "PI = " ~ fcvt!(4.0 * (4*atan!(1/5.0)  atan!(1/239.0))) ); 
