# HG changeset patch # User dbateman # Date 1137088522 0 # Node ID 61d6cebd243b45fa4dac6dcec17bfff16f17ce88 # Parent e7e45fe274f1908687cc62a684c95a9c27df9379 [project @ 2006-01-12 17:55:22 by dbateman] diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -1,3 +1,8 @@ +2006-01-12 David Bateman + + * general/blkdiag.m: Compatible behavior for empty matrices + * statistics/base/unidrnd.m: Documentation buglet. + 2005-12-14 David Bateman * testfun/assert.m, testfun/fail.m, testfun/test.m, testfun/demo.m, diff --git a/scripts/general/blkdiag.m b/scripts/general/blkdiag.m --- a/scripts/general/blkdiag.m +++ b/scripts/general/blkdiag.m @@ -41,15 +41,12 @@ error ("all of the arguments to blkdiag must be two-dimensional matrices"); endif - ## Ignore empty matrices. - notempty = ! cellfun ("isempty", varargin); - varargin = varargin(notempty); - ## size is an option for cellfun, but it's a bit different from ## calling size directly. csz = cumsum ([0 0; (cell2mat (cellfun (@size, varargin')))], 1); retval = zeros (csz(end,:)); - for p = 1:(length (notempty(notempty))) + + for p = 1:nargin retval((csz(p,1)+1):csz(p+1,1),(csz(p,2)+1):csz(p+1,2)) = varargin{p}; endfor diff --git a/scripts/statistics/base/unidrnd.m b/scripts/statistics/base/unidrnd.m --- a/scripts/statistics/base/unidrnd.m +++ b/scripts/statistics/base/unidrnd.m @@ -19,8 +19,8 @@ ## -*- texinfo -*- ## @deftypefn {Function File} {} unidrnd (@var{mx}); -## @deftypefn {Function File} {} unidrnd (@var{mx}, @var{v}); -## @deftypefn {Function File} {} unidrnd (@var{mx}, @var{m}, @var{n}, @dots{}); +## @deftypefnx {Function File} {} unidrnd (@var{mx}, @var{v}); +## @deftypefnx {Function File} {} unidrnd (@var{mx}, @var{m}, @var{n}, @dots{}); ## Return random values from discrete uniform distribution, with maximum ## value(s) given by the integer @var{mx}, which may be a scalar or ## multidimensional array. diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,30 @@ +2006-01-12 David Bateman + + * help.cc (make_name_list): Add autoload functions to list of + available completions. + (simple_help): Add autoloaded functions to functions listed + (first_help_sentence): Avoid issue with single line help string + that is not terminated in \n. + (Flookfor): Check for string match in the keyword/function, etc + name. Also look for string match in help of autoloaded functions. + Load oct-files to be able to access their help string. + * parse.y (string_vector autoloaded_functions (void)): New + function to list all autloaded functions. + (string_vector reverse_lookup_autoload (const std::string& nm)): + Reverse lookup function to match file to autoloaded functions. + * parse.h (autoloaded_functions, reverse_lookup_autoload): + Declaration. + + * oct-map.cc (maybe_delete_elements): New function. + * oct-map.h (maybe_delete_elements): Declare it. + * ov-struct.cc (octave_struct::subsref): Handle indexing empty + structure. + (octave_struct::subsasgn): If rhs is [], delete elements. + (octave_struct::print_raw): Handle printing empty structure. + + * ls-mat5.cc (read_mat5_binary_element): Allow reading of sparse + elements when nnz doesn't equal nzmax. + 2006-01-10 David Bateman * DLD-FUNCTIONS/sparse.cc (sparse_find): Use Sparse::nonzero() diff --git a/src/help.cc b/src/help.cc --- a/src/help.cc +++ b/src/help.cc @@ -407,7 +407,10 @@ string_vector ffl = octave_fcn_file_name_cache::list_no_suffix (); int ffl_len = ffl.length (); - int total_len = key_len + fbi_len + glb_len + top_len + lcl_len + ffl_len; + string_vector afl = autoloaded_functions (); + int afl_len = afl.length (); + + int total_len = key_len + fbi_len + glb_len + top_len + lcl_len + ffl_len + afl_len; string_vector list (total_len); @@ -433,6 +436,9 @@ for (i = 0; i < ffl_len; i++) list[j++] = ffl[i]; + for (i = 0; i < afl_len; i++) + list[j++] = afl[i]; + return list; } @@ -542,6 +548,17 @@ names.list_in_columns (octave_stdout); } } + + string_vector autoloaded = autoloaded_functions (); + + if (! autoloaded.empty ()) + { + octave_stdout << "\n*** autoloaded functions:\n\n"; + + autoloaded.qsort (); + + autoloaded.list_in_columns (octave_stdout); + } } static int @@ -1138,8 +1155,8 @@ size_t pos = 0; if (looks_like_texinfo (h, pos)) - { - // Get the parsed help string. + { + // Get the parsed help string. pos = 0; OSSTREAM os; display_help_text (os, h); @@ -1232,7 +1249,7 @@ if (lower.find_first_of ('-') == 0 || lower.substr (0, 5) == "usage") { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1247,7 +1264,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1257,7 +1274,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1273,7 +1290,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1304,7 +1321,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1315,7 +1332,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1328,7 +1345,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1345,7 +1362,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1361,7 +1378,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1380,7 +1397,7 @@ if (line_pos == NPOS) { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1392,7 +1409,7 @@ || line.find_first_not_of ("\n\t ", line_pos) == NPOS || line.substr (line_pos, 2) == "!/") { - pos = new_pos + 1; + pos = (new_pos == NPOS ? NPOS : new_pos + 1); continue; } @@ -1571,15 +1588,7 @@ std::string name = ptr->name; std::string h = ptr->help; - std::string s; - if (first_sentence_only) - s = first_help_sentence (h); - else - s = h; - - transform (s.begin (), s.end (), s.begin (), tolower); - - if (s.length () > 0 && s.find (txt) != NPOS) + if (name.find (txt) != NPOS) { if (nargout) { @@ -1589,6 +1598,28 @@ else print_lookfor (name, first_help_sentence (h)); } + else + { + std::string s; + + if (first_sentence_only) + s = first_help_sentence (h); + else + s = h; + + transform (s.begin (), s.end (), s.begin (), tolower); + + if (s.length () > 0 && s.find (txt) != NPOS) + { + if (nargout) + { + ret[0].append (name); + ret[1].append (first_help_sentence (h)); + } + else + print_lookfor (name, first_help_sentence (h)); + } + } OCTAVE_QUIT; @@ -1601,15 +1632,7 @@ std::string name = ptr->name; std::string h = ptr->help; - std::string s; - if (first_sentence_only) - s = first_help_sentence (h); - else - s = h; - - transform (s.begin (), s.end (), s.begin (), tolower); - - if (s.length () > 0 && s.find (txt) != NPOS) + if (name.find (txt) != NPOS) { if (nargout) { @@ -1619,6 +1642,27 @@ else print_lookfor (name, first_help_sentence (h)); } + else + { + std::string s; + if (first_sentence_only) + s = first_help_sentence (h); + else + s = h; + + transform (s.begin (), s.end (), s.begin (), tolower); + + if (s.length () > 0 && s.find (txt) != NPOS) + { + if (nargout) + { + ret[0].append (name); + ret[1].append (first_help_sentence (h)); + } + else + print_lookfor (name, first_help_sentence (h)); + } + } OCTAVE_QUIT; @@ -1639,15 +1683,8 @@ if (sr && sr->is_defined ()) { std::string h = sr->help (); - std::string s; - if (first_sentence_only) - s = first_help_sentence (h); - else - s = h; - - transform (s.begin (), s.end (), s.begin (), tolower); - if (s.length () > 0 && s.find (txt) != NPOS) + if (name.find (txt) != NPOS) { if (nargout) { @@ -1657,6 +1694,28 @@ else print_lookfor (name, first_help_sentence (h)); } + else + { + std::string s; + + if (first_sentence_only) + s = first_help_sentence (h); + else + s = h; + + transform (s.begin (), s.end (), s.begin (), tolower); + + if (s.length () > 0 && s.find (txt) != NPOS) + { + if (nargout) + { + ret[0].append (name); + ret[1].append (first_help_sentence (h)); + } + else + print_lookfor (name, first_help_sentence (h)); + } + } } } @@ -1697,24 +1756,24 @@ std::string file_name = Vload_path_dir_path.find_first_of (tmp); - if (file_name == dirs[i] + tmp(0) || file_name == dirs[i] + tmp(1)) { bool symbol_found; - std::string h - = get_help_from_file (file_name, symbol_found); + std::string h; + if (file_name == dirs[i] + tmp(0)) + { + // oct-file. Must load to get help + sr = lookup_by_name (name, false); - std::string s; - if (first_sentence_only) - s = first_help_sentence (h); + if (sr && sr->is_defined ()) + h = sr->help (); + } else - s = h; + h = get_help_from_file (file_name, symbol_found); - transform (s.begin (), s.end (), s.begin (), tolower); - - if (s.length () > 0 && s.find (txt) != NPOS) + if (name.find (txt) != NPOS) { if (nargout) { @@ -1724,13 +1783,91 @@ else print_lookfor (name, first_help_sentence (h)); } + else + { + std::string s; + if (first_sentence_only) + s = first_help_sentence (h); + else + s = h; + + transform (s.begin (), s.end (), s.begin (), tolower); + + if (s.length () > 0 && s.find (txt) != NPOS) + { + if (nargout) + { + ret[0].append (name); + ret[1].append (first_help_sentence (h)); + } + else + print_lookfor (name, first_help_sentence (h)); + } + } + } + } + + // Check if this function has autoloaded functions attached to it + std::string file_name = Vload_path_dir_path.find_first_of (names(j)); + string_vector autoload_fcns = reverse_lookup_autoload (file_name); + + if (! autoload_fcns.empty ()) + { + for (int k = 0; k < autoload_fcns.length (); k++) + { + std::string aname = autoload_fcns (k); + + // Check if already in symbol table + sr = fbi_sym_tab->lookup (aname); + + if (!sr) + { + // Must load to get help + sr = lookup_by_name (name, false); + + std::string h; + if (sr && sr->is_defined ()) + h = sr->help (); + + if (aname.find (txt) != NPOS) + { + if (nargout) + { + ret[0].append (aname); + ret[1].append (first_help_sentence (h)); + } + else + print_lookfor (aname, first_help_sentence (h)); + } + else + { + std::string s; + if (first_sentence_only) + s = first_help_sentence (h); + else + s = h; + + transform (s.begin (), s.end (), s.begin (), + tolower); + + if (s.length () > 0 && s.find (txt) != NPOS) + { + if (nargout) + { + ret[0].append (aname); + ret[1].append (first_help_sentence (h)); + } + else + print_lookfor (aname, first_help_sentence (h)); + } + } + } } } } } } - if (nargout != 0) { retval (1) = ret[1]; diff --git a/src/ls-mat5.cc b/src/ls-mat5.cc --- a/src/ls-mat5.cc +++ b/src/ls-mat5.cc @@ -403,7 +403,7 @@ bool imag; bool logicalvar; enum arrayclasstype arrayclass; - FOUR_BYTE_INT nnz; + FOUR_BYTE_INT nzmax; FOUR_BYTE_INT flags; dim_vector dims; int len; @@ -495,7 +495,7 @@ global = (flags & 0x0400) != 0; // global variable? logicalvar = (flags & 0x0200) != 0; // boolean ? arrayclass = (arrayclasstype)(flags & 0xff); - read_int (is, swap, nnz); // number of non-zero in sparse + read_int (is, swap, nzmax); // max number of non-zero in sparse // dimensions array subelement { @@ -587,7 +587,6 @@ int nc = dims(1); SparseMatrix sm; SparseComplexMatrix scm; - NDArray re; int *ridx; int *cidx; double *data; @@ -597,17 +596,16 @@ { scm = SparseComplexMatrix (static_cast (nr), static_cast (nc), - static_cast (nnz)); + static_cast (nzmax)); ridx = scm.ridx (); cidx = scm.cidx (); - re = NDArray (dim_vector (static_cast (nnz))); - data = re.fortran_vec (); + data = 0; } else { sm = SparseMatrix (static_cast (nr), static_cast (nc), - static_cast (nnz)); + static_cast (nzmax)); ridx = sm.ridx (); cidx = sm.cidx (); data = sm.data (); @@ -624,7 +622,7 @@ tmp_pos = is.tellg (); - read_mat5_integer_data (is, ridx, nnz, swap, + read_mat5_integer_data (is, ridx, nzmax, swap, (enum mat5_data_type) type); if (! is || error_state) @@ -662,6 +660,14 @@ goto data_read_error; } + FOUR_BYTE_INT nnz = cidx[nc]; + NDArray re; + if (imag) + { + re = NDArray (dim_vector (static_cast (nnz))); + data = re.fortran_vec (); + } + tmp_pos = is.tellg (); read_mat5_binary_data (is, data, nnz, swap, (enum mat5_data_type) type, flt_fmt); diff --git a/src/oct-map.cc b/src/oct-map.cc --- a/src/oct-map.cc +++ b/src/oct-map.cc @@ -210,6 +210,31 @@ } Octave_map& +Octave_map::maybe_delete_elements (const octave_value_list& idx) +{ + string_vector t_keys = keys(); + octave_idx_type len = t_keys.length (); + + if (len > 0) + { + for (octave_idx_type i = 0; i < len; i++) + { + std::string k = t_keys[i]; + + map[k] = contents (k).assign (idx, Cell()); + + if (error_state) + break; + } + + if (!error_state) + dimensions = contents(t_keys[0]).dims(); + } + + return *this; +} + +Octave_map& Octave_map::assign (const octave_value_list& idx, const Octave_map& rhs) { string_vector t_keys = empty () ? rhs.keys () : equiv_keys (*this, rhs); diff --git a/src/oct-map.h b/src/oct-map.h --- a/src/oct-map.h +++ b/src/oct-map.h @@ -133,6 +133,8 @@ Octave_map concat (const Octave_map& rb, const Array& ra_idx); + Octave_map& maybe_delete_elements (const octave_value_list& idx); + Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs); Octave_map& assign (const octave_value_list& idx, const std::string& k, diff --git a/src/ov-struct.cc b/src/ov-struct.cc --- a/src/ov-struct.cc +++ b/src/ov-struct.cc @@ -133,9 +133,12 @@ case '.': { - Cell t = dotref (idx.front ()); + if (map.numel() > 0) + { + Cell t = dotref (idx.front ()); - retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true); + retval(0) = (t.length () == 1) ? t(0) : octave_value (t, true); + } } break; @@ -307,19 +310,36 @@ } else { - Octave_map rhs_map = t_rhs.map_value (); - - if (! error_state) + if (t_rhs.is_map()) { - map.assign (idx.front (), rhs_map); + Octave_map rhs_map = t_rhs.map_value (); if (! error_state) - retval = octave_value (this, count + 1); + { + map.assign (idx.front (), rhs_map); + + if (! error_state) + retval = octave_value (this, count + 1); + else + gripe_failed_assignment (); + } else - gripe_failed_assignment (); + error ("invalid structure assignment"); } else - error ("invalid structure assignment"); + { + if (t_rhs.is_empty()) + { + map.maybe_delete_elements (idx.front()); + + if (! error_state) + retval = octave_value (this, count + 1); + else + gripe_failed_assignment (); + } + else + error ("invalid structure assignment"); + } } } break; @@ -393,7 +413,8 @@ if (Vstruct_levels_to_print >= 0) { - bool print_keys_only = (Vstruct_levels_to_print == 0); + bool print_keys_only = (Vstruct_levels_to_print == 0 || + map.numel() == 0); Vstruct_levels_to_print--; @@ -403,7 +424,7 @@ increment_indent_level (); - octave_idx_type n = map.numel (); + octave_idx_type n = map_keys().length(); if (n > 1 && print_keys_only) { @@ -482,12 +503,12 @@ return dims.length () == 2 && dims (0) == 1 && dims (1) == 1; } -// XXX FIXME XXX -- move these tests to the test directory? /* %!shared x %! x(1).a=1; x(2).a=2; x(1).b=3; x(2).b=3; %!assert(struct('a',1,'b',3),x(1)) -%!assert(struct('a',{},'b',{}),x([])) +%!assert(isempty(x([]))) +%!assert(isempty(struct('a',{},'b',{}))) %!assert(struct('a',{1,2},'b',{3,3}),x) %!assert(struct('a',{1,2},'b',3),x) %!assert(struct('a',{1,2},'b',{3}),x) diff --git a/src/parse.h b/src/parse.h --- a/src/parse.h +++ b/src/parse.h @@ -98,6 +98,10 @@ extern std::string lookup_autoload (const std::string& nm); +extern string_vector autoloaded_functions (void); + +extern string_vector reverse_lookup_autoload (const std::string& nm); + extern bool load_fcn_from_file (const std::string& nm, bool exec_script); diff --git a/src/parse.y b/src/parse.y --- a/src/parse.y +++ b/src/parse.y @@ -3379,6 +3379,34 @@ octave_env::getcwd ()); } +string_vector +autoloaded_functions (void) +{ + string_vector names (autoload_map.size()); + + octave_idx_type i = 0; + std::map::const_iterator p; + for (p = std::map::iterator (autoload_map.begin ()); + p != std::map::iterator (autoload_map.end ()); p++) + names[i++] = p->first; + + return names; +} + +string_vector +reverse_lookup_autoload (const std::string& nm) +{ + string_vector names; + + std::map::const_iterator p; + for (p = std::map::iterator (autoload_map.begin ()); + p != std::map::iterator (autoload_map.end ()); p++) + if (nm == p->second) + names.append (p->first); + + return names; +} + bool load_fcn_from_file (const std::string& nm, bool exec_script) {