title: Modifying python code to get imaginary solutions of numerical integration method
body: <p>I stumbled upon this code to integrate functions using the numerical method Gauss Kronrod which I have been recommended for the functions I am integrating. So far in all the trials I have used I have found that it works to a reasonably well accuracy. However it completely omits the imaginary parts of the solution.</p>
  
  <p>Here is the example for integrating ln(x) from -5 to 0, the real part is correct but there is no imaginary part:</p>
  
  <pre><code># let's test integrazi for ln(x) from -1 to 2
  import scipy
  import cmath
  from scipy import array
  
  
  def quad_routine(func, a, b, x_list, w_list):
      c_1 = (b-a)/2.0
      c_2 = (b+a)/2.0
      eval_points = map(lambda x: c_1*x+c_2, x_list)
      func_evals = map(func, eval_points)
      return c_1 * sum(array(func_evals) * array(w_list))
  
  def quad_kronrod_15(func, a, b):
      x_kr = [-0.991455371120813,-0.949107912342759, -0.864864423359769, -0.741531185599394, -0.586087235467691,-0.405845151377397, -0.207784955007898, 0.0, 0.207784955007898,0.405845151377397, 0.586087235467691, 0.741531185599394, 0.864864423359769, 0.949107912342759, 0.991455371120813]
      w_kr = [0.022935322010529, 0.063092092629979, 0.104790010322250, 0.140653259715525, 0.169004726639267, 0.190350578064785, 0.204432940075298, 0.209482141084728, 0.204432940075298, 0.190350578064785, 0.169004726639267, 0.140653259715525,  0.104790010322250, 0.063092092629979, 0.022935322010529]
      return quad_routine(func,a,b,x_kr, w_kr)
  
  class Memoize(object):
      def __init__(self, func):
          self.func = func
          self.eval_points = {}
      def __call__(self, *args):
          if args not in self.eval_points:
              self.eval_points[args] = self.func(*args)
          return self.eval_points[args]
  
  def quadt(func,a,b):
      func = Memoize(func) #  Memoize function to skip repeated function calls.
      k15 = quad_kronrod_15(func,a,b)
      # I don't have much faith in this error estimate taken from wikipedia
      # without incorporating how it should scale with changing limits
      return k15
  
  def INTEGRATEME(func, **kwargs):       # INTEGRATEZI short for Integrating from zero to infinity
      def real_func(x):
          return scipy.real(func(x))
      integral = quadt(real_func, -5.0, 0)  # lower limit of integral is -5 and upper limit is 0.
      return (integral)
  
  
  print INTEGRATEME( lambda kp: cmath.log(kp)) # integrating ln(x) from -5 to 0
  </code></pre>
  
  <p>Here is the output:</p>
  
  <pre><code>%run "c:\users\envy14~1\appdata\local\temp\tmpnsvrem.py"
  3.05565292766
  </code></pre>
  
  <h1>the true solution is 3.04719 + 15.708i</h1>