# HG changeset patch
# User Nguyễn Gia Phong <vn.mcsinyx@gmail.com>
# Date 1569596657 -25200
#      Fri Sep 27 22:04:17 2019 +0700
# Node ID 814b350aa96ff155d44ef51616137476948317b8
# Parent  396996f1dad0cdd4ccddb65064f520cfca315c51
fzero.m: implement display option (bug #56954)

diff -r 396996f1dad0 -r 814b350aa96f scripts/optimization/fzero.m
--- a/scripts/optimization/fzero.m	Wed Sep 25 17:57:08 2019 -0400
+++ b/scripts/optimization/fzero.m	Fri Sep 27 22:04:17 2019 +0700
@@ -42,8 +42,8 @@
 ##
 ## @var{options} is a structure specifying additional options.  Currently,
 ## @code{fzero} recognizes these options:
-## @qcode{"FunValCheck"}, @qcode{"MaxFunEvals"}, @qcode{"MaxIter"},
-## @qcode{"OutputFcn"}, and @qcode{"TolX"}.
+## @qcode{"Display"}, @qcode{"FunValCheck"}, @qcode{"MaxFunEvals"},
+## @qcode{"MaxIter"}, @qcode{"OutputFcn"}, and @qcode{"TolX"}.
 ##
 ## @qcode{"MaxFunEvals"} proscribes the maximum number of function evaluations
 ## before the search is halted.  The default value is @code{Inf}.
@@ -137,8 +137,18 @@ function [x, fval, info, output] = fzero
     fun = str2func (fun);
   endif
 
-  ## FIXME: Display is not yet implemented
-  ## displev = optimget (options, "Display", "notify");
+  display = optimget (options, "Display", "notify");
+  switch (display)
+    case "iter"
+      trace = 1;
+    case "final"
+      trace = 2;
+    case "notify"
+      trace = 3;
+    otherwise  # "none"
+      trace = 0;
+  endswitch
+
   funvalchk = strcmpi (optimget (options, "FunValCheck", "off"), "on");
   maxfev = optimget (options, "MaxFunEvals", Inf);
   maxiter = optimget (options, "MaxIter", Inf);
@@ -168,6 +178,9 @@ function [x, fval, info, output] = fzero
     nfev += 1;
   else
     ## Try to find a value for b which brackets a zero-crossing
+    if (trace == 1)
+      printf ("\nSearch for an interval around %g containing a sign change:\n", a);
+    end
 
     ## For very small values, switch to absolute rather than relative search
     if (abs (a) < .001)
@@ -175,11 +188,20 @@ function [x, fval, info, output] = fzero
     else
       aa = a;
     endif
+    [b fb] = deal (a, fun (a));
+    if (trace == 1)
+      printf ("Func-eval %d,  how = initial,  a = %g,  f(a) = %g,  b = %g,  f(b) = %g\n",
+              nfev, a, fa, b, fb);
+    end
     ## Search in an ever-widening range around the initial point.
     for srch = [-.01 +.025 -.05 +.10 -.25 +.50 -1 +2.5 -5 +10 -50 +100 -500 +1000]
       b = aa + aa*srch;
       fb = fun (b);
       nfev += 1;
+      if (trace == 1)
+        printf ("Func-eval %d,  how = search,  a = %g,  f(a) = %g,  b = %g,  f(b) = %g\n",
+                nfev, a, fa, b, fb);
+      end
       if (sign (fa) * sign (fb) <= 0)
         break;
       endif
@@ -200,6 +222,10 @@ function [x, fval, info, output] = fzero
     error ("Octave:fzero:bracket", "fzero: not a valid initial bracketing");
   endif
 
+  if (trace == 1)
+    printf ("\nSearch for a a zero in the interval [%g, %g]:\n", a, b);
+  end
+
   slope0 = (fb - fa) / (b - a);
 
   if (fa == 0)
@@ -217,6 +243,11 @@ function [x, fval, info, output] = fzero
   else
     u = b; fu = fb;
   endif
+  nfev += 1;
+  if (trace == 1)
+    printf ("Func-eval %d,  how = initial,  x = %g,  f(x) = %g\n",
+            nfev, u, fu);
+  end
 
   if (isa (x0, "single") || isa (fa, "single"))
     macheps = eps ("single");
@@ -304,9 +335,13 @@ function [x, fval, info, output] = fzero
     endif
 
     ## Calculate new point.
-    x = c;
-    fval = fc = fun (c);
+    [x fc] = deal (c, fun (c));
     niter += 1; nfev += 1;
+    if (trace == 1)
+      printf ("Func-eval %d,  how = interpolation,  x = %g,  f(x) = %g  (%2.1f%%)\n",
+              nfev, x, fc, 100*(fc-fval)/(abs(fval)+eps));
+    end
+    fval = fc;
 
     ## Modification 2: skip inverse cubic interpolation if
     ## nonmonotonicity is detected.
@@ -372,6 +407,19 @@ function [x, fval, info, output] = fzero
     endif
   endif
 
+  if ((trace == 1) || (trace == 2) || trace == 3 && info != 1)
+    switch (info)
+      case 1
+        disp ("\nAlgorithm converged\n");
+      case -1
+        disp ("\nAlgorithm has been terminated by user\n");
+      case -5
+        disp ("\nAlgorithm seemingly converged to a singular point\n");
+      otherwise
+        disp ("\nMaximum number of iterations or function evaluations reached\n");
+    endswitch
+  endif
+
   output.iterations = niter;
   output.funcCount = nfev;
   output.algorithm = "bisection, interpolation";
