changeset 14905:05bf75eaea2a

maint: periodic merge of default to jit
author Max Brister <max@2bass.com>
date Tue, 15 May 2012 18:43:18 -0600
parents 3513df68d580 (current diff) e3d03b48ecb5 (diff)
children 3f81e8b42955
files
diffstat 6 files changed, 350 insertions(+), 306 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/general/bitset.m	Sat May 12 19:39:44 2012 -0600
+++ b/scripts/general/bitset.m	Tue May 15 18:43:18 2012 -0600
@@ -1,4 +1,5 @@
 ## Copyright (C) 2004-2012 David Bateman
+## Copyright (C) 2012 Jordi GutiƩrrez Hermoso
 ##
 ## This file is part of Octave.
 ##
@@ -21,7 +22,8 @@
 ## @deftypefnx {Function File} {@var{C} =} bitset (@var{A}, @var{n}, @var{val})
 ## Set or reset bit(s) @var{n} of unsigned integers in @var{A}.
 ## @var{val} = 0 resets and @var{val} = 1 sets the bits.
-## The lowest significant bit is: @var{n} = 1
+## The lowest significant bit is: @var{n} = 1. All variables must be the
+## same size or scalars.
 ##
 ## @example
 ## @group
@@ -32,65 +34,54 @@
 ## @seealso{bitand, bitor, bitxor, bitget, bitcmp, bitshift, bitmax}
 ## @end deftypefn
 
-## Liberally based on the version by Kai Habel from octave-forge
-
-function C = bitset (A, n, val)
+function A = bitset (A, n, val)
 
   if (nargin < 2 || nargin > 3)
     print_usage ();
   endif
 
+  sz = size (A);
+
   if (nargin == 2)
-    val = 1;
+    val = true (sz);
   endif
 
-  if (isa (A, "double"))
-    Bmax = bitmax;
-    Amax = log2 (Bmax) + 1;
-    _conv = @double;
+  cl = class (A);
+
+  if (isfloat (A) && isreal (A))
+    Bmax = bitmax (cl);
+    Amax = log2 (Bmax);
+  elseif (isinteger (A))
+    Bmax = intmax (cl);
+    ## FIXME: Better way to get number of bits than regexping?
+    Amax = str2num (nthargout (4, @regexp, cl, '\d{1,2}'){1});
   else
-    if (isa (A, "uint8"))
-      Amax = 8;
-      _conv = @uint8;
-    elseif (isa (A, "uint16"))
-      Amax = 16;
-      _conv = @uint16;
-    elseif (isa (A, "uint32"))
-      Amax = 32;
-      _conv = @uint32;
-    elseif (isa (A, "uint64"))
-      Amax = 64;
-      _conv = @uint64;
-    elseif (isa (A, "int8"))
-      Amax = 8;
-      _conv = @int8;
-    elseif (isa (A, "int16"))
-      Amax = 16;
-      _conv = @int16;
-    elseif (isa (A, "int32"))
-      Amax = 32;
-      _conv = @int32;
-    elseif (isa (A, "int64"))
-      Amax = 64;
-      _conv = @int64;
-    else
-      error ("bitset: invalid class %s", class (A));
-    endif
-    Bmax = intmax (class (A));
+    error ("bitset: invalid class %s", cl);
   endif
 
-  m = double (n(:));
-  if (any (m < 1) || any (m > Amax))
+  if (any ((n < 1)(:)) || any ((n > Amax)(:)))
     error ("bitset: N must be in the range [1,%d]", Amax);
   endif
 
-  mask = bitshift (_conv (1), uint8 (n) - uint8 (1));
-  C = bitxor (A, bitand (A, mask));
+  mask = bitshift (cast (1, cl), uint8 (n) - uint8 (1));
+
+  on = logical (val);
+  off = !on;
 
-  if (val)
-    C = bitor (A, mask);
+  if (isscalar (mask))
+    onmask = mask;
+    offmask = mask;
+  else
+    if (! size_equal (A, n))
+      error ("bitset: N must be scalar or the same size as A");
+    endif
+    onmask = mask(on);
+    offmask = mask(off);
   endif
 
+  A(on) = bitor (A(on), onmask);
+  A(off) = bitand (A(off), bitcmp (offmask));
+
 endfunction
 
 
@@ -104,6 +95,9 @@
 %!   endfor
 %! endfor
 
+## Bug #36458
+%!assert (bitset(uint8 ([1, 2;3 4]), 1, [0 1; 0 1]), uint8 ([0, 3; 2 5]))
+
 %!error bitset (0, 0)
 %!error bitset (0, 55)
 %!error bitset (int8 (0), 9)
--- a/scripts/help/doc.m	Sat May 12 19:39:44 2012 -0600
+++ b/scripts/help/doc.m	Tue May 15 18:43:18 2012 -0600
@@ -86,7 +86,7 @@
     have_fname = ! isempty (fname);
 
     if (have_fname)
-      status = system (sprintf ("%s --index-search %s", cmd, fname));
+      status = system (sprintf ("%s --index-search \"%s\"", cmd, fname));
     endif
 
     if (! (have_fname && status == 0))
--- a/src/bitfcns.cc	Sat May 12 19:39:44 2012 -0600
+++ b/src/bitfcns.cc	Tue May 15 18:43:18 2012 -0600
@@ -42,224 +42,248 @@
 #include "ov-re-mat.h"
 #include "ov-bool.h"
 
-// FIXME -- could probably eliminate some code duplication by
-// clever use of templates.
+#include <functional>
+
+template <typename OP, typename T>
+octave_value
+bitopxx(const OP& op, const std::string& fname,
+        const Array<T>& x, const Array<T>& y)
+{
+  int nelx = x.numel ();
+  int nely = y.numel ();
+
+  bool is_scalar_op = (nelx == 1 || nely == 1);
+
+  dim_vector dvx = x.dims ();
+  dim_vector dvy = y.dims ();
+
+  bool is_array_op = (dvx == dvy);
+
+  octave_value retval;
+  if (is_array_op || is_scalar_op)
+    {
+      Array<T> result;
+
+      if (nelx != 1)
+        result.resize (dvx);
+      else
+        result.resize (dvy);
+
+      for (int i = 0; i < nelx; i++)
+        if (is_scalar_op)
+          for (int k = 0; k < nely; k++)
+            result(i+k) = op(x(i), y(k));
+        else
+          result(i) = op(x(i), y(i));
+
+      retval = result;
+    }
+  else
+    error ("%s: size of X and Y must match, or one operand must be a scalar",
+           fname.c_str());
+
+  return retval;
+}
 
-#define BITOPX(OP, FNAME, RET) \
-      { \
-        int nelx = x.numel (); \
-        int nely = y.numel (); \
- \
-        bool is_scalar_op = (nelx == 1 || nely == 1); \
- \
-        dim_vector dvx = x.dims (); \
-        dim_vector dvy = y.dims (); \
- \
-        bool is_array_op = (dvx == dvy); \
- \
-        if (is_array_op || is_scalar_op) \
-          { \
-            RET result; \
- \
-            if (nelx != 1) \
-              result.resize (dvx); \
-            else \
-              result.resize (dvy); \
- \
-            for (int i = 0; i < nelx; i++) \
-              if (is_scalar_op) \
-                for (int k = 0; k < nely; k++) \
-                  result(i+k) = x(i) OP y(k); \
-              else \
-                result(i) = x(i) OP y(i); \
- \
-              retval = result; \
-          } \
-        else \
-          error ("%s: size of X and Y must match, or one operand must be a scalar", FNAME); \
-      }
+// Trampoline function, instantiates the proper template above, with
+// reflective information hardwired. We can't hardwire this information
+// in Fbitxxx DEFUNs below, because at that moment, we still don't have
+// information about which integer types we need to instantiate.
+template<typename T>
+octave_value
+bitopx(const std::string& fname, const Array<T>& x, const Array<T>& y)
+{
+  if (fname == "bitand")
+    return bitopxx (std::bit_and<T>(), fname, x, y);
+  if (fname == "bitor")
+    return bitopxx (std::bit_or<T>(), fname, x, y);
+
+  //else (fname == "bitxor")
+  return bitopxx (std::bit_xor<T>(), fname, x, y);
+}
+
+octave_value
+bitop(const std::string& fname, const octave_value_list& args)
+{
+  octave_value retval;
+
+  int nargin = args.length ();
+
+  if (nargin == 2)
+    {
+      if ((args(0).class_name () == octave_scalar::static_class_name ())
+          || (args(0).class_name () == octave_bool::static_class_name ())
+          || (args(1).class_name () == octave_scalar::static_class_name ())
+          || (args(1).class_name () == octave_bool::static_class_name ()))
+        {
+          bool arg0_is_int = (args(0).class_name () !=
+                              octave_scalar::static_class_name () &&
+                              args(0).class_name () !=
+                              octave_bool::static_class_name ());
+          bool arg1_is_int = (args(1).class_name () !=
+                              octave_scalar::static_class_name () &&
+                              args(1).class_name () !=
+                              octave_bool::static_class_name ());
+
+          if (! (arg0_is_int || arg1_is_int))
+            {
+              uint64NDArray x (args(0).array_value ());
+              uint64NDArray y (args(1).array_value ());
+              if (! error_state)
+                retval = bitopx (fname, x, y).array_value();
+            }
+          else
+            {
+              int p = (arg0_is_int ? 1 : 0);
+              int q = (arg0_is_int ? 0 : 1);
+
+              NDArray dx = args(p).array_value ();
 
-#define BITOP(OP, FNAME) \
- \
-  octave_value retval; \
- \
-  int nargin = args.length (); \
- \
-  if (nargin == 2) \
-    { \
-      if ((args(0).class_name () == octave_scalar::static_class_name ()) \
-          || (args(0).class_name () == octave_bool::static_class_name ()) \
-          || (args(1).class_name () == octave_scalar::static_class_name ()) \
-          || (args(1).class_name () == octave_bool::static_class_name ())) \
-        { \
-          bool arg0_is_int = (args(0).class_name () !=  \
-                              octave_scalar::static_class_name () && \
-                              args(0).class_name () != \
-                              octave_bool::static_class_name ()); \
-          bool arg1_is_int = (args(1).class_name () !=  \
-                              octave_scalar::static_class_name () && \
-                              args(1).class_name () != \
-                              octave_bool::static_class_name ()); \
-          \
-          if (! (arg0_is_int || arg1_is_int))   \
-            { \
-              uint64NDArray x (args(0).array_value ()); \
-              uint64NDArray y (args(1).array_value ()); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, uint64NDArray); \
-              retval = retval.array_value (); \
-            } \
-          else \
-            { \
-              int p = (arg0_is_int ? 1 : 0); \
-              int q = (arg0_is_int ? 0 : 1); \
- \
-              NDArray dx = args(p).array_value (); \
- \
-              if (args(q).type_id () == octave_uint64_matrix::static_type_id () \
-                  || args(q).type_id () == octave_uint64_scalar::static_type_id ()) \
-                { \
-                  uint64NDArray x (dx); \
-                  uint64NDArray y = args(q).uint64_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, uint64NDArray); \
-                 } \
-              else if (args(q).type_id () == octave_uint32_matrix::static_type_id () \
-                       || args(q).type_id () == octave_uint32_scalar::static_type_id ()) \
-                { \
-                  uint32NDArray x (dx); \
-                  uint32NDArray y = args(q).uint32_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, uint32NDArray); \
-                } \
-              else if (args(q).type_id () == octave_uint16_matrix::static_type_id () \
-                       || args(q).type_id () == octave_uint16_scalar::static_type_id ()) \
-                { \
-                  uint16NDArray x (dx); \
-                  uint16NDArray y = args(q).uint16_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, uint16NDArray); \
-                } \
-              else if (args(q).type_id () == octave_uint8_matrix::static_type_id () \
-                       || args(q).type_id () == octave_uint8_scalar::static_type_id ()) \
-                { \
-                  uint8NDArray x (dx); \
-                  uint8NDArray y = args(q).uint8_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, uint8NDArray); \
-                } \
-              else if (args(q).type_id () == octave_int64_matrix::static_type_id () \
-                       || args(q).type_id () == octave_int64_scalar::static_type_id ()) \
-                { \
-                  int64NDArray x (dx); \
-                  int64NDArray y = args(q).int64_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, int64NDArray); \
-                } \
-              else if (args(q).type_id () == octave_int32_matrix::static_type_id () \
-                       || args(q).type_id () == octave_int32_scalar::static_type_id ()) \
-                { \
-                  int32NDArray x (dx); \
-                  int32NDArray y = args(q).int32_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, int32NDArray); \
-                } \
-              else if (args(q).type_id () == octave_int16_matrix::static_type_id () \
-                       || args(q).type_id () == octave_int16_scalar::static_type_id ()) \
-                { \
-                  int16NDArray x (dx); \
-                  int16NDArray y = args(q).int16_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, int16NDArray); \
-                } \
-              else if (args(q).type_id () == octave_int8_matrix::static_type_id () \
-                       || args(q).type_id () == octave_int8_scalar::static_type_id ()) \
-                { \
-                  int8NDArray x (dx); \
-                  int8NDArray y = args(q).int8_array_value (); \
-                  if (! error_state) \
-                    BITOPX (OP, FNAME, int8NDArray); \
-                } \
-              else \
-                error ("%s: invalid operand type", FNAME); \
-            } \
-        } \
-      else if (args(0).class_name () == args(1).class_name ()) \
-        { \
-          if (args(0).type_id () == octave_uint64_matrix::static_type_id () \
-              || args(0).type_id () == octave_uint64_scalar::static_type_id ()) \
-            { \
-              uint64NDArray x = args(0).uint64_array_value (); \
-              uint64NDArray y = args(1).uint64_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, uint64NDArray); \
-            } \
-          else if (args(0).type_id () == octave_uint32_matrix::static_type_id () \
-                   || args(0).type_id () == octave_uint32_scalar::static_type_id ()) \
-            { \
-              uint32NDArray x = args(0).uint32_array_value (); \
-              uint32NDArray y = args(1).uint32_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, uint32NDArray); \
-            } \
-          else if (args(0).type_id () == octave_uint16_matrix::static_type_id () \
-                   || args(0).type_id () == octave_uint16_scalar::static_type_id ()) \
-            { \
-              uint16NDArray x = args(0).uint16_array_value (); \
-              uint16NDArray y = args(1).uint16_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, uint16NDArray); \
-            } \
-          else if (args(0).type_id () == octave_uint8_matrix::static_type_id () \
-                   || args(0).type_id () == octave_uint8_scalar::static_type_id ()) \
-            { \
-              uint8NDArray x = args(0).uint8_array_value (); \
-              uint8NDArray y = args(1).uint8_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, uint8NDArray); \
-            } \
-          else if (args(0).type_id () == octave_int64_matrix::static_type_id () \
-                   || args(0).type_id () == octave_int64_scalar::static_type_id ()) \
-            { \
-              int64NDArray x = args(0).int64_array_value (); \
-              int64NDArray y = args(1).int64_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, int64NDArray); \
-            } \
-          else if (args(0).type_id () == octave_int32_matrix::static_type_id () \
-                   || args(0).type_id () == octave_int32_scalar::static_type_id ()) \
-            { \
-              int32NDArray x = args(0).int32_array_value (); \
-              int32NDArray y = args(1).int32_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, int32NDArray); \
-            } \
-          else if (args(0).type_id () == octave_int16_matrix::static_type_id () \
-                   || args(0).type_id () == octave_int16_scalar::static_type_id ()) \
-            { \
-              int16NDArray x = args(0).int16_array_value (); \
-              int16NDArray y = args(1).int16_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, int16NDArray); \
-            } \
-          else if (args(0).type_id () == octave_int8_matrix::static_type_id () \
-                   || args(0).type_id () == octave_int8_scalar::static_type_id ()) \
-            { \
-              int8NDArray x = args(0).int8_array_value (); \
-              int8NDArray y = args(1).int8_array_value (); \
-              if (! error_state) \
-                BITOPX (OP, FNAME, int8NDArray); \
-            } \
-          else \
-            error ("%s: invalid operand type", FNAME); \
-        } \
-      else \
-        error ("%s: must have matching operand types", FNAME); \
-    } \
-  else \
-    print_usage (); \
- \
-  return retval
+              if (args(q).type_id () == octave_uint64_matrix::static_type_id ()
+                  || args(q).type_id () == octave_uint64_scalar::static_type_id ())
+                {
+                  uint64NDArray x (dx);
+                  uint64NDArray y = args(q).uint64_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_uint32_matrix::static_type_id ()
+                       || args(q).type_id () == octave_uint32_scalar::static_type_id ())
+                {
+                  uint32NDArray x (dx);
+                  uint32NDArray y = args(q).uint32_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_uint16_matrix::static_type_id ()
+                       || args(q).type_id () == octave_uint16_scalar::static_type_id ())
+                {
+                  uint16NDArray x (dx);
+                  uint16NDArray y = args(q).uint16_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_uint8_matrix::static_type_id ()
+                       || args(q).type_id () == octave_uint8_scalar::static_type_id ())
+                {
+                  uint8NDArray x (dx);
+                  uint8NDArray y = args(q).uint8_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_int64_matrix::static_type_id ()
+                       || args(q).type_id () == octave_int64_scalar::static_type_id ())
+                {
+                  int64NDArray x (dx);
+                  int64NDArray y = args(q).int64_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_int32_matrix::static_type_id ()
+                       || args(q).type_id () == octave_int32_scalar::static_type_id ())
+                {
+                  int32NDArray x (dx);
+                  int32NDArray y = args(q).int32_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_int16_matrix::static_type_id ()
+                       || args(q).type_id () == octave_int16_scalar::static_type_id ())
+                {
+                  int16NDArray x (dx);
+                  int16NDArray y = args(q).int16_array_value ();
+                  if (! error_state)
+                    retval  = bitopx (fname, x, y);
+                }
+              else if (args(q).type_id () == octave_int8_matrix::static_type_id ()
+                       || args(q).type_id () == octave_int8_scalar::static_type_id ())
+                {
+                  int8NDArray x (dx);
+                  int8NDArray y = args(q).int8_array_value ();
+                  if (! error_state)
+                    retval = bitopx (fname, x, y);
+                }
+              else
+                error ("%s: invalid operand type", fname.c_str());
+            }
+        }
+      else if (args(0).class_name () == args(1).class_name ())
+        {
+          if (args(0).type_id () == octave_uint64_matrix::static_type_id ()
+              || args(0).type_id () == octave_uint64_scalar::static_type_id ())
+            {
+              uint64NDArray x = args(0).uint64_array_value ();
+              uint64NDArray y = args(1).uint64_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_uint32_matrix::static_type_id ()
+                   || args(0).type_id () == octave_uint32_scalar::static_type_id ())
+            {
+              uint32NDArray x = args(0).uint32_array_value ();
+              uint32NDArray y = args(1).uint32_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_uint16_matrix::static_type_id ()
+                   || args(0).type_id () == octave_uint16_scalar::static_type_id ())
+            {
+              uint16NDArray x = args(0).uint16_array_value ();
+              uint16NDArray y = args(1).uint16_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_uint8_matrix::static_type_id ()
+                   || args(0).type_id () == octave_uint8_scalar::static_type_id ())
+            {
+              uint8NDArray x = args(0).uint8_array_value ();
+              uint8NDArray y = args(1).uint8_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_int64_matrix::static_type_id ()
+                   || args(0).type_id () == octave_int64_scalar::static_type_id ())
+            {
+              int64NDArray x = args(0).int64_array_value ();
+              int64NDArray y = args(1).int64_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_int32_matrix::static_type_id ()
+                   || args(0).type_id () == octave_int32_scalar::static_type_id ())
+            {
+              int32NDArray x = args(0).int32_array_value ();
+              int32NDArray y = args(1).int32_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_int16_matrix::static_type_id ()
+                   || args(0).type_id () == octave_int16_scalar::static_type_id ())
+            {
+              int16NDArray x = args(0).int16_array_value ();
+              int16NDArray y = args(1).int16_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else if (args(0).type_id () == octave_int8_matrix::static_type_id ()
+                   || args(0).type_id () == octave_int8_scalar::static_type_id ())
+            {
+              int8NDArray x = args(0).int8_array_value ();
+              int8NDArray y = args(1).int8_array_value ();
+              if (! error_state)
+                retval = bitopx (fname, x, y);
+            }
+          else
+            error ("%s: invalid operand type", fname.c_str());
+        }
+      else
+        error ("%s: must have matching operand types", fname.c_str());
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
 
 DEFUN (bitand, args, ,
   "-*- texinfo -*-\n\
@@ -269,7 +293,7 @@
 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
 @end deftypefn")
 {
-  BITOP (&, "bitand");
+  return bitop ("bitand", args);
 }
 
 DEFUN (bitor, args, ,
@@ -280,7 +304,7 @@
 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
 @end deftypefn")
 {
-  BITOP (|, "bitor");
+  return bitop ("bitor", args);
 }
 
 DEFUN (bitxor, args, ,
@@ -291,7 +315,7 @@
 @seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
 @end deftypefn")
 {
-  BITOP (^, "bitxor");
+  return bitop ("bitxor", args);
 }
 
 static int64_t
--- a/src/data.cc	Sat May 12 19:39:44 2012 -0600
+++ b/src/data.cc	Tue May 15 18:43:18 2012 -0600
@@ -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<octave_uint64> (1e6 * tmp);
+    {
+      double ip = 0.0;
+      double frac = modf (tmp, &ip);
+      uint64_t microsecs = static_cast<uint64_t> (CLOCKS_PER_SEC * frac);
+      microsecs += CLOCKS_PER_SEC * static_cast<uint64_t> (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<double> (val / CLOCKS_PER_SEC)
+                   + static_cast<double> (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\
--- a/src/mex.cc	Sat May 12 19:39:44 2012 -0600
+++ b/src/mex.cc	Tue May 15 18:43:18 2012 -0600
@@ -1188,7 +1188,7 @@
         for (size_t i = 0; i < tmp_len; i++)
           cpr[m*i+j] = static_cast<mxChar> (ptr[i]);
 
-        for (size_t i = tmp_len; i < nc; i++)
+        for (size_t i = tmp_len; i < static_cast<size_t>(nc); i++)
           cpr[m*i+j] = static_cast<mxChar> (' ');
       }
   }
--- a/src/oct-map.cc	Sat May 12 19:39:44 2012 -0600
+++ b/src/oct-map.cc	Tue May 15 18:43:18 2012 -0600
@@ -1426,7 +1426,7 @@
 string_vector
 Octave_map::keys (void) const
 {
-  assert (nfields () == key_list.size ());
+  assert (static_cast<size_t>(nfields ()) == key_list.size ());
 
   return string_vector (key_list);
 }