# L-16 MCS 275 Wed 20 Feb 2008 : chebiter.py

# The value of the n-th Chebyshev polynomial
# T(n,x) is recursively computed as follows
# T(0,x) = 1, T(1,x) = x, 
# T(n,x) = 2x T(n-1,x) - T(n-2,x),  for n > 1.
# Define a function to compute the value for 
# T(n,x) iteratively, in two versions:
# once using a stack of function calls;
# and once by storing the computed function 
# values in a list.

def Chebyshev(n,x):
   """
   Recursive evaluation of n-th Chebyshev
   polynomial at x.
   """
   if n == 0:
      return 1
   elif n == 1:
      return x
   else:
      return 2*x*Chebyshev(n-1,x) - Chebyshev(n-2,x)

def Chebyshev0(n,x,k):
   """
   Recursive Chebyshev with trace shows
   how wasteful this recursion is.
   """
   s = k*' '
   s = s + 'T(%d,' % n + str(x) + '): '
   if n == 0:
      print s + 'return 1'
      return 1
   elif n == 1:
      print s + 'return ' + str(x)
      return x
   else:
      c1 = Chebyshev0(n-1,x,k+1)
      c2 = Chebyshev0(n-2,x,k+1)
      r = 2*x*c1 - c2
      print s + 'return ' + str(r)
      return r

def Chebyshev1(n,x):
   """
   Maintains a stack of function calls
   to compute the value of the nth Chebyshev
   polynomial at x.  Observe how the stack
   is accumulating the products.
   """
   S = [(1,n,x)]
   result = 0
   while S != []:
       print 'S =', S
       (a,n,x) = S.pop(0)
       if n == 0:
          result = result + a
       elif n == 1:
          result = result + a*x
       else:
          S.insert(0,(-a,n-2,x))
          S.insert(0,(2*x*a,n-1,x))
   return result

def Chebyshev2(n,x):
   """
   Maintains a list of function values
   to compute the value of the nth Chebyshev
   polynomial at x. 
   """
   L = map(lambda i:0,range(0,n+1))
   L[0] = 1
   L[1] = x
   for k in range(2,n+1):
      L[k] = 2*x*L[k-1] - L[k-2]
   return L

def main():
   """
   Prompts the user for degree and x.
   """
   n = input('give n : ')
   x = input('give x : ')
   y = Chebyshev(n,x)
   y0 = Chebyshev0(n,x,0)
   y1 = Chebyshev1(n,x)
   Ly = Chebyshev2(n,x)
   print y, y0, y1
   print Ly

main()
