/* This is a BCPL implementation of the program that appears in section 10.7 of the book "Number Theory, A Programmer's Guide" by Mark Herkommer. He uses a miraculous formula for pi discovered by David Bailey, Peter Borwein and Simon Plouffe. The formula is pi = the sum from n = 0 to infinity of (4/(8n+1) - 2/(8n+4) - 1/(8n+5) - 1/(8n+6))/(16**n) Using modulo arithmetic, it is possible to find the nth hexadecimal digit of pi without having to compute the others. Herkommer's program uses double length floating point values, but mine uses 32-bit scaled fixed point arithmetic, as a result my version suffer rounding errors for smaller values of n. Using scaled numbers with 28 bits after the decimal point allows this program to compute the hex digits of pi from position 0 to 5000 correctly. It also calculates the digits from position 100000 to 100050 correctly as well as the digit at position one million. There is no guarantee that all the other positions will be computed correctly since errors can arise when long sequences of ones occur in the binary representation of pi, and this is unpredictable. I have just modified this program to output the digits of pi in both hexadecimal and decimal. With 28 fraction bits the first decimal digit to be wrong is at position 7007. Implemented in BCPL by Martin Richards (c) october 2014 */ GET "libhdr" MANIFEST { // Define the scaled arithmetic parameters fraclen = 28 // Number of binary digits after the decimal point // 28 allows numbers in the range -8.0 <= x < 8.0 One = 1<>(fraclen-4)) & #xF } AND powmod(x, n, m) = VALOF { LET res = 1 LET p = x MOD m WHILE n DO { UNLESS (n & 1)=0 DO res := (res * p) MOD m n := n>>1 p := (p*p) MOD m } RESULTIS res } AND tr(str, x) BE { // Output scaled number x in decimal and hex LET d = muldiv( 1_000_000, x, One) LET h = muldiv(#x10000000, x, One) // Just in case fraclen is not 28 writef("%s = %9.6d %8x*n", str, d, h) }