changeset 20636:6e81f4b37e13

Performance improvements for ODE functions. * odeget.m: Place code for "fast" extraction of values at start of code before any other input validation. * odeset.m: Combine special input processing for nargin == 0 into one block of code. * integrate_adaptive.m, integrate_const.m: Use in-place operator "+= 1" rather than "++" because it is faster.
author Rik <rik@octave.org>
date Mon, 19 Oct 2015 08:22:23 -0700
parents 80e630b37ba1
children 31219c56874f
files scripts/ode/odeget.m scripts/ode/odeset.m scripts/ode/private/integrate_adaptive.m scripts/ode/private/integrate_const.m
diffstat 4 files changed, 36 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ode/odeget.m	Sun Oct 18 09:55:41 2015 -0700
+++ b/scripts/ode/odeget.m	Mon Oct 19 08:22:23 2015 -0700
@@ -37,7 +37,20 @@
 
 ## FIXME: 4th input argument "opt" is undocumented.
 
-function val = odeget (ode_opt, field, default = [], opt)
+function val = odeget (ode_opt, field, default = [], opt = "")
+
+  ## Shortcut for quickly extracting option
+  if (strncmp (opt, "fast", 4))
+    try
+      val = ode_opt.(field);
+      if (strcmp (opt, "fast_not_empty") && isempty (val))
+        val = default;
+      endif
+    catch
+      val = default;
+    end_try_catch
+    return;
+  endif
 
   if (nargin < 1 || nargin > 4)
     print_usage ();
@@ -59,27 +72,6 @@
     error ("odeget: FIELD must be a string");
   endif
 
-  if (nargin == 4 && strcmpi (opt, "fast"))
-    try
-      val = ode_opt.(field);
-    catch
-      val = default;
-    end_try_catch
-    return;
-  endif
-
-  if (nargin == 4 && strcmpi (opt, "fast_not_empty"))
-    try
-      val = ode_opt.(field);
-      if (isempty (val))
-        val = default;
-      endif
-    catch
-      val = default;
-    end_try_catch
-    return;
-  endif
-
   ## Check if the given struct is a valid ODEOPT struct
   ode_struct_value_check ("odeget", ode_opt);
 
--- a/scripts/ode/odeset.m	Sun Oct 18 09:55:41 2015 -0700
+++ b/scripts/ode/odeset.m	Mon Oct 19 08:22:23 2015 -0700
@@ -47,12 +47,6 @@
 
 function odestruct = odeset (varargin)
 
-  ## Special calling syntax to display defaults
-  if (nargin == 0 && nargout == 0)
-    print_options ();
-    return;
-  endif
-
   ## Column vector of all possible ODE options
   persistent options = {"AbsTol"; "BDF"; "Events"; "InitialSlope";
                         "InitialStep"; "Jacobian"; "JConstant"; "JPattern";
@@ -61,13 +55,19 @@
                         "NonNegative"; "NormControl"; "OutputFcn"; "OutputSel";
                         "Refine"; "RelTol"; "Stats"; "Vectorized"};
 
+  if (nargin == 0)
+    ## Special calling syntax to display defaults
+    if (nargout == 0)
+      print_options ();
+    else
+      odestruct = cell2struct (cell (numel (options), 1), options);
+    endif
+    return;
+  endif
+
   ## initialize output
   odestruct = cell2struct (cell (numel (options), 1), options);
 
-  if (nargin == 0)
-    return;
-  endif
-
   if (isstruct (varargin{1}))
     oldstruct = varargin{1};
 
--- a/scripts/ode/private/integrate_adaptive.m	Sun Oct 18 09:55:41 2015 -0700
+++ b/scripts/ode/private/integrate_adaptive.m	Mon Oct 19 08:22:23 2015 -0700
@@ -122,7 +122,7 @@
     [t_new, x_new, x_est, new_k_vals] = ...
       stepper (func, t_old, x_old, dt, options, k_vals, t_new);
 
-    solution.cntcycles++;
+    solution.cntcycles += 1;
 
     if (options.havenonnegative)
       x_new(nn, end) = abs (x_new(nn, end));
@@ -135,8 +135,8 @@
     ## Accept solution only if err <= 1.0
     if (err <= 1)
 
-      solution.cntloop++;
-      ireject = 0;
+      solution.cntloop += 1;
+      ireject = 0;              # Clear reject counter
 
       ## if output time steps are fixed
       if (fixed_times)
@@ -150,10 +150,10 @@
           iout = max (t_caught);
           x(:, t_caught) = ...
             runge_kutta_interpolate (order, [t_old t_new], [x_old x_new],
-                                tspan(t_caught), new_k_vals, dt,
-                                options.funarguments{:});
+                                     tspan(t_caught), new_k_vals, dt,
+                                     options.funarguments{:});
 
-          istep++;
+          istep += 1;
 
           ## Call Events function only if a valid result has been found.
           ## Stop integration if eventbreak is true.
@@ -256,7 +256,7 @@
 
     else
 
-      ireject++;
+      ireject += 1;
 
       ## Stop solving because, in the last 5,000 steps, no successful valid
       ## value has been found
--- a/scripts/ode/private/integrate_const.m	Sun Oct 18 09:55:41 2015 -0700
+++ b/scripts/ode/private/integrate_const.m	Mon Oct 19 08:22:23 2015 -0700
@@ -135,7 +135,7 @@
     if ((z(end) == tspan(counter))
         || (abs (z(end) - tspan(counter)) /
             (max (abs (z(end)), abs (tspan(counter)))) < 8*eps) )
-      counter++;
+      counter += 1;
 
     ## if there is an element in time vector at which the solution is required
     ## the program must compute this solution before going on with next steps
@@ -149,7 +149,7 @@
             && (((z(i) == tspan(counter))
                  || (abs (z(i) - tspan(counter)) /
                      (max (abs (z(i)), abs (tspan(counter)))) < 8*eps))) )
-          counter++;
+          counter += 1;
         endif
         ## else, loop until there are requested values inside this subinterval
         while ((counter <= k)
@@ -161,14 +161,14 @@
           z = [z(1:i-1);tspan(counter);z(i:end)];
 
           ## update counters
-          counter++;
-          i++;
+          counter += 1;
+          i += 1;
         endwhile
 
         ## if new time requested is not out of this interval
         if (counter <= k && direction * z(end) > direction * tspan(counter))
           ## update the counter
-          i++;
+          i += 1;
         else
           ## else, stop the cycle and go on with the next iteration
           i = length (z)+1;