code: def _linesearch_powell(
      func,
      p,
      xi,
      tol=1e-3,
      lower_bound=None,
      upper_bound=None,
      fval=None,
  ):
      """Line-search algorithm using fminbound.
  
      Find the minimium of the function ``func(x0 + alpha*direc)``.
  
      lower_bound : np.array.
          The lower bounds for each parameter in ``x0``. If the ``i``th
          parameter in ``x0`` is unbounded below, then ``lower_bound[i]``
          should be ``-np.inf``.
          Note ``np.shape(lower_bound) == (n,)``.
      upper_bound : np.array.
          The upper bounds for each parameter in ``x0``. If the ``i``th
          parameter in ``x0`` is unbounded above, then ``upper_bound[i]``
          should be ``np.inf``.
          Note ``np.shape(upper_bound) == (n,)``.
      fval : number.
          ``fval`` is equal to ``func(p)``, the idea is just to avoid
          recomputing it so we can limit the ``fevals``.
  
      """
  
      def myfunc(alpha):
          return func(p + alpha * xi)
  
      # if xi is zero, then don't optimize
      if not np.any(xi):
          return (fval, p, xi) if fval is not None else (func(p), p, xi)
      elif lower_bound is None and upper_bound is None:
          # non-bounded minimization
          alpha_min, fret, _, _ = brent(myfunc, full_output=1, tol=tol)
          xi = alpha_min * xi
          return squeeze(fret), p + xi, xi
      else:
          bound = _line_for_search(p, xi, lower_bound, upper_bound)
          if np.isneginf(bound[0]) and np.isposinf(bound[1]):
              # equivalent to unbounded
              return _linesearch_powell(func, p, xi, fval=fval, tol=tol)
          elif not np.isneginf(bound[0]) and not np.isposinf(bound[1]):
              # we can use a bounded scalar minimization
              res = _minimize_scalar_bounded(
                  myfunc, bound, xatol=tol / 100
              )
              xi = res.x * xi
              return squeeze(res.fun), p + xi, xi
          else:
              # only bounded on one side. use the tangent function to convert
              # the infinity bound to a finite bound. The new bounded region
              # is a subregion of the region bounded by -np.pi/2 and np.pi/2.
              bound = np.arctan(bound[0]), np.arctan(bound[1])
              res = _minimize_scalar_bounded(
                  lambda x: myfunc(np.tan(x)), bound, xatol=tol / 100
              )
              xi = np.tan(res.x) * xi
              return squeeze(res.fun), p + xi, xi
  
imports: import warnings
  import sys
  from numpy import atleast_1d, eye, argmin, zeros, shape, squeeze, asarray, sqrt, Inf, asfarray, isinf
  import numpy
  from .linesearch import line_search_wolfe1, line_search_wolfe2, line_search_wolfe2, LineSearchWarning
  from ._numdiff import approx_derivative
  from scipy._lib._util import getfullargspec_no_self
  from scipy._lib._util import MapWrapper
  from scipy.optimize._differentiable_functions import ScalarFunction, FD_METHODS
label_desc: Use image node_id 32 for calling a global function with example usage: _linesearch_powell(func, p, xi, tol, lower_bound, upper_bound, fval) and returns: func, unknown, squeeze,  unknown,  xi, _linesearch_powell, squeeze,  unknown,  xi, squeeze,  unknown,  xi