def secant(x1, x2, f, steptol=1e-12, roottol=1e-12, maxIter=30, callback=None):
    """
	Find an approximation to a point xf such that f(xf)=0 for a 
	scalar function f using the secant method.  The method requires
	two initial points x1 and x2, ideally close to a root,
	and proceeds iteratively.

	Parameters
	----------
	x1 : float or complex
		An initial point for iteration, should be close to a 
		root of f.
	x2 : float or complex
		An initial point for iteration, should be close to a 
		root of f.  Should not equal x1.
	f : function
		Function of a single variable which we seek to find a root of.
	steptol: float, optional
		The routine ends if the step size, dx, between sucessive
		iterations satisfies abs(dx) < steptol and attemptBest is False.
	roottol: float, optional
		The routine ends if abs(f(x)) < roottol and attemptBest is False.
	maxIter : int, optional
		The routine ends after maxIter iterations.
	callback : function, optional
		After each iteration callback(x, dx, f(x), iteration) will be 
		called where 'x' is the current iteration of the estimated root, 
		'dx' is the step size between the previous and current 'x' and 
		'iteration' the number of iterations that have been taken.  If 
		the callback function evaluates to True then the routine will end.

	Returns
	-------
	complex
		The approximation to a root of f.
	float
		abs(f(x)) where x is the final approximation for the root of f.
	"""
    y1, y2 = f(x1), f(x2)
    if abs(y1) < abs(y2):
        x1, x2 = x2, x1
        y1, y2 = y2, y1
    for iteration in range(maxIter):
        dx = -(x2 - x1) * y2 / (y2 - y1)
        x1, x2 = x2, x2 + dx
        y1, y2 = y2, f(x2)
        if callback is not None and callback(x2, dx, y2, iteration + 1):
            break
        if abs(dx) < steptol or abs(y2) < roottol:
            break
    return x2, abs(y2)
