changeset 22648:9bc03a3f7a34 stable

ode_event_handler.m: Overhaul function. * ode_event_handler.m: Rewrite docstring. Place most common case first in if/elseif tree for performance. Return an empty 1x4 cell array for the "init" and "done" cases.
author Rik <rik@octave.org>
date Wed, 19 Oct 2016 15:17:17 -0700
parents cf8ec7abb4ae
children 2d9393be9a18 7458bacc631a
files scripts/ode/private/ode_event_handler.m
diffstat 1 files changed, 56 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ode/private/ode_event_handler.m	Wed Oct 19 14:34:15 2016 -0700
+++ b/scripts/ode/private/ode_event_handler.m	Wed Oct 19 15:17:17 2016 -0700
@@ -19,44 +19,44 @@
 ## -*- texinfo -*-
 ## @deftypefn {} {@var{retval} =} ode_event_handler (@var{@@evtfun}, @var{t}, @var{y}, @var{flag}, @var{par1}, @var{par2}, @dots{})
 ##
-## Return the solution of the event function that is specified as the first
-## input argument @var{@@evtfun} in the form of a function handle.
+## Return the solution of the event function (@var{@@evtfun}) which is
+## specified in the form of a function handle.
+#
+## The second input argument @var{t} is a scalar double and specifies the time
+## of the event evaluation.
 ##
-## The second input argument @var{t} is of type double scalar and
-## specifies the time of the event evaluation, the third input argument
-## @var{y} either is of type double column vector (for ODEs and DAEs) and
-## specifies the solutions or is of type cell array (for IDEs and DDEs) and
-## specifies the derivatives or the history values, the third input argument
-## @var{flag} is of type string and can be of the form
+## The third input argument @var{y} may be a column vector of type double
+## (for ODEs and DAEs) which specifies the solutions.  Alternatives, @var{y}
+## may be a cell array (for IDEs and DDEs) which specifies the solutions and
+## derivatives.
+##
+## The fourth input argument @var{flag} is of type string.  Valid values are:
 ##
 ## @table @option
 ## @item  @qcode{"init"}
-## then initialize internal persistent variables of the function
-## @code{ode_event_handler} and return an empty cell array of size 4,
+## Initialize internal persistent variables of the function
+## @code{ode_event_handler} and return an empty cell array of size 4.
 ##
 ## @item  @qcode{"calc"}
-## then do the evaluation of the event function and return the solution
-## @var{retval} as type cell array of size 4,
+## Evaluate the event function and return the solution @var{retval} as a cell
+## array of size 4.
 ##
 ## @item  @qcode{"done"}
-## then cleanup internal variables of the function
-## @code{ode_event_handler} and return an empty cell array of size 4.
+## Clean up internal variables of the function @code{ode_event_handler} and
+## return an empty cell array of size 4.
 ## @end table
 ##
-## Optionally if further input arguments @var{par1}, @var{par2}, @dots{} of
-## any type are given then pass these parameters through
-## @code{ode_event_handler} to the event function.
+## If additional input arguments @var{par1}, @var{par2}, @dots{} are given
+## these parameters are passed directly to the event function.
 ##
-## This function is an ODE internal helper function therefore it should
-## never be necessary that this function is called directly by a user.  There
-## is only little error detection implemented in this function file to
-## achieve the highest performance.
+## This function is an ODE internal helper function and it should never be
+## necessary to call it directly.
 ## @end deftypefn
 
 function retval = ode_event_handler (evtfun, t, y, flag = "", varargin)
 
   ## No error handling has been implemented in this function to achieve
-  ## the highest performance available.
+  ## the highest performance possible.
 
   ## retval{1} is true (to terminate) or false (to continue)
   ## retval{2} is the index information for which an event occurred
@@ -70,33 +70,12 @@
   ## yold    the ODE result
   ## retcell the return values cell array
   ## evtcnt  the counter for how often this function has been called
-  persistent evtold told yold retcell evtcnt;
-
-  ## Call the event function if an event function has been defined to
-  ## initialize the internal variables of the event function and to get
-  ## a value for evtold.
-  if (strcmp (flag, "init"))
+  persistent evtold told yold retcell;
+  persistent evtcnt = 1;   # Don't remove.  Required for Octave parser.
 
-    if (! iscell (y))
-      inpargs = {evtfun, t, y};
-    else
-      inpargs = {evtfun, t, y{1}, y{2}};
-      y = y{1};  # Delete cell element 2
-    endif
-    if (nargin > 4)
-      inpargs = {inpargs{:}, varargin{:}};
-    endif
-    [evtold, term, dir] = feval (inpargs{:});
-
-    ## FIXME: This actually seems to assume that everything must be row vectors
-    ## We assume that all return values must be column vectors
-    evtold = evtold(:)'; term = term(:)'; dir = dir(:)';
-    told = t; yold = y; evtcnt = 1; retcell = cell (1,4);
-
-  ## Process the event, i.e.,
-  ## find the zero crossings for either a rising or falling edge
-  elseif (isempty (flag))
-
+  if (isempty (flag))
+    ## Process the event, i.e.,
+    ## find the zero crossings for either a rising or falling edge
     if (! iscell (y))
       inpargs = {evtfun, t, y};
     else
@@ -108,8 +87,7 @@
     endif
     [evt, term, dir] = feval (inpargs{:});
 
-    ## FIXME: This actually seems to assume that everything must be row vectors
-    ## We assume that all return values must be column vectors
+    ## We require that all return values be row vectors
     evt = evt(:)'; term = term(:)'; dir = dir(:)';
 
     ## Check if one or more signs of the event has changed
@@ -143,12 +121,35 @@
         evtcnt += 1;
       endif
 
-    endif  # Check for one or more signs ...
-    evtold = evt; told = t; retval = retcell; yold = y;
+    endif
+    evtold = evt; told = t; yold = y;
+    retval = retcell;
+
+  elseif (strcmp (flag, "init"))
+    ## Call the event function if an event function has been defined to
+    ## initialize the internal variables of the event function and to get
+    ## a value for evtold.
 
-  elseif (strcmp (flag, "done"))  # Clear this event handling function
-    clear ("evtold", "told", "retcell", "yold", "evtcnt");
-    retcell = cell (1,4);
+    if (! iscell (y))
+      inpargs = {evtfun, t, y};
+    else
+      inpargs = {evtfun, t, y{1}, y{2}};
+      y = y{1};  # Delete cell element 2
+    endif
+    if (nargin > 4)
+      inpargs = {inpargs{:}, varargin{:}};
+    endif
+    [evtold, ~, ~] = feval (inpargs{:});
+
+    ## We require that all return values be row vectors
+    evtold = evtold(:)'; told = t; yold = y;
+    evtcnt = 1;
+    retval = retcell = cell (1,4);
+
+  elseif (strcmp (flag, "done"))
+    ## Clear this event handling function
+    evtold = told = yold = evtcnt = [];
+    retval = retcell = cell (1,4);
 
   endif