00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <cfloat>
00028 #include <cstring>
00029 #include <cctype>
00030
00031 #include <fstream>
00032 #include <iomanip>
00033 #include <iostream>
00034 #include <string>
00035 #include <vector>
00036
00037 #include "byte-swap.h"
00038 #include "data-conv.h"
00039 #include "file-ops.h"
00040 #include "glob-match.h"
00041 #include "lo-mappers.h"
00042 #include "mach-info.h"
00043 #include "oct-env.h"
00044 #include "oct-time.h"
00045 #include "quit.h"
00046 #include "str-vec.h"
00047 #include "oct-locbuf.h"
00048
00049 #include "Cell.h"
00050 #include "defun.h"
00051 #include "error.h"
00052 #include "gripes.h"
00053 #include "load-save.h"
00054 #include "oct-obj.h"
00055 #include "oct-map.h"
00056 #include "ov-cell.h"
00057 #include "pager.h"
00058 #include "pt-exp.h"
00059 #include "sysdep.h"
00060 #include "unwind-prot.h"
00061 #include "utils.h"
00062 #include "variables.h"
00063 #include "version.h"
00064 #include "dMatrix.h"
00065 #include "dSparse.h"
00066
00067 #include "ls-mat4.h"
00068
00069
00070
00071
00072
00073
00074
00075 static void
00076 read_mat_binary_data (std::istream& is, double *data, int precision,
00077 int len, bool swap,
00078 oct_mach_info::float_format flt_fmt)
00079 {
00080 switch (precision)
00081 {
00082 case 0:
00083 read_doubles (is, data, LS_DOUBLE, len, swap, flt_fmt);
00084 break;
00085
00086 case 1:
00087 read_doubles (is, data, LS_FLOAT, len, swap, flt_fmt);
00088 break;
00089
00090 case 2:
00091 read_doubles (is, data, LS_INT, len, swap, flt_fmt);
00092 break;
00093
00094 case 3:
00095 read_doubles (is, data, LS_SHORT, len, swap, flt_fmt);
00096 break;
00097
00098 case 4:
00099 read_doubles (is, data, LS_U_SHORT, len, swap, flt_fmt);
00100 break;
00101
00102 case 5:
00103 read_doubles (is, data, LS_U_CHAR, len, swap, flt_fmt);
00104 break;
00105
00106 default:
00107 break;
00108 }
00109 }
00110
00111 int
00112 read_mat_file_header (std::istream& is, bool& swap, int32_t& mopt,
00113 int32_t& nr, int32_t& nc,
00114 int32_t& imag, int32_t& len,
00115 int quiet)
00116 {
00117 swap = false;
00118
00119
00120
00121
00122
00123 is.read (reinterpret_cast<char *> (&mopt), 4);
00124 if (! is)
00125 return 1;
00126
00127 if (! is.read (reinterpret_cast<char *> (&nr), 4))
00128 goto data_read_error;
00129
00130 if (! is.read (reinterpret_cast<char *> (&nc), 4))
00131 goto data_read_error;
00132
00133 if (! is.read (reinterpret_cast<char *> (&imag), 4))
00134 goto data_read_error;
00135
00136 if (! is.read (reinterpret_cast<char *> (&len), 4))
00137 goto data_read_error;
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 if (oct_mach_info::words_big_endian () && mopt == 0)
00149 swap = true;
00150
00151
00152
00153 if (mopt > 9999 || mopt < 0)
00154 swap = true;
00155
00156 if (swap)
00157 {
00158 swap_bytes<4> (&mopt);
00159 swap_bytes<4> (&nr);
00160 swap_bytes<4> (&nc);
00161 swap_bytes<4> (&imag);
00162 swap_bytes<4> (&len);
00163 }
00164
00165 if (mopt > 9999 || mopt < 0 || imag > 1 || imag < 0)
00166 {
00167 if (! quiet)
00168 error ("load: can't read binary file");
00169 return -1;
00170 }
00171
00172 return 0;
00173
00174 data_read_error:
00175 return -1;
00176 }
00177
00178
00179
00180
00181 oct_mach_info::float_format
00182 mopt_digit_to_float_format (int mach)
00183 {
00184 oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
00185
00186 switch (mach)
00187 {
00188 case 0:
00189 flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
00190 break;
00191
00192 case 1:
00193 flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
00194 break;
00195
00196 case 2:
00197 flt_fmt = oct_mach_info::flt_fmt_vax_d;
00198 break;
00199
00200 case 3:
00201 flt_fmt = oct_mach_info::flt_fmt_vax_g;
00202 break;
00203
00204 case 4:
00205 flt_fmt = oct_mach_info::flt_fmt_cray;
00206 break;
00207
00208 default:
00209 flt_fmt = oct_mach_info::flt_fmt_unknown;
00210 break;
00211 }
00212
00213 return flt_fmt;
00214 }
00215
00216 int
00217 float_format_to_mopt_digit (oct_mach_info::float_format flt_fmt)
00218 {
00219 int retval = -1;
00220
00221 switch (flt_fmt)
00222 {
00223 case oct_mach_info::flt_fmt_ieee_little_endian:
00224 retval = 0;
00225 break;
00226
00227 case oct_mach_info::flt_fmt_ieee_big_endian:
00228 retval = 1;
00229 break;
00230
00231 case oct_mach_info::flt_fmt_vax_d:
00232 retval = 2;
00233 break;
00234
00235 case oct_mach_info::flt_fmt_vax_g:
00236 retval = 3;
00237 break;
00238
00239 case oct_mach_info::flt_fmt_cray:
00240 retval = 4;
00241 break;
00242
00243 default:
00244 break;
00245 }
00246
00247 return retval;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 std::string
00261 read_mat_binary_data (std::istream& is, const std::string& filename,
00262 octave_value& tc)
00263 {
00264 std::string retval;
00265
00266
00267
00268
00269
00270 Matrix re;
00271 oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
00272 bool swap = false;
00273 int type = 0;
00274 int prec = 0;
00275 int order = 0;
00276 int mach = 0;
00277 int dlen = 0;
00278
00279 int32_t mopt, nr, nc, imag, len;
00280
00281 int err = read_mat_file_header (is, swap, mopt, nr, nc, imag, len);
00282 if (err)
00283 {
00284 if (err < 0)
00285 goto data_read_error;
00286 else
00287 return retval;
00288 }
00289
00290 type = mopt % 10;
00291 mopt /= 10;
00292 prec = mopt % 10;
00293 mopt /= 10;
00294 order = mopt % 10;
00295 mopt /= 10;
00296 mach = mopt % 10;
00297
00298 flt_fmt = mopt_digit_to_float_format (mach);
00299
00300 if (flt_fmt == oct_mach_info::flt_fmt_unknown)
00301 {
00302 error ("load: unrecognized binary format!");
00303 return retval;
00304 }
00305
00306 if (imag && type == 1)
00307 {
00308 error ("load: encountered complex matrix with string flag set!");
00309 return retval;
00310 }
00311
00312
00313
00314
00315
00316 {
00317 OCTAVE_LOCAL_BUFFER (char, name, len+1);
00318 name[len] = '\0';
00319 if (! is.read (name, len))
00320 goto data_read_error;
00321 retval = name;
00322
00323 dlen = nr * nc;
00324 if (dlen < 0)
00325 goto data_read_error;
00326
00327 if (order)
00328 {
00329 octave_idx_type tmp = nr;
00330 nr = nc;
00331 nc = tmp;
00332 }
00333
00334 if (type == 2)
00335 {
00336 if (nc == 4)
00337 {
00338 octave_idx_type nr_new, nc_new;
00339 Array<Complex> data (dim_vector (1, nr - 1));
00340 Array<octave_idx_type> c (dim_vector (1, nr - 1));
00341 Array<octave_idx_type> r (dim_vector (1, nr - 1));
00342 OCTAVE_LOCAL_BUFFER (double, dtmp, nr);
00343 OCTAVE_LOCAL_BUFFER (double, ctmp, nr);
00344
00345 read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
00346 for (octave_idx_type i = 0; i < nr - 1; i++)
00347 r.xelem(i) = dtmp[i] - 1;
00348 nr_new = dtmp[nr - 1];
00349 read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
00350 for (octave_idx_type i = 0; i < nr - 1; i++)
00351 c.xelem(i) = dtmp[i] - 1;
00352 nc_new = dtmp[nr - 1];
00353 read_mat_binary_data (is, dtmp, prec, nr - 1, swap, flt_fmt);
00354 read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);
00355 read_mat_binary_data (is, ctmp, prec, nr - 1, swap, flt_fmt);
00356
00357 for (octave_idx_type i = 0; i < nr - 1; i++)
00358 data.xelem(i) = Complex (dtmp[i], ctmp[i]);
00359 read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt);
00360
00361 SparseComplexMatrix smc = SparseComplexMatrix (data, r, c,
00362 nr_new, nc_new);
00363
00364 tc = order ? smc.transpose () : smc;
00365 }
00366 else
00367 {
00368 octave_idx_type nr_new, nc_new;
00369 Array<double> data (dim_vector (1, nr - 1));
00370 Array<octave_idx_type> c (dim_vector (1, nr - 1));
00371 Array<octave_idx_type> r (dim_vector (1, nr - 1));
00372 OCTAVE_LOCAL_BUFFER (double, dtmp, nr);
00373
00374 read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
00375 for (octave_idx_type i = 0; i < nr - 1; i++)
00376 r.xelem(i) = dtmp[i] - 1;
00377 nr_new = dtmp[nr - 1];
00378 read_mat_binary_data (is, dtmp, prec, nr, swap, flt_fmt);
00379 for (octave_idx_type i = 0; i < nr - 1; i++)
00380 c.xelem(i) = dtmp[i] - 1;
00381 nc_new = dtmp[nr - 1];
00382 read_mat_binary_data (is, data.fortran_vec (), prec, nr - 1, swap, flt_fmt);
00383 read_mat_binary_data (is, dtmp, prec, 1, swap, flt_fmt);
00384
00385 SparseMatrix sm = SparseMatrix (data, r, c, nr_new, nc_new);
00386
00387 tc = order ? sm.transpose () : sm;
00388 }
00389 }
00390 else
00391 {
00392 re.resize (nr, nc);
00393
00394 read_mat_binary_data (is, re.fortran_vec (), prec, dlen, swap, flt_fmt);
00395
00396 if (! is || error_state)
00397 {
00398 error ("load: reading matrix data for '%s'", name);
00399 goto data_read_error;
00400 }
00401
00402 if (imag)
00403 {
00404 Matrix im (nr, nc);
00405
00406 read_mat_binary_data (is, im.fortran_vec (), prec, dlen, swap,
00407 flt_fmt);
00408
00409 if (! is || error_state)
00410 {
00411 error ("load: reading imaginary matrix data for '%s'", name);
00412 goto data_read_error;
00413 }
00414
00415 ComplexMatrix ctmp (nr, nc);
00416
00417 for (octave_idx_type j = 0; j < nc; j++)
00418 for (octave_idx_type i = 0; i < nr; i++)
00419 ctmp (i, j) = Complex (re (i, j), im (i, j));
00420
00421 tc = order ? ctmp.transpose () : ctmp;
00422 }
00423 else
00424 tc = order ? re.transpose () : re;
00425
00426 if (type == 1)
00427 tc = tc.convert_to_str (false, true, '\'');
00428 }
00429
00430 return retval;
00431 }
00432
00433 data_read_error:
00434 error ("load: trouble reading binary file '%s'", filename.c_str ());
00435 return retval;
00436 }
00437
00438
00439
00440
00441 bool
00442 save_mat_binary_data (std::ostream& os, const octave_value& tc,
00443 const std::string& name)
00444 {
00445 int32_t mopt = 0;
00446
00447 mopt += tc.is_sparse_type () ? 2 : tc.is_string () ? 1 : 0;
00448
00449 oct_mach_info::float_format flt_fmt =
00450 oct_mach_info::native_float_format ();;
00451
00452 mopt += 1000 * float_format_to_mopt_digit (flt_fmt);
00453
00454 os.write (reinterpret_cast<char *> (&mopt), 4);
00455
00456 octave_idx_type len;
00457 int32_t nr = tc.rows ();
00458
00459 int32_t nc = tc.columns ();
00460
00461 if (tc.is_sparse_type ())
00462 {
00463 len = tc.nnz ();
00464 uint32_t nnz = len + 1;
00465 os.write (reinterpret_cast<char *> (&nnz), 4);
00466
00467 uint32_t iscmplx = tc.is_complex_type () ? 4 : 3;
00468 os.write (reinterpret_cast<char *> (&iscmplx), 4);
00469
00470 uint32_t tmp = 0;
00471 os.write (reinterpret_cast<char *> (&tmp), 4);
00472 }
00473 else
00474 {
00475 os.write (reinterpret_cast<char *> (&nr), 4);
00476 os.write (reinterpret_cast<char *> (&nc), 4);
00477
00478 int32_t imag = tc.is_complex_type () ? 1 : 0;
00479 os.write (reinterpret_cast<char *> (&imag), 4);
00480
00481 len = nr * nc;
00482 }
00483
00484
00485
00486
00487
00488 int32_t name_len = name.length () + 1;
00489
00490 os.write (reinterpret_cast<char *> (&name_len), 4);
00491 os << name << '\0';
00492
00493 if (tc.is_string ())
00494 {
00495 unwind_protect frame;
00496
00497 charMatrix chm = tc.char_matrix_value ();
00498
00499 octave_idx_type nrow = chm.rows ();
00500 octave_idx_type ncol = chm.cols ();
00501
00502 OCTAVE_LOCAL_BUFFER (double, buf, ncol*nrow);
00503
00504 for (octave_idx_type i = 0; i < nrow; i++)
00505 {
00506 std::string tstr = chm.row_as_string (i);
00507 const char *s = tstr.data ();
00508
00509 for (octave_idx_type j = 0; j < ncol; j++)
00510 buf[j*nrow+i] = static_cast<double> (*s++ & 0x00FF);
00511 }
00512 os.write (reinterpret_cast<char *> (buf), nrow*ncol*sizeof(double));
00513 }
00514 else if (tc.is_range ())
00515 {
00516 Range r = tc.range_value ();
00517 double base = r.base ();
00518 double inc = r.inc ();
00519 octave_idx_type nel = r.nelem ();
00520 for (octave_idx_type i = 0; i < nel; i++)
00521 {
00522 double x = base + i * inc;
00523 os.write (reinterpret_cast<char *> (&x), 8);
00524 }
00525 }
00526 else if (tc.is_real_scalar ())
00527 {
00528 double tmp = tc.double_value ();
00529 os.write (reinterpret_cast<char *> (&tmp), 8);
00530 }
00531 else if (tc.is_sparse_type ())
00532 {
00533 double ds;
00534 OCTAVE_LOCAL_BUFFER (double, dtmp, len);
00535 if (tc.is_complex_matrix ())
00536 {
00537 SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
00538
00539 for (octave_idx_type i = 0; i < len; i++)
00540 dtmp [i] = m.ridx(i) + 1;
00541 os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
00542 ds = nr;
00543 os.write (reinterpret_cast<const char *> (&ds), 8);
00544
00545 octave_idx_type ii = 0;
00546 for (octave_idx_type j = 0; j < nc; j++)
00547 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++)
00548 dtmp[ii++] = j + 1;
00549 os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
00550 ds = nc;
00551 os.write (reinterpret_cast<const char *> (&ds), 8);
00552
00553 for (octave_idx_type i = 0; i < len; i++)
00554 dtmp [i] = std::real (m.data(i));
00555 os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
00556 ds = 0.;
00557 os.write (reinterpret_cast<const char *> (&ds), 8);
00558
00559 for (octave_idx_type i = 0; i < len; i++)
00560 dtmp [i] = std::imag (m.data(i));
00561 os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
00562 os.write (reinterpret_cast<const char *> (&ds), 8);
00563 }
00564 else
00565 {
00566 SparseMatrix m = tc.sparse_matrix_value ();
00567
00568 for (octave_idx_type i = 0; i < len; i++)
00569 dtmp [i] = m.ridx(i) + 1;
00570 os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
00571 ds = nr;
00572 os.write (reinterpret_cast<const char *> (&ds), 8);
00573
00574 octave_idx_type ii = 0;
00575 for (octave_idx_type j = 0; j < nc; j++)
00576 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++)
00577 dtmp[ii++] = j + 1;
00578 os.write (reinterpret_cast<const char *> (dtmp), 8 * len);
00579 ds = nc;
00580 os.write (reinterpret_cast<const char *> (&ds), 8);
00581
00582 os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
00583 ds = 0.;
00584 os.write (reinterpret_cast<const char *> (&ds), 8);
00585 }
00586 }
00587 else if (tc.is_real_matrix ())
00588 {
00589 Matrix m = tc.matrix_value ();
00590 os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
00591 }
00592 else if (tc.is_complex_scalar ())
00593 {
00594 Complex tmp = tc.complex_value ();
00595 os.write (reinterpret_cast<char *> (&tmp), 16);
00596 }
00597 else if (tc.is_complex_matrix ())
00598 {
00599 ComplexMatrix m_cmplx = tc.complex_matrix_value ();
00600 Matrix m = ::real (m_cmplx);
00601 os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
00602 m = ::imag (m_cmplx);
00603 os.write (reinterpret_cast<const char *> (m.data ()), 8 * len);
00604 }
00605 else
00606 gripe_wrong_type_arg ("save", tc, false);
00607
00608 return os;
00609 }