## Ex 5.1
def f(x):
    return x*x-2

def dicho(a,b,f,tol):
    """
    Ma super fonction
    """
    c=(a+b)/2
    n=0
    while abs(f(c))>tol:
        c=(a+b)/2
        if f(a)*f(c)<0:
            b=c
        else:
            a=c
        n+=1
    return c,n

a=0
b=2
tol=1e-4

res = dicho(a,b,f,tol)

print(f"Dicho : la racine carrée de 2 vaut : {res[0]} ({res[1]} tours de boucle).\n")

##Ex5.2
def f(x):
    return x*x-2

def secante(x0,x1,f,tol):
    assert x0!=x1, 'Attention, x0 \neq x1!!!'
    n=0
    while abs(f(x1))>tol: # f(xn) est une suite qui tend vers 0
        x_temp = x1 - ((x1-x0)/(f(x1)-f(x0))) * f(x1) # on stocke temporairement le terme suivant
        x0=x1 # Actualisation
        x1=x_temp
        n+=1
    return x1,n

x0=1
x1=2
tol=1e-4

res = secante(x0,x1,f,tol)

print(f"Secante : la racine carrée de 2 vaut : {res[0]} ({res[1]} tours de boucle).\n")

##Ex5.3 Newton
def f(x):
    return x*x-2

def deriv(f,x,h=1e-6):
    """
    Renvoie f'(x)
    """
    return (f(x+h)-f(x))/h

# print(deriv(f,50))
# assert 0==1

def newton(x0,f,tol):
    n=0
    while abs(f(x0))>tol:
        x0 = x0-(f(x0))/(deriv(f,x0))
        n+=1
    return x0,n

x0=2
tol=1e-4

res = newton(x0,f,tol)

print(f"Newton : la racine carrée de 2 vaut : {res[0]} ({res[1]} tours de boucle).\n")

##Ex5.4 Regula
def f(x):
    return x*x-2

def regula(f,a,b,tol):
    assert a!=b, 'Attention, x0 \neq x1!!!'
    n=0
    c=a-((b-a)/(f(b)-f(a)))*f(a)
    while abs(f(c))>tol:
        c=a-((b-a)/(f(b)-f(a)))*f(a)
        if f(a)*f(c)>0:
            a=c
        else:
            b=c
        n+=1
    return c,n

a=1
b=2
tol=1e-4

res = regula(f,a,b,tol)

print(f"Regula : la racine carrée de 2 vaut : {res[0]} ({res[1]} tours de boucle).\n")

## Fiche 2 (1.2)
import numpy as np
import matplotlib.pyplot as plt

a=-50
b=50
n=100

def f(x):
    return np.cos(x)

# np.sqrt(2)

XX = np.linspace(a,b,n) # intervalle [-5,5] discretisé

YY=f(XX)

# print(XX)
print(len(XX))
print(f"Premier elt {XX[0]}")
print(f"Dernier elt {XX[-1]}")
print(f"Avant dernier elt {XX[-2]}")
print(f"51ème elt {XX[50]}")
print(f"Type de XX : {type(XX)}")

# plt.plot(XX,XX)
plt.plot(XX,YY)
plt.show()

## Exemple bilan
import numpy as np
import matplotlib.pyplot as plt

xmax=2.5
xmin=-xmax
n=500

def f(x):
    return ((np.cos(2*x))**2)-x*x

XX = np.linspace(xmin,xmax,n)

# print(len(XX))

plt.plot(XX,f(XX))
plt.axvline(x=0, c="blue", linewidth=1)
plt.axhline(y=0, c="blue", linewidth=1)
# plt.show()

def deriv(f,x,h=1e-6):
    """
    Renvoie f'(x)
    """
    return (f(x+h)-f(x))/h

def newton(x0,f,tol):
    n=0
    while abs(f(x0))>tol:
        x0 = x0-(f(x0))/(deriv(f,x0))
        n+=1
    return x0,n

def newtonN(x0,f,n):
    for _ in range(n):
        x0 = x0-(f(x0))/(deriv(f,x0))
    return x0

x0=2
tol=1e-12

res = newton(x0,f,tol)

print(f"Newton : la racine de f vaut : {res[0]} ({res[1]} tours de boucle).\n")









