%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Part of the replication package for the paper
%   "Marginal Effects for Probit and Tobit with Endogeneity"
%   by Kirill S. Evdokimov, Ilze Kalnina, and Andrei Zeleneev.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [x,fval,exitflag] = fast_fminbnd_U_shaped(fn, lb0, ub0, TolX)
  % For U-shaped function minimum at the interior happens only if fn'(lb)<0 && fn'(ub)>0.
  % Only then we need to run fminbnd. This function implements a more robust version of this.
  % Also, in contrast to fminbnd, evaluates fn(lb0) and fn(ub0).
  if nargin<4; TolX=1e-5; end
  
  lb = min(lb0,ub0);
  ub = max(lb0,ub0);
 
  arr_xs = [lb; ub; (lb+ub)/2];
  
  if ub-lb>2*TolX
    arr_xs = [arr_xs; lb + TolX; ub - TolX];
  end
  
  arr_fvals = arrayfun(fn, arr_xs);
  [~, i_min] = min(arr_fvals);
    
  if i_min > 2  % the min is not on the boundary, so running fminbnd
    [x_opt,fval_opt,exitflag] = fminbnd(fn, lb, ub, optimset("TolX", TolX)); %not requesting output
    arr_fvals = [arr_fvals; fval_opt];
    arr_xs = [arr_xs; x_opt];
  else
    exitflag = 1;
  end
  [~,i_min] = min(arr_fvals); % just in case, checking that x_opt is indeed the minimizer
  x = arr_xs(i_min);
  fval = arr_fvals(i_min);
end

