from math import floor import support.parsing from support.canonicalize import * from src.newton import newton from src.differentiation import evaluate_diff from math import factorial, ceil @cache def nth_derivative(func, n): """self explanatory for now...""" return None @cache def taylor(func_name, x, N): """ Returns the taylor expansion of func as a function of x, centered at 'b'. Since the 0th term is just the function itself (which we don't have the answer for yet), it should be replaced with a variable 'q' instead of the actual function. The expansion should go to N terms (see variable defined above). """ return None def taylor_at(func_name, b, f_at_b, N): """ Returns taylor(-), evaluated by plugging in f_at_b for 'q' and b for 'b'. """ return None def max_error(func_name, a, x, n): """ Calculates the maximum error of the estimate below using Taylor's Theorem in the following way. Taylor's Theorem says that we can upper bound the error of a taylor series with N terms with the following expression for some a <= c <= x (or x <= c <= a, symmetrically): error(x) = f^(N + 1)(c) * (x - a)^(N + 1)/(n+1)! So, if we can find an upper bound for f^(N + 1)(c), then we can upper bound the error. We consider three cases: 1) f^(N + 1) is increasing on the interval [a, x]. Then, f^(N + 1)(x) is the maximum. 2) f^(N + 1) is decreasing on the interval [a, x]. Then, f^(N + 1)(a) is the maximum. 3) There is a turning point on the interval [a, x]. Then, we need to attempt to find the maximum in that interval. To do this, we find a zero of f^(N + 2), which indicates a maximum in f^(N + 1). To do that, we use our newton(-) function from the previous part on f^(N + 2) with an initial guess of x. Then, we take the max of the absolute value of each of the 3 cases. This should give us some M, where M >= f^(N + 1)(c). Finally, plug M into the equation above for f^(N + 1)(c) and return that value. """ return None @cache def estimate(func_name, x, a, func_at_a, N): """ Uses the taylor expansion centered around a to compute an estimate for func(x). """ return None PI = 3.14159265358979323846264338327950288419716939937510582097494 @cache def arctan(x): N = 10 if x == 0: return 0, 0 elif x == 1: return PI/4, 10**(-1) total_error = max_error('arctan', floor(x), x, N) prev_value, total_error = arctan(floor(float(x) - 0.0001)) return float(estimate('arctan', x, floor(x), prev_value, N)), total_error + float(max_error('arctan', floor(x), x, N)) if __name__ == "__main__": for i in range(0, 4): for j in range(10): x = i + j/10 v, e = arctan(Decimal(x)) print('arctan(' + str(x) + ') =', v, '(error <= ' + str(e) + ')')