from math import *

sinc = lambda x: sin(x) / x

def binary_search(f, left, right, ε=1e-5):
    middle = left + (right - left)  / 2

    if abs(right - left) / 2 < ε:
        return middle

    if f(start) * f(middle) > 0:
        return binary_search(f, middle, right, ε)
    else:
        return binary_search(f, start, middle, ε)

def newton(f, df, start, iterations: int, ε: float = 1e-9):
    root = start
    for _ in range(iterations):
        root -= f(root) / df(root)
        if abs(f(root)) <= ε:
            return root
    else:
        raise ValueError("Not found")

def rectangles(f, start, end, precision: int):
    integral = 0
    for k in range(precision):
        integral += f(start + k*(end - start)/precision)
    return (end - start)/precision * integral

def trapezoids(f, start, end, precision: int):
    return (
            rectangles(f, start, end, precision) +
            (end - start) / (2 * precision) * (f(end) - f(start))
    )

def euler(F, t_0, y_0, t_1, n):
    values = [y_0]
    t = t_0
    h = (t_1 - t_0) / n
    for k in range(n):
        t = t_0 + k * h
        values.append(
                values[-1] + h * F(t, values[-1])
            )
    return values


import matplotlib.pyplot as plt
from numpy import linspace

plt.plot(linspace(0, 1, 11), euler(lambda t, y: y, 0, 1, 1, 10))
plt.plot(linspace(0, 1, 11), [exp(x) for x in linspace(0, 1, 11)])

plt.show()
