
# padeExp.py
# Andrew Davison, ad@coe.psu.ac.th, June 2026
"""
Code for the Pade question at the end of
the Function Approximations chapter.

"""

import math
from fractions import Fraction
import faUtils
import sympy as sp


x = sp.symbols('x')
fName = "exp(-x)" 
spFn = lambda x: sp.exp(-x)
fn = lambda x: math.exp(-x)
data = [0.2, 0.4, 0.6, 0.8, 1]

# Uncommemnt one of these lines:
# n = 0; m = 5
# n = 1; m = 4
# n = 2; m = 3
# n = 3; m = 2
# n = 4; m = 1
n = 5; m = 0

print(f"\nMaclaurin series of {fName} with {n+m+1} terms")
fCoeffs = faUtils.seriesCoefs(spFn, nTerms=(n+m+1), verbose=True)

print(f"\nPade Approx of {fName} for order ({n},{m})")
p, q, _ = faUtils.padeApprox(spFn, n, m)

print()
print("    x      Actual     Pade       Mac"
      "         Pade Err    Mac Err" )
print( "-"*67)

tot = 0.0
for xVal in data:
  try:
    actual = fn(xVal)
    pade = float( faUtils.evalPade(xVal, p, q))
    mac =  faUtils.evalPowers(fCoeffs, xVal)
  except (ValueError, ZeroDivisionError, TypeError):
    print(f"{xVal:8.3f}   (domain error, skipped)")
    continue

  pErr = abs(pade - actual)
  tot += pErr
  mErr = abs(mac - actual)
  print(f"{xVal:8.3f} {actual:10.6f} {pade:10.6f} "
        f"{mac:10.6f}  {pErr:10.6f}  {mErr:10.6f}")

print(f"\nAverage Pade error {(tot/len(data)):10.6f}")
