comparison src/data.cc @ 14635:f8d5095fa90d

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.
author John W. Eaton <jwe@octave.org>
date Mon, 14 May 2012 16:24:12 -0400
parents 88e67d58b06b
children 7d4f87c75dbb
comparison
equal deleted inserted replaced
14634:7e10eb490b87 14635:f8d5095fa90d
5646 static double tic_toc_timestamp = -1.0; 5646 static double tic_toc_timestamp = -1.0;
5647 5647
5648 DEFUN (tic, args, nargout, 5648 DEFUN (tic, args, nargout,
5649 "-*- texinfo -*-\n\ 5649 "-*- texinfo -*-\n\
5650 @deftypefn {Built-in Function} {} tic ()\n\ 5650 @deftypefn {Built-in Function} {} tic ()\n\
5651 @deftypefnx {Built-in Function} {@var{id} =} tic ()\n\
5651 @deftypefnx {Built-in Function} {} toc ()\n\ 5652 @deftypefnx {Built-in Function} {} toc ()\n\
5653 @deftypefnx {Built-in Function} {} toc (@var{id})\n\
5654 @deftypefnx {Built-in Function} {@var{val} =} toc (@dots{})\n\
5652 Set or check a wall-clock timer. Calling @code{tic} without an\n\ 5655 Set or check a wall-clock timer. Calling @code{tic} without an\n\
5653 output argument sets the timer. Subsequent calls to @code{toc}\n\ 5656 output argument sets the internal timer state. Subsequent calls\n\
5654 return the number of seconds since the timer was set. For example,\n\ 5657 to @code{toc} return the number of seconds since the timer was set.\n\
5658 For example,\n\
5655 \n\ 5659 \n\
5656 @example\n\ 5660 @example\n\
5657 @group\n\ 5661 @group\n\
5658 tic ();\n\ 5662 tic ();\n\
5659 # many computations later@dots{}\n\ 5663 # many computations later@dots{}\n\
5663 \n\ 5667 \n\
5664 @noindent\n\ 5668 @noindent\n\
5665 will set the variable @code{elapsed_time} to the number of seconds since\n\ 5669 will set the variable @code{elapsed_time} to the number of seconds since\n\
5666 the most recent call to the function @code{tic}.\n\ 5670 the most recent call to the function @code{tic}.\n\
5667 \n\ 5671 \n\
5668 If called with one output argument then this function returns a scalar\n\ 5672 If called with one output argument, @code{tic} returns a scalar\n\
5669 of type @code{uint64} and the wall-clock timer is not started.\n\ 5673 of type @code{uint64} that may be later passed to @code{toc}.\n\
5670 \n\ 5674 \n\
5671 @example\n\ 5675 @example\n\
5672 @group\n\ 5676 @group\n\
5673 t = tic; sleep (5); (double (tic ()) - double (t)) * 1e-6\n\ 5677 id = tic; sleep (5); toc (id)\n\
5674 @result{} 5\n\ 5678 @result{} 5.0010\n\
5675 @end group\n\ 5679 @end group\n\
5676 @end example\n\ 5680 @end example\n\
5677 \n\ 5681 \n\
5678 Nested timing with @code{tic} and @code{toc} is not supported.\n\ 5682 Calling @code{tic} and @code{toc} this way allows nested timing calls.\n\
5679 Therefore @code{toc} will always return the elapsed time from the most\n\
5680 recent call to @code{tic}.\n\
5681 \n\ 5683 \n\
5682 If you are more interested in the CPU time that your process used, you\n\ 5684 If you are more interested in the CPU time that your process used, you\n\
5683 should use the @code{cputime} function instead. The @code{tic} and\n\ 5685 should use the @code{cputime} function instead. The @code{tic} and\n\
5684 @code{toc} functions report the actual wall clock time that elapsed\n\ 5686 @code{toc} functions report the actual wall clock time that elapsed\n\
5685 between the calls. This may include time spent processing other jobs or\n\ 5687 between the calls. This may include time spent processing other jobs or\n\
5686 doing nothing at all. For example:\n\ 5688 doing nothing at all.\n\
5687 \n\
5688 @example\n\
5689 @group\n\
5690 tic (); sleep (5); toc ()\n\
5691 @result{} 5\n\
5692 t = cputime (); sleep (5); cputime () - t\n\
5693 @result{} 0\n\
5694 @end group\n\
5695 @end example\n\
5696 \n\
5697 @noindent\n\
5698 (This example also illustrates that the CPU timer may have a fairly\n\
5699 coarse resolution.)\n\
5700 @end deftypefn") 5689 @end deftypefn")
5701 { 5690 {
5702 octave_value retval; 5691 octave_value retval;
5703 5692
5704 int nargin = args.length (); 5693 int nargin = args.length ();
5709 octave_time now; 5698 octave_time now;
5710 5699
5711 double tmp = now.double_value (); 5700 double tmp = now.double_value ();
5712 5701
5713 if (nargout > 0) 5702 if (nargout > 0)
5714 retval = static_cast<octave_uint64> (1e6 * tmp); 5703 {
5704 double ip = 0.0;
5705 double frac = modf (tmp, &ip);
5706 uint64_t microsecs = static_cast<uint64_t> (CLOCKS_PER_SEC * frac);
5707 microsecs += CLOCKS_PER_SEC * static_cast<uint64_t> (ip);
5708 retval = octave_uint64 (microsecs);
5709 }
5715 else 5710 else
5716 tic_toc_timestamp = tmp; 5711 tic_toc_timestamp = tmp;
5717 5712
5718 return retval; 5713 return retval;
5719 } 5714 }
5720 5715
5721 DEFUN (toc, args, nargout, 5716 DEFUN (toc, args, nargout,
5722 "-*- texinfo -*-\n\ 5717 "-*- texinfo -*-\n\
5723 @deftypefn {Built-in Function} {} toc ()\n\ 5718 @deftypefn {Built-in Function} {} toc ()\n\
5719 @deftypefnx {Built-in Function} {} toc (@var{id})\n\
5720 @deftypefnx {Built-in Function} {@var{val} = } toc (@dots{})\n\
5724 See tic.\n\ 5721 See tic.\n\
5725 @end deftypefn") 5722 @end deftypefn")
5726 { 5723 {
5727 octave_value retval; 5724 octave_value retval;
5728 5725
5729 int nargin = args.length (); 5726 int nargin = args.length ();
5730 5727
5731 if (nargin != 0) 5728 double start_time = tic_toc_timestamp;
5732 warning ("tic: ignoring extra arguments"); 5729
5733 5730 if (nargin > 1)
5734 if (tic_toc_timestamp < 0) 5731 print_usage ();
5735 {
5736 warning ("toc called before timer set");
5737 if (nargout > 0)
5738 retval = Matrix ();
5739 }
5740 else 5732 else
5741 { 5733 {
5742 octave_time now; 5734 if (nargin == 1)
5743 5735 {
5744 double tmp = now.double_value () - tic_toc_timestamp; 5736 octave_uint64 id = args(0).uint64_scalar_value ();
5745 5737
5746 if (nargout > 0) 5738 if (! error_state)
5747 retval = tmp; 5739 {
5748 else 5740 uint64_t val = id.value ();
5749 octave_stdout << "Elapsed time is " << tmp << " seconds.\n"; 5741
5742 start_time
5743 = (static_cast<double> (val / CLOCKS_PER_SEC)
5744 + static_cast<double> (val % CLOCKS_PER_SEC) / CLOCKS_PER_SEC);
5745
5746 // FIXME -- should we also check to see whether the start
5747 // time is after the beginning of this Octave session?
5748 }
5749 else
5750 error ("toc: invalid ID");
5751 }
5752
5753 if (! error_state)
5754 {
5755 if (start_time < 0)
5756 error ("toc called before timer set");
5757 else
5758 {
5759 octave_time now;
5760
5761 double tmp = now.double_value () - start_time;
5762
5763 if (nargout > 0)
5764 retval = tmp;
5765 else
5766 octave_stdout << "Elapsed time is " << tmp << " seconds.\n";
5767 }
5768 }
5750 } 5769 }
5751 5770
5752 return retval; 5771 return retval;
5753 } 5772 }
5773
5774 /*
5775 %!shared id
5776 %! id = tic ();
5777 %!assert (isa (id, "uint64"));
5778 %!assert (isa (toc (id), "double"));
5779 */
5754 5780
5755 DEFUN (cputime, args, , 5781 DEFUN (cputime, args, ,
5756 "-*- texinfo -*-\n\ 5782 "-*- texinfo -*-\n\
5757 @deftypefn {Built-in Function} {[@var{total}, @var{user}, @var{system}] =} cputime ();\n\ 5783 @deftypefn {Built-in Function} {[@var{total}, @var{user}, @var{system}] =} cputime ();\n\
5758 Return the CPU time used by your Octave session. The first output is\n\ 5784 Return the CPU time used by your Octave session. The first output is\n\