# HG changeset patch
# User jcorno <jacopo.corno@gmail.com>
# Date 1420539139 -3600
#      Tue Jan 06 11:12:19 2015 +0100
# Node ID ab9ec60bedf4726702ed3f0a0f504df7d6309c8b
# Parent  3b0a9a83236071066c7a39023230ccb92c1a0096
insertion of odeset, odeget in core-octave

diff -r 3b0a9a832360 -r ab9ec60bedf4 scripts/ode/odeget.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/odeget.m	Tue Jan 06 11:12:19 2015 +0100
@@ -0,0 +1,177 @@
+## Copyright (C) 2013, Roberto Porcu' <roberto.porcu@polimi.it>
+## Copyright (C) 2006-2012, Thomas Treichl <treichl@users.sourceforge.net>
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {[@var{}] =} odeget (@var{ode_opt}, @var{field},
+## [@var{default}], [@var{opt}])
+## @deftypefnx  {Command} {[@var{res}] =} odeget (@var{ode_opt}, @var{field},
+## [@var{default}], [@var{opt}])
+##
+## If this function is called with two input arguments and the first input
+## argument @var{ode_opt} is of type structure array and the second input
+## argument @var{field} is of type string then return the option
+## value @var{res} that is specified by the option name @var{field} in
+## the OdePkg option structure @var{ode_opt}. Optionally if this function
+## is called with a third input argument then return the default value
+## @var{default} if @var{field} is not set in the structure @var{ode_opt}.
+## @end deftypefn
+##
+## @seealso{odeset}
+
+## Note: 20061022, Thomas Treichl
+##   We cannot create a function of the form odeget (@var{odestruct},
+##   @var{name1}, @var{name2}) because we would get a mismatch with
+##   the function form 1 like described above.
+
+function res = odeget (ode_opt, field, default, opt)
+
+  ## Check number and types of input arguments
+  if (nargin == 1)
+    error ("OdePkg:InvalidArgument",
+           "input arguments number must be at least 2");
+  endif
+
+  if (isempty (ode_opt))
+    if (nargin == 2)
+      res = [];
+      return
+    endif
+    res = default;
+    return
+  endif
+
+  if (! isstruct (ode_opt))
+    error ("OdePkg:InvalidArgument",
+           "first input argument must be a valid ODE_STRUCT.");
+  endif
+
+  if (! ischar (field))
+    error ("OdePkg:InvalidArgument",
+           "second input argument must be a string.");
+  endif
+
+  if (nargin == 2)
+    default = [];
+  endif
+
+  if ((nargin == 4)
+      && strcmp (lower (deblank (opt)), "fast"))
+    if (isfield (ode_opt, field))
+      res = ode_opt.(field);
+    else
+      res = default;
+    endif
+    return
+  endif
+
+  if ((nargin == 4)
+      && strcmp (lower (deblank (opt)), "fast_not_empty"))
+    if (isfield (ode_opt, field)
+        && ! isempty (ode_opt.(field)) )
+      res = ode_opt.(field);
+    else
+      res = default;
+    endif
+    return
+  endif
+
+  ## check if the given struct is a valid OdePkg struct
+  ode_struct_value_check (ode_opt);
+
+  ## define all the possible OdePkg fields
+  options = ["AbsTol"; "Algorithm"; "BDF"; "Choice"; "Eta"; "Events";
+             "Explicit"; "InexactSolver"; "InitialSlope"; "InitialStep";
+             "Jacobian";"JConstant";"JPattern";"Mass"; "MassConstant";
+             "MassSingular"; "MaxNewtonIterations"; "MaxOrder"; "MaxStep";
+             "MStateDependence"; "MvPattern"; "NewtonTol"; "NonNegative";
+             "NormControl"; "OutputFcn"; "OutputSave"; "OutputSel";
+             "PolynomialDegree"; "QuadratureOrder"; "Refine"; "RelTol";
+             "Restart"; "Stats"; "TimeStepNumber"; "TimeStepSize";
+             "UseJacobian"; "Vectorized"];
+
+  while (1)
+    pos = fuzzy_compare (field, options);
+
+    if (size (pos, 1) == 0) # no matching for the given option
+      if (nargin == 2)
+        error ("OdePkg:InvalidArgument",
+               "invalid property. No property found with name ''%s''.", field);
+      endif
+      warning ("odeget:NoExactMatching",
+               "no property found with name ''%s''. ",
+               "Assuming default value.", field);
+      res = default;
+      return
+    endif
+
+    if (size (pos, 1) == 1) # one matching
+      if (! strcmp (lower (deblank (field)),
+                    lower (deblank (options(pos,:)))) )
+        warning ("OdePkg:InvalidArgument",
+                 "no exact matching for ''%s''. ",
+                 "Assuming you was intending ''%s''.",
+                 field, deblank (options(pos,:)));
+      endif
+      res = ode_opt.(deblank (options(pos,:)));
+      if (isempty (res))
+        res = default;
+        return
+      endif
+      return
+    endif
+
+    ## if there are more matching, ask the user to be more precise
+    warning ("OdePkg:InvalidArgument", ...
+             "no exact matching for ''%s''. %d possible fields were found.",
+             field, size (pos, 1));
+    for j = 1:(size (pos, 1))
+      fprintf ("%s\n", deblank (options(pos(j),:)));
+    endfor
+    do
+      fprintf ("Please insert field name again.\n");
+      field = input ("New field name: ");
+    until (ischar (field))
+  endwhile
+
+endfunction
+
+%! ## Turn off output of warning messages for all tests, turn them on
+%! ## again if the last test is called
+%!  warning ('off', 'OdePkg:InvalidArgument');
+%!test assert (odeget (odeset (), 'RelTol'), []);
+%!test assert (odeget (odeset (), 'RelTol', 10), 10);
+%!test assert (odeget (odeset (), 'Stats'), []);
+%!test assert (odeget (odeset (), 'Stats', 'on'), 'on');
+%!test assert (odeget (odeset (), 'AbsTol', 1.e-6, 'fast'), []);
+%!test assert (odeget (odeset (), 'AbsTol', 1.e-6, 'fast_not_empty'), 1.e-6);
+%!test assert (odeget (odeset (), 'AbsTol', 1e-9), 1e-9);
+%!
+%!  warning ('on', 'OdePkg:InvalidArgument');
+
+%!demo
+%! # Return the manually changed value RelTol of the OdePkg options
+%! # strutcure A. If RelTol wouldn't have been changed then an
+%! # empty matrix value would have been returned.
+%!
+%! A = odeset ('RelTol', 1e-1, 'AbsTol', 1e-2);
+%! odeget (A, 'RelTol', [])
+
+## Local Variables: ***
+## mode: octave ***
+## End: ***
diff -r 3b0a9a832360 -r ab9ec60bedf4 scripts/ode/odeset.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/odeset.m	Tue Jan 06 11:12:19 2015 +0100
@@ -0,0 +1,376 @@
+## Copyright (C) 2013, Roberto Porcu' <roberto.porcu@polimi.it>
+## Copyright (C) 2006-2012, Thomas Treichl <treichl@users.sourceforge.net>
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {[@var{}] =} odeset ()
+## @deftypefnx {Command}  {[@var{odestruct}] =} odeset (@var{"field1"},
+## @var{value1}, @var{"field2"}, @var{value2}, @dots{})
+## @deftypefnx {Command}  {[@var{odestruct}] =} odeset (@var{oldstruct},
+## @var{"field1"}, @var{value1}, @var{"field2"}, @var{value2}, @dots{})
+## @deftypefnx {Command}  {[@var{odestruct}] =} odeset (@var{oldstruct},
+## @var{newstruct})
+##
+## If this function is called without an input argument then return a new
+## OdePkg options structure array that contains all the necessary fields and
+## sets the values of all fields to default values.
+##
+## If this function is called with string input arguments @var{"field1"},
+## @var{"field2"}, @dots{} identifying valid OdePkg options then return a
+## new OdePkg options structure with all necessary fields and set the values
+## of the fields @var{"field1"}, @var{"field2"}, @dots{} to the values
+## @var{value1}, @var{value2}, @dots{}
+##
+## If this function is called with a first input argument @var{oldstruct}
+## of type structure array then overwrite all values of the options
+## @var{"field1"}, @var{"field2"}, @dots{} of the structure @var{oldstruct}
+## with new values @var{value1}, @var{value2}, @dots{} and return the
+## modified structure array.
+##
+## If this function is called with two input arguments @var{oldstruct}
+## and @var{newstruct} of type structure array then overwrite all values
+## in the fields from the structure @var{oldstruct} with new values of the
+## fields from the structure @var{newstruct}. Empty values of @var{newstruct}
+## will not overwrite values in @var{oldstruct}.
+##
+## For a detailed explanation about valid fields and field values in an
+## OdePkg structure array have a look at the @file{odepkg.pdf},
+## Section 'ODE/DAE/IDE/DDE options' or run the command @command{doc odepkg}
+## to open the tutorial.
+## @end deftypefn
+##
+## @seealso{odeget}
+
+function opt = odeset (varargin)
+
+  ## Check number and types of all input arguments
+  if ((nargin == 0)
+      && (nargout == 0))
+    print_options;
+    return
+  endif
+
+  ## Creating a vector of OdePkg possible fields
+  fields = ["AbsTol"; "Algorithm"; "BDF"; "Choice"; "Eta"; "Events";
+            "Explicit"; "InexactSolver"; "InitialSlope"; "InitialStep";
+            "Jacobian";"JConstant";"JPattern";"Mass"; "MassConstant";
+            "MassSingular"; "MaxNewtonIterations"; "MaxOrder"; "MaxStep";
+            "MStateDependence"; "MvPattern"; "NewtonTol"; "NonNegative";
+            "NormControl"; "OutputFcn"; "OutputSave"; "OutputSel";
+            "PolynomialDegree"; "QuadratureOrder"; "Refine"; "RelTol";
+            "Restart"; "Stats"; "TimeStepNumber"; "TimeStepSize";
+            "UseJacobian"; "Vectorized"];
+
+  fields_nb = size (fields, 1);
+
+  ## initialize output
+  opt = [];
+  for i = 1:1:fields_nb
+    opt.(deblank (fields(i,:))) = [];
+  endfor
+
+  opt.Refine = 0;
+  opt.OutputSave = 1;
+
+  if ((nargin == 0)
+      && (nargout == 1))
+    return
+  endif
+
+  ode_fields = fieldnames (opt);
+  
+  if (isstruct (varargin{1}))
+    ode_struct_value_check (varargin{1});
+
+    optA_fields = fieldnames (varargin{1});
+    optA_f_nb = length (optA_fields);
+
+    ## loop on first struct options for updating
+    for i = 1:optA_f_nb
+      name = lower (deblank (optA_fields{i}));
+
+      while (1)
+        pos = fuzzy_compare (name, fields);
+        if (size (pos, 1) == 0)
+          warning ("OdePkg:InvalidArgument",
+                   "no property found with name ''%s''", name);
+        endif
+
+        if (size (pos, 1) == 1)
+          if (! strcmp (lower (deblank (name)),
+                        lower (deblank (fields(pos,:)))))
+            warning ("OdePkg:InvalidArgument", "no exact matching for ",
+                     "''%s''. Assuming you were intending ''%s''",
+                     name, deblank (fields(pos,:)));
+          endif
+
+          opt.(deblank (fields(pos,:))) = varargin{1}.(optA_fields{i});
+          break
+        endif
+
+        ## if there are more matching, ask the user to be more precise
+        warning ("OdePkg:InvalidArgument",
+                 "no exact matching for ''%s''. %d possible fields were found",
+                 name, size(pos, 1));
+        for j = 1:(size (pos, 1))
+          fprintf ("%s\n", deblank (fields(pos(j),:)));
+        endfor
+        do
+          fprintf ("Please insert field name again\n");
+          name = input ("New field name: ");
+        until (ischar (name))
+      endwhile
+    endfor
+
+    if ((nargin == 2)
+        && (isstruct (varargin{2})))
+      ode_struct_value_check (varargin{2});
+
+      optB_fields = fieldnames (varargin{2});
+      optB_f_nb = length (optB_fields);
+
+      ## update the first struct with the values in the second one
+      for i = 1:optB_f_nb
+        name = lower (deblank (optB_fields{i}));
+        while (1)
+          pos = fuzzy_compare (name, fields);
+
+          if (size (pos, 1) == 0)
+            warning ("OdePkg:InvalidArgument", ...
+                     "no property found with name ''%s''", name);
+          endif
+
+          if (size(pos, 1) == 1)
+            if (! strcmp (lower (deblank (name)),
+                          lower (deblank (fields(pos,:)))))
+              warning ("OdePkg:InvalidArgument", "no exact matching for ",
+                       "''%s''. Assuming you were intending ''%s''",
+                        name, deblank (fields(pos,:)));
+            endif
+            opt.(deblank (fields(pos,:))) = varargin{2}.(optB_fields{i});
+            break
+          endif
+
+          ## if there are more matching, ask the user to be more precise
+          warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+                   "%d possible fields were found",
+                   name, size (pos, 1));
+          for j = 1:(size (pos, 1))
+            fprintf ("%s\n", deblank (fields(pos(j),:)));
+          endfor
+          do
+            fprintf ("Please insert field name again\n");
+            name = input ("New field name: ");
+          until (ischar (name))
+        endwhile
+      endfor
+      return
+    endif
+
+    ## if the second argument is not a struct,
+    ## pass new values of the OdePkg options to the first struct
+    if (mod (nargin, 2) != 1)
+      error ("OdePkg:InvalidArgument",
+             "odeset expects an odd number of input arguments",
+             " when the first is a ODE_STRUCT");
+    endif
+
+    ## loop on the input arguments
+    for i = 2:2:(nargin - 1)
+
+      if (! ischar(varargin{i}))
+        error ("OdePkg:InvalidArgument",
+               "not all odd input arguments are strings");
+      endif
+
+      name = varargin{i};
+
+      while (1)
+        pos = fuzzy_compare (name, fields);
+
+        if (size (pos, 1) == 0)
+          error ("OdePkg:InvalidArgument",
+                 "no property found with name ''%s''", name);
+        endif
+
+        if (size (pos, 1) == 1)
+          if (! strcmp (lower (deblank (name)),
+                        lower (deblank (fields(pos,:)))))
+            warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+                     "%d possible fields were found",
+                     name, size (pos, 1));
+          endif
+          opt.(deblank (fields(pos,:))) = varargin{i+1};
+          break
+        endif
+
+        ## if there are more matching, ask the user to be more precise
+        warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+                 "%d possible fields were found",
+                 name, size (pos, 1));
+        for j = 1:(size (pos, 1))
+          fprintf ("%s\n", deblank (fields(pos(j),:)));
+        endfor
+        do
+          fprintf ("Please insert field name again\n");
+          name = input ("New field name: ");
+        until (ischar (name))
+      endwhile
+    endfor
+
+    ## check if all has been done gives a valid OdePkg struct
+    ode_struct_value_check (opt);
+    return
+  endif
+
+  ## first input argument was not a struct
+  if (mod (nargin, 2) != 0)
+    error ("OdePkg:InvalidArgument", "odeset expects an even number ",
+           "of input arguments when the first is a string");
+  endif
+
+  for i = 1:2:(nargin-1)
+    if (! ischar (varargin{i}))
+      error ("OdePkg:InvalidArgument",
+             "not all even input arguments are strings");
+    endif
+
+    name = varargin{i};
+
+    while (1)
+      pos = fuzzy_compare (name, fields);
+
+      if (size (pos, 1) == 0)
+        error ("OdePkg:InvalidArgument",
+               "invalid property. No property found with name ''%s''", name);
+      endif
+
+      if (size (pos, 1) == 1)
+        if (! strcmp (lower (deblank (name)),
+                      lower (deblank (fields(pos,:)))))
+          warning ("OdePkg:InvalidArgument", "no exact matching for ",
+                   "''%s''. Assuming you were intending ''%s''",
+                   name, deblank (fields(pos,:)));
+        endif
+        opt.(deblank (fields(pos,:))) = varargin{i+1};
+        break
+      endif
+
+      ## if there are more matching, ask the user to be more precise
+      warning ("OdePkg:InvalidArgument", "no exact matching for ''%s''. ",
+               "%d possible fields were found",
+               name, size (pos, 1));
+      for j = 1:(size (pos, 1))
+        fprintf ("%s\n", deblank (fields(pos(j),:)));
+      endfor
+      do
+        fprintf ("Please insert field name again\n");
+        name = input ("New field name: ");
+      until (ischar (name))
+    endwhile
+  endfor
+
+  ## check if all has been done gives a valid OdePkg struct
+  ode_struct_value_check (opt);
+endfunction
+
+## function useful to print all the possible options
+function print_options ()
+  
+  fprintf ("These following are all possible options.\n",
+           "Default values are put in square brackets.\n\n");
+  
+  disp ("             AbsTol:  scalar or vector, >0, [1.e-6]");
+  disp ("          Algorithm:  string, {[''gmres''], ''pcg'', ''bicgstab''}");
+  disp ("                BDF:  binary, {''on'', [''off'']}");
+  disp ("             Choice:  switch, {[1], 2}");
+  disp ("                Eta:  scalar, >=0, <1, [0.5]");
+  disp ("             Events:  function_handle, []");
+  disp ("           Explicit:  binary, {''yes'', [''no'']}");
+  disp ("      InexactSolver:  string, {''inexact_newton'', ''fsolve'', []}");
+  disp ("       InitialSlope:  vector, []");
+  disp ("        InitialStep:  scalar, >0, []");
+  disp ("           Jacobian:  matrix or function_handle, []");
+  disp ("          JConstant:  binary, {''on'', [''off'']}");
+  disp ("           JPattern:  sparse matrix, []");
+  disp ("               Mass:  matrix or function_handle, []");
+  disp ("       MassConstant:  binary, {''on'', [''off'']}");
+  disp ("       MassSingular:  switch, {''yes'', [''maybe''], ''no''}");
+  disp ("MaxNewtonIterations:  scalar, integer, >0, [1.e3]");
+  disp ("           MaxOrder:  switch, {1, 2, 3, 4, [5]}");
+  disp ("            MaxStep:  scalar, >0, []");
+  disp ("   MStateDependence:  switch, {''none'', [''weak''], ''strong''}");
+  disp ("          MvPattern:  sparse matrix, []");
+  disp ("          NewtonTol:  scalar or vector, >0, []");
+  disp ("        NonNegative:  vector of integers, []");
+  disp ("        NormControl:  binary, {''on'', [''off'']}");
+  disp ("          OutputFcn:  function_handle, []");
+  disp ("         OutputSave:  scalar, integer, >0, []");
+  disp ("          OutputSel:  scalar or vector, []");
+  disp ("   PolynomialDegree:  scalar, integer, >0, []");
+  disp ("    QuadratureOrder:  scalar, integer, >0, []");
+  disp ("             Refine:  scalar, integer, >0, []");
+  disp ("             RelTol:  scalar, >0, [1.e-3]");
+  disp ("            Restart:  scalar, integer, >0, [20]");
+  disp ("              Stats:  binary, {''on'', [''off'']}");
+  disp ("     TimeStepNumber:  scalar, integer, >0, []");
+  disp ("       TimeStepSize:  scalar, >0, []");
+  disp ("        UseJacobian:  binary, {''yes'', [''no'']}");
+  disp ("         Vectorized:  binary, {''on'', [''off'']}");
+
+endfunction
+
+## All tests that are needed to check if a correct resp. valid option
+## has been set are implemented in ode_struct_value_check.m.
+%! ## Turn off output of warning messages for all tests, turn them on
+%! ## again if the last test is called
+%!  warning ('off', 'OdePkg:InvalidArgument');
+%!test odeoptA = odeset ();
+%!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!     if (odeoptB.AbsTol != 1e-2), error; endif
+%!     if (odeoptB.RelTol != 1e-1), error; endif
+%!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!     odeoptC = odeset (odeoptB, 'NormControl', 'on');
+%!test odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!     odeoptC = odeset (odeoptB, 'NormControl', 'on');
+%!     odeoptD = odeset (odeoptC, odeoptB);
+%!
+%!  warning ('on', 'OdePkg:InvalidArgument');
+
+%!demo
+%! # A new OdePkg options structure with default values is created.
+%!
+%! odeoptA = odeset ();
+%!
+%!demo
+%! # A new OdePkg options structure with manually set options 
+%! # "AbsTol" and "RelTol" is created.
+%!
+%! odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%!
+%!demo
+%! # A new OdePkg options structure from odeoptB is created with
+%! # a modified value for option "NormControl".
+%!
+%! odeoptB = odeset ('AbsTol', 1e-2, 'RelTol', 1e-1);
+%! odeoptC = odeset (odeoptB, 'NormControl', 'on');
+
+## Local Variables: ***
+## mode: octave ***
+## End: ***
diff -r 3b0a9a832360 -r ab9ec60bedf4 scripts/ode/private/fuzzy_compare.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/private/fuzzy_compare.m	Tue Jan 06 11:12:19 2015 +0100
@@ -0,0 +1,202 @@
+## Copyright (C) 2013, Roberto Porcu' <roberto.porcu@polimi.it>
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+
+## -*- texinfo -*-
+## @deftypefn {Command} {[@var{res}] =} fuzzy_compare @
+## (@var{"string1"}, @var{string_set}, [@var{correctness}])
+##
+## Compare a string with a set of strings and returns the positions
+## in the set of strings at which there are the fields that best fit
+## the one we are comparing.
+##
+## The distance used to compare the words is the Levenshtein distance
+## and for more details see
+## @url{http://en.wikipedia.org/wiki/Levenshtein_distance}.
+##
+## This function must be called with one output argument @var{res}
+## which contains the positions of the elements in @var{string_set}
+## which best fit the given word. The tolerance that is used to
+## determine if a field of the list fits or not the given word is a
+## function of the length of the word and of the minimum distance of
+## the word from all the elements of the list. The more the length,
+## the more the tolerance. The less the minimum, the less the
+## tolerance but if the minimum is close to the length of the word,
+## the tolerance must be small because it means that no field in the
+## list is really fitting the given word. So that the function is:
+##
+## @ifhtml
+## @example
+## @math{tolerance = 2 * (length-minimum) * minimum / length}
+## @end example
+## @end ifhtml
+## @ifnothtml
+## @math{tolerance = 2 * (length-minimum) * minimum / length}.
+## @end ifnothtml
+##
+## The first input argument must be a string containing the word to
+## compare.
+##
+## The second input argument must be a vector of strings or a
+## cell_array of strings and should contain the fields to use for the
+## comparison.
+##
+## The third input argument is optional and represents a fixed
+## tolerance that will replace the implemented one.
+## @end deftypefn
+##
+## @seealso{odeset,odeget,levenshtein}
+
+function res = fuzzy_compare (string1, string_set, correctness)
+
+  ## check on output arguments
+  if (nargout > 1)
+    error ("OdePkg:InvalidArgument",
+           "too many output arguments");
+  endif
+
+  ## check on input arguments
+  if (nargin < 2 || nargin > 3)
+    error ("OdePkg:InvalidArgument",
+           "wrong input arguments number");
+  endif
+
+  if (! ischar (string1)
+      || (! iscellstr (string_set)
+          && ! ischar (string_set)))
+    error ("OdePkg:InvalidArgument",
+           "first argument must be a string, second argument ",
+           "must be an array of strings or a cell array of strings");
+  endif
+
+  if (nargin == 3)
+    if ((! isnumeric (correctness) || ! isscalar (correctness))
+        && (! ischar (correctness)))
+      error ("OdePkg:InvalidArgument",
+             "third input argument must be a positive ",
+             "integer or a string");
+    endif
+
+    if (isnumeric (correctness)
+        && ( correctness < 0 || mod (correctness, 1) != 0))
+      error ("OdePkg:InvalidArgument",
+             "third input argument must be a positive integer");
+    endif
+  endif
+
+  res = [];
+
+  m = length (string1);
+  fields_nb = size (string_set, 1);
+
+  values = inf .* ones (fields_nb, 1);
+
+  string1 = deblank (string1);
+  string2 = [];
+
+  minimus = inf;
+  ## loop on every field of the list
+  for i = 1:fields_nb
+    if (iscellstr (string_set))
+      string2 = deblank (string_set{i});
+    else
+      string2 = deblank (string_set(i,:));
+    endif
+    ## compute Levenshtein distance (not case sensitive)
+    values(i) = levenshtein (lower (string1),
+                             lower (string2),
+                             minimus);
+    ## update the upper_bound to speedup the computation
+    minimus = min (minimus, values(i));
+  endfor
+
+  positions = find (values == minimus);
+
+  if (minimus == 0) # exact match
+    if (size (positions, 1) != 1)
+      error ("OdePkg:InvalidArgument",
+             "there are %d strings perfectly matching ''%s''",
+             size (positions, 1), string1);
+    endif
+    res = positions;
+    return
+  endif
+
+  ## determine the tolerance with the formula described in the
+  ## textinfo section it is a downwards parable with zeros in 0 and m
+  ## and with a maximum in m/2 of value m/2
+  tolerance = m * (-(minimus - m) * minimus * (2 / (m*m)));
+
+  ## if the degree of correctness is fixed by the user, it will
+  ## replace the tolerance
+  if (nargin == 3)
+    if ((isnumeric (correctness)
+         && isscalar (correctness)
+         && correctness == 0)
+        || (ischar (correctness)
+            && strcmp (lower (deblank (correctness)), "exact")))
+      error ("OdePkg:InvalidArgument",
+             "no exact matching for string ''%s''", string1);
+    endif
+    if (isnumeric (correctness)
+        && isscalar (correctness))
+      tolerance = correctness;
+    endif
+  endif
+
+  ## returning the positions of the fields whose distance is lower
+  ## than the tolerance
+  for i = 1:1:fields_nb
+    if (values(i) <= tolerance)
+      res = [res; i];
+    endif
+  endfor
+
+endfunction
+
+%! ## Turn off output of warning messages for all tests, turn them on
+%! ## again if the last test is called
+%!test
+%!  warning ('off', 'OdePkg:InvalidArgument');
+%!  a = struct ('Green', 5, 'Yellow', 6, 'Orange', 6, 'Blue', 4, 'Red', 3);
+%!  a_f = fieldnames (a);
+%!  pos = fuzzy_compare ('rrd', a_f);
+%!  assert (pos, 5);
+%!
+%!test
+%!  a = ['Green'; 'Yellow'; 'Orange'; 'Blue'; 'Red'];
+%!  pos = fuzzy_compare ('rrd', a);
+%!  assert (pos, 5);
+%!
+%!test
+%!  a = struct ('Green', 5, 'Yellow', 6, 'Orange', 6, 'Blue', 4, 'Red', 3);
+%!  a_f = fieldnames (a);
+%!  pos = fuzzy_compare ('rrd', a_f, 1);
+%!  assert (pos, 5);
+%!
+%!test
+%!  a = struct('Green', 5, 'Yellow', 6, 'Orange', 6, 'Blue', 4, 'Red', 3);
+%!  a_f = fieldnames (a);
+%!  pos = fuzzy_compare ('rrd', a_f, 4);
+%!  assert (pos, [1 4 5]');
+%!
+%!  warning ('on', 'OdePkg:InvalidArgument');
+
+## Local Variables: ***
+## mode: octave ***
+## End: ***
diff -r 3b0a9a832360 -r ab9ec60bedf4 scripts/ode/private/levenshtein.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/private/levenshtein.m	Tue Jan 06 11:12:19 2015 +0100
@@ -0,0 +1,145 @@
+## Copyright (C) 2013, Roberto Porcu' <roberto.porcu@polimi.it>
+## OdePkg - A package for solving ordinary differential equations and more
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Command} {[@var{dist}] =}
+## levenshtein (@var{"string1"}, @var{"string2"}, [@var{upper_bound}])
+## @deftypefnx {Command} {[@var{dist}, @var{d}] =}
+## levenshtein (@var{"string1"}, @var{"string2"}, [@var{upper_bound}])
+##
+## This function file can be used to compare two strings and it uses the
+## Levenshtein distance as definition of metric between strings.
+## More details at @url{http://en.wikipedia.org/wiki/Levenshtein_distance}.
+##
+## This function must be called with two output arguments: @var{dist} is the
+## distance between the two strings and @var{d} is the matrix computed by
+## Levenshtein algorithm.
+##
+## The first and the second input arguments are the two strings to be compared.
+## This comparison is case-sensitive.
+##
+## The third argument is optional and fixes an upper bound for the distance.
+## If the distance is greater than this limit then the function ends and
+## returns a value equal to Inf.
+## @end deftypefn
+##
+## @seealso{odeset, odeget, fuzzy_compare}
+
+function [dist, d] = levenshtein (string1, string2, upper_bound)
+
+  ## check on output arguments
+  if (nargout > 2)
+    error ("OdePkg:InvalidArgument",
+           "too many output arguments");
+  endif
+
+  ## check on input arguments
+  if (nargin < 2 || nargin > 3)
+    error ("OdePkg:InvalidArgument",
+           "input arguments number must be equal to 2 or 3");
+  endif
+  if (! ischar (string1) || ! ischar (string2))
+    error ("OdePkg:InvalidArgument",
+           "input arguments must be strings");
+  endif
+
+  ## lengths of the two strings
+  m = length (string1);
+  n = length (string2);
+
+  ## taking lower cases of the two strings if no case sensitive
+  ## comparison is required
+  if (nargin != 3)
+    upper_bound = inf;
+  elseif (isempty (upper_bound))
+    upper_bound = inf;
+  endif
+
+  ## initializing the matrix
+  d = zeros (m+1, n+1);
+  d(2:m+1,1) = [1:1:m];
+  d(1,2:n+1) = [1:1:n];
+
+  ## the following algorithm is described in
+  ## <http://en.wikipedia.org/wiki/Levenshtein_distance>
+  for j = 2:1:n+1
+    for k = 2:1:m+1
+      if (string1(k-1) == string2(j-1))
+        d(k,j) = d(k-1,j-1);
+      else
+        d(k,j) = min (d(k-1,j) + 1, min (d(k,j-1) + 1, d(k-1,j-1) + 1));
+      endif
+    endfor
+
+    if (d(min (j, m+1), j) > upper_bound )
+      dist = inf;
+      return
+    endif
+
+  endfor
+
+  ## the distance between the strings is given by the last element of the matrix
+  dist = d(m+1,n+1);
+endfunction
+
+%! # A simple test which is taken from
+%! <http://en.wikipedia.org/wiki/Levenshtein_distance>.
+%!
+%! ## Turn off output of warning messages for all tests, turn them on
+%! ## again if the last test is called
+%!test ## one output argument
+%!  warning ('off', 'OdePkg:InvalidArgument');
+%!  res = levenshtein ('sitting', 'kitten');
+%!  assert (res == 3);
+%!test ## two output arguments
+%!  [res, matrix] = levenshtein ('sitting', 'kitten');
+%!  ex_matrix = [0 1 2 3 4 5 6;
+%!               1 1 2 3 4 5 6;
+%!               2 2 1 2 3 4 5;
+%!               3 3 2 1 2 3 4;
+%!               4 4 3 2 1 2 3;
+%!               5 5 4 3 2 2 3;
+%!               6 6 5 4 3 3 2;
+%!               7 7 6 5 4 4 3];
+%!  assert (res == 3);
+%!  assert (matrix == ex_matrix);
+%!test ## two output arguments
+%!  [res, matrix] = levenshtein ('Sunday', 'Saturday');
+%!  ex_matrix = [0 1 2 3 4 5 6 7 8;
+%!               1 0 1 2 3 4 5 6 7;
+%!               2 1 1 2 2 3 4 5 6;
+%!               3 2 2 2 3 3 4 5 6;
+%!               4 3 3 3 3 4 3 4 5;
+%!               5 4 3 4 4 4 4 3 4;
+%!               6 5 4 4 5 5 5 4 3];
+%!  assert (res == 3);
+%!  assert (matrix == ex_matrix);
+%!test ## two output arguments case sensitiveness
+%!  [res, matrix] = levenshtein ('Sunday', 'saturday');
+%!  assert (res == 4);
+%!test ## two output arguments case no-sensitiveness
+%!  [res, matrix] = levenshtein ('Sunday', 'saturday', 1);
+%!  assert (res > 1e6);
+%!  [res, matrix] = levenshtein ('Sunday', 'saturday', 10);
+%!  assert (res == 4);
+%!  warning ('on', 'OdePkg:InvalidArgument');
+
+## Local Variables: ***
+## mode: octave ***
+## End: ***
diff -r 3b0a9a832360 -r ab9ec60bedf4 scripts/ode/private/ode_struct_value_check.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/ode/private/ode_struct_value_check.m	Tue Jan 06 11:12:19 2015 +0100
@@ -0,0 +1,592 @@
+## Copyright (C) 2006-2012, Thomas Treichl <treichl@users.sourceforge.net>
+## Copyright (C) 2013, Roberto Porcu' <roberto.porcu@polimi.it>
+## OdePkg - A package for solving ordinary differential equations and more
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{}] =}
+## ode_struct_value_check (@var{arg}, [@var{"solver"}])
+##
+## If this function is called with one input argument of type structure array
+## then check the field names and the field values of the OdePkg structure
+## @var{arg}. Optionally if this function is called with a second input
+## argument @var{"solver"} of type string that specifies the name of a valid
+## OdePkg solver then a higher level error detection is performed. The function
+## does not modify any of the field names or field values but terminates with
+## an error if an invalid option or value is found.
+##
+## This function is an OdePkg internal helper function therefore it should
+## never be necessary that this function is called directly by a user.
+## @end deftypefn
+##
+## @seealso{odeset, odeget}
+
+function ode_struct_value_check (arg, solver)
+
+  ## Check the number of input arguments
+  if (nargin == 0 || nargin > 2)
+    error ("OdePkg:InvalidArgument",
+           "wrong input arguments number");
+  endif
+
+  if (! isstruct (arg))
+    error ("OdePkg:InvalidArgument",
+           "first input argument is not a struct");
+  endif
+
+  if (nargin == 1)
+    solver = [];
+  elseif (! ischar (solver) )
+    error ("OdePkg:InvalidArgument",
+           "second input argument is not a string");
+  endif
+
+  fields = fieldnames (arg);
+  fields_nb = length (fields);
+
+  for i = 1:1:fields_nb # Run through the number of given structure field names
+    switch (fields{i})
+
+      case "AbsTol"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              || any (arg.(fields{i}) <= 0)
+              || ~isreal (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (! isvector (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif ( any (arg.(fields{i}) <= 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Algorithm"
+        if (! isempty (arg.(fields{i})))
+          if (! ischar (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "BDF"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "on")
+              && ! strcmp (arg.(fields{i}), "off"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Choice"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (arg.(fields{i}) != 1 && arg.(fields{i}) != 2)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Eta"
+        if ( ~isempty (arg.(fields{i})) )
+          if ( ~isreal (arg.(fields{i})) )
+            error ("OdePkg:InvalidArgument", ...
+              "value assigned to field %s is not a valid one", fields{i});
+          elseif ( arg.(fields{i})<0 || arg.(fields{i})>=1 )
+            error ("OdePkg:InvalidArgument", ...
+              "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Events"
+        if (! isempty (arg.(fields{i})))
+          if (! isa (arg.(fields{i}), "function_handle"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Explicit"
+        if (! isempty (arg.(fields{i})))
+          if (! ischar (arg.(fields{i}))
+              || (! strcmp (arg.(fields{i}), "yes")
+                  && ! strcmp (arg.(fields{i}), "no")))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "InexactSolver"
+        if (! isempty (arg.(fields{i})))
+          if (! ischar (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "InitialSlope"
+        if (! isempty (arg.(fields{i})))
+          if (! ischar (arg.(fields{i}))
+              && (! isnumeric (arg.(fields{i}))
+                  || (! isvector (arg.(fields{i}))
+                      && ! isreal (arg.(fields{i})))))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "InitialStep"
+        if (! isempty (arg.(fields{i})) )
+          if (! isnumeric (arg.(fields{i}))
+              || ! isscalar (arg.(fields{i}))
+              || ! isreal (arg.(fields{i}))
+              || arg.(fields{i}) <=0)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Jacobian"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i})))
+            if (! isa (arg.(fields{i}), "function_handle")
+                && ! iscell (arg.(fields{i})))
+              error ("OdePkg:InvalidArgument",
+                     "value assigned to field %s is not a valid one",
+                     fields{i});
+            endif
+          endif
+        endif
+
+      case "JConstant"
+        if (! isempty(arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "on")
+              && ! strcmp (arg.(fields{i}), "off"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "JPattern"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              && ! isscalar (arg.(fields{i}))
+              && ! isvector (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Mass"
+        if (! isempty (arg.(fields{i})))
+          if ((! isnumeric (arg.(fields{i}))
+               || ~ismatrix (arg.(fields{i})))
+              && ! isa (arg.(fields{i}), "function_handle"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MassConstant"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "on")
+              && ! strcmp (arg.(fields{i}), "off"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MassSingular"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "yes")
+              && ! strcmp (arg.(fields{i}), "no")
+              && ! strcmp (arg.(fields{i}), "maybe"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MaxNewtonIterations"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (mod (arg.(fields{i}), 1) != 0
+                  || arg.(fields{i}) <= 0)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MaxOrder"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (mod (arg.(fields{i}), 1) != 0
+                  || arg.(fields{i}) <= 0
+                  || arg.(fields{i}) >= 8 )
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MaxStep"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              || ! isscalar (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (arg.(fields{i}) <= 0)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MStateDependence"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "none")
+              && ! strcmp (arg.(fields{i}), "weak")
+              && ! strcmp (arg.(fields{i}), "strong"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "MvPattern"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              && ! isvector (arg.(fields{i})) )
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "NewtonTol"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              || ! isreal (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (any (arg.(fields{i}) <= 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "NonNegative"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              || ! isvector (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (any (arg.(fields{i}) <= 0)
+                  || any (mod (arg.(fields{i}), 1) != 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "NormControl"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "on")
+              && ! strcmp (arg.(fields{i}), "off"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "OutputFcn"
+        if (! isempty (arg.(fields{i})))
+          if (! isa (arg.(fields{i}), "function_handle"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "OutputSave"
+        if (! isempty (arg.(fields{i})))
+          if (! isscalar (arg.(fields{i}))
+              && arg.(fields{i}) != Inf)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif ((mod (arg.(fields{i}), 1) != 0 || arg.(fields{i}) <= 0)
+                  && arg.(fields{i}) != Inf)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "OutputSel"
+        if (! isempty (arg.(fields{i})))
+          if (! isscalar (arg.(fields{i})) )
+            if (! isnumeric (arg.(fields{i}))
+                || ! isvector (arg.(fields{i})))
+              error ("OdePkg:InvalidArgument",
+                     "value assigned to field %s is not a valid one",
+                     fields{i});
+            endif
+          endif
+        endif
+
+      case "PolynomialDegree"
+        if (! isempty (arg.(fields{i})) )
+          if (! isnumeric (arg.(fields{i}))
+              || ! isvector (arg.(fields{i})) )
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (any (arg.(fields{i}) <= 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "QuadratureOrder"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              || ! isvector (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (any(arg.(fields{i}) <= 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Refine"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i}))
+              || ! isscalar (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (mod (arg.(fields{i}), 1) != 0
+                  || arg.(fields{i}) < 0
+                  || arg.(fields{i}) > 5 )
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "RelTol"
+        if (! isempty (arg.(fields{i})) )
+          if (! isnumeric (arg.(fields{i})) )
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (! isreal (arg.(fields{i}))
+                  || any (arg.(fields{i}) <= 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+        switch (solver)
+          case {"ode23", "ode23d", "ode45", "ode45d",
+                "ode54", "ode54d", "ode78", "ode78d"}
+            if (! isempty (arg.(fields{i})))
+              if (! isscalar (arg.(fields{i})))
+                error ("OdePkg:InvalidArgument",
+                       "for this type of solver, value assigned to field %s ",
+                       "is not a valid one", fields{i});
+              endif
+            endif
+          otherwise
+        endswitch
+
+      case "Restart"
+        if (! isempty (arg.(fields{i})))
+          if (! isnumeric (arg.(fields{i})))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          elseif (mod (arg.(fields{i}), 1) != 0
+                  || arg.(fields{i}) <=0 )
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Stats"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "on")
+              && ! strcmp (arg.(fields{i}), "off"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "TimeStepNumber"
+        if (! isempty (arg.(fields{i})))
+          if (mod (arg.(fields{i}), 1) != 0
+              || arg.(fields{i}) <= 0)
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "TimeStepSize"
+        if (! isempty (arg.(fields{i})))
+          if (! isreal (arg.(fields{i}))
+              || (arg.(fields{i}) == 0))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "UseJacobian"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "yes")
+              && ! strcmp (arg.(fields{i}), "no"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      case "Vectorized"
+        if (! isempty (arg.(fields{i})))
+          if (! strcmp (arg.(fields{i}), "on")
+              && ! strcmp (arg.(fields{i}), "off"))
+            error ("OdePkg:InvalidArgument",
+                   "value assigned to field %s is not a valid one", fields{i});
+          endif
+        endif
+
+      otherwise
+        warning ("OdePkg:InvalidArgument",
+                 "no fields with name %s in ODE options.", fields{i});
+    endswitch
+  endfor
+
+endfunction
+
+%!test  A = odeset ('RelTol', 1e-4);
+%!test  A = odeset ('RelTol', [1e-4, 1e-3]);
+%!test  A = odeset ('RelTol', []);
+%!error A = odeset ('RelTol', '1e-4');
+%!error A = odeset ('RelTol', -1e-3);
+%!test  A = odeset ('AbsTol', 1e-4);
+%!test  A = odeset ('AbsTol', [1e-4, 1e-3]);
+%!test  A = odeset ('AbsTol', []);
+%!error A = odeset ('AbsTol', '1e-4');
+%!error A = odeset ('AbsTol', -1e-4);
+%!test  A = odeset ('NormControl', 'on');
+%!test  A = odeset ('NormControl', 'off');
+%!test  A = odeset ('NormControl', []);
+%!error A = odeset ('NormControl', '12');
+%!test  A = odeset ('NonNegative', 1);
+%!test  A = odeset ('NonNegative', [1, 2, 3]);
+%!test  A = odeset ('NonNegative', []);
+%!error A = odeset ('NonNegative', '12');
+%!test  A = odeset ('OutputFcn', []);
+%!test  A = odeset ('OutputSel', 1);
+%!test  A = odeset ('OutputSel', [1, 2, 3]);
+%!test  A = odeset ('OutputSel', []);
+%!error A = odeset ('OutputSel', '12');
+%!test  A = odeset ('Refine', 3);
+%!error A = odeset ('Refine', [1, 2, 3]);
+%!test  A = odeset ('Refine', []);
+%!error A = odeset ('Refine', 6);
+%!test  A = odeset ('Stats', 'on');
+%!test  A = odeset ('Stats', 'off');
+%!test  A = odeset ('Stats', []);
+%!error A = odeset ('Stats', '12');
+%!test  A = odeset ('InitialStep', 3);
+%!error A = odeset ('InitialStep', [1, 2, 3]);
+%!error A = odeset ('InitialStep', -2);
+%!test  A = odeset ('InitialStep', []);
+%!test  A = odeset ('InitialStep', 6);
+%!test  A = odeset ('MaxStep', 3);
+%!error A = odeset ('MaxStep', [1, 2, 3]);
+%!error A = odeset ('MaxStep', -1);
+%!test  A = odeset ('MaxStep', []);
+%!test  A = odeset ('MaxStep', 6);
+%!test  A = odeset ('Events', @demo);
+%!error A = odeset ('Events', 'off');
+%!test  A = odeset ('Events', []);
+%!error A = odeset ('Events', '12');
+%!test  A = odeset ('Jacobian', @demo);
+%!test  A = odeset ('Jacobian', [1, 2; 3, 4]);
+%!test  A = odeset ('Jacobian', []);
+%!error A = odeset ('Jacobian', '12');
+%!test  A = odeset ('JPattern', []);
+%!test  A = odeset ('JPattern', [1, 2, 4]);
+%!test  A = odeset ('JPattern', [1, 2; 3, 4]);
+%!test  A = odeset ('JPattern', 1);
+%!test  A = odeset ('Vectorized', 'on');
+%!test  A = odeset ('Vectorized', 'off');
+%!test  A = odeset ('Vectorized', []);
+%!error A = odeset ('Vectorized', '12');
+%!test  A = odeset ('Mass', @demo);
+%!test  A = odeset ('Mass', [1, 2; 3, 4]);
+%!test  A = odeset ('Mass', []);
+%!error A = odeset ('Mass', '12');
+%!test  A = odeset ('MStateDependence', 'none');
+%!test  A = odeset ('MStateDependence', 'weak');
+%!test  A = odeset ('MStateDependence', 'strong');
+%!error A = odeset ('MStateDependence', [1, 2; 3, 4]);
+%!test  A = odeset ('MStateDependence', []);
+%!error A = odeset ('MStateDependence', '12');
+%!test  A = odeset ('MvPattern', []);
+%!test  A = odeset ('MvPattern', [1, 2, 3 ]);
+%!test  A = odeset ('MvPattern', [1, 2; 3, 4]);
+%!test  A = odeset ('MvPattern', 1);
+%!test  A = odeset ('MassSingular', 'yes');
+%!test  A = odeset ('MassSingular', 'no');
+%!test  A = odeset ('MassSingular', 'maybe');
+%!error A = odeset ('MassSingular', [1, 2; 3, 4]);
+%!test  A = odeset ('MassSingular', []);
+%!error A = odeset ('MassSingular', '12');
+%!test  A = odeset ('InitialSlope', [1, 2, 3]);
+%!test  A = odeset ('InitialSlope', 1);
+%!test  A = odeset ('InitialSlope', []);
+%!test  A = odeset ('InitialSlope', '12');
+%!test  A = odeset ('MaxOrder', 3);
+%!error A = odeset ('MaxOrder', 3.5);
+%!test  A = odeset ('MaxOrder', [1, 2; 3, 4]);
+%!test  A = odeset ('MaxOrder', []);
+%!test  A = odeset ('BDF', 'on');
+%!test  A = odeset ('BDF', 'off');
+%!test  A = odeset ('BDF', []);
+%!error A = odeset ('BDF', [1, 2; 3, 4]);
+%!test  A = odeset ('NewtonTol', []);
+%!test  A = odeset ('NewtonTol', 1e-3);
+%!test  A = odeset ('NewtonTol', [1e-3, 1e-3, 1e-3]);
+%!error A = odeset ('NewtonTol', 'string');
+%!test  A = odeset ('MaxNewtonIterations', []);
+%!test  A = odeset ('MaxNewtonIterations', 2);
+%!error A = odeset ('MaxNewtonIterations', 'string');
+
+%!demo
+%! # Return the checked OdePkg options structure that is created by
+%! # the command odeset.
+%!
+%! ode_struct_value_check (odeset);
+%!
+%!demo
+%! # Create the OdePkg options structure A with odeset and check it 
+%! # with odepkg_structure_check. This actually is unnecessary
+%! # because odeset automtically calls odepkg_structure_check before
+%! # returning.
+%!
+%! A = odeset (); ode_struct_value_check (A);
+
+## Local Variables: ***
+## mode: octave ***
+## End: ***
