# HG changeset patch # User John W. Eaton # Date 1337027052 14400 # Node ID f8d5095fa90df432b5f9b1311fe8456ac9c6ba5f # Parent 7e10eb490b87fb917e2b9096a94263e42b8e0417 improve compatibility of tic and toc * data.cc (Ftic): Attempt to avoid loss of precision. (Ftoc): If passed a uint64 argument, use it as the start time (in microseconds). (Ftic, Ftoc): Update doc string New tests. diff -r 7e10eb490b87 -r f8d5095fa90d src/data.cc --- a/src/data.cc Mon May 14 02:09:27 2012 -0400 +++ b/src/data.cc Mon May 14 16:24:12 2012 -0400 @@ -5648,10 +5648,14 @@ DEFUN (tic, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} tic ()\n\ +@deftypefnx {Built-in Function} {@var{id} =} tic ()\n\ @deftypefnx {Built-in Function} {} toc ()\n\ +@deftypefnx {Built-in Function} {} toc (@var{id})\n\ +@deftypefnx {Built-in Function} {@var{val} =} toc (@dots{})\n\ Set or check a wall-clock timer. Calling @code{tic} without an\n\ -output argument sets the timer. Subsequent calls to @code{toc}\n\ -return the number of seconds since the timer was set. For example,\n\ +output argument sets the internal timer state. Subsequent calls\n\ +to @code{toc} return the number of seconds since the timer was set.\n\ +For example,\n\ \n\ @example\n\ @group\n\ @@ -5665,38 +5669,23 @@ will set the variable @code{elapsed_time} to the number of seconds since\n\ the most recent call to the function @code{tic}.\n\ \n\ -If called with one output argument then this function returns a scalar\n\ -of type @code{uint64} and the wall-clock timer is not started.\n\ +If called with one output argument, @code{tic} returns a scalar\n\ +of type @code{uint64} that may be later passed to @code{toc}.\n\ \n\ @example\n\ @group\n\ -t = tic; sleep (5); (double (tic ()) - double (t)) * 1e-6\n\ - @result{} 5\n\ +id = tic; sleep (5); toc (id)\n\ + @result{} 5.0010\n\ @end group\n\ @end example\n\ \n\ -Nested timing with @code{tic} and @code{toc} is not supported.\n\ -Therefore @code{toc} will always return the elapsed time from the most\n\ -recent call to @code{tic}.\n\ +Calling @code{tic} and @code{toc} this way allows nested timing calls.\n\ \n\ If you are more interested in the CPU time that your process used, you\n\ should use the @code{cputime} function instead. The @code{tic} and\n\ @code{toc} functions report the actual wall clock time that elapsed\n\ between the calls. This may include time spent processing other jobs or\n\ -doing nothing at all. For example:\n\ -\n\ -@example\n\ -@group\n\ -tic (); sleep (5); toc ()\n\ - @result{} 5\n\ -t = cputime (); sleep (5); cputime () - t\n\ - @result{} 0\n\ -@end group\n\ -@end example\n\ -\n\ -@noindent\n\ -(This example also illustrates that the CPU timer may have a fairly\n\ -coarse resolution.)\n\ +doing nothing at all.\n\ @end deftypefn") { octave_value retval; @@ -5711,7 +5700,13 @@ double tmp = now.double_value (); if (nargout > 0) - retval = static_cast (1e6 * tmp); + { + double ip = 0.0; + double frac = modf (tmp, &ip); + uint64_t microsecs = static_cast (CLOCKS_PER_SEC * frac); + microsecs += CLOCKS_PER_SEC * static_cast (ip); + retval = octave_uint64 (microsecs); + } else tic_toc_timestamp = tmp; @@ -5721,6 +5716,8 @@ DEFUN (toc, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} toc ()\n\ +@deftypefnx {Built-in Function} {} toc (@var{id})\n\ +@deftypefnx {Built-in Function} {@var{val} = } toc (@dots{})\n\ See tic.\n\ @end deftypefn") { @@ -5728,30 +5725,59 @@ int nargin = args.length (); - if (nargin != 0) - warning ("tic: ignoring extra arguments"); - - if (tic_toc_timestamp < 0) - { - warning ("toc called before timer set"); - if (nargout > 0) - retval = Matrix (); - } + double start_time = tic_toc_timestamp; + + if (nargin > 1) + print_usage (); else { - octave_time now; - - double tmp = now.double_value () - tic_toc_timestamp; - - if (nargout > 0) - retval = tmp; - else - octave_stdout << "Elapsed time is " << tmp << " seconds.\n"; + if (nargin == 1) + { + octave_uint64 id = args(0).uint64_scalar_value (); + + if (! error_state) + { + uint64_t val = id.value (); + + start_time + = (static_cast (val / CLOCKS_PER_SEC) + + static_cast (val % CLOCKS_PER_SEC) / CLOCKS_PER_SEC); + + // FIXME -- should we also check to see whether the start + // time is after the beginning of this Octave session? + } + else + error ("toc: invalid ID"); + } + + if (! error_state) + { + if (start_time < 0) + error ("toc called before timer set"); + else + { + octave_time now; + + double tmp = now.double_value () - start_time; + + if (nargout > 0) + retval = tmp; + else + octave_stdout << "Elapsed time is " << tmp << " seconds.\n"; + } + } } return retval; } +/* +%!shared id +%! id = tic (); +%!assert (isa (id, "uint64")); +%!assert (isa (toc (id), "double")); +*/ + DEFUN (cputime, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {[@var{total}, @var{user}, @var{system}] =} cputime ();\n\