changeset 21099:52af4092f863

For optimization scripts, correctly choose tolerance (eps) based on class of fun and X0. * fminbnd.m, fminsearch.m, fminunc.m, fsolve.m: Use 'isa (..., "single")' to check both initial guess X0 and result of function evaluation to decide whether eps should be single or double.
author Rik <rik@octave.org>
date Mon, 18 Jan 2016 10:00:56 -0800
parents 99d373870017
children e39e05d90788
files scripts/optimization/fminbnd.m scripts/optimization/fminsearch.m scripts/optimization/fminunc.m scripts/optimization/fsolve.m
diffstat 4 files changed, 24 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/optimization/fminbnd.m	Wed Dec 16 12:09:59 2015 +1100
+++ b/scripts/optimization/fminbnd.m	Mon Jan 18 10:00:56 2016 -0800
@@ -98,7 +98,6 @@
   info = 0;
   niter = 0;
   nfev = 0;
-  sqrteps = eps (class (xmin + xmax));
 
   c = 0.5*(3 - sqrt (5));
   a = xmin; b = xmax;
@@ -108,6 +107,12 @@
   fv = fw = fval = fun (x);
   nfev += 1;
 
+  if (isa (xmin, "single") || isa (xmax, "single") || isa (fval, "single"))
+    sqrteps = eps ("single");
+  else
+    sqrteps = eps ("double");
+  endif
+
   ## Only for display purposes.
   iter(1).funccount = nfev;
   iter(1).x = x;
@@ -117,7 +122,7 @@
     xm = 0.5*(a+b);
     ## FIXME: the golden section search can actually get closer than sqrt(eps)
     ## sometimes.  Sometimes not, it depends on the function.  This is the
-    ## strategy from the Netlib code.  Something yet smarter would be good.
+    ## strategy from the Netlib code.  Something smarter would be good.
     tol = 2 * sqrteps * abs (x) + tolx / 3;
     if (abs (x - xm) <= (2*tol - 0.5*(b-a)))
       info = 1;
--- a/scripts/optimization/fminsearch.m	Wed Dec 16 12:09:59 2015 +1100
+++ b/scripts/optimization/fminsearch.m	Mon Jan 18 10:00:56 2016 -0800
@@ -52,10 +52,10 @@
 ## PKG_ADD: ## Discard result to avoid polluting workspace with ans at startup.
 ## PKG_ADD: [~] = __all_opts__ ("fminsearch");
 
-## FIXME: Add support for "exitflag" output variable
-## FIXME: Add support for "output" output variable
+## FIXME: Add support for "exitflag" output variable.
+## FIXME: Add support for "output" output variable.
 ## FIXME: For Display option, add 'final' and 'notify' options.  Not too hard.
-## FIXME: Add support for OutputFcn.  See fminunc for a template
+## FIXME: Add support for OutputFcn.  See fminunc for a template.
 ## FIXME: Add support for exiting based on TolFun.  See fminunc for an idea.
 
 function [x, fval] = fminsearch (fun, x0, options = struct ())
--- a/scripts/optimization/fminunc.m	Wed Dec 16 12:09:59 2015 +1100
+++ b/scripts/optimization/fminunc.m	Mon Jan 18 10:00:56 2016 -0800
@@ -143,8 +143,6 @@
   ## These defaults are rather stringent.  I think that normally, user
   ## prefers accuracy to performance.
 
-  macheps = eps (class (x0));
-
   tolx = optimget (options, "TolX", 1e-7);
   tolf = optimget (options, "TolFun", 1e-7);
 
@@ -175,6 +173,12 @@
     endif
   endif
 
+  if (isa (x0, "single") || isa (fval, "single"))
+    macheps = eps ("single");
+  else
+    macheps = eps ("double");
+  endif
+
   nsuciter = 0;
   lastratio = 0;
 
--- a/scripts/optimization/fsolve.m	Wed Dec 16 12:09:59 2015 +1100
+++ b/scripts/optimization/fsolve.m	Mon Jan 18 10:00:56 2016 -0800
@@ -185,10 +185,8 @@
     fcn = @(x) guarded_eval (fcn, x, complexeqn);
   endif
 
-  ## These defaults are rather stringent. I think that normally, user
-  ## prefers accuracy to performance.
-
-  macheps = eps (class (x0));
+  ## These defaults are rather stringent.
+  ## Normally user prefers accuracy to performance.
 
   tolx = optimget (options, "TolX", 1e-7);
   tolf = optimget (options, "TolFun", 1e-7);
@@ -223,6 +221,12 @@
     endif
   endif
 
+  if (isa (x0, "single") || isa (fvec, "single"))
+    macheps = eps ("single");
+  else
+    macheps = eps ("double");
+  endif
+
   nsuciter = 0;
 
   ## Outer loop.