From octave-maintainers-request at bevo dot che dot wisc dot edu Sun Nov 23 15:12:29 2003 Subject: Patch for asci load/save [ Was: Re: restructuring load-save ] From: David Bateman To: "John W. Eaton" Cc: octave-maintainers mailing list Date: Sun, 23 Nov 2003 23:12:07 +0100 --5vNYLRcllDrimb99 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Ok, as it appears that the CVS is working now, I've built the changes I made for the ascii load/save functions. Attached you'll find a patch against the current CVS... In doing this conversion I made some small changes to the format with a limited compatiability issue. Firstly, for global cell arrays only the toplevel of the array is marked as global and not all of the elements. As the cell names aren't used, this should have no affect on compatiability. The other change is that all types are now save individually. This means * Ranges aren't converted into matrices in certain cases, but always stored as ranges * "bool matrix" types aren't converted to matrices to be saved. This has a backward compatiability issue, as saved "bool" and "bool matrices" can't be loaded on old versions. Are there other variables in the same situation? I propose to ignore this situation, since the only real way to treat this is with an external conversion program in any case. * The "string" type is now saved a "string" and not "string array". The old "string" type has been eliminated. As the existing code can't save "string"'s in any case it seems that this is here only for backward compatibilities with even older versions of octave. Should special code to handle "string array" be included? Should backward compatibility with the old "string" saved variables be kept? I haven't done anything to treat the saveing/loading of N-D arrays. As the previous code didn't either I don't see this as an issue.... In any case, not knowing much about the N-D arrays, I'm probably not the best to add this functionality. In the small tests I've done the code appears to work perfectly, and its a big step forward for me as I can now save variables with user defined types.. So I hope this can make it into a future release. The next step is to attack the octave binary format, however 1) it appears that there is still some discussion on what to do here and 2) I'm not around for the next couple of days and can't do anything in any case... So I won't touch this yet. For the binary format, I think it is probably better to use the HDF format as the octave format, supplying an external script for the old octave binary formats. This reduction in the number of supported formats is to my liking, but at this point I don't know much about the HDF format or how simple we could make the load_hdf and save_hdf function (similar to load_ascii and save_ascii functions in the attached patch). I'll do the changes in this way eventually if 1) someone else doesn't get there first, 2) I can figure out the HDF format, 3) there are no objections, and 4) there is a chance that such a patch might be accepted D. According to John W. Eaton (on 11/23/03): > On 22-Nov-2003, David Bateman wrote: > > | According to John W. Eaton (on 11/22/03): > | > > | > except that now every > | > class that uses those macros must provide a default constructor that > | > takes no args. > | > | Yeah, I found that out :-) > > I tried to fix this earlier this morning but didn't get it right. > When I have it working, I will check something in. Until then, CVS > Octave is broken. Sorry. > > jwe -- David Bateman David dot Bateman at motorola dot com Motorola CRM +33 1 69 35 48 04 (Ph) Parc Les Algorithmes, Commune de St Aubin +33 1 69 35 77 01 (Fax) 91193 Gif-Sur-Yvette FRANCE The information contained in this communication has been classified as: [x] General Business Information [ ] Motorola Internal Use Only [ ] Motorola Confidential Proprietary --5vNYLRcllDrimb99 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=patch Index: src/ls-oct-ascii.cc =================================================================== RCS file: /cvs/octave/src/ls-oct-ascii.cc,v retrieving revision 1.1 diff -c -r1.1 ls-oct-ascii.cc *** src/ls-oct-ascii.cc 2003/11/19 21:22:39 1.1 --- src/ls-oct-ascii.cc 2003/11/23 20:41:49 *************** *** 26,32 **** #include #endif - #include #include #include --- 26,31 ---- *************** *** 71,97 **** // The number of decimal digits to use when writing ascii data. static int Vsave_precision; - #define CELL_ELT_TAG "" - - // Used when converting Inf to something that gnuplot can read. - - #ifndef OCT_RBV - #define OCT_RBV DBL_MAX / 100.0 - #endif - // Functions for reading ascii data. - static void - ascii_save_type (std::ostream& os, const char *type, bool mark_as_global) - { - if (mark_as_global) - os << "# type: global "; - else - os << "# type: "; - - os << type << "\n"; - } - static Matrix strip_infnan (const Matrix& m) { --- 70,77 ---- *************** *** 123,191 **** return retval; } - static ComplexMatrix - strip_infnan (const ComplexMatrix& m) - { - int nr = m.rows (); - int nc = m.columns (); - - ComplexMatrix retval (nr, nc); - - int k = 0; - for (int i = 0; i < nr; i++) - { - for (int j = 0; j < nc; j++) - { - Complex c = m (i, j); - if (xisnan (c)) - goto next_row; - else - { - double re = real (c); - double im = imag (c); - - re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re; - im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im; - - retval (k, j) = Complex (re, im); - } - } - k++; - - next_row: - continue; - } - - if (k > 0) - retval.resize (k, nc); - - return retval; - } - - // Skip white space and comments on stream IS. - - static void - skip_comments (std::istream& is) - { - char c = '\0'; - while (is.get (c)) - { - if (c == ' ' || c == '\t' || c == '\n') - ; // Skip whitespace on way to beginning of next line. - else - break; - } - - for (;;) - { - if (is && (c == '%' || c == '#')) - while (is.get (c) && c != '\n') - ; // Skip to beginning of next line, ignoring everything. - else - break; - } - } - // Extract a KEYWORD and its value from stream IS, returning the // associated value in a new string. // --- 103,108 ---- *************** *** 267,273 **** // // [%#][ \t]*keyword[ \t]*int-value.*\n ! static bool extract_keyword (std::istream& is, const char *keyword, int& value) { bool status = false; --- 184,190 ---- // // [%#][ \t]*keyword[ \t]*int-value.*\n ! bool extract_keyword (std::istream& is, const char *keyword, int& value) { bool status = false; *************** *** 441,637 **** } else typ = tag; - - if (SUBSTRING_COMPARE_EQ (typ, 0, 6, "scalar")) - { - double tmp = octave_read_double (is); - if (is) - tc = tmp; - else - error ("load: failed to load scalar constant"); - } - else if (SUBSTRING_COMPARE_EQ (typ, 0, 6, "matrix")) - { - int nr = 0; - int nc = 0; - - if (extract_keyword (is, "rows", nr) && nr >= 0 - && extract_keyword (is, "columns", nc) && nc >= 0) - { - if (nr > 0 && nc > 0) - { - Matrix tmp (nr, nc); - is >> tmp; - if (is) - tc = tmp; - else - error ("load: failed to load matrix constant"); - } - else if (nr == 0 || nc == 0) - tc = Matrix (nr, nc); - else - panic_impossible (); - } - else - error ("load: failed to extract number of rows and columns"); - } - else if (SUBSTRING_COMPARE_EQ (typ, 0, 4, "cell")) - { - int nr = 0; - int nc = 0; - - if (extract_keyword (is, "rows", nr) && nr >= 0 - && extract_keyword (is, "columns", nc) && nc >= 0) - { - if (nr > 0 && nc > 0) - { - Cell tmp (nr, nc); - - for (int j = 0; j < nc; j++) - { - for (int i = 0; i < nr; i++) - { - octave_value t2; - - // recurse to read cell elements - std::string nm - = read_ascii_data (is, filename, global, t2, count); - - if (nm == CELL_ELT_TAG) - { - if (is) - tmp.elem (i, j) = t2; - } - else - { - error ("load: cell array element had unexpected name"); - goto cell_read_error; - } - } - } - - cell_read_error: - - if (is) - tc = tmp; - else - error ("load: failed to load cell element"); - } - else if (nr == 0 || nc == 0) - tc = Cell (nr, nc); - else - panic_impossible (); - } - else - error ("load: failed to extract number of rows and columns for cell array"); - } - else if (SUBSTRING_COMPARE_EQ (typ, 0, 14, "complex scalar")) - { - Complex tmp = octave_read_complex (is); - if (is) - tc = tmp; - else - error ("load: failed to load complex scalar constant"); - } - else if (SUBSTRING_COMPARE_EQ (typ, 0, 14, "complex matrix")) - { - int nr = 0; - int nc = 0; - - if (extract_keyword (is, "rows", nr) && nr > 0 - && extract_keyword (is, "columns", nc) && nc > 0) - { - ComplexMatrix tmp (nr, nc); - is >> tmp; - if (is) - tc = tmp; - else - error ("load: failed to load complex matrix constant"); - } - else - error ("load: failed to extract number of rows and columns"); - } - else if (SUBSTRING_COMPARE_EQ (typ, 0, 12, "string array")) - { - int elements; - if (extract_keyword (is, "elements", elements) && elements >= 0) - { - // XXX FIXME XXX -- need to be able to get max length - // before doing anything. - - charMatrix chm (elements, 0); - int max_len = 0; - for (int i = 0; i < elements; i++) - { - int len; - if (extract_keyword (is, "length", len) && len >= 0) - { - OCTAVE_LOCAL_BUFFER (char, tmp, len+1); - - if (len > 0 && ! is.read (X_CAST (char *, tmp), len)) - { - error ("load: failed to load string constant"); - break; - } - else - { - tmp [len] = '\0'; - if (len > max_len) - { - max_len = len; - chm.resize (elements, max_len, 0); - } - chm.insert (tmp, i, 0); - } - } - else - error ("load: failed to extract string length for element %d", i+1); - } - - if (! error_state) - tc = octave_value (chm, true); - } - else - error ("load: failed to extract number of string elements"); - } - else if (SUBSTRING_COMPARE_EQ (typ, 0, 6, "string")) - { - int len; - if (extract_keyword (is, "length", len) && len >= 0) - { - OCTAVE_LOCAL_BUFFER (char, tmp, len+1); - - if (len > 0 && ! is.read (X_CAST (char *, tmp), len)) - { - error ("load: failed to load string constant"); - } - else - { - tmp [len] = '\0'; ! if (is) ! tc = tmp; ! else ! error ("load: failed to load string constant"); ! } ! } ! else ! error ("load: failed to extract string length"); ! } ! else if (SUBSTRING_COMPARE_EQ (typ, 0, 5, "range")) ! { ! // # base, limit, range comment added by save (). ! skip_comments (is); ! Range tmp; ! is >> tmp; ! if (is) ! tc = tmp; ! else ! error ("load: failed to load range constant"); ! } ! else ! error ("load: unknown constant type `%s'", tag.c_str ()); } else error ("load: failed to extract keyword specifying value type"); --- 358,367 ---- } else typ = tag; ! tc = octave_value_typeinfo::lookup_type (typ); ! tc.load_ascii (is); } else error ("load: failed to extract keyword specifying value type"); *************** *** 678,864 **** os.precision (precision); octave_value val = val_arg; - - if (val.is_range ()) - { - Range r = val.range_value (); - double base = r.base (); - double limit = r.limit (); - double inc = r.inc (); - if (! (NINT (base) == base - && NINT (limit) == limit - && NINT (inc) == inc)) - val = val.matrix_value (); - } - - if (val.is_string ()) - { - ascii_save_type (os, "string array", mark_as_global); - charMatrix chm = val.char_matrix_value (); - int elements = chm.rows (); - os << "# elements: " << elements << "\n"; - for (int i = 0; i < elements; i++) - { - unsigned len = chm.cols (); - os << "# length: " << len << "\n"; - std::string tstr = chm.row_as_string (i, false, true); - const char *tmp = tstr.data (); - if (tstr.length () > len) - panic_impossible (); - os.write (X_CAST (char *, tmp), len); - os << "\n"; - } - } - else if (val.is_range ()) - { - ascii_save_type (os, "range", mark_as_global); - Range tmp = val.range_value (); - os << "# base, limit, increment\n"; - octave_write_double (os, tmp.base ()); - os << " "; - octave_write_double (os, tmp.limit ()); - os << " "; - octave_write_double (os, tmp.inc ()); - os << "\n"; - } - else if (val.is_real_scalar ()) - { - ascii_save_type (os, "scalar", mark_as_global); - - double d = val.double_value (); - - if (strip_nan_and_inf) - { - if (xisnan (d)) - { - error ("only value to plot is NaN"); - success = false; - } - else - { - d = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d; - octave_write_double (os, d); - os << "\n"; - } - } - else - { - if (! infnan_warned && (xisnan (d) || xisinf (d))) - { - warning ("save: Inf or NaN values may not be reloadable"); - infnan_warned = true; - } - - octave_write_double (os, d); - os << "\n"; - } - } - else if (val.is_real_matrix ()) - { - ascii_save_type (os, "matrix", mark_as_global); - - os << "# rows: " << val.rows () << "\n" - << "# columns: " << val.columns () << "\n"; - - Matrix tmp = val.matrix_value (); ! if (strip_nan_and_inf) ! tmp = strip_infnan (tmp); ! else if (! infnan_warned && tmp.any_element_is_inf_or_nan ()) ! { ! warning ("save: Inf or NaN values may not be reloadable"); ! infnan_warned = true; ! } ! ! os << tmp; ! } ! else if (val.is_cell ()) ! { ! ascii_save_type (os, "cell", mark_as_global); ! ! os << "# rows: " << val.rows () << "\n" ! << "# columns: " << val.columns () << "\n"; ! ! Cell tmp = val.cell_value (); ! ! for (int j = 0; j < tmp.cols (); j++) ! { ! for (int i = 0; i < tmp.rows (); i++) ! { ! octave_value o_val = tmp.elem (i, j); ! ! // Recurse to print sub-value. ! bool b = save_ascii_data (os, o_val, CELL_ELT_TAG, ! infnan_warned, strip_nan_and_inf, ! mark_as_global, 0); ! ! if (! b) ! return os; ! } ! ! os << "\n"; ! } ! } ! else if (val.is_complex_scalar ()) ! { ! ascii_save_type (os, "complex scalar", mark_as_global); ! ! Complex c = val.complex_value (); ! ! if (strip_nan_and_inf) ! { ! if (xisnan (c)) ! { ! error ("only value to plot is NaN"); ! success = false; ! } ! else ! { ! double re = real (c); ! double im = imag (c); ! ! re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re; ! im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im; ! ! c = Complex (re, im); ! ! octave_write_complex (os, c); ! os << "\n"; ! } ! } ! else ! { ! if (! infnan_warned && (xisnan (c) || xisinf (c))) ! { ! warning ("save: Inf or NaN values may not be reloadable"); ! infnan_warned = true; ! } ! ! octave_write_complex (os, c); ! os << "\n"; ! } ! } ! else if (val.is_complex_matrix ()) ! { ! ascii_save_type (os, "complex matrix", mark_as_global); ! ! os << "# rows: " << val.rows () << "\n" ! << "# columns: " << val.columns () << "\n"; ! ! ComplexMatrix tmp = val.complex_matrix_value (); ! ! if (strip_nan_and_inf) ! tmp = strip_infnan (tmp); ! else if (! infnan_warned && tmp.any_element_is_inf_or_nan ()) ! { ! warning ("save: Inf or NaN values may not be reloadable"); ! infnan_warned = true; ! } ! ! os << tmp; ! } else ! gripe_wrong_type_arg ("save", val, false); os.precision (old_precision); --- 408,420 ---- os.precision (precision); octave_value val = val_arg; ! if (mark_as_global) ! os << "# type: global " << val.type_name () << "\n"; else ! os << "# type: " << val.type_name() << "\n"; ! ! success = val . save_ascii(os, infnan_warned, strip_nan_and_inf); os.precision (old_precision); Index: src/ls-oct-ascii.h =================================================================== RCS file: /cvs/octave/src/ls-oct-ascii.h,v retrieving revision 1.1 diff -c -r1.1 ls-oct-ascii.h *** src/ls-oct-ascii.h 2003/11/19 21:22:39 1.1 --- src/ls-oct-ascii.h 2003/11/23 20:41:49 *************** *** 23,30 **** --- 23,44 ---- #if !defined (octave_ls_oct_ascii_h) #define octave_ls_oct_ascii_h 1 + #include + + // Flag for cell elements + #define CELL_ELT_TAG "" + + // Used when converting Inf to something that gnuplot can read. + + #ifndef OCT_RBV + #define OCT_RBV DBL_MAX / 100.0 + #endif + extern std::string extract_keyword (std::istream& is, const char *keyword); + + extern bool + extract_keyword (std::istream& is, const char *keyword, int& value); extern std::string read_ascii_data (std::istream& is, const std::string& filename, bool& global, Index: src/ov-base.cc =================================================================== RCS file: /cvs/octave/src/ov-base.cc,v retrieving revision 1.54 diff -c -r1.54 ov-base.cc *** src/ov-base.cc 2003/11/23 08:07:53 1.54 --- src/ov-base.cc 2003/11/23 20:41:49 *************** *** 521,526 **** --- 521,541 ---- return retval; } + bool octave_base_value::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + gripe_wrong_type_arg ("octave_base_value::save_ascii()", type_name()); + + return false; + } + + bool octave_base_value::load_ascii (std::istream& is) + { + gripe_wrong_type_arg ("octave_base_value::load_ascii()", type_name()); + + return false; + } + CONVDECLX (matrix_conv) { return new octave_matrix (); Index: src/ov-base.h =================================================================== RCS file: /cvs/octave/src/ov-base.h,v retrieving revision 1.62 diff -c -r1.62 ov-base.h *** src/ov-base.h 2003/11/23 08:07:53 1.62 --- src/ov-base.h 2003/11/23 20:41:49 *************** *** 250,255 **** --- 250,260 ---- void print_info (std::ostream& os, const std::string& prefix) const; + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA; Index: src/ov-bool-mat.cc =================================================================== RCS file: /cvs/octave/src/ov-bool-mat.cc,v retrieving revision 1.20 diff -c -r1.20 ov-bool-mat.cc *** src/ov-bool-mat.cc 2003/11/22 12:25:44 1.20 --- src/ov-bool-mat.cc 2003/11/23 20:41:49 *************** *** 44,49 **** --- 44,51 ---- #include "ov-re-mat.h" #include "pr-output.h" + #include "ls-oct-ascii.h" + template class octave_base_matrix; DEFINE_OCTAVE_ALLOCATOR (octave_bool_matrix); *************** *** 146,151 **** --- 148,209 ---- { octave_print_internal (os, matrix, pr_as_read_syntax, current_print_indent_level ()); + } + + + bool + octave_bool_matrix::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + os << "# rows: " << rows () << "\n" + << "# columns: " << columns () << "\n"; + + Matrix tmp = matrix_value (); + + os << tmp; + + return true; + } + + bool + octave_bool_matrix::load_ascii (std::istream& is) + { + int nr = 0; + int nc = 0; + bool success = true; + + if (extract_keyword (is, "rows", nr) && nr >= 0 + && extract_keyword (is, "columns", nc) && nc >= 0) + { + if (nr > 0 && nc > 0) + { + Matrix tmp (nr, nc); + is >> tmp; + if (!is) + { + error ("load: failed to load matrix constant"); + success = false; + } + + boolMatrix btmp (nr,nc); + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + btmp.elem (i,j) = (tmp.elem (i, j) != 0.); + + matrix = btmp; + } + else if (nr == 0 || nc == 0) + matrix = boolMatrix (nr, nc); + else + panic_impossible (); + } + else + { + error ("load: failed to extract number of rows and columns"); + success = false; + } + + return success; } /* Index: src/ov-bool-mat.h =================================================================== RCS file: /cvs/octave/src/ov-bool-mat.h,v retrieving revision 1.30 diff -c -r1.30 ov-bool-mat.h *** src/ov-bool-mat.h 2003/11/22 12:25:44 1.30 --- src/ov-bool-mat.h 2003/11/23 20:41:49 *************** *** 117,122 **** --- 117,127 ---- void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + protected: DECLARE_OCTAVE_ALLOCATOR Index: src/ov-bool.cc =================================================================== RCS file: /cvs/octave/src/ov-bool.cc,v retrieving revision 1.16 diff -c -r1.16 ov-bool.cc *** src/ov-bool.cc 2003/11/14 19:49:56 1.16 --- src/ov-bool.cc 2003/11/23 20:41:49 *************** *** 43,48 **** --- 43,50 ---- #include "ov-scalar.h" #include "pr-output.h" + #include "ls-oct-ascii.h" + template class octave_base_scalar; DEFINE_OCTAVE_ALLOCATOR (octave_bool); *************** *** 110,115 **** --- 112,143 ---- s[1] = '\0'; return octave_value (s); + } + + bool + octave_bool::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + double d = double_value (); + + octave_write_double (os, d); + os << "\n"; + + return true; + } + + bool + octave_bool::load_ascii (std::istream& is) + { + scalar = (octave_read_double (is) != 0.); + + if (!is) + { + error ("load: failed to load scalar constant"); + return false; + } + + return true; } /* Index: src/ov-bool.h =================================================================== RCS file: /cvs/octave/src/ov-bool.h,v retrieving revision 1.22 diff -c -r1.22 ov-bool.h *** src/ov-bool.h 2003/11/18 18:18:16 1.22 --- src/ov-bool.h 2003/11/23 20:41:50 *************** *** 110,115 **** --- 110,120 ---- octave_value convert_to_str_internal (bool pad, bool force) const; + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OCTAVE_ALLOCATOR Index: src/ov-cell.cc =================================================================== RCS file: /cvs/octave/src/ov-cell.cc,v retrieving revision 1.30 diff -c -r1.30 ov-cell.cc *** src/ov-cell.cc 2003/11/14 19:49:56 1.30 --- src/ov-cell.cc 2003/11/23 20:41:50 *************** *** 45,50 **** --- 45,52 ---- #include "ov-re-mat.h" #include "ov-scalar.h" + #include "ls-oct-ascii.h" + template class octave_base_matrix; DEFINE_OCTAVE_ALLOCATOR (octave_cell); *************** *** 393,398 **** --- 395,491 ---- os << "{" << dv.str () << " Cell Array}"; newline (os); } + } + + #define CELL_ELT_TAG "" + + bool + octave_cell::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + os << "# rows: " << rows () << "\n" + << "# columns: " << columns () << "\n"; + + Cell tmp = cell_value (); + + for (int j = 0; j < tmp.cols (); j++) + { + for (int i = 0; i < tmp.rows (); i++) + { + octave_value o_val = tmp.elem (i, j); + + // Recurse to print sub-value. + bool b = save_ascii_data (os, o_val, CELL_ELT_TAG, + infnan_warned, strip_nan_and_inf, 0, 0); + + if (! b) + return os; + } + + os << "\n"; + } + return true; + } + + bool + octave_cell::load_ascii (std::istream& is) + { + int nr = 0; + int nc = 0; + bool success = true; + + if (extract_keyword (is, "rows", nr) && nr >= 0 + && extract_keyword (is, "columns", nc) && nc >= 0) + { + if (nr > 0 && nc > 0) + { + Cell tmp (nr, nc); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + { + octave_value t2; + bool dummy; + + // recurse to read cell elements + std::string nm + = read_ascii_data (is, 0, dummy, t2, count); + + if (nm == CELL_ELT_TAG) + { + if (is) + tmp.elem (i, j) = t2; + } + else + { + error ("load: cell array element had unexpected name"); + success = false; + goto cell_read_error; + } + } + } + + cell_read_error: + + if (is) + matrix = tmp; + else + { + error ("load: failed to load cell element"); + success = false; + } + } + else if (nr == 0 || nc == 0) + matrix = Cell (nr, nc); + else + panic_impossible (); + } + else { + error ("load: failed to extract number of rows and columns for cell array"); + success = false; + } + return success; } DEFUN (iscell, args, , Index: src/ov-cell.h =================================================================== RCS file: /cvs/octave/src/ov-cell.h,v retrieving revision 1.21 diff -c -r1.21 ov-cell.h *** src/ov-cell.h 2003/11/23 08:07:53 1.21 --- src/ov-cell.h 2003/11/23 20:41:50 *************** *** 111,116 **** --- 111,122 ---- void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OCTAVE_ALLOCATOR Index: src/ov-complex.cc =================================================================== RCS file: /cvs/octave/src/ov-complex.cc,v retrieving revision 1.22 diff -c -r1.22 ov-complex.cc *** src/ov-complex.cc 2003/11/14 19:49:56 1.22 --- src/ov-complex.cc 2003/11/23 20:41:50 *************** *** 43,48 **** --- 43,50 ---- #include "gripes.h" #include "pr-output.h" + #include "ls-oct-ascii.h" + template class octave_base_scalar; DEFINE_OCTAVE_ALLOCATOR (octave_complex); *************** *** 144,149 **** --- 146,207 ---- octave_complex::complex_array_value (bool force_conversion) const { return ComplexNDArray (dim_vector (1, 1), scalar); + } + + bool + octave_complex::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + Complex c = complex_value (); + + if (strip_nan_and_inf) + { + if (xisnan (c)) + { + error ("only value to plot is NaN"); + return false; + } + else + { + double re = real (c); + double im = imag (c); + + re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re; + im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im; + + c = Complex (re, im); + + octave_write_complex (os, c); + os << "\n"; + } + } + else + { + if (! infnan_warned && (xisnan (c) || xisinf (c))) + { + warning ("save: Inf or NaN values may not be reloadable"); + infnan_warned = true; + } + + octave_write_complex (os, c); + os << "\n"; + } + + return true; + } + + bool + octave_complex::load_ascii (std::istream& is) + { + scalar = octave_read_complex (is); + + if (!is) + { + error ("load: failed to load complex scalar constant"); + return false; + } + + return true; } /* Index: src/ov-complex.h =================================================================== RCS file: /cvs/octave/src/ov-complex.h,v retrieving revision 1.22 diff -c -r1.22 ov-complex.h *** src/ov-complex.h 2003/11/14 19:49:56 1.22 --- src/ov-complex.h 2003/11/23 20:41:50 *************** *** 98,103 **** --- 98,108 ---- void decrement (void) { scalar -= 1.0; } + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OCTAVE_ALLOCATOR Index: src/ov-cx-mat.cc =================================================================== RCS file: /cvs/octave/src/ov-cx-mat.cc,v retrieving revision 1.31 diff -c -r1.31 ov-cx-mat.cc *** src/ov-cx-mat.cc 2003/11/22 12:25:44 1.31 --- src/ov-cx-mat.cc 2003/11/23 20:41:50 *************** *** 45,50 **** --- 45,52 ---- #include "ov-scalar.h" #include "pr-output.h" + #include "ls-oct-ascii.h" + template class octave_base_matrix; DEFINE_OCTAVE_ALLOCATOR (octave_complex_matrix); *************** *** 170,175 **** --- 172,266 ---- octave_complex_matrix::complex_matrix_value (bool) const { return matrix.matrix_value (); + } + + static ComplexMatrix + strip_infnan (const ComplexMatrix& m) + { + int nr = m.rows (); + int nc = m.columns (); + + ComplexMatrix retval (nr, nc); + + int k = 0; + for (int i = 0; i < nr; i++) + { + for (int j = 0; j < nc; j++) + { + Complex c = m (i, j); + if (xisnan (c)) + goto next_row; + else + { + double re = real (c); + double im = imag (c); + + re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re; + im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im; + + retval (k, j) = Complex (re, im); + } + } + k++; + + next_row: + continue; + } + + if (k > 0) + retval.resize (k, nc); + + return retval; + } + + bool + octave_complex_matrix::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + os << "# rows: " << rows () << "\n" + << "# columns: " << columns () << "\n"; + + ComplexMatrix tmp = complex_matrix_value (); + + if (strip_nan_and_inf) + tmp = strip_infnan (tmp); + else if (! infnan_warned && tmp.any_element_is_inf_or_nan ()) + { + warning ("save: Inf or NaN values may not be reloadable"); + infnan_warned = true; + } + + os << tmp; + + return true; + } + + bool + octave_complex_matrix::load_ascii (std::istream& is) + { + int nr = 0; + int nc = 0; + bool success = true; + + if (extract_keyword (is, "rows", nr) && nr > 0 + && extract_keyword (is, "columns", nc) && nc > 0) + { + ComplexMatrix tmp (nr, nc); + is >> tmp; + if (! is) + { + error ("load: failed to load complex matrix constant"); + success = false; + } + matrix = tmp; + } + else + { + error ("load: failed to extract number of rows and columns"); + success = false; + } + + return success; } void Index: src/ov-cx-mat.h =================================================================== RCS file: /cvs/octave/src/ov-cx-mat.h,v retrieving revision 1.29 diff -c -r1.29 ov-cx-mat.h *** src/ov-cx-mat.h 2003/11/22 12:25:44 1.29 --- src/ov-cx-mat.h 2003/11/23 20:41:50 *************** *** 108,113 **** --- 108,118 ---- void decrement (void) { matrix -= Complex (1.0); } + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; private: Index: src/ov-range.cc =================================================================== RCS file: /cvs/octave/src/ov-range.cc,v retrieving revision 1.34 diff -c -r1.34 ov-range.cc *** src/ov-range.cc 2003/11/14 19:49:56 1.34 --- src/ov-range.cc 2003/11/23 20:41:51 *************** *** 250,255 **** --- 250,316 ---- return retval; } + // Skip white space and comments on stream IS. + + static void + skip_comments (std::istream& is) + { + char c = '\0'; + while (is.get (c)) + { + if (c == ' ' || c == '\t' || c == '\n') + ; // Skip whitespace on way to beginning of next line. + else + break; + } + + for (;;) + { + if (is && (c == '%' || c == '#')) + while (is.get (c) && c != '\n') + ; // Skip to beginning of next line, ignoring everything. + else + break; + } + } + + bool + octave_range::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + Range r = range_value (); + double base = r.base (); + double limit = r.limit (); + double inc = r.inc (); + + os << "# base, limit, increment\n"; + octave_write_double (os, base); + os << " "; + octave_write_double (os, limit); + os << " "; + octave_write_double (os, inc); + os << "\n"; + + return true; + } + + bool + octave_range::load_ascii (std::istream& is) + { + // # base, limit, range comment added by save (). + skip_comments (is); + + is >> range; + + if (!is) + { + error ("load: failed to load range constant"); + return false; + } + + return true; + } + /* ;;; Local Variables: *** ;;; mode: C++ *** Index: src/ov-range.h =================================================================== RCS file: /cvs/octave/src/ov-range.h,v retrieving revision 1.35 diff -c -r1.35 ov-range.h *** src/ov-range.h 2003/11/17 03:48:04 1.35 --- src/ov-range.h 2003/11/23 20:41:51 *************** *** 166,171 **** --- 166,176 ---- bool print_name_tag (std::ostream& os, const std::string& name) const; + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: Range range; Index: src/ov-re-mat.cc =================================================================== RCS file: /cvs/octave/src/ov-re-mat.cc,v retrieving revision 1.38 diff -c -r1.38 ov-re-mat.cc *** src/ov-re-mat.cc 2003/11/23 08:07:53 1.38 --- src/ov-re-mat.cc 2003/11/23 20:41:51 *************** *** 49,54 **** --- 49,56 ---- #include "pr-output.h" #include "variables.h" + #include "ls-oct-ascii.h" + #if ! defined (UCHAR_MAX) #define UCHAR_MAX 255 #endif *************** *** 224,229 **** --- 226,319 ---- } return retval; + } + + static Matrix + strip_infnan (const Matrix& m) + { + int nr = m.rows (); + int nc = m.columns (); + + Matrix retval (nr, nc); + + int k = 0; + for (int i = 0; i < nr; i++) + { + for (int j = 0; j < nc; j++) + { + double d = m (i, j); + if (xisnan (d)) + goto next_row; + else + retval (k, j) = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d; + } + k++; + + next_row: + continue; + } + + if (k > 0) + retval.resize (k, nc); + + return retval; + } + + bool + octave_matrix::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + os << "# rows: " << rows () << "\n" + << "# columns: " << columns () << "\n"; + + Matrix tmp = matrix_value (); + + if (strip_nan_and_inf) + tmp = strip_infnan (tmp); + else if (! infnan_warned && tmp.any_element_is_inf_or_nan ()) + { + warning ("save: Inf or NaN values may not be reloadable"); + infnan_warned = true; + } + + os << tmp; + + return true; + } + + bool + octave_matrix::load_ascii (std::istream& is) + { + int nr = 0; + int nc = 0; + bool success = true; + + if (extract_keyword (is, "rows", nr) && nr >= 0 + && extract_keyword (is, "columns", nc) && nc >= 0) + { + if (nr > 0 && nc > 0) + { + Matrix tmp (nr, nc); + is >> tmp; + if (!is) + { + error ("load: failed to load matrix constant"); + success = false; + } + matrix = tmp; + } + else if (nr == 0 || nc == 0) + matrix = Matrix (nr, nc); + else + panic_impossible (); + } + else + { + error ("load: failed to extract number of rows and columns"); + success = false; + } + + return success; } void Index: src/ov-re-mat.h =================================================================== RCS file: /cvs/octave/src/ov-re-mat.h,v retrieving revision 1.35 diff -c -r1.35 ov-re-mat.h *** src/ov-re-mat.h 2003/11/23 08:07:53 1.35 --- src/ov-re-mat.h 2003/11/23 20:41:51 *************** *** 114,119 **** --- 114,124 ---- void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OCTAVE_ALLOCATOR Index: src/ov-scalar.cc =================================================================== RCS file: /cvs/octave/src/ov-scalar.cc,v retrieving revision 1.23 diff -c -r1.23 ov-scalar.cc *** src/ov-scalar.cc 2003/11/23 08:07:53 1.23 --- src/ov-scalar.cc 2003/11/23 20:41:51 *************** *** 43,48 **** --- 43,50 ---- #include "xdiv.h" #include "xpow.h" + #include "ls-oct-ascii.h" + template class octave_base_scalar; DEFINE_OCTAVE_ALLOCATOR (octave_scalar); *************** *** 113,118 **** --- 115,168 ---- } return retval; + } + + bool + octave_scalar::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + double d = double_value (); + + if (strip_nan_and_inf) + { + if (xisnan (d)) + { + error ("only value to plot is NaN"); + return false; + } + else + { + d = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d; + octave_write_double (os, d); + os << "\n"; + } + } + else + { + if (! infnan_warned && (xisnan (d) || xisinf (d))) + { + warning ("save: Inf or NaN values may not be reloadable"); + infnan_warned = true; + } + + octave_write_double (os, d); + os << "\n"; + } + + return true; + } + + bool + octave_scalar::load_ascii (std::istream& is) + { + scalar = octave_read_double (is); + if (!is) + { + error ("load: failed to load scalar constant"); + return false; + } + + return true; } /* Index: src/ov-scalar.h =================================================================== RCS file: /cvs/octave/src/ov-scalar.h,v retrieving revision 1.29 diff -c -r1.29 ov-scalar.h *** src/ov-scalar.h 2003/11/23 08:07:53 1.29 --- src/ov-scalar.h 2003/11/23 20:41:51 *************** *** 108,113 **** --- 108,118 ---- void decrement (void) { --scalar; } + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OCTAVE_ALLOCATOR Index: src/ov-str-mat.cc =================================================================== RCS file: /cvs/octave/src/ov-str-mat.cc,v retrieving revision 1.35 diff -c -r1.35 ov-str-mat.cc *** src/ov-str-mat.cc 2003/11/22 12:25:44 1.35 --- src/ov-str-mat.cc 2003/11/23 20:41:51 *************** *** 41,46 **** --- 41,48 ---- #include "pr-output.h" #include "pt-mat.h" + #include "ls-oct-ascii.h" + DEFINE_OCTAVE_ALLOCATOR (octave_char_matrix_str); DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_char_matrix_str, "string", "char"); *************** *** 211,216 **** --- 213,298 ---- { octave_print_internal (os, matrix, pr_as_read_syntax, current_print_indent_level (), true); + } + + bool + octave_char_matrix_str::save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { + charMatrix chm = char_matrix_value (); + int elements = chm.rows (); + os << "# elements: " << elements << "\n"; + for (int i = 0; i < elements; i++) + { + unsigned len = chm.cols (); + os << "# length: " << len << "\n"; + std::string tstr = chm.row_as_string (i, false, true); + const char *tmp = tstr.data (); + if (tstr.length () > len) + panic_impossible (); + os.write (X_CAST (char *, tmp), len); + os << "\n"; + } + + return true; + } + + bool + octave_char_matrix_str::load_ascii (std::istream& is) + { + int elements; + bool success = true; + + if (extract_keyword (is, "elements", elements) && elements >= 0) + { + // XXX FIXME XXX -- need to be able to get max length + // before doing anything. + + charMatrix chm (elements, 0); + int max_len = 0; + for (int i = 0; i < elements; i++) + { + int len; + if (extract_keyword (is, "length", len) && len >= 0) + { + OCTAVE_LOCAL_BUFFER (char, tmp, len+1); + + if (len > 0 && ! is.read (X_CAST (char *, tmp), len)) + { + error ("load: failed to load string constant"); + success = false; + break; + } + else + { + tmp [len] = '\0'; + if (len > max_len) + { + max_len = len; + chm.resize (elements, max_len, 0); + } + chm.insert (tmp, i, 0); + } + } + else + { + error ("load: failed to extract string length for element %d", + i+1); + success = false; + } + } + + if (! error_state) + matrix = chm; + + } + else + { + error ("load: failed to extract number of string elements"); + success = false; + } + + return success; } /* Index: src/ov-str-mat.h =================================================================== RCS file: /cvs/octave/src/ov-str-mat.h,v retrieving revision 1.31 diff -c -r1.31 ov-str-mat.h *** src/ov-str-mat.h 2003/11/22 12:25:44 1.31 --- src/ov-str-mat.h 2003/11/23 20:41:51 *************** *** 116,121 **** --- 116,126 ---- void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf); + + bool load_ascii (std::istream& is); + private: DECLARE_OCTAVE_ALLOCATOR Index: src/ov.cc =================================================================== RCS file: /cvs/octave/src/ov.cc,v retrieving revision 1.99 diff -c -r1.99 ov.cc *** src/ov.cc 2003/11/23 08:07:53 1.99 --- src/ov.cc 2003/11/23 20:41:52 *************** *** 1521,1527 **** rep->print_info (os, prefix + " "); } - static void gripe_unary_op (const std::string& on, const std::string& tn) { --- 1521,1526 ---- Index: src/ov.h =================================================================== RCS file: /cvs/octave/src/ov.h,v retrieving revision 1.93 diff -c -r1.93 ov.h *** src/ov.h 2003/11/23 08:07:53 1.93 --- src/ov.h 2003/11/23 20:41:53 *************** *** 637,642 **** --- 637,650 ---- virtual void print_info (std::ostream& os, const std::string& prefix = std::string ()) const; + virtual bool save_ascii (std::ostream& os, bool& infnan_warned, + bool strip_nan_and_inf) + { return rep->save_ascii (os, infnan_warned, strip_nan_and_inf); } + + virtual bool load_ascii (std::istream& is) + { return rep->load_ascii (is); } + + protected: octave_value (const octave_xvalue&) : rep (0) { } --5vNYLRcllDrimb99--