You are on page 1of 3

#An algorithm that implements the BBP algorithm (Bailey-Borwein-Plouffe

formula).
#Ported from the c implementation by David H. Bailey. It allows the nth
digit of
#pi to be calculated without calculating the n-1 digits before. This method
holds
#advantages over alternative method of calculating Pi. Such as a small
memory
#footprint that does not increase. Output is an array of hexadecimal values
where
#the number of correct values after the nth digit is dependent on floating
point
#precisions.
#
#“On most systems using IEEE 64-bit floating-
# Point arithmetic, this code works correctly so long as d is less than
# Approximately 1.18 x 10^7. If 80-bit arithmetic can be employed, this
limit
# is significantly higher. Whatever arithmetic is used, results for a
given
# position id can be checked by repeating with id-1 or id+1, and
verifying
# that the hex digits perfectly overlap with an offset of one, except
possibly
# for a few trailing digits. The resulting fractions are typically
accurate
# to at least 11 decimal digits, and to at least 9 hex digits” – from
David H.
# Bailey’s notes on implementation.

#Tested againest c applications for a varity of values all tests passed

def hexpi_nth_digits(id):

#id is the digit position. Digits generated id + onwards.

s1 = float(series(1, id))
s2 = float(series(4, id))
s3 = float(series(5, id))
s4 = float(series(6, id))

pid = float((4.0 * s1 - 2.0 * s2 - s3 - s4))


pid = pid - int(pid)
if (pid < 0.0):
pid = pid + 1.0
chx = ihex(pid, 16)
return chx
def ihex(x,nhx):

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

hx = [0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F"]
y = float(abs(x))
chx = range(nhx)

for i in range(0, nhx):


y = 16.0 * (y % 1);
chx[i] = hx[int(y)]

return chx

def series(m,id):

# This routine evaluates the series sum_k 16^(id-k)/(8*k+m)


# modular exponentiation technique.

s =0.0
ak=0.0
p=0.0
s=0.0
t=0.0
eps = float((10**(-17)))

#series being sumed

for k in range(0, id):


ak = 8 * k + m
p = id - k
t = expm(p, ak)
s = s + t / ak
s = s - int(s)

for k in range(id, id+100):


ak = 8 * k + m
t = (16.0 ** float((id - k))) / ak
if (t < eps):
break
s = s + t
s = s - int(s)

return s
def expm(p,ak):

#left to right binary exponentiation

ntp = 25
exi = 0
p1 = 0.0
pt = 0.0
r = 0.0
tp1 = 1
tp = range(ntp)

if (tp1 == 0):
tp1 = 1
tp[0] = 1.0

for i in range(1, ntp):


tp[i] = 2.0 * tp[i-1]
exi = ntp
if (ak == 1.0):
return 0.0

exi = ntp
for i in range(1, ntp):
exi = i
if (tp[i] > p):
break

pt = float(tp[exi-1])
p1 = p
r = 1.0

for j in range(1, exi):


if (p1 >= pt):
r = 16.0 * r
r = r - int((int((r/ak))*ak))
p1 = p1 - pt
pt = 0.5*pt
if (pt >= 1.0):
r = r*r
r = r - int((int((r/ak)) * ak))

return r

You might also like