
# seriesPi.py
'''
  Leibniz’ formula
  https://en.wikipedia.org/wiki/Leibniz_formula_for_%CF%80
  pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 - ...

and
  Gregory's series for the inverse tangent function
  https://en.wikipedia.org/wiki/Gregory%27s_series
  https://www.craig-wood.com/nick/articles/pi-gregorys-series/

and
    https://en.wikipedia.org/wiki/Wallis_product
    PI     2     2     4     4     6     6     8    
   ---- = --- * --- * --- * --- * --- * --- * --- *  ....
    2      1     3     3     5     5     7     7 

and
  The Basel problem
  https://en.wikipedia.org/wiki/Basel_problem
  pi^2/6 = \sum 1/n^2
'''

import math, time

def leibniz(n):
  return sum([4/i - 4/(i+2) for i in range(1, 2*n+1, 4)])

def gregory(n):
  return 4*atan(1,n)

def atan(x, n):
  tot = 0
  mult = 1
  for i in range(n):
    tot += mult * (x**(2*i+1))/(2*i+1)
    mult *= -1
  return tot

def wallis(n):
  return 2 * math.prod((i*i)/((i-1)*(i+1)) for i in range(2, n, 2))

def basel(n):
  return math.sqrt(6*sum([1/(x*x) for x in range(1, n)]))

# ------------------------------------

fnm = input("fnm (leibniz, gregory, wallis, basel)? ")
fn =  globals()[fnm]  # string --> function

ns = [ 10, 100, 1000, 10000, 1000000, 10000000 ]
print("Series " + fnm +"(n)")
print("     n         estPi              err      secs")
for n in ns:
  start = time.time()
  estPi = fn(n)
  end = time.time() - start
  err = estPi - math.pi
  print(f"{n:8d}: {estPi:.12f}; {err:.12f}; {end:.3f}")

print("\n math.pi:", math.pi)
