def _needs_bisect(val, f_lim):
  """Checks whether a candidate end-point calls for bisection.

  This is the case if the derivative at that point is negative, suggesting that
  this should be a left end-point, but the function value is too high, implying
  that it must instead be a right end-point but that it is unsuitable for secant
  steps and requires bisection steps.

  This check is careful about a +inf value, in which case the derivative is
  ignored and we move to bisection.

  Args:
    val: A namedtuple with fields `f` and `df` holding the function value and
      derivative at the point of interest.  May be batched.
    f_lim: Upper bound on acceptable function values.

  Returns:
    needs_bisect: Boolean Tensor mask giving whether each end-point in the batch
      calls for bisection.
  """
  return (val.f >= float('inf')) | ((val.df < 0) & (val.f > f_lim))