Mercurial > octave
changeset 26180:55564fdb3e4d
optimset.m: preserve empty options if given as arguments (bug #54952).
* optimset.m: Don't recursively call optimset with structure
arguments, but use a subfunction. Let the subfunction drop empty new
fields only if new options were given as a structure argument to
optimset.
author | Olaf Till <i7tiol@t-online.de> |
---|---|
date | Sat, 08 Dec 2018 12:49:39 +0100 |
parents | a0b63c183d4b |
children | d77938ba31c4 |
files | scripts/optimization/optimset.m |
diffstat | 1 files changed, 42 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/scripts/optimization/optimset.m Sat Dec 08 01:38:45 2018 +0100 +++ b/scripts/optimization/optimset.m Sat Dec 08 12:49:39 2018 +0100 @@ -118,6 +118,8 @@ nargs = nargin; opts = __all_opts__ (); + ## Skip validation if we're in the internal query. + validation = ! isempty (opts); if (nargs == 0) if (nargout == 0) @@ -142,45 +144,54 @@ ## Should we be checking to ensure that the field names are expected? old = varargin{1}; new = varargin{2}; - fnames = fieldnames (old); - ## skip validation if we're in the internal query - validation = ! isempty (opts); - for [val, key] = new - if (validation) - ## Case insensitive lookup in all options. - i = strncmpi (opts, key, length (key)); - nmatch = sum (i); - ## Validate option. - if (nmatch == 1) - key = opts{find (i)}; - elseif (nmatch == 0) - warning ("optimset: unrecognized option: %s", key); - else - fmt = sprintf ("optimset: ambiguous option: %%s (%s%%s)", - repmat ("%s, ", 1, nmatch-1)); - warning (fmt, key, opts{i}); - endif - endif - if (! isempty (val)) - old.(key) = val; - endif - endfor - retval = old; + useempty = false; # Matlab drops empty new fields, too. + retval = setoptionfields (opts, old, new, validation, useempty); elseif (rem (nargs, 2) && isstruct (varargin{1})) ## Set values in old from name/value pairs. + old = varargin{1}; pairs = reshape (varargin(2:end), 2, []); - retval = optimset (varargin{1}, cell2struct (pairs(2, :), pairs(1, :), 2)); + new = cell2struct (pairs(2, :), pairs(1, :), 2); + useempty = true; # Matlab preserves empty arguments, too. + retval = setoptionfields (opts, old, new, validation, useempty); elseif (rem (nargs, 2) == 0) ## Create struct. ## Default values are replaced by those specified by name/value pairs. + old = struct (); pairs = reshape (varargin, 2, []); - retval = optimset (struct (), cell2struct (pairs(2, :), pairs(1, :), 2)); + new = cell2struct (pairs(2, :), pairs(1, :), 2); + useempty = true; # Matlab preserves empty arguments, too. + retval = setoptionfields (opts, old, new, validation, useempty); else print_usage (); endif endfunction +function retval = setoptionfields (opts, old, new, validation, useempty) + + for [val, key] = new + if (validation) + ## Case insensitive lookup in all options. + i = strncmpi (opts, key, length (key)); + nmatch = sum (i); + ## Validate option. + if (nmatch == 1) + key = opts{find (i)}; + elseif (nmatch == 0) + warning ("optimset: unrecognized option: %s", key); + else + fmt = sprintf ("optimset: ambiguous option: %%s (%s%%s)", + repmat ("%s, ", 1, nmatch-1)); + warning (fmt, key, opts{i}); + endif + endif + if (useempty || ! isempty (val)) + old.(key) = val; + endif + endfor + retval = old; + +endfunction %!assert (isfield (optimset (), "TolFun")) %!assert (isfield (optimset ("tolFun", 1e-3), "TolFun")) @@ -194,6 +205,11 @@ %! assert (joint.TolX, 1e-2); %! assert (joint.TolFun, 1e-3); +## Test preserving empty values given as arguments +%!test +%! opts = optimset ("TypicalX", []); +%! assert (isempty (opts.TypicalX)); + ## Test input validation %!error optimset ("1_Parameter") %!error <no defaults for function> optimset ("%NOT_A_REAL_FUNCTION_NAME%")