In general, you want to avoid calls to transcendent functions like sin, cos, exp, ln as much as possible, especially in a "hot" function like an integrand.
- Replace x**2 by x*x (often x**2 calls a generic=slow exponentiation function)
- use variables for "expensive" intermediate terms which are used more than once
- transform your equation to reduce or eliminate transcendent functions
- special-case for typical parameter values. Integer exponents are a frequent candidate.
- precompute everything that is constant, espc. in parameterized functions
For the particular example you can substitute z=cos(theta). It is dz = -sin(theta)dtheta. Your integrand becomes
-exp(E*(z^2 + cos(arccos(z)^2))
saving you some of the transcendent function calls. The boundaries [0, pi] become [1, -1]. Also avoid x**2, better use x*x.
Complete code:
import mpmath as mp
import numpy as np
from time import time as epochTime
def func(E):
def f(z):
acz = mp.acos(z)
return -mp.exp(E * (mp.cos(acz*acz) + z*z))
return f
start = epochTime()
mp.mp.dps = 15
mp.mp.pretty = True
E = np.linspace(0, 10, 200)
ints = [mp.quadgl(func(e), [1.0, -1.0]) for e in E] # Main Job
print ('Took:{:.3}s'.format(epochTime() - start))