# -*- coding: utf-8 -*-
"""
 methode_rectangle.py
 
 
"""

# Import

import numpy as np
import matplotlib.pyplot as plt

# Fonctions communes


def f1(x):
    return 4/(1+x**2)

def f2(x):
    return 1/(1+x)

def f3(x):
    return 4*np.sqrt(1-x**2)

def test(x):
    """
    Fonction polynomiale de degré 1 ou 2 pour tester les méthodes
    """
    return x**2-2*x+3

def Rectangle_g(f,a,b,n):
    """ 
    Arguments : une fonction f, un intervalle [a,b] , un nombre de subdivision n
    Sortie : la valeur approchée de intégrale de f sur [a,b] par la méthode des rectangles à gauche avec n rectangles
    """
    x=a
    S=0
    for k in range(n):
        S = S + f(x)
        x = x + (b-a)/n
    return (b-a)/n*S

def Rectangle_m(f,a,b,n):
    """ 
    Arguments : une fonction f, un intervalle [a,b] , un nombre de subdivision n
    Sortie : la valeur approchée de intégrale de f sur [a,b] par la méthode des rectangles milieux avec n rectangles
    """
    h= (b-a)/n  # pas de la subdivision
    m=(a+a+h)/2 # milieu de l'intervalle
    S=0
    for k in range(n):
        S = S + f(m)
        m = m + h
    return h*S

def Trapeze(f,a,b,n):
    """ 
    Arguments : une fonction f, un intervalle [a,b] , un nombre de subdivision n
    Sortie : la valeur approchée de intégrale de f sur [a,b] par la méthode des trapèzes avec n rectangles
    """
    h= (b-a)/n # pas de la subdivision
    x=a
    S=0
    for k in range(n):
        S = S + 1/2*h*(f(x)+f(x+h))
        x=x+h
    return S

def Simpson(f,a,b,n):
    """ 
    Arguments : une fonction f, un intervalle [a,b] , un nombre de subdivision n
    Sortie : la valeur approchée de intégrale de f sur [a,b] par la méthode de Simpson avec n rectangles
    """
    h=(b-a)/n #pas de la subdivision
    x = a
    S = 0
    for k in range(n):
        S = S + f(x)+f(x+h)+4*f(x+h/2)
        x = x+h
    return h/6*S

# Constante :

F1 = np.pi # int(0,1,f1)
F2 = np.log(2) #int(0,1,f2)

#%% Tests polynomiaux

# Méthode des rectangles milieux : exacte sur des polynomes de deg 1 
# Méthode de Simpson : exacte sur des polynomes de deg 2  

for n in range(1,10):
    print(Simpson(test,0,1,n))

#%% Comparaison

N =range(2,50)
E1 = [np.abs(Simpson(f1,0,1,n)-np.pi) for n in N]  # erreur en fonction de n pour Simpson
E2 = [np.abs(Rectangle_m(f1,0,1,n)-np.pi) for n in N]  # erreur en fonction de n pour Rectangles milieux
E3 = [np.abs(Trapeze(f1,0,1,n)-np.pi) for n in N]      # g+erreur en fonction de n pour Trapèze
E4 = [np.abs(Rectangle_g(f1,0,1,n)-np.pi) for n in N] # erreur en fonction de n pour Rectangles gauche
#plt.plot(N,E3,label='Trapeze')
plt.plot(N,E1, label='Simpson')
plt.plot(N,E2, label='Rectangles milieux')
#plt.plot(N,E4, label='Rectangles gauche')
plt.legend()
plt.show()