# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 07:30:49 2018

@author: adrian
"""

# Regla de Simpson 1/3

import math
from scipy.optimize import fsolve
from numpy import sign
from numpy import exp
 
# Función f(x)
def f(x):
    return 4+math.cos(x+1)

# Función g(x)
def g(x):
    return (math.exp(x))*(math.sin(x))
 
# Función para aproximación de la integral
def simpson( limInf, limSup, nParticiones, funcion ):
 
    # Cálculo del valor de h
    h = ( limSup - limInf )/nParticiones
 
    # List for storing value of x and f(x)
    x = list()
    fx = list()
     
    # Calcular valores de x y f(x)
    i = 0
    while i<= nParticiones:
        x.append(limInf + i * h)
        fx.append(funcion(x[i]))
        i += 1
 
    # Cálculo del resultado
    res = 0
    i = 0
    while i<= nParticiones:
        if i == 0 or i == nParticiones:
            res+= fx[i]
        elif i % 2 != 0:
            res+= 4 * fx[i]
        else:
            res+= 2 * fx[i]
        i+= 1
    res = res * (h / 3)
    return res

def busquedaIncremental(f,a,b,intervalo,error):
    
    x1 = a
    x2 = a + intervalo
    f1 = f(a) 
    f2 = f(x2)   
    
    while (sign(f1) == sign(f2) and abs(x2-x1)>=error):
        if (x2 >= b): 
            return None
        else:        
            x1 = x2 
            x2 = x1 + intervalo
            f1 = f2
            f2 = f(x2)
        
    return (x1 + x2)/2.0

def resta(x): return f(x) - g(x)

def encontrarRaices():
    intervalo = 0.0001
    error = 0.000001
    maximo = 5
    contador = -5
    
    raices = []       
    
    while (contador < maximo):
        
        a = contador
        b = contador + intervalo    
        resultado = busquedaIncremental(resta,a,b,intervalo,error)  
        
        if (resultado != None):
            raices.append(resultado)
        contador += intervalo
        
    print("\nPuntos de intersección de las dos curvas: \n",raices,"\n")
    return raices

def main():
    
    raices = encontrarRaices()
    
    limInferior = raices[0]
    limSuperior = raices[1]
    
    puntoMedio = (limSuperior + limInferior)/2
        
    if(f(puntoMedio) > g(puntoMedio)):
        fMayor = f
        fMenor = g
    else:
        fMayor = g
        fMenor = f
     
    nParticiones = 10
    
    simpsonMayor = simpson(limInferior, limSuperior, nParticiones, fMayor)
    simpsonMenor = simpson(limInferior, limSuperior, nParticiones, fMenor)
    
    resultado = simpsonMayor - simpsonMenor
    print('Área encerrada por las curvas entre x =',limInferior,' y x =',limSuperior,' es ',resultado,' unidades cuadradas (u^2)')

if __name__ == "__main__":
    main()