changeset 32797:75d34a95da34 bytecode-interpreter

maint: merge default to bytecode-interpreter
author John W. Eaton <jwe@octave.org>
date Sat, 20 Jan 2024 14:01:56 -0500
parents dfa22c226af6 (current diff) 5252c3621c7a (diff)
children f3b913b27750
files etc/NEWS.9.md libinterp/corefcn/stack-frame.h libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h
diffstat 10 files changed, 232 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/doc/interpreter/func.txi	Fri Jan 19 15:03:38 2024 -0500
+++ b/doc/interpreter/func.txi	Sat Jan 20 14:01:56 2024 -0500
@@ -628,6 +628,25 @@
 @end group
 @end example
 
+Functions may take advantage of ignored outputs to reduce the number of
+calculations performed.  To do so, use the @code{isargout} function to query
+whether the output argument is wanted.  For example:
+
+@example
+@group
+function [out1, out2] = long_function (x, y, z)
+  if (isargout (1))
+    ## Long calculation
+    @dots{}
+    out1 = result;
+  endif
+  @dots{}
+endfunction
+@end group
+@end example
+
+@DOCSTRING(isargout)
+
 @node Default Arguments
 @section Default Arguments
 @cindex default arguments
--- a/etc/NEWS.9.md	Fri Jan 19 15:03:38 2024 -0500
+++ b/etc/NEWS.9.md	Sat Jan 20 14:01:56 2024 -0500
@@ -11,35 +11,28 @@
   encouraged.  To learn more, type `bytecode` or `help bytecode` at the Octave
   prompt.
 
-- `oruntests`: The current directory now changes to the directory
-  containing the files with the tests for the duration of the test.  This
-  aligns the behavior of this function with Octave's test suite.  This also
-  means that the file encoding specified in the `.oct-config` file for the
-  respective directory is taken into account for the tests.
-
 - `dec2base`, `dec2bin`, and `dec2hex` have all been overhauled.  All three
   functions now accommodate negative inputs and fractional inputs, and repeated
   code between the functions has been reduced or eliminated.  Previously only
   `dec2bin` and `dec2hex` accepted negative inputs but `dec2base` did not, and
-  none of the three accepted fractional inputs.  But now, `dec2base (100*pi,
-  16, 4, 6)`, for example, returns a base-16 string with four places for the
-  integer part and six places for the fractional part.  Omitting the number of
-  decimal places (the fourth input) retains old behavior for backward
-  compatibility, except that non-integer inputs will no longer produce
-  errors.
+  none of the three accepted fractional inputs.  Now, `dec2base (100*pi, 16, 4,
+  6)`, for example, returns a base-16 string with four places for the integer
+  part and six places for the fractional part.  Omitting the number of decimal
+  places (the fourth input) retains old behavior for backward compatibility,
+  except that non-integer inputs will no longer produce errors.
 
 - `quiver` and `quiver3` now properly plot non-float numeric inputs by
-  internally recasting them to 'double' (bug #59695).  Both functions now honor
+  internally casting them to 'double' (bug #59695).  Both functions now honor
   a previously ignored scaling factor input when there is only a single arrow
   (bug #39552), and `quiver3` no longer produces an error when a scaling factor
-  is input without x and y inputs. Both functions now also accept a scale
+  is given without x and y inputs.  Both functions now also accept a scale
   factor of "off" which is equivalent to setting it to 0.  When a linestyle
   with a base marker is set suppressing arrowhead display, subsequent
-  name-value property pairs in the quiver/quiver3 function call will no longer
-  turn arrowhead display back on (bug #64143).  The linewidth property now also
-  affects the line width of the base marker.
+  name-value property pairs in the `quiver`/`quiver3` function call will no
+  longer turn arrowhead display back on (bug #64143).  The linewidth property
+  now also affects the line width of the base marker.
 
-- Classdefs now support breakpoints inside them.
+- Classdef files now support breakpoints inside them.
 
 - The `inputParser` function has been re-architected for a 60% performance
   improvement.
@@ -49,13 +42,19 @@
 - The `audiowrite` function now supports writing to MPEG audio
   formats---including MP3---if the `sndfile` library supports it.
 
+- `oruntests`: The current directory now changes to the directory
+  containing the files with the tests for the duration of the test.  This
+  aligns the behavior of this function with Octave's test suite.  This also
+  means that the file encoding specified in the `.oct-config` file for the
+  respective directory is taken into account for the tests.
+
 ### Graphical User Interface
 
 - The Graphical User Interface (GUI) of Octave is now compatible with Qt6.  Qt6
   is selected by default if the necessary Qt modules are detected and the used
   compiler is compatible.  Support for building with Qt5 is still available but
   might be removed in a future version of Octave.  Qt5 is used if configuring
-  with `--with-qt=5` or as a fallback by default if Qt6 cannot be used.
+  with `--with-qt=5` or as a fallback if Qt6 cannot be used.
 
 ### Graphics backend
 
@@ -81,13 +80,14 @@
   is now set to true by default which may change the behavior of existing code.
 
 - Overhauled `mean`, `median`, `var`, and `std` functions have been imported
-  from statistics package v1.5.4 to compatibly implement 'nanflag' (bug
-  #50571), 'all' (bug #58116), and 'vecdim' (bug #58089) options, preserve
+  from statistics package v1.5.4 to compatibly implement 'nanflag'
+  (bug #50571), 'all' (bug #58116), and 'vecdim' (bug #58089) options, preserve
   output class, and match expected output behavior for empty (bug #50583) and
-  sparse inputs (bug #63291).  Both `median` and `mean` can handle large int
-  values without overflow or precision concerns (bug #54567), and `mean` avoids
-  errors due to limits of single precision by processing as doubles (bug
-  #63848).  `median` has also adopted the 'outtype' option from `mean`.
+  sparse inputs (bug #63291).  Both `median` and `mean` can handle large
+  integer values without overflow or precision concerns (bug #54567), and
+  `mean` avoids errors due to limits of single precision by processing as
+  doubles (bug #63848).  `median` has also adopted the 'outtype' option from
+  `mean`.
 
 - Code such as `A = ones (3, 3); A(:, :, 1) = []` is now Matlab compatible.
 
@@ -98,7 +98,7 @@
 
 - `mode` now produces Matlab compatible output for empty inputs (bug #50583).
 
-- `linspace` and `logspace` now handle `inf` inputs in a Matlab compatible way.
+- `linspace` and `logspace` now handle `Inf` inputs in a Matlab compatible way.
 
 - `normalize` now produces Matlab compatible output for inputs containing NaN
   values (bug #50571).
@@ -115,15 +115,15 @@
   columnwise covariance calculation can obtain the previous results using
   `cov([x,y])(1:nx, nx+1:end)`, where nx = columns(x).
 
-- `qz` now handles input and output arguments in a Matlab compatible way. It
+- `qz` now handles input and output arguments in a Matlab compatible way.  It
   always computes the complex QZ decomposition if there are only two input
   arguments, and it accepts an optional third input argument 'real' or
-  'complex' to select the type of decomposition. The output arguments are
+  'complex' to select the type of decomposition.  The output arguments are
   always in the same order independently of the input arguments, and the
   generalized eigenvalues are no longer returned (one can use the `ordeig`
-  function for that purpose). The optional reordering of the generalized
-  eigenvalues has been removed (one can use the `ordqz`
-  function for that purpose).
+  function for that purpose).  The optional reordering of the generalized
+  eigenvalues has been removed (one can use the `ordqz` function for that
+  purpose).
 
 - `pcolor` now sets the axes limits to be just large enough to display the
   plotted data (equivalent of `axis tight`).
@@ -159,8 +159,8 @@
   double-quoted strings (e.g., "foo") representing character vectors as
   opposed to string objects, then start replacing all double-quoted strings
   with single-quoted strings in your code over time (e.g., replace "foo" with
-  'foo'). Single-quoted strings are expected to retain current behavior.
-  Further, if your code relies on backslash escape sequence interpretation in
+  'foo').  Single-quoted strings will retain their current behavior.  Further,
+  if your code relies on backslash escape sequence interpretation in
   double-quoted strings (except in special cases like the `printf` family),
   that code may need to change as well.
 
@@ -173,17 +173,14 @@
 
 ### Deprecated functions, properties, and operators
 
-The following functions and properties have been deprecated in Octave 9
-and will be removed from Octave 11 (or whatever version is the second
-major release after 9):
+The following functions and properties have been deprecated in Octave 9 and
+will be removed from Octave 11 (or whatever version is the second major release
+after 9):
 
 - Functions
 
         Function               | Replacement
         -----------------------|------------------
-        isargout               | none (see below)
-
-    * The implementation of `isargout` has been the source of a number of bugs and was inefficient, even for functions that did not use it.  It may be removed in a future version of Octave.  Until then, `isargout(k)` will return true for k in the range `1:min (1, nargout)`.
 
 - Properties
 
@@ -196,17 +193,19 @@
 - Core
 
     * The `idx_vector::bool()` function is obsolete and always returns true.
-Any uses can simply be removed from existing code with no loss of function.
+      Any uses can simply be removed from existing code with no loss of
+      function.
 
     * The `all_ok(const Array<octave::idx_vector>&)` function in `Array-util.h`
-is obsolete and always returns true.  Any uses can simply be removed from
-existing code with no loss of function.
+      is obsolete and always returns true.  Any uses can simply be removed from
+      existing code with no loss of function.
 
     * The member variable `octave_base_value::count` is deprecated and will be
-removed from Octave 11.  Replace all instances with the new name `m_count`.
+      removed from Octave 11.  Replace all instances with the new name
+      `m_count`.
 
-The following features were deprecated in Octave 7 and have been removed
-from Octave 9.
+The following features were deprecated in Octave 7 and have been removed from
+Octave 9.
 
 - Functions
 
@@ -231,22 +230,22 @@
 
 - Interpreter
 
-    * The use of `'...'` for line continuations *inside* double-quoted
-    strings has been removed.  Use `'\'` for line continuations inside strings
-    instead.
+    * The use of `'...'` for line continuations *inside* double-quoted strings
+      has been removed.  Use `'\'` for line continuations inside strings
+      instead.
 
     * The use of `'\'` as a line continuation *outside* of double-quoted
-    strings has been removed.  Use `'...'` for line continuations instead.
+      strings has been removed.  Use `'...'` for line continuations instead.
 
     * Support for trailing whitespace after a `'\'` line continuation has been
-    removed.  Delete unnecessary trailing whitespace.
+      removed.  Delete unnecessary trailing whitespace.
 
-- For plot functions, the use of numbers to select line colors in
-  shorthand formats was an undocumented feature that was removed in Octave 9.
+- For plot functions, the use of numbers to select line colors in shorthand
+  formats was an undocumented feature that was removed in Octave 9.
 
 - The environment variable used by `mkoctfile` for linker flags is now
-  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` was deprecated in Octave 6
-  and has been removed.
+  `LDFLAGS` rather than `LFLAGS`.  `LFLAGS` was deprecated in Octave 6 and has
+  been removed.
 
 Summary of bugs fixed for version 9.1.0 (yyyy-mm-dd):
 ----------------------------------------------------
--- a/libinterp/corefcn/stack-frame.h	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/corefcn/stack-frame.h	Sat Jan 20 14:01:56 2024 -0500
@@ -134,6 +134,7 @@
   enum auto_var_type
   {
     ARG_NAMES,
+    IGNORED,
     NARGIN,
     NARGOUT,
     SAVED_WARNING_STATES,
--- a/libinterp/octave-value/ov-usr-fcn.cc	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Sat Jan 20 14:01:56 2024 -0500
@@ -843,7 +843,7 @@
 
 Programming Note.  @code{nargout} does not work for built-in functions and
 returns -1 for all anonymous functions.
-@seealso{nargin, varargout, nthargout}
+@seealso{nargin, varargout, isargout, nthargout}
 @end deftypefn */)
 {
   int nargin = args.length ();
@@ -939,27 +939,39 @@
 }
 
 static bool
-isargout1 (int nargout, double k)
+val_in_table (const Matrix& table, double val)
+{
+  if (table.isempty ())
+    return false;
+
+  octave_idx_type i = table.lookup (val, ASCENDING);
+  return (i > 0 && table(i-1) == val);
+}
+
+static bool
+isargout1 (int nargout, const Matrix& ignored, double k)
 {
   if (k != math::fix (k) || k <= 0)
     error ("isargout: K must be a positive integer");
 
-  return k == 1 || k <= nargout;
+  return (k == 1 || k <= nargout) && ! val_in_table (ignored, k);
 }
 
-// LEGACY FUNCTION as of Octave 9.
-
 DEFMETHOD (isargout, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn {} {@var{tf} =} isargout (@var{k})
-This function is obsolete and may be removed from a future version of
-Octave.  Inside a function and now always returns true for @var{k} in
-the range @code{1:min (1, nargout)}.
+Within a function, return a logical value indicating whether the argument
+@var{k} will be assigned to a variable on output.
 
-@var{k} can also be an array, in which case the function works
-element-by-element and a logical array is returned.
+If the result is false, the argument has been ignored during the function
+call through the use of the tilde (~) special output argument.  Functions
+can use @code{isargout} to avoid performing unnecessary calculations for
+outputs which are unwanted.
 
-At the top level, @code{isargout} returns an error.
+If @var{k} is outside the range @code{1:max (nargout)}, the function returns
+false.  @var{k} can also be an array, in which case the function works
+element-by-element and a logical array is returned.  At the top level,
+@code{isargout} returns an error.
 @seealso{nargout, varargout, nthargout}
 @end deftypefn */)
 {
@@ -978,11 +990,16 @@
   if (tmp.is_defined ())
     nargout1 = tmp.int_value ();
 
+  Matrix ignored;
+  tmp = tw.get_auto_fcn_var (stack_frame::IGNORED);
+  if (tmp.is_defined ())
+    ignored = tmp.matrix_value ();
+
   if (args(0).is_scalar_type ())
     {
       double k = args(0).double_value ();
 
-      return ovl (isargout1 (nargout1, k));
+      return ovl (isargout1 (nargout1, ignored, k));
     }
   else if (args(0).isnumeric ())
     {
@@ -990,7 +1007,7 @@
 
       boolNDArray r (ka.dims ());
       for (octave_idx_type i = 0; i < ka.numel (); i++)
-        r(i) = isargout1 (nargout1, ka(i));
+        r(i) = isargout1 (nargout1, ignored, ka(i));
 
       return ovl (r);
     }
@@ -1002,50 +1019,83 @@
 
 /*
 %!function [x, y] = try_isargout ()
-%!  global isargout_global
-%!  isargout_global = [isargout(1), isargout(2)];
-%!  x = 1;
-%!  y = 2;
+%!  if (isargout (1))
+%!    if (isargout (2))
+%!      x = 1; y = 2;
+%!    else
+%!      x = -1;
+%!    endif
+%!  else
+%!    if (isargout (2))
+%!      y = -2;
+%!    else
+%!      error ("no outputs requested");
+%!    endif
+%!  endif
+%!endfunction
+%!
+%!function [a, b] = try_isargout2 (x, y)
+%!  a = y;
+%!  b = {isargout(1), isargout(2), x};
 %!endfunction
 %!
 %!test
-%! global isargout_global
-%! unwind_protect
-%!   [x, y] = try_isargout ();
-%!   assert ([x, y], [1, 2]);
-%!   assert (isargout_global, [true, true]);
-%! unwind_protect_cleanup
-%!   clear -global isargout_global
-%! end_unwind_protect
+%! [x, y] = try_isargout ();
+%! assert ([x, y], [1, 2]);
+%!
+%!test
+%! [x, ~] = try_isargout ();
+%! assert (x, -1);
 %!
 %!test
-%! global isargout_global
-%! unwind_protect
-%!   [x, ~] = try_isargout ();
-%!   assert (x, 1);
-%!   assert (isargout_global, [true, true]);
-%! unwind_protect_cleanup
-%!   clear -global isargout_global
-%! end_unwind_protect
+%! [~, y] = try_isargout ();
+%! assert (y, -2);
+%!
+%!error [~, ~] = try_isargout ()
+%!
+## Check to see that isargout isn't sticky:
+%!test
+%! [x, y] = try_isargout ();
+%! assert ([x, y], [1, 2]);
 %!
+## It should work without ():
+%!test
+%! [~, y] = try_isargout;
+%! assert (y, -2);
+%!
+## It should work in function handles,
+%!test
+%! fh = @try_isargout;
+%! [~, y] = fh ();
+%! assert (y, -2);
+%!
+## anonymous functions,
 %!test
-%! global isargout_global
-%! unwind_protect
-%!   [~, y] = try_isargout ();
-%!   assert (y, 2);
-%!   assert (isargout_global, [true, true]);
-%! unwind_protect_cleanup
-%!   clear -global isargout_global
-%! end_unwind_protect
+%! af = @() try_isargout;
+%! [~, y] = af ();
+%! assert (y, -2);
 %!
+## and cell arrays of handles or anonymous functions.
 %!test
-%! global isargout_global
-%! unwind_protect
-%!   [~, ~] = try_isargout ()
-%!   assert (isargout_global, [true, true]);
-%! unwind_protect_cleanup
-%!   clear -global isargout_global
-%! end_unwind_protect
+%! fh = @try_isargout;
+%! af = @() try_isargout;
+%! c = {fh, af};
+%! [~, y] = c{1}();
+%! assert (y, -2);
+%!test
+%! fh = @try_isargout;
+%! af = @() try_isargout;
+%! c = {fh, af};
+%! [~, y] = c{2}();
+%! assert (y, -2);
+%!
+## Nesting, anyone?
+%!test
+%! [~, b] = try_isargout2 (try_isargout, rand);
+%! assert (b, {0, 1, -1});
+%!test
+%! [~, b] = try_isargout2 ({try_isargout, try_isargout}, rand);
+%! assert (b, {0, 1, {-1, -1}});
 */
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/op-kw-docs	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/op-kw-docs	Sat Jan 20 14:01:56 2024 -0500
@@ -873,14 +873,14 @@
 -*- texinfo -*-
 @deftypefn {} {} varargin
 Pass an arbitrary number of arguments into a function.
-@seealso{varargout, nargin, nargout, nthargout}
+@seealso{varargout, nargin, isargout, nargout, nthargout}
 @end deftypefn
 varargout
 @c libinterp/parse-tree/oct-parse.yy
 -*- texinfo -*-
 @deftypefn {} {} varargout
 Pass an arbitrary number of arguments out of a function.
-@seealso{varargin, nargin, nargout, nthargout}
+@seealso{varargin, nargin, isargout, nargout, nthargout}
 @end deftypefn
 while
 @c libinterp/parse-tree/oct-parse.yy
--- a/libinterp/parse-tree/pt-assign.cc	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/parse-tree/pt-assign.cc	Sat Jan 20 14:01:56 2024 -0500
@@ -207,8 +207,6 @@
                                          ? rhs_val1(0).list_value ()
                                          : rhs_val1);
 
-      tw.set_lvalue_list (nullptr);
-
       octave_idx_type k = 0;
 
       octave_idx_type n = rhs_val.length ();
--- a/libinterp/parse-tree/pt-eval.cc	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/parse-tree/pt-eval.cc	Sat Jan 20 14:01:56 2024 -0500
@@ -1450,6 +1450,40 @@
   return frame->inputname (n, ids_only);
 }
 
+Matrix
+tree_evaluator::ignored_fcn_outputs () const
+{
+  Matrix retval;
+
+  const std::list<octave_lvalue> *lvalues = m_lvalue_list;
+
+  if (! lvalues)
+    return retval;
+
+  octave_idx_type nbh = 0;
+
+  for (const auto& lval : *lvalues)
+    nbh += lval.is_black_hole ();
+
+  if (nbh > 0)
+    {
+      retval.resize (1, nbh);
+
+      octave_idx_type k = 0;
+      octave_idx_type l = 0;
+
+      for (const auto& lval : *lvalues)
+        {
+          if (lval.is_black_hole ())
+            retval(l++) = k+1;
+
+          k += lval.numel ();
+        }
+    }
+
+  return retval;
+}
+
 // If NAME is an operator (like "+", "-", ...), convert it to the
 // corresponding function name ("plus", "minus", ...).
 
@@ -3557,6 +3591,17 @@
 
   octave_value_list args (xargs);
 
+  // FIXME: this probably shouldn't be a double-precision matrix.
+  Matrix ignored_outputs = ignored_fcn_outputs ();
+
+  unwind_protect frame;
+
+  if (! user_function.is_anonymous_function ())
+    {
+      frame.protect_var (m_lvalue_list);
+      m_lvalue_list = nullptr;
+    }
+
   octave_value_list ret_args;
 
   int nargin = args.length ();
@@ -3619,8 +3664,8 @@
         }
     }
 
-  bind_auto_fcn_vars (xargs.name_tags (), nargin, nargout,
-                      user_function.takes_varargs (),
+  bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin,
+                      nargout, user_function.takes_varargs (),
                       user_function.all_va_args (args));
 
   // For classdef constructor, pre-populate the output arguments
@@ -5233,11 +5278,13 @@
 
 void
 tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names,
+                                    const Matrix& ignored_outputs,
                                     int nargin, int nargout,
                                     bool takes_varargs,
                                     const octave_value_list& va_args)
 {
   set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names));
+  set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs);
   set_auto_fcn_var (stack_frame::NARGIN, nargin);
   set_auto_fcn_var (stack_frame::NARGOUT, nargout);
   set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ());
@@ -5672,12 +5719,4 @@
 %!error <N must be a scalar index> inputname (-1)
 */
 
-// DEPRECATED in Octave 9.
-
-Matrix
-tree_evaluator::ignored_fcn_outputs () const
-{
-  return Matrix ();
-}
-
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-eval.h	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/parse-tree/pt-eval.h	Sat Jan 20 14:01:56 2024 -0500
@@ -355,7 +355,6 @@
     SC_OTHER      // command-line input or eval string
   };
 
-  OCTAVE_DEPRECATED (9, "tree_evaluator::ignored_fcn_outputs is obsolete and now always returns an empty Matrix object");
   Matrix ignored_fcn_outputs () const;
 
   std::string inputname (int n, bool ids_only = true) const;
@@ -927,7 +926,8 @@
   bool quit_loop_now ();
 
   void bind_auto_fcn_vars (const string_vector& arg_names,
-                           int nargin, int nargout, bool takes_varargs,
+                           const Matrix& ignored_outputs, int nargin,
+                           int nargout, bool takes_varargs,
                            const octave_value_list& va_args);
 
   std::string check_autoload_file (const std::string& nm) const;
--- a/libinterp/parse-tree/pt-mat.cc	Fri Jan 19 15:03:38 2024 -0500
+++ b/libinterp/parse-tree/pt-mat.cc	Sat Jan 20 14:01:56 2024 -0500
@@ -47,6 +47,13 @@
 octave_value
 tree_matrix::evaluate (tree_evaluator& tw, int)
 {
+  unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)
+  {
+    tw.set_lvalue_list (lvl);
+  }, tw.lvalue_list ());
+
+  tw.set_lvalue_list (nullptr);
+
   tm_const tmp (*this, tw);
 
   return tmp.concat (tw.string_fill_char ());
--- a/scripts/miscellaneous/nthargout.m	Fri Jan 19 15:03:38 2024 -0500
+++ b/scripts/miscellaneous/nthargout.m	Sat Jan 20 14:01:56 2024 -0500
@@ -68,7 +68,7 @@
 ## @var{USV} = nthargout ([1:3], @@svd, hilb (5));
 ## @end example
 ##
-## @seealso{nargin, nargout, varargin, varargout}
+## @seealso{nargin, nargout, varargin, varargout, isargout}
 ## @end deftypefn
 
 function arg = nthargout (n, varargin)