Mercurial > hg > octave-lojdl
changeset 4791:62f2fb593455
[project @ 2004-02-20 18:02:59 by jwe]
author | jwe |
---|---|
date | Fri, 20 Feb 2004 18:02:59 +0000 |
parents | 91a84c9bdadb |
children | d2038299c683 |
files | liboctave/ChangeLog liboctave/Range.cc src/ChangeLog src/load-save.cc src/load-save.h src/ov-base-scalar.h src/ov-base.h src/ov-bool-mat.h src/ov-cell.cc src/ov-cell.h src/ov-ch-mat.h src/ov-cx-mat.h src/ov-list.cc src/ov-list.h src/ov-range.h src/ov-re-mat.h src/ov-streamoff.h src/ov-struct.cc src/ov-struct.h src/ov.cc src/ov.h src/pr-output.cc src/sighandlers.cc |
diffstat | 23 files changed, 370 insertions(+), 100 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,9 @@ +2004-02-20 John W. Eaton <jwe@bevo.che.wisc.edu> + + * Range.cc (Range::matrix_value, Range::min, Range::max): + Don't compute values beyond the limits of the range. + (operator << (std::ostream&, const Range&)): Likewise. + 2004-02-18 John W. Eaton <jwe@bevo.che.wisc.edu> * oct-fftw.cc (octave_fftw_planner::create_plan):
--- a/liboctave/Range.cc +++ b/liboctave/Range.cc @@ -61,7 +61,17 @@ double b = rng_base; double increment = rng_inc; for (int i = 0; i < rng_nelem; i++) - retval.elem (0, i) = b + i * increment; + retval(i) = b + i * increment; + + // On some machines (x86 with extended precision floating point + // arithmetic, for example) it is possible that we can overshoot + // the limit by approximately the machine precision even though + // we were very careful in our calculation of the number of + // elements. + + if ((rng_inc > 0 && retval(rng_nelem-1) > rng_limit) + || (rng_inc < 0 && retval(rng_nelem-1) < rng_limit)) + retval(rng_nelem-1) = rng_limit; } return retval; @@ -78,7 +88,15 @@ if (rng_inc > 0) retval = rng_base; else - retval = rng_base + (rng_nelem - 1) * rng_inc; + { + retval = rng_base + (rng_nelem - 1) * rng_inc; + + // See the note in the matrix_value method above. + + if (retval < rng_limit) + retval = rng_limit; + } + } return retval; } @@ -90,7 +108,14 @@ if (rng_nelem > 0) { if (rng_inc > 0) - retval = rng_base + (rng_nelem - 1) * rng_inc; + { + retval = rng_base + (rng_nelem - 1) * rng_inc; + + // See the note in the matrix_value method above. + + if (retval > rng_limit) + retval = rng_limit; + } else retval = rng_base; } @@ -125,10 +150,13 @@ double increment = a.inc (); int num_elem = a.nelem (); - for (int i = 0; i < num_elem; i++) + for (int i = 0; i < num_elem-1; i++) os << b + i * increment << " "; - os << "\n"; + // Prevent overshoot. See comment in the matrix_value method + // above. + + os << (increment > 0 ? a.max () : a.min ()) << "\n"; return os; }
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,50 @@ +2004-02-20 John W. Eaton <jwe@bevo.che.wisc.edu> + + * pr-output.cc (octave_print_internal (std::ostream&, const + Range&, bool, int)): Don't print values beyond the limits of the + range. + + * sighandlers.cc (sigint_handler): Print message after two + consecutive interrupts, dump core after three or more. + + * load-save.cc (dump_octave_core): Handle core size limit. + Rename from save_user_variables. Change all callers. + (Fload, dump_octave_core, Fsave): Open HDF5 fils in binary mode. + (do_save): Extract switch over file types to separate function. + + * load-save.cc (Voctave_core_file_limit): New variable. + (octave_core_file_limit): New function. + (symbols_of_load_save): Add DEFVAR for octave_core_file_limit. + + * load-save.cc (Voctave_core_file_name): New variable. + (octave_core_file_name): New function. + (symbols_of_load_save): Add DEFVAR for octave_core_file_name. + + * load-save.cc (Voctave_core_file_format): + Rename from Voctave_core_format. + (octave_core_file_format): Rename from octave_core_format. + (symbols_of_load_save): Fix DEFVAR to match. + 2004-02-19 John W. Eaton <jwe@bevo.che.wisc.edu> + * ov.cc (Fsizeof): New function. + + * ov.h (octave_value::byte_size): New function. + * ov-base.h (octave_base_value::byte_size): New function. + * ov-base-scalar.h (octave_base_scalar::byte_size): New function. + * ov-bool-mat.h (octave_bool_matrix::byte_size): New function. + * ov-ch-mat.h (octave_char_matrix::byte_size): New function. + * ov-cx-mat.h (octave_complex_matrix::byte_size): New function. + * ov-re-mat.h (octave_matrix::byte_size): New function. + * ov-range.h (octave_range::byte_size): New function. + * ov-cell.cc (octave_cell::byte_size): New function. + * ov-cell.h: Provide decl. + * ov-struct.cc (octave_struct::byte_size): New function. + * ov-struct.h: Provide decl. + * ov-streamoff.h (octave_streamoff::byte_size): New function. + * ov-list.cc (octave_list::byte_size): New function. + * ov-list.h: Provide decl. + * xpow.cc (elem_xpow (const Matrix&, double)): Convert both operands to Complex if any element of A is negative. (elem_xpow (const NDArray&, double)): Likewise.
--- a/src/load-save.cc +++ b/src/load-save.cc @@ -83,13 +83,20 @@ // Write octave-core file if Octave crashes or is killed by a signal. static bool Vcrash_dumps_octave_core; +// The maximum amount of memory (in kilobytes) that we will attempt to +// write to the Octave core file. +static double Voctave_core_file_limit; + +// The name of the Octave core file. +static std::string Voctave_core_file_name; + // The default output format. May be one of "binary", "text", // "mat-binary", or "hdf5". static std::string Vdefault_save_format; -// The output format for octave-core files. May be one of "binary", +// The output format for Octave core files. May be one of "binary", // "text", "mat-binary", or "hdf5". -static std::string Voctave_core_format; +static std::string Voctave_core_file_format; // The format string for the comment line at the top of text-format // save files. Passed to strftime. Should begin with `#' and contain @@ -738,9 +745,13 @@ i++; std::ios::openmode mode = std::ios::in; - if (format == LS_BINARY || - format == LS_MAT_BINARY || - format == LS_MAT5_BINARY) + + if (format == LS_BINARY +#ifdef HAVE_HDF5 + || format == LS_HDF5 +#endif + || format == LS_MAT_BINARY + || format == LS_MAT5_BINARY) mode |= std::ios::binary; std::ifstream file (fname.c_str (), mode); @@ -818,27 +829,12 @@ return false; } -// Save the info from sr on stream os in the format specified by fmt. - -void -do_save (std::ostream& os, symbol_record *sr, load_save_format fmt, - int save_as_floats, bool& infnan_warned) +static void +do_save (std::ostream& os, const octave_value& tc, + const std::string& name, const std::string& help, + int global, load_save_format fmt, bool save_as_floats, + bool& infnan_warned) { - if (! sr->is_variable ()) - { - error ("save: can only save variables, not functions"); - return; - } - - std::string name = sr->name (); - std::string help = sr->help (); - int global = sr->is_linked_to_global (); - - octave_value tc = sr->def (); - - if (tc.is_undefined ()) - return; - switch (fmt) { case LS_ASCII: @@ -869,13 +865,39 @@ } } +// Save the info from SR on stream OS in the format specified by FMT. + +void +do_save (std::ostream& os, symbol_record *sr, load_save_format fmt, + bool save_as_floats, bool& infnan_warned) +{ + if (! sr->is_variable ()) + { + error ("save: can only save variables, not functions"); + return; + } + + octave_value tc = sr->def (); + + if (tc.is_defined ()) + { + std::string name = sr->name (); + std::string help = sr->help (); + + int global = sr->is_linked_to_global (); + + do_save (os, tc, name, help, global, fmt, save_as_floats, + infnan_warned); + } +} + // Save variables with names matching PATTERN on stream OS in the // format specified by FMT. If SAVE_BUILTINS is TRUE, also save // builtin variables with names that match PATTERN. static int save_vars (std::ostream& os, const std::string& pattern, bool save_builtins, - load_save_format fmt, int save_as_floats) + load_save_format fmt, bool save_as_floats) { Array<symbol_record *> vars = curr_sym_tab->glob (pattern, symbol_record::USER_VARIABLE, SYMTAB_ALL_SCOPES); @@ -886,7 +908,7 @@ for (int i = 0; i < saved; i++) { - do_save (os, vars (i), fmt, save_as_floats, infnan_warned); + do_save (os, vars(i), fmt, save_as_floats, infnan_warned); if (error_state) break; @@ -903,7 +925,7 @@ for (int i = 0; i < count; i++) { - do_save (os, vars (i), fmt, save_as_floats, infnan_warned); + do_save (os, vars(i), fmt, save_as_floats, infnan_warned); if (error_state) break; @@ -1039,23 +1061,79 @@ } void -save_user_variables (void) +dump_octave_core (std::ostream& os, const char *fname, load_save_format fmt) +{ + write_header (os, fmt); + + Array<symbol_record *> vars = curr_sym_tab->glob + ("*", symbol_record::USER_VARIABLE, SYMTAB_ALL_SCOPES); + + int num_to_save = vars.length (); + + bool infnan_warned = false; + + double save_mem_size = 0; + + for (int i = 0; i < num_to_save; i++) + { + symbol_record *sr = vars(i); + + if (sr->is_variable ()) + { + octave_value tc = sr->def (); + + if (tc.is_defined ()) + { + double tc_size = tc.byte_size () / 1024; + + // XXX FIXME XXX -- maybe we should try to throw out hte + // largest first... + + if (Voctave_core_file_limit < 0 + || save_mem_size + tc_size < Voctave_core_file_limit) + { + save_mem_size += tc_size; + + std::string name = sr->name (); + std::string help = sr->help (); + + int global = sr->is_linked_to_global (); + + do_save (os, tc, name, help, global, fmt, false, + infnan_warned); + + if (error_state) + break; + } + } + } + } + + message (0, "save to `%s' complete", fname); +} + +void +dump_octave_core (void) { if (Vcrash_dumps_octave_core) { // XXX FIXME XXX -- should choose better file name? - const char *fname = "octave-core"; + const char *fname = Voctave_core_file_name.c_str (); message (0, "attempting to save variables to `%s'...", fname); load_save_format format - = get_save_format (Voctave_core_format, LS_BINARY); + = get_save_format (Voctave_core_file_format, LS_BINARY); std::ios::openmode mode = std::ios::out|std::ios::trunc; - if (format == LS_BINARY || - format == LS_MAT_BINARY || - format == LS_MAT5_BINARY) + + if (format == LS_BINARY +#ifdef HAVE_HDF5 + || format == LS_HDF5 +#endif + || format == LS_MAT_BINARY + || format == LS_MAT5_BINARY) mode |= std::ios::binary; #ifdef HAVE_HDF5 @@ -1065,10 +1143,7 @@ if (file.file_id >= 0) { - save_vars (string_vector (), 0, 0, file, - false, format, false, true); - - message (0, "save to `%s' complete", fname); + dump_octave_core (file, fname, format); file.close (); } @@ -1084,9 +1159,8 @@ if (file) { - save_vars (string_vector (), 0, 0, file, - false, format, false, true); - message (0, "save to `%s' complete", fname); + dump_octave_core (file, fname, format); + file.close (); } else @@ -1295,9 +1369,13 @@ i++; std::ios::openmode mode = std::ios::out; - if (format == LS_BINARY || - format == LS_MAT_BINARY || - format == LS_MAT5_BINARY) + + if (format == LS_BINARY +#ifdef HAVE_HDF5 + || format == LS_HDF5 +#endif + || format == LS_MAT_BINARY + || format == LS_MAT5_BINARY) mode |= std::ios::binary; mode |= append ? std::ios::ate : std::ios::trunc; @@ -1374,19 +1452,53 @@ } static int -octave_core_format (void) +octave_core_file_limit (void) +{ + double val; + + if (builtin_real_scalar_variable ("octave_core_file_limit", val)) + { + Voctave_core_file_limit = val; + return 0; + } + else + gripe_invalid_value_specified ("octave_core_file_limit"); + + return -1; +} + +static int +octave_core_file_name (void) { int status = 0; - std::string s = builtin_string_variable ("octave_core_format"); + std::string s = builtin_string_variable ("octave_core_file_name"); if (s.empty ()) { - gripe_invalid_value_specified ("octave_core_format"); + gripe_invalid_value_specified ("octave_core_file_name"); status = -1; } else - Voctave_core_format = s; + Voctave_core_file_name = s; + + return status; +} + +static int +octave_core_file_format (void) +{ + int status = 0; + + std::string s = builtin_string_variable ("octave_core_file_format"); + + if (s.empty ()) + { + gripe_invalid_value_specified ("octave_core_file_format"); + status = -1; + } + else + Voctave_core_file_format = s; return status; } @@ -1430,6 +1542,7 @@ If this variable is set to a nonzero value, Octave tries to save all\n\ current variables the the file \"octave-core\" if it crashes or receives a\n\ hangup, terminate or similar signal. The default value is 1.\n\ +@seealso{octave_core_file_limit, octave_core_file_name, and octave_core_file_format}\n\ @end defvr"); DEFVAR (default_save_format, "ascii", default_save_format, @@ -1439,18 +1552,38 @@ It should have one of the following values: @code{\"ascii\"},\n\ @code{\"binary\"}, @code{float-binary}, or @code{\"mat-binary\"}. The\n\ initial default save format is Octave's text format.\n\ -@seealso{octave_core_format}\n\ +@end defvr"); + + DEFVAR (octave_core_file_limit, -1.0, octave_core_file_limit, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} octave_core_file_limit\n\ +The maximum amount of memory (in kilobytes) of the top-level workspace\n\ +that Octave will attempt to write when saving data to the\n\ +@var{octave_core_file_name}. If @var{octave_core_file_format} is a\n\ +binary format, then @var{octave_core_file_limit} will be approximately\n\ +the maximum size of the file. If a text file format is used, then the\n\ +file could be much larger than the limit.\n\ +The default value is -1 (unlimited)\n\ +@seealso{crash_dumps_octave_core, octave_core_file_name, and octave_core_file_format}\n\ @end defvr"); - DEFVAR (octave_core_format, "binary", octave_core_format, + DEFVAR (octave_core_file_name, "octave-core", octave_core_file_name, "-*- texinfo -*-\n\ -@defvr {Built-in Variable} octave_core_format\n\ +@defvr {Built-in Variable} octave_core_file_name\n\ +The name of the file used for saving data from the top-level workspace\n\ +when Octave aborts. The default value is @code{\"octave-core\"}\n\ +@seealso{crash_dumps_octave_core, octave_core_file_name, and octave_core_file_format}\n\ +@end defvr"); + + DEFVAR (octave_core_file_format, "binary", octave_core_file_format, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} octave_core_file_format\n\ If Octave aborts, it attempts to save the contents of the top-level\n\ workspace in a file using this format. The value of\n\ -@code{octave_core_format} should have one of the following values:\n\ +@code{octave_core_file_format} should have one of the following values:\n\ @code{\"ascii\"}, @code{\"binary\"}, @code{float-binary}, or\n\ @code{\"mat-binary\"}. The default value is Octave's binary format.\n\ -@seealso{default_save_format}\n\ +@seealso{crash_dumps_octave_core, octave_core_file_name, and octave_core_file_limit}\n\ @end defvr"); DEFVAR (save_header_format_string, default_save_header_format (),
--- a/src/load-save.h +++ b/src/load-save.h @@ -50,8 +50,7 @@ save_three_d (std::ostream& os, const octave_value& t, bool parametric = false); -extern void -save_user_variables (void); +extern void dump_octave_core (void); extern int read_binary_file_header (std::istream& is, bool& swap, @@ -66,7 +65,7 @@ extern void do_save (std::ostream& os, symbol_record *sr, load_save_format fmt, - int save_as_floats, bool& infnan_warned); + bool save_as_floats, bool& infnan_warned); extern void write_header (std::ostream& os, load_save_format format);
--- a/src/ov-base-scalar.h +++ b/src/ov-base-scalar.h @@ -81,6 +81,8 @@ dim_vector dims (void) const { static dim_vector dv (1, 1); return dv; } + size_t byte_size (void) const { return sizeof (ST); } + octave_value all (int = 0) const { return (scalar != 0.0); } octave_value any (int = 0) const { return (scalar != 0.0); }
--- a/src/ov-base.h +++ b/src/ov-base.h @@ -96,6 +96,8 @@ dim_vector dims (void) const { return dim_vector (-1, -1); } + size_t byte_size (void) const { return 0; } + octave_value reshape (const dim_vector&) const; octave_value permute (const Array<int>& vec, bool = false) const;
--- a/src/ov-bool-mat.h +++ b/src/ov-bool-mat.h @@ -78,6 +78,8 @@ idx_vector index_vector (void) const { return idx_vector (matrix); } + size_t byte_size (void) const { return numel () * sizeof (bool); } + bool is_bool_matrix (void) const { return true; } bool is_bool_type (void) const { return true; }
--- a/src/ov-cell.cc +++ b/src/ov-cell.cc @@ -241,6 +241,17 @@ octave_base_matrix<Cell>::assign (idx, Cell (rhs)); } +size_t +octave_cell::byte_size (void) const +{ + size_t retval = 0; + + for (int i = 0; i < numel (); i++) + retval += matrix(i).byte_size (); + + return retval; +} + octave_value_list octave_cell::list_value (void) const {
--- a/src/ov-cell.h +++ b/src/ov-cell.h @@ -87,6 +87,8 @@ const std::list<octave_value_list>& idx, const octave_value& rhs); + size_t byte_size (void) const; + bool is_matrix_type (void) const { return false; } bool is_numeric_type (void) const { return false; }
--- a/src/ov-ch-mat.h +++ b/src/ov-ch-mat.h @@ -83,6 +83,8 @@ octave_value *clone (void) const { return new octave_char_matrix (*this); } octave_value *empty_clone (void) const { return new octave_char_matrix (); } + size_t byte_size (void) const { return numel () * sizeof (char); } + bool is_char_matrix (void) const { return true; } bool is_real_matrix (void) const { return true; }
--- a/src/ov-cx-mat.h +++ b/src/ov-cx-mat.h @@ -85,6 +85,8 @@ void assign (const octave_value_list& idx, const NDArray& rhs); + size_t byte_size (void) const { return numel () * sizeof (Complex); } + bool is_complex_matrix (void) const { return true; } bool is_complex_type (void) const { return true; }
--- a/src/ov-list.cc +++ b/src/ov-list.cc @@ -241,6 +241,17 @@ error ("lists may only be indexed by a single scalar"); } +size_t +octave_list::byte_size (void) const +{ + size_t retval = 0; + + for (int i = 0; i < numel (); i++) + retval += data(i).byte_size (); + + return retval; +} + octave_value_list octave_list::list_value (void) const {
--- a/src/ov-list.h +++ b/src/ov-list.h @@ -86,6 +86,8 @@ dim_vector dims (void) const { return dim_vector (1, data.length ()); } + size_t byte_size (void) const; + bool is_defined (void) const { return true; } bool is_constant (void) const { return true; }
--- a/src/ov-range.h +++ b/src/ov-range.h @@ -108,6 +108,8 @@ return dim_vector (n > 0, n); } + size_t byte_size (void) const { 3 * sizeof (double); } + octave_value reshape (const dim_vector& new_dims) const { return NDArray (matrix_value().reshape (new_dims)); }
--- a/src/ov-re-mat.h +++ b/src/ov-re-mat.h @@ -84,6 +84,8 @@ idx_vector index_vector (void) const { return idx_vector (matrix); } + size_t byte_size (void) const { return numel () * sizeof (double); } + bool is_real_matrix (void) const { return true; } bool is_real_type (void) const { return true; }
--- a/src/ov-streamoff.h +++ b/src/ov-streamoff.h @@ -63,6 +63,8 @@ octave_value *clone (void) const { return new octave_streamoff (*this); } octave_value *empty_clone (void) const { return new octave_streamoff (); } + size_t byte_size (void) const { return numel () * sizeof (std::streamoff); } + bool is_defined (void) const { return true; } bool is_streamoff (void) const { return true; }
--- a/src/ov-struct.cc +++ b/src/ov-struct.cc @@ -353,6 +353,25 @@ return retval; } +size_t +octave_struct::byte_size (void) const +{ + // Neglect the size of the fieldnames. + + size_t retval = 0; + + for (Octave_map::const_iterator p = map.begin (); p != map.end (); p++) + { + std::string key = map.key (p); + + octave_value val = octave_value (map.contents (p)); + + retval += val.byte_size (); + } + + return retval; +} + void octave_struct::print (std::ostream& os, bool) const {
--- a/src/ov-struct.h +++ b/src/ov-struct.h @@ -88,6 +88,8 @@ dim_vector dims (void) const { return map.dims (); } + size_t byte_size (void) const; + octave_value reshape (const dim_vector& new_dims) const { return map.reshape (new_dims); }
--- a/src/ov.cc +++ b/src/ov.cc @@ -1916,6 +1916,22 @@ octave_streamoff::register_type (); } +DEFUN (sizeof, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} sizeof (@var{val})\n\ +Return the size of @var{val} in bytes\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () == 1) + retval = args(0).byte_size (); + else + print_usage ("sizeof"); + + return retval; +} + static int warn_fortran_indexing (void) {
--- a/src/ov.h +++ b/src/ov.h @@ -338,6 +338,9 @@ int numel (void) const; + virtual size_t byte_size (void) const + { return rep->byte_size (); } + virtual octave_value reshape (const dim_vector& dv) const { return rep->reshape (dv); }
--- a/src/pr-output.cc +++ b/src/pr-output.cc @@ -1874,6 +1874,15 @@ double val = base + i * increment; + if (i == num_elem - 1) + { + // See the comments in Range::matrix_value. + + if ((increment > 0 && val > limit) + || (increment < 0 && val < limit)) + val = limit; + } + os << " "; pr_float (os, val, fw, scale);
--- a/src/sighandlers.cc +++ b/src/sighandlers.cc @@ -115,7 +115,7 @@ std::cerr << "panic: " << sig_name << " -- stopping myself...\n"; if (save_vars) - save_user_variables (); + dump_octave_core (); if (sig_number < 0) exit (1); @@ -259,7 +259,7 @@ case SIGHUP: { if (Vsighup_dumps_octave_core) - save_user_variables (); + dump_octave_core (); } break; #endif @@ -268,7 +268,7 @@ case SIGTERM: { if (Vsigterm_dumps_octave_core) - save_user_variables (); + dump_octave_core (); } break; #endif @@ -336,43 +336,11 @@ { octave_interrupt_state++; - if (interactive) - { - if (octave_interrupt_state > 3) - { - // XXX FIXME XXX -- might want to attempt to flush - // any pending input first... - - std::cerr << "abort [y/N]? "; - - int c = octave_kbhit (); - - std::cerr << static_cast<char> (c) << std::endl; - - if (c == 'y' || c == 'Y') - { - std::cerr << "save top-level workspace [y/N]? "; - - c = octave_kbhit (); + if (interactive && octave_interrupt_state == 2) + std::cerr << "Press Control-C again to abort." << std::endl; - std::cerr << static_cast<char> (c) << std::endl; - - my_friendly_exit (sys_siglist[sig], sig, - (c == 'y' || c == 'Y')); - } - else - { - // We will still eventually interrupt and jump to - // the top level even if no additional interrupts - // happen, but we will have to wait until it is - // safe to do so. It will take 3 more - // consecutive interrupts before we offer to - // abort again. - - octave_interrupt_state = 1; - } - } - } + if (octave_interrupt_state >= 3) + my_friendly_exit (sys_siglist[sig], sig, true); } }