<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def bisect(func, a, b, xtol=1e-6, errorcontrol=True, testkwargs=dict(), outside='extrapolate', ascending=None, disp=False):
 """Find root by bysection search. If the function evaluation is noisy then use `errorcontrol=True` for adaptive sampling of the function during the bisection search. Parameters func: callable Function of which the root should be found. If `errorcontrol=True` then the function should be derived from `AverageBase`. a, b: float initial interval xtol: float target tolerance for interval size errorcontrol: boolean if true, assume that function is derived from `AverageBase`. testkwargs: only for `errorcontrol=True` see `AverageBase.test0` outside: ['extrapolate', 'raise'] How to handle the case where f(a) and f(b) have same sign, i.e. where the root lies outside of the interval. If 'raise' throws a `BisectException`. ascending: allow passing in directly whether function is ascending or not if ascending=True then it is assumed without check that f(a) < 0 and f(b) > 0 if ascending=False then it is assumed without check that f(a) > 0 and f(b) < 0 Returns ------- float, root of function """

    search = True
    # check whether function is ascending or not
    if ascending is None:
        if errorcontrol:
            testkwargs.update(dict(type_='smaller', force=True))
            fa = func.test0(a, **testkwargs)
            fb = func.test0(b, **testkwargs)
        else:
            fa = func(a) < 0
            fb = func(b) < 0
        if fa and not fb:
            ascending = True
        elif fb and not fa:
            ascending =  False
        else:
            if disp:
                print('Warning: func(a) and func(b) do not have opposing signs -> no search done')
            if outside == 'raise':
                raise BisectException()
            search = False

    # refine interval until it has reached size xtol, except if root outside
    while (b-a > xtol) and search:
        mid = (a+b)/2.0
        if ascending:
            if ((not errorcontrol) and (func(mid) < 0)) or \
                    (errorcontrol and func.test0(mid, **testkwargs)):
                a = mid 
            else:
                b = mid
        else:
            if ((not errorcontrol) and (func(mid) < 0)) or \
                    (errorcontrol and func.test0(mid, **testkwargs)):
                b = mid 
            else:
                a = mid
        if disp:
            print('bisect bounds', a, b)
    # interpolate linearly to get zero
    if errorcontrol:
        ya, yb = func(a)[0], func(b)[0]
    else:
        ya, yb = func(a), func(b)
    m = (yb-ya) / (b-a)
    res = a-ya/m
    if disp:
        print('bisect final value', res)
    return res