Mercurial > octave
diff src/ov-usr-fcn.cc @ 10832:1b2fcd122c6a
allow user detect ignored outputs in m-functions
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Thu, 29 Jul 2010 12:45:23 +0200 |
parents | 9cd5aa83fa62 |
children | 89f4d7e294cc |
line wrap: on
line diff
--- a/src/ov-usr-fcn.cc Thu Jul 29 08:51:23 2010 +0200 +++ b/src/ov-usr-fcn.cc Thu Jul 29 12:45:23 2010 +0200 @@ -31,6 +31,7 @@ #include "Cell.h" #include "defun.h" #include "error.h" +#include "gripes.h" #include "input.h" #include "oct-obj.h" #include "ov-usr-fcn.h" @@ -282,6 +283,14 @@ const std::list<octave_value_list>& idx, int nargout) { + return octave_user_function::subsref (type, idx, nargout, 0); +} + +octave_value_list +octave_user_function::subsref (const std::string& type, + const std::list<octave_value_list>& idx, + int nargout, const std::list<octave_lvalue>* lvalue_list) +{ octave_value_list retval; switch (type[0]) @@ -290,7 +299,8 @@ { int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout; - retval = do_multi_index_op (tmp_nargout, idx.front ()); + retval = do_multi_index_op (tmp_nargout, idx.front (), + idx.size () == 1 ? lvalue_list : 0); } break; @@ -320,6 +330,14 @@ octave_user_function::do_multi_index_op (int nargout, const octave_value_list& args) { + return do_multi_index_op (nargout, args, 0); +} + +octave_value_list +octave_user_function::do_multi_index_op (int nargout, + const octave_value_list& args, + const std::list<octave_lvalue>* lvalue_list) +{ octave_value_list retval; if (error_state) @@ -392,7 +410,8 @@ frame.add_fcn (symbol_table::clear_variables); } - bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args)); + bind_automatic_vars (arg_names, nargin, nargout, all_va_args (args), + lvalue_list); bool echo_commands = (Vecho_executing_commands & ECHO_FUNCTIONS); @@ -522,7 +541,7 @@ void octave_user_function::bind_automatic_vars (const string_vector& arg_names, int nargin, int nargout, - const octave_value_list& va_args) + const octave_value_list& va_args, const std::list<octave_lvalue> *lvalue_list) { if (! arg_names.empty ()) symbol_table::varref ("argn") = arg_names; @@ -535,6 +554,31 @@ if (takes_varargs ()) symbol_table::varref ("varargin") = va_args.cell_value (); + + if (lvalue_list) + { + octave_idx_type nbh = 0; + for (std::list<octave_lvalue>::const_iterator p = lvalue_list->begin (); + p != lvalue_list->end (); p++) + nbh += p->is_black_hole (); + + if (nbh > 0) + { + // Only assign the hidden variable if black holes actually present. + Matrix bh (1, nbh); + octave_idx_type k = 0, l = 0; + for (std::list<octave_lvalue>::const_iterator p = lvalue_list->begin (); + p != lvalue_list->end (); p++) + { + if (p->is_black_hole ()) + bh(l++) = k+1; + k += p->numel (); + } + + symbol_table::varref (".ignored.") = bh; + symbol_table::mark_hidden (".ignored."); + } + } } DEFUN (nargin, args, , @@ -683,3 +727,69 @@ { return SET_INTERNAL_VARIABLE (optimize_subsasgn_calls); } + +static bool val_in_table (const Matrix& table, double val) +{ + if (table.is_empty ()) + return false; + + octave_idx_type i = table.lookup (val, ASCENDING); + return (i > 0 && table(i-1) == val); +} + +DEFUN (is_ignored_output, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} is_ignored_output (@var{k})\n\ +Within a function, given an index @var{k} within the range @code{1:nargout},\n\ +return a logical value indicating whether the argument will be ignored on output\n\ +using the tilde (~) special output argument. If @var{k} is outside the range,\n\ +the function yields false. @var{k} can also be an array, in which case the function\n\ +works element-wise and a logical array is returned.\n\ +\n\ +At the top level, @code{is_ignored_output} returns an error.\n\ +@seealso{nargout, nargin, varargin, varargout}\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 1) + { + if (! symbol_table::at_top_level ()) + { + Matrix ignored; + octave_value tmp = symbol_table::varval (".ignored."); + if (tmp.is_defined ()) + ignored = tmp.matrix_value (); + + if (args(0).is_scalar_type ()) + { + double k = args(0).double_value (); + if (! error_state) + retval = val_in_table (ignored, k); + } + else if (args(0).is_numeric_type ()) + { + const NDArray ka = args(0).array_value (); + if (! error_state) + { + boolNDArray r (ka.dims ()); + for (octave_idx_type i = 0; i < ka.numel (); i++) + r(i) = val_in_table (ignored, ka(i)); + + retval = r; + } + } + else + gripe_wrong_type_arg ("is_ignored_output", args(0)); + } + else + error ("is_ignored_output: invalid call at top level"); + } + else + print_usage (); + + return retval; +} +