comparison src/ls-mat5.cc @ 10349:d4d13389c957

make load-save to matlab format work when using --enable-64
author John W. Eaton <jwe@octave.org>
date Mon, 22 Feb 2010 23:07:21 -0500
parents 57a59eae83cc
children 12884915a8e4
comparison
equal deleted inserted replaced
10348:df1df5f0c236 10349:d4d13389c957
121 // each element before copying to DATA. FLT_FMT specifies the format 121 // each element before copying to DATA. FLT_FMT specifies the format
122 // of the data if we are reading floating point numbers. 122 // of the data if we are reading floating point numbers.
123 123
124 static void 124 static void
125 read_mat5_binary_data (std::istream& is, double *data, 125 read_mat5_binary_data (std::istream& is, double *data,
126 int count, bool swap, mat5_data_type type, 126 octave_idx_type count, bool swap, mat5_data_type type,
127 oct_mach_info::float_format flt_fmt) 127 oct_mach_info::float_format flt_fmt)
128 { 128 {
129 129
130 switch (type) 130 switch (type)
131 { 131 {
186 } 186 }
187 } 187 }
188 188
189 template <class T> 189 template <class T>
190 void 190 void
191 read_mat5_integer_data (std::istream& is, T *m, int count, bool swap, 191 read_mat5_integer_data (std::istream& is, T *m, octave_idx_type count,
192 mat5_data_type type) 192 bool swap, mat5_data_type type)
193 { 193 {
194 194
195 #define READ_INTEGER_DATA(TYPE, swap, data, size, len, stream) \ 195 #define READ_INTEGER_DATA(TYPE, swap, data, size, len, stream) \
196 do \ 196 do \
197 { \ 197 { \
199 { \ 199 { \
200 OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \ 200 OCTAVE_LOCAL_BUFFER (TYPE, ptr, len); \
201 stream.read (reinterpret_cast<char *> (ptr), size * len); \ 201 stream.read (reinterpret_cast<char *> (ptr), size * len); \
202 if (swap) \ 202 if (swap) \
203 swap_bytes< size > (ptr, len); \ 203 swap_bytes< size > (ptr, len); \
204 for (int i = 0; i < len; i++) \ 204 for (octave_idx_type i = 0; i < len; i++) \
205 data[i] = ptr[i]; \ 205 data[i] = ptr[i]; \
206 } \ 206 } \
207 } \ 207 } \
208 while (0) 208 while (0)
209 209
255 255
256 #undef READ_INTEGER_DATA 256 #undef READ_INTEGER_DATA
257 257
258 } 258 }
259 259
260 template void read_mat5_integer_data (std::istream& is, octave_int8 *m, 260 template void
261 int count, bool swap, 261 read_mat5_integer_data (std::istream& is, octave_int8 *m,
262 mat5_data_type type); 262 octave_idx_type count, bool swap,
263 template void read_mat5_integer_data (std::istream& is, octave_int16 *m, 263 mat5_data_type type);
264 int count, bool swap, 264
265 mat5_data_type type); 265 template void
266 template void read_mat5_integer_data (std::istream& is, octave_int32 *m, 266 read_mat5_integer_data (std::istream& is, octave_int16 *m,
267 int count, bool swap, 267 octave_idx_type count, bool swap,
268 mat5_data_type type); 268 mat5_data_type type);
269 template void read_mat5_integer_data (std::istream& is, octave_int64 *m, 269
270 int count, bool swap, 270 template void
271 mat5_data_type type); 271 read_mat5_integer_data (std::istream& is, octave_int32 *m,
272 template void read_mat5_integer_data (std::istream& is, octave_uint8 *m, 272 octave_idx_type count, bool swap,
273 int count, bool swap, 273 mat5_data_type type);
274 mat5_data_type type); 274
275 template void read_mat5_integer_data (std::istream& is, octave_uint16 *m, 275 template void
276 int count, bool swap, 276 read_mat5_integer_data (std::istream& is, octave_int64 *m,
277 mat5_data_type type); 277 octave_idx_type count, bool swap,
278 template void read_mat5_integer_data (std::istream& is, octave_uint32 *m, 278 mat5_data_type type);
279 int count, bool swap, 279
280 mat5_data_type type); 280 template void
281 template void read_mat5_integer_data (std::istream& is, octave_uint64 *m, 281 read_mat5_integer_data (std::istream& is, octave_uint8 *m,
282 int count, bool swap, 282 octave_idx_type count, bool swap,
283 mat5_data_type type); 283 mat5_data_type type);
284 284
285 template void read_mat5_integer_data (std::istream& is, int *m, 285 template void
286 int count, bool swap, 286 read_mat5_integer_data (std::istream& is, octave_uint16 *m,
287 mat5_data_type type); 287 octave_idx_type count, bool swap,
288 mat5_data_type type);
289
290 template void
291 read_mat5_integer_data (std::istream& is, octave_uint32 *m,
292 octave_idx_type count, bool swap,
293 mat5_data_type type);
294
295 template void
296 read_mat5_integer_data (std::istream& is, octave_uint64 *m,
297 octave_idx_type count, bool swap,
298 mat5_data_type type);
299
300 template void
301 read_mat5_integer_data (std::istream& is, int *m,
302 octave_idx_type count, bool swap,
303 mat5_data_type type);
288 304
289 #define OCTAVE_MAT5_INTEGER_READ(TYP) \ 305 #define OCTAVE_MAT5_INTEGER_READ(TYP) \
290 { \ 306 { \
291 TYP re (dims); \ 307 TYP re (dims); \
292 \ 308 \
296 { \ 312 { \
297 error ("load: reading matrix data for `%s'", retval.c_str ()); \ 313 error ("load: reading matrix data for `%s'", retval.c_str ()); \
298 goto data_read_error; \ 314 goto data_read_error; \
299 } \ 315 } \
300 \ 316 \
301 int n = re.length (); \ 317 octave_idx_type n = re.numel (); \
302 tmp_pos = is.tellg (); \ 318 tmp_pos = is.tellg (); \
303 read_mat5_integer_data (is, re.fortran_vec (), n, swap, \ 319 read_mat5_integer_data (is, re.fortran_vec (), n, swap, \
304 static_cast<enum mat5_data_type> (type)); \ 320 static_cast<enum mat5_data_type> (type)); \
305 \ 321 \
306 if (! is || error_state) \ 322 if (! is || error_state) \
321 error ("load: reading matrix data for `%s'", \ 337 error ("load: reading matrix data for `%s'", \
322 retval.c_str ()); \ 338 retval.c_str ()); \
323 goto data_read_error; \ 339 goto data_read_error; \
324 } \ 340 } \
325 \ 341 \
326 n = im.length (); \ 342 n = im.numel (); \
327 read_mat5_binary_data (is, im.fortran_vec (), n, swap, \ 343 read_mat5_binary_data (is, im.fortran_vec (), n, swap, \
328 static_cast<enum mat5_data_type> (type), flt_fmt); \ 344 static_cast<enum mat5_data_type> (type), flt_fmt); \
329 \ 345 \
330 if (! is || error_state) \ 346 if (! is || error_state) \
331 { \ 347 { \
334 goto data_read_error; \ 350 goto data_read_error; \
335 } \ 351 } \
336 \ 352 \
337 ComplexNDArray ctmp (dims); \ 353 ComplexNDArray ctmp (dims); \
338 \ 354 \
339 for (int i = 0; i < n; i++) \ 355 for (octave_idx_type i = 0; i < n; i++) \
340 ctmp(i) = Complex (re(i).double_value (), im(i)); \ 356 ctmp(i) = Complex (re(i).double_value (), im(i)); \
341 \ 357 \
342 tc = ctmp; \ 358 tc = ctmp; \
343 } \ 359 } \
344 else \ 360 else \
404 read_mat5_binary_element (std::istream& is, const std::string& filename, 420 read_mat5_binary_element (std::istream& is, const std::string& filename,
405 bool swap, bool& global, octave_value& tc) 421 bool swap, bool& global, octave_value& tc)
406 { 422 {
407 std::string retval; 423 std::string retval;
408 424
409 // These are initialized here instead of closer to where they are 425 global = false;
410 // first used to avoid errors from gcc about goto crossing 426
427 // NOTE: these are initialized here instead of closer to where they
428 // are first used to avoid errors from gcc about goto crossing
411 // initialization of variable. 429 // initialization of variable.
412 430
431 bool imag;
432 bool isclass = false;
433 bool logicalvar;
434 dim_vector dims;
435 enum arrayclasstype arrayclass;
436 int16_t number = *(reinterpret_cast<const int16_t *>("\x00\x01"));
437 octave_idx_type nzmax;
438 std::string classname;
439
440 // MAT files always use IEEE floating point
413 oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown; 441 oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
414 int32_t type = 0;
415 std::string classname;
416 bool isclass = false;
417 bool imag;
418 bool logicalvar;
419 enum arrayclasstype arrayclass;
420 int32_t nzmax;
421 int32_t flags;
422 dim_vector dims;
423 int32_t len;
424 int32_t element_length;
425 std::streampos pos;
426 int16_t number;
427 number = *(reinterpret_cast<const int16_t *>("\x00\x01"));
428
429 global = false;
430
431 // MAT files always use IEEE floating point
432 if ((number == 1) ^ swap) 442 if ((number == 1) ^ swap)
433 flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian; 443 flt_fmt = oct_mach_info::flt_fmt_ieee_big_endian;
434 else 444 else
435 flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian; 445 flt_fmt = oct_mach_info::flt_fmt_ieee_little_endian;
436 446
437 // element type and length 447 // element type and length
448 int32_t type = 0;
449 int32_t element_length;
438 if (read_mat5_tag (is, swap, type, element_length)) 450 if (read_mat5_tag (is, swap, type, element_length))
439 return retval; // EOF 451 return retval; // EOF
440 452
441 #ifdef HAVE_ZLIB 453 #ifdef HAVE_ZLIB
442 if (type == miCOMPRESSED) 454 if (type == miCOMPRESSED)
443 { 455 {
444 // If C++ allowed us direct access to the file descriptor of an ifstream 456 // If C++ allowed us direct access to the file descriptor of an
445 // in a uniform way, the code below could be vastly simplified, and 457 // ifstream in a uniform way, the code below could be vastly
446 // additional copies of the data in memory wouldn't be needed!! 458 // simplified, and additional copies of the data in memory
459 // wouldn't be needed.
447 460
448 OCTAVE_LOCAL_BUFFER (char, inbuf, element_length); 461 OCTAVE_LOCAL_BUFFER (char, inbuf, element_length);
449 is.read (inbuf, element_length); 462 is.read (inbuf, element_length);
450 463
451 // We uncompress the first 8 bytes of the header to get the buffer length 464 // We uncompress the first 8 bytes of the header to get the buffer length
463 destLen = tmp[1] + 8; 476 destLen = tmp[1] + 8;
464 std::string outbuf (destLen, ' '); 477 std::string outbuf (destLen, ' ');
465 478
466 // FIXME -- find a way to avoid casting away const here! 479 // FIXME -- find a way to avoid casting away const here!
467 480
468 int err = uncompress (reinterpret_cast<Bytef *> (const_cast<char *> (outbuf.c_str ())), &destLen, 481 int err = uncompress (reinterpret_cast<Bytef *> (const_cast<char *> (outbuf.c_str ())),
469 reinterpret_cast<Bytef *> (inbuf), element_length); 482 &destLen, reinterpret_cast<Bytef *> (inbuf),
483 element_length);
470 484
471 if (err != Z_OK) 485 if (err != Z_OK)
472 error ("load: error uncompressing data element"); 486 error ("load: error uncompressing data element");
473 else 487 else
474 { 488 {
482 496
483 return retval; 497 return retval;
484 } 498 }
485 #endif 499 #endif
486 500
501 std::streampos pos;
502
487 if (type != miMATRIX) 503 if (type != miMATRIX)
488 { 504 {
489 pos = is.tellg (); 505 pos = is.tellg ();
490 error ("load: invalid element type = %d", type); 506 error ("load: invalid element type = %d", type);
491 goto early_read_error; 507 goto early_read_error;
498 } 514 }
499 515
500 pos = is.tellg (); 516 pos = is.tellg ();
501 517
502 // array flags subelement 518 // array flags subelement
519 int32_t len;
503 if (read_mat5_tag (is, swap, type, len) || type != miUINT32 || len != 8) 520 if (read_mat5_tag (is, swap, type, len) || type != miUINT32 || len != 8)
504 { 521 {
505 error ("load: invalid array flags subelement"); 522 error ("load: invalid array flags subelement");
506 goto early_read_error; 523 goto early_read_error;
507 } 524 }
508 525
526 int32_t flags;
509 read_int (is, swap, flags); 527 read_int (is, swap, flags);
528
510 imag = (flags & 0x0800) != 0; // has an imaginary part? 529 imag = (flags & 0x0800) != 0; // has an imaginary part?
530
511 global = (flags & 0x0400) != 0; // global variable? 531 global = (flags & 0x0400) != 0; // global variable?
532
512 logicalvar = (flags & 0x0200) != 0; // boolean ? 533 logicalvar = (flags & 0x0200) != 0; // boolean ?
534
513 arrayclass = static_cast<arrayclasstype> (flags & 0xff); 535 arrayclass = static_cast<arrayclasstype> (flags & 0xff);
514 read_int (is, swap, nzmax); // max number of non-zero in sparse 536
537 int32_t tmp_nzmax;
538 read_int (is, swap, tmp_nzmax); // max number of non-zero in sparse
539 nzmax = tmp_nzmax;
515 540
516 // dimensions array subelement 541 // dimensions array subelement
517 if (arrayclass != MAT_FILE_WORKSPACE_CLASS) 542 if (arrayclass != MAT_FILE_WORKSPACE_CLASS)
518 { 543 {
519 int32_t dim_len; 544 int32_t dim_len;
573 { 598 {
574 case MAT_FILE_CELL_CLASS: 599 case MAT_FILE_CELL_CLASS:
575 { 600 {
576 Cell cell_array (dims); 601 Cell cell_array (dims);
577 602
578 int n = cell_array.length (); 603 octave_idx_type n = cell_array.numel ();
579 604
580 for (int i = 0; i < n; i++) 605 for (octave_idx_type i = 0; i < n; i++)
581 { 606 {
582 octave_value tc2; 607 octave_value tc2;
583 608
584 std::string nm 609 std::string nm
585 = read_mat5_binary_element (is, filename, swap, global, tc2); 610 = read_mat5_binary_element (is, filename, swap, global, tc2);
596 tc = cell_array; 621 tc = cell_array;
597 } 622 }
598 break; 623 break;
599 624
600 case MAT_FILE_SPARSE_CLASS: 625 case MAT_FILE_SPARSE_CLASS:
601 #if SIZEOF_INT != SIZEOF_OCTAVE_IDX_TYPE
602 warning ("load: sparse objects are not implemented");
603 goto skip_ahead;
604 #else
605 { 626 {
606 int nr = dims(0); 627 octave_idx_type nr = dims(0);
607 int nc = dims(1); 628 octave_idx_type nc = dims(1);
608 SparseMatrix sm; 629 SparseMatrix sm;
609 SparseComplexMatrix scm; 630 SparseComplexMatrix scm;
610 int *ridx; 631 octave_idx_type *ridx;
611 int *cidx; 632 octave_idx_type *cidx;
612 double *data; 633 double *data;
613 634
614 // Setup return value 635 // Setup return value
615 if (imag) 636 if (imag)
616 { 637 {
617 scm = SparseComplexMatrix (static_cast<octave_idx_type> (nr), 638 scm = SparseComplexMatrix (nr, nc, nzmax);
618 static_cast<octave_idx_type> (nc),
619 static_cast<octave_idx_type> (nzmax));
620 ridx = scm.ridx (); 639 ridx = scm.ridx ();
621 cidx = scm.cidx (); 640 cidx = scm.cidx ();
622 data = 0; 641 data = 0;
623 } 642 }
624 else 643 else
625 { 644 {
626 sm = SparseMatrix (static_cast<octave_idx_type> (nr), 645 sm = SparseMatrix (nr, nc, nzmax);
627 static_cast<octave_idx_type> (nc),
628 static_cast<octave_idx_type> (nzmax));
629 ridx = sm.ridx (); 646 ridx = sm.ridx ();
630 cidx = sm.cidx (); 647 cidx = sm.cidx ();
631 data = sm.data (); 648 data = sm.data ();
632 } 649 }
633 650
678 { 695 {
679 error ("load: reading sparse matrix data for `%s'", retval.c_str ()); 696 error ("load: reading sparse matrix data for `%s'", retval.c_str ());
680 goto data_read_error; 697 goto data_read_error;
681 } 698 }
682 699
683 int32_t nnz = cidx[nc]; 700 octave_idx_type nnz = cidx[nc];
684 NDArray re; 701 NDArray re;
685 if (imag) 702 if (imag)
686 { 703 {
687 re = NDArray (dim_vector (static_cast<int> (nnz))); 704 re = NDArray (dim_vector (nnz));
688 data = re.fortran_vec (); 705 data = re.fortran_vec ();
689 } 706 }
690 707
691 tmp_pos = is.tellg (); 708 tmp_pos = is.tellg ();
692 read_mat5_binary_data (is, data, nnz, swap, 709 read_mat5_binary_data (is, data, nnz, swap,
719 error ("load: reading imaginary sparse matrix data for `%s'", 736 error ("load: reading imaginary sparse matrix data for `%s'",
720 retval.c_str ()); 737 retval.c_str ());
721 goto data_read_error; 738 goto data_read_error;
722 } 739 }
723 740
724 for (int i = 0; i < nnz; i++) 741 for (octave_idx_type i = 0; i < nnz; i++)
725 scm.xdata (i) = Complex (re (i), im (i)); 742 scm.xdata (i) = Complex (re (i), im (i));
726 743
727 tc = scm; 744 tc = scm;
728 } 745 }
729 else 746 else
730 tc = sm; 747 tc = sm;
731 } 748 }
732 #endif
733 break; 749 break;
734 750
735 case MAT_FILE_FUNCTION_CLASS: 751 case MAT_FILE_FUNCTION_CLASS:
736 { 752 {
737 octave_value tc2; 753 octave_value tc2;
1142 // variable and convert it. 1158 // variable and convert it.
1143 1159
1144 if (logicalvar) 1160 if (logicalvar)
1145 { 1161 {
1146 uint8NDArray in = tc.uint8_array_value (); 1162 uint8NDArray in = tc.uint8_array_value ();
1147 int nel = in.nelem (); 1163 octave_idx_type nel = in.numel ();
1148 boolNDArray out (dims); 1164 boolNDArray out (dims);
1149 1165
1150 for (int i = 0; i < nel; i++) 1166 for (octave_idx_type i = 0; i < nel; i++)
1151 out (i) = in(i).bool_value (); 1167 out (i) = in(i).bool_value ();
1152 1168
1153 tc = out; 1169 tc = out;
1154 } 1170 }
1155 } 1171 }
1196 { 1212 {
1197 error ("load: reading matrix data for `%s'", retval.c_str ()); 1213 error ("load: reading matrix data for `%s'", retval.c_str ());
1198 goto data_read_error; 1214 goto data_read_error;
1199 } 1215 }
1200 1216
1201 int n = re.length (); 1217 octave_idx_type n = re.numel ();
1202 tmp_pos = is.tellg (); 1218 tmp_pos = is.tellg ();
1203 read_mat5_binary_data (is, re.fortran_vec (), n, swap, 1219 read_mat5_binary_data (is, re.fortran_vec (), n, swap,
1204 static_cast<enum mat5_data_type> (type), flt_fmt); 1220 static_cast<enum mat5_data_type> (type), flt_fmt);
1205 1221
1206 if (! is || error_state) 1222 if (! is || error_state)
1217 // MAT_FILE_DOUBLE_CLASS, so check if we have a logical 1233 // MAT_FILE_DOUBLE_CLASS, so check if we have a logical
1218 // variable and convert it. 1234 // variable and convert it.
1219 1235
1220 boolNDArray out (dims); 1236 boolNDArray out (dims);
1221 1237
1222 for (int i = 0; i < n; i++) 1238 for (octave_idx_type i = 0; i < n; i++)
1223 out (i) = static_cast<bool> (re (i)); 1239 out (i) = static_cast<bool> (re (i));
1224 1240
1225 tc = out; 1241 tc = out;
1226 } 1242 }
1227 else if (imag) 1243 else if (imag)
1234 { 1250 {
1235 error ("load: reading matrix data for `%s'", retval.c_str ()); 1251 error ("load: reading matrix data for `%s'", retval.c_str ());
1236 goto data_read_error; 1252 goto data_read_error;
1237 } 1253 }
1238 1254
1239 n = im.length (); 1255 n = im.numel ();
1240 read_mat5_binary_data (is, im.fortran_vec (), n, swap, 1256 read_mat5_binary_data (is, im.fortran_vec (), n, swap,
1241 static_cast<enum mat5_data_type> (type), flt_fmt); 1257 static_cast<enum mat5_data_type> (type), flt_fmt);
1242 1258
1243 if (! is || error_state) 1259 if (! is || error_state)
1244 { 1260 {
1247 goto data_read_error; 1263 goto data_read_error;
1248 } 1264 }
1249 1265
1250 ComplexNDArray ctmp (dims); 1266 ComplexNDArray ctmp (dims);
1251 1267
1252 for (int i = 0; i < n; i++) 1268 for (octave_idx_type i = 0; i < n; i++)
1253 ctmp(i) = Complex (re(i), im(i)); 1269 ctmp(i) = Complex (re(i), im(i));
1254 1270
1255 tc = ctmp; 1271 tc = ctmp;
1256 } 1272 }
1257 else 1273 else
1259 if (arrayclass == MAT_FILE_CHAR_CLASS) 1275 if (arrayclass == MAT_FILE_CHAR_CLASS)
1260 { 1276 {
1261 if (type == miUTF16 || type == miUTF32) 1277 if (type == miUTF16 || type == miUTF32)
1262 { 1278 {
1263 bool found_big_char = false; 1279 bool found_big_char = false;
1264 for (int i = 0; i < n; i++) 1280 for (octave_idx_type i = 0; i < n; i++)
1265 { 1281 {
1266 if (re(i) > 127) { 1282 if (re(i) > 127) {
1267 re(i) = '?'; 1283 re(i) = '?';
1268 found_big_char = true; 1284 found_big_char = true;
1269 } 1285 }
1279 { 1295 {
1280 // Search for multi-byte encoded UTF8 characters and 1296 // Search for multi-byte encoded UTF8 characters and
1281 // replace with 0x3F for '?'... Give the user a warning 1297 // replace with 0x3F for '?'... Give the user a warning
1282 1298
1283 bool utf8_multi_byte = false; 1299 bool utf8_multi_byte = false;
1284 for (int i = 0; i < n; i++) 1300 for (octave_idx_type i = 0; i < n; i++)
1285 { 1301 {
1286 unsigned char a = static_cast<unsigned char> (re(i)); 1302 unsigned char a = static_cast<unsigned char> (re(i));
1287 if (a > 0x7f) 1303 if (a > 0x7f)
1288 utf8_multi_byte = true; 1304 utf8_multi_byte = true;
1289 } 1305 }
1290 1306
1291 if (utf8_multi_byte) 1307 if (utf8_multi_byte)
1292 { 1308 {
1293 warning ("load: can not read multi-byte encoded UTF8 characters."); 1309 warning ("load: can not read multi-byte encoded UTF8 characters.");
1294 warning (" Replacing unreadable characters with '?'."); 1310 warning (" Replacing unreadable characters with '?'.");
1295 for (int i = 0; i < n; i++) 1311 for (octave_idx_type i = 0; i < n; i++)
1296 { 1312 {
1297 unsigned char a = static_cast<unsigned char> (re(i)); 1313 unsigned char a = static_cast<unsigned char> (re(i));
1298 if (a > 0x7f) 1314 if (a > 0x7f)
1299 re(i) = '?'; 1315 re(i) = '?';
1300 } 1316 }
1375 return -1; 1391 return -1;
1376 1392
1377 if (tc.is_uint8_type ()) 1393 if (tc.is_uint8_type ())
1378 { 1394 {
1379 const uint8NDArray itmp = tc.uint8_array_value(); 1395 const uint8NDArray itmp = tc.uint8_array_value();
1380 octave_idx_type ilen = itmp.nelem (); 1396 octave_idx_type ilen = itmp.numel ();
1381 1397
1382 // Why should I have to initialize outbuf as just overwrite 1398 // Why should I have to initialize outbuf as just overwrite
1383 std::string outbuf (ilen - 7, ' '); 1399 std::string outbuf (ilen - 7, ' ');
1384 1400
1385 // FIXME -- find a way to avoid casting away const here 1401 // FIXME -- find a way to avoid casting away const here
1403 1419
1404 return 0; 1420 return 0;
1405 } 1421 }
1406 1422
1407 static int 1423 static int
1408 write_mat5_tag (std::ostream& is, int type, int bytes) 1424 write_mat5_tag (std::ostream& is, int type, octave_idx_type bytes)
1409 { 1425 {
1410 int32_t temp; 1426 int32_t temp;
1411 1427
1412 if (bytes > 0 && bytes <= 4) 1428 if (bytes > 0 && bytes <= 4)
1413 temp = (bytes << 16) + type; 1429 temp = (bytes << 16) + type;
1431 // write out the numeric values in M to OS, 1447 // write out the numeric values in M to OS,
1432 // preceded by the appropriate tag. 1448 // preceded by the appropriate tag.
1433 static void 1449 static void
1434 write_mat5_array (std::ostream& os, const NDArray& m, bool save_as_floats) 1450 write_mat5_array (std::ostream& os, const NDArray& m, bool save_as_floats)
1435 { 1451 {
1436 int nel = m.nelem ();
1437 double max_val, min_val;
1438 save_type st = LS_DOUBLE; 1452 save_type st = LS_DOUBLE;
1439 mat5_data_type mst;
1440 int size;
1441 unsigned len;
1442 const double *data = m.data (); 1453 const double *data = m.data ();
1443 1454
1444 // Have to use copy here to avoid writing over data accessed via 1455 // Have to use copy here to avoid writing over data accessed via
1445 // Matrix::data(). 1456 // Matrix::data().
1446 1457
1447 #define MAT5_DO_WRITE(TYPE, data, count, stream) \ 1458 #define MAT5_DO_WRITE(TYPE, data, count, stream) \
1448 do \ 1459 do \
1449 { \ 1460 { \
1450 OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \ 1461 OCTAVE_LOCAL_BUFFER (TYPE, ptr, count); \
1451 for (int i = 0; i < count; i++) \ 1462 for (octave_idx_type i = 0; i < count; i++) \
1452 ptr[i] = static_cast<TYPE> (data[i]); \ 1463 ptr[i] = static_cast<TYPE> (data[i]); \
1453 stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \ 1464 stream.write (reinterpret_cast<char *> (ptr), count * sizeof (TYPE)); \
1454 } \ 1465 } \
1455 while (0) 1466 while (0)
1456 1467
1463 } 1474 }
1464 else 1475 else
1465 st = LS_FLOAT; 1476 st = LS_FLOAT;
1466 } 1477 }
1467 1478
1479 double max_val, min_val;
1468 if (m.all_integers (max_val, min_val)) 1480 if (m.all_integers (max_val, min_val))
1469 st = get_save_type (max_val, min_val); 1481 st = get_save_type (max_val, min_val);
1470 1482
1483 mat5_data_type mst;
1484 int size;
1471 switch (st) 1485 switch (st)
1472 { 1486 {
1473 default: 1487 default:
1474 case LS_DOUBLE: mst = miDOUBLE; size = 8; break; 1488 case LS_DOUBLE: mst = miDOUBLE; size = 8; break;
1475 case LS_FLOAT: mst = miSINGLE; size = 4; break; 1489 case LS_FLOAT: mst = miSINGLE; size = 4; break;
1479 case LS_CHAR: mst = miINT8; size = 1; break; 1493 case LS_CHAR: mst = miINT8; size = 1; break;
1480 case LS_SHORT: mst = miINT16; size = 2; break; 1494 case LS_SHORT: mst = miINT16; size = 2; break;
1481 case LS_INT: mst = miINT32; size = 4; break; 1495 case LS_INT: mst = miINT32; size = 4; break;
1482 } 1496 }
1483 1497
1484 len = nel*size; 1498 octave_idx_type nel = m.numel ();
1499 octave_idx_type len = nel*size;
1500
1485 write_mat5_tag (os, mst, len); 1501 write_mat5_tag (os, mst, len);
1486 1502
1487 { 1503 {
1488 switch (st) 1504 switch (st)
1489 { 1505 {
1540 } 1556 }
1541 } 1557 }
1542 1558
1543 template <class T> 1559 template <class T>
1544 void 1560 void
1545 write_mat5_integer_data (std::ostream& os, const T *m, int size, int nel) 1561 write_mat5_integer_data (std::ostream& os, const T *m, int size,
1562 octave_idx_type nel)
1546 { 1563 {
1547 mat5_data_type mst; 1564 mat5_data_type mst;
1548 unsigned len; 1565 unsigned len;
1549 1566
1550 switch (size) 1567 switch (size)
1590 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00"; 1607 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
1591 os.write (buf, PAD (len) - len); 1608 os.write (buf, PAD (len) - len);
1592 } 1609 }
1593 } 1610 }
1594 1611
1595 template void write_mat5_integer_data (std::ostream& os, const octave_int8 *m, 1612 template void
1596 int size, int nel); 1613 write_mat5_integer_data (std::ostream& os, const octave_int8 *m,
1597 template void write_mat5_integer_data (std::ostream& os, const octave_int16 *m, 1614 int size, octave_idx_type nel);
1598 int size, int nel); 1615
1599 template void write_mat5_integer_data (std::ostream& os, const octave_int32 *m, 1616 template void
1600 int size, int nel); 1617 write_mat5_integer_data (std::ostream& os, const octave_int16 *m,
1601 template void write_mat5_integer_data (std::ostream& os, const octave_int64 *m, 1618 int size, octave_idx_type nel);
1602 int size, int nel); 1619
1603 template void write_mat5_integer_data (std::ostream& os, const octave_uint8 *m, 1620 template void
1604 int size, int nel); 1621 write_mat5_integer_data (std::ostream& os, const octave_int32 *m,
1605 template void write_mat5_integer_data (std::ostream& os, const octave_uint16 *m, 1622 int size, octave_idx_type nel);
1606 int size, int nel); 1623
1607 template void write_mat5_integer_data (std::ostream& os, const octave_uint32 *m, 1624 template void
1608 int size, int nel); 1625 write_mat5_integer_data (std::ostream& os, const octave_int64 *m,
1609 template void write_mat5_integer_data (std::ostream& os, const octave_uint64 *m, 1626 int size, octave_idx_type nel);
1610 int size, int nel); 1627
1611 template void write_mat5_integer_data (std::ostream& os, const int *m, 1628 template void
1612 int size, int nel); 1629 write_mat5_integer_data (std::ostream& os, const octave_uint8 *m,
1630 int size, octave_idx_type nel);
1631
1632 template void
1633 write_mat5_integer_data (std::ostream& os, const octave_uint16 *m,
1634 int size, octave_idx_type nel);
1635
1636 template void
1637 write_mat5_integer_data (std::ostream& os, const octave_uint32 *m,
1638 int size, octave_idx_type nel);
1639
1640 template void
1641 write_mat5_integer_data (std::ostream& os, const octave_uint64 *m,
1642 int size, octave_idx_type nel);
1643
1644 template void
1645 write_mat5_integer_data (std::ostream& os, const int *m,
1646 int size, octave_idx_type nel);
1613 1647
1614 // Write out cell element values in the cell array to OS, preceded by 1648 // Write out cell element values in the cell array to OS, preceded by
1615 // the appropriate tag. 1649 // the appropriate tag.
1616 1650
1617 static bool 1651 static bool
1618 write_mat5_cell_array (std::ostream& os, const Cell& cell, 1652 write_mat5_cell_array (std::ostream& os, const Cell& cell,
1619 bool mark_as_global, bool save_as_floats) 1653 bool mark_as_global, bool save_as_floats)
1620 { 1654 {
1621 int nel = cell.nelem (); 1655 octave_idx_type nel = cell.numel ();
1622 1656
1623 for (int i = 0; i < nel; i++) 1657 for (octave_idx_type i = 0; i < nel; i++)
1624 { 1658 {
1625 octave_value ov = cell(i); 1659 octave_value ov = cell(i);
1626 1660
1627 if (! save_mat5_binary_element (os, ov, "", mark_as_global, 1661 if (! save_mat5_binary_element (os, ov, "", mark_as_global,
1628 false, save_as_floats)) 1662 false, save_as_floats))
1631 1665
1632 return true; 1666 return true;
1633 } 1667 }
1634 1668
1635 int 1669 int
1636 save_mat5_array_length (const double* val, int nel, bool save_as_floats) 1670 save_mat5_array_length (const double* val, octave_idx_type nel,
1671 bool save_as_floats)
1637 { 1672 {
1638 if (nel > 0) 1673 if (nel > 0)
1639 { 1674 {
1640 int size = 8; 1675 int size = 8;
1641 1676
1642 if (save_as_floats) 1677 if (save_as_floats)
1643 { 1678 {
1644 bool too_large_for_float = false; 1679 bool too_large_for_float = false;
1645 for (int i = 0; i < nel; i++) 1680 for (octave_idx_type i = 0; i < nel; i++)
1646 { 1681 {
1647 double tmp = val [i]; 1682 double tmp = val [i];
1648 1683
1649 if (! (xisnan (tmp) || xisinf (tmp)) 1684 if (! (xisnan (tmp) || xisinf (tmp))
1650 && fabs (tmp) > FLT_MAX) 1685 && fabs (tmp) > FLT_MAX)
1704 else 1739 else
1705 return 8; 1740 return 8;
1706 } 1741 }
1707 1742
1708 int 1743 int
1709 save_mat5_array_length (const Complex* val, int nel, bool save_as_floats) 1744 save_mat5_array_length (const Complex* val, octave_idx_type nel,
1745 bool save_as_floats)
1710 { 1746 {
1711 int ret; 1747 int ret;
1712 1748
1713 OCTAVE_LOCAL_BUFFER (double, tmp, nel); 1749 OCTAVE_LOCAL_BUFFER (double, tmp, nel);
1714 1750
1715 for (int i = 1; i < nel; i++) 1751 for (octave_idx_type i = 1; i < nel; i++)
1716 tmp[i] = std::real (val[i]); 1752 tmp[i] = std::real (val[i]);
1717 1753
1718 ret = save_mat5_array_length (tmp, nel, save_as_floats); 1754 ret = save_mat5_array_length (tmp, nel, save_as_floats);
1719 1755
1720 for (int i = 1; i < nel; i++) 1756 for (octave_idx_type i = 1; i < nel; i++)
1721 tmp[i] = std::imag (val[i]); 1757 tmp[i] = std::imag (val[i]);
1722 1758
1723 ret += save_mat5_array_length (tmp, nel, save_as_floats); 1759 ret += save_mat5_array_length (tmp, nel, save_as_floats);
1724 1760
1725 return ret; 1761 return ret;
1727 1763
1728 int 1764 int
1729 save_mat5_element_length (const octave_value& tc, const std::string& name, 1765 save_mat5_element_length (const octave_value& tc, const std::string& name,
1730 bool save_as_floats, bool mat7_format) 1766 bool save_as_floats, bool mat7_format)
1731 { 1767 {
1732 int max_namelen = (mat7_format ? 63 : 31); 1768 size_t max_namelen = (mat7_format ? 63 : 31);
1733 int len = name.length (); 1769 size_t len = name.length ();
1734 std::string cname = tc.class_name (); 1770 std::string cname = tc.class_name ();
1735 int ret = 32; 1771 int ret = 32;
1736 1772
1737 if (len > 4) 1773 if (len > 4)
1738 ret += PAD (len > max_namelen ? max_namelen : len); 1774 ret += PAD (len > max_namelen ? max_namelen : len);
1741 1777
1742 if (tc.is_string ()) 1778 if (tc.is_string ())
1743 { 1779 {
1744 charNDArray chm = tc.char_array_value (); 1780 charNDArray chm = tc.char_array_value ();
1745 ret += 8; 1781 ret += 8;
1746 if (chm.nelem () > 2) 1782 if (chm.numel () > 2)
1747 ret += PAD (2 * chm.nelem ()); 1783 ret += PAD (2 * chm.numel ());
1748 } 1784 }
1749 else if (tc.is_sparse_type ()) 1785 else if (tc.is_sparse_type ())
1750 { 1786 {
1751 if (tc.is_complex_type ()) 1787 if (tc.is_complex_type ())
1752 { 1788 {
1753 SparseComplexMatrix m = tc.sparse_complex_matrix_value (); 1789 SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
1754 int nc = m.cols (); 1790 octave_idx_type nc = m.cols ();
1755 int nnz = m.nzmax (); 1791 octave_idx_type nnz = m.nzmax ();
1756 1792
1757 ret += 16 + PAD (nnz * sizeof (int)) + PAD ((nc + 1) * sizeof (int)) + 1793 ret += 16 + PAD (nnz * sizeof (int)) + PAD ((nc + 1) * sizeof (int)) +
1758 save_mat5_array_length (m.data (), m.nelem (), save_as_floats); 1794 save_mat5_array_length (m.data (), nnz, save_as_floats);
1759 } 1795 }
1760 else 1796 else
1761 { 1797 {
1762 SparseMatrix m = tc.sparse_matrix_value (); 1798 SparseMatrix m = tc.sparse_matrix_value ();
1763 int nc = m.cols (); 1799 octave_idx_type nc = m.cols ();
1764 int nnz = m.nzmax (); 1800 octave_idx_type nnz = m.nzmax ();
1765 1801
1766 ret += 16 + PAD (nnz * sizeof (int)) + PAD ((nc + 1) * sizeof (int)) + 1802 ret += 16 + PAD (nnz * sizeof (int)) + PAD ((nc + 1) * sizeof (int)) +
1767 save_mat5_array_length (m.data (), m.nelem (), save_as_floats); 1803 save_mat5_array_length (m.data (), nnz, save_as_floats);
1768 } 1804 }
1769 } 1805 }
1770 1806
1771 #define INT_LEN(nel, size) \ 1807 #define INT_LEN(nel, size) \
1772 { \ 1808 { \
1773 ret += 8; \ 1809 ret += 8; \
1774 int sz = nel * size; \ 1810 octave_idx_type sz = nel * size; \
1775 if (sz > 4) \ 1811 if (sz > 4) \
1776 ret += PAD (sz); \ 1812 ret += PAD (sz); \
1777 } 1813 }
1778 1814
1779 else if (cname == "int8") 1815 else if (cname == "int8")
1780 INT_LEN (tc.int8_array_value ().nelem (), 1) 1816 INT_LEN (tc.int8_array_value ().numel (), 1)
1781 else if (cname == "int16") 1817 else if (cname == "int16")
1782 INT_LEN (tc.int16_array_value ().nelem (), 2) 1818 INT_LEN (tc.int16_array_value ().numel (), 2)
1783 else if (cname == "int32") 1819 else if (cname == "int32")
1784 INT_LEN (tc.int32_array_value ().nelem (), 4) 1820 INT_LEN (tc.int32_array_value ().numel (), 4)
1785 else if (cname == "int64") 1821 else if (cname == "int64")
1786 INT_LEN (tc.int64_array_value ().nelem (), 8) 1822 INT_LEN (tc.int64_array_value ().numel (), 8)
1787 else if (cname == "uint8") 1823 else if (cname == "uint8")
1788 INT_LEN (tc.uint8_array_value ().nelem (), 1) 1824 INT_LEN (tc.uint8_array_value ().numel (), 1)
1789 else if (cname == "uint16") 1825 else if (cname == "uint16")
1790 INT_LEN (tc.uint16_array_value ().nelem (), 2) 1826 INT_LEN (tc.uint16_array_value ().numel (), 2)
1791 else if (cname == "uint32") 1827 else if (cname == "uint32")
1792 INT_LEN (tc.uint32_array_value ().nelem (), 4) 1828 INT_LEN (tc.uint32_array_value ().numel (), 4)
1793 else if (cname == "uint64") 1829 else if (cname == "uint64")
1794 INT_LEN (tc.uint64_array_value ().nelem (), 8) 1830 INT_LEN (tc.uint64_array_value ().numel (), 8)
1795 else if (tc.is_bool_type ()) 1831 else if (tc.is_bool_type ())
1796 INT_LEN (tc.bool_array_value ().nelem (), 1) 1832 INT_LEN (tc.bool_array_value ().numel (), 1)
1797 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()) 1833 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
1798 { 1834 {
1799 NDArray m = tc.array_value (); 1835 NDArray m = tc.array_value ();
1800 ret += save_mat5_array_length (m.fortran_vec (), m.nelem (), 1836 ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
1801 save_as_floats); 1837 save_as_floats);
1802 } 1838 }
1803 else if (tc.is_cell ()) 1839 else if (tc.is_cell ())
1804 { 1840 {
1805 Cell cell = tc.cell_value (); 1841 Cell cell = tc.cell_value ();
1806 int nel = cell.nelem (); 1842 octave_idx_type nel = cell.numel ();
1807 1843
1808 for (int i = 0; i < nel; i++) 1844 for (int i = 0; i < nel; i++)
1809 ret += 8 + 1845 ret += 8 +
1810 save_mat5_element_length (cell (i), "", save_as_floats, mat7_format); 1846 save_mat5_element_length (cell (i), "", save_as_floats, mat7_format);
1811 } 1847 }
1812 else if (tc.is_complex_scalar () || tc.is_complex_matrix ()) 1848 else if (tc.is_complex_scalar () || tc.is_complex_matrix ())
1813 { 1849 {
1814 ComplexNDArray m = tc.complex_array_value (); 1850 ComplexNDArray m = tc.complex_array_value ();
1815 ret += save_mat5_array_length (m.fortran_vec (), m.nelem (), 1851 ret += save_mat5_array_length (m.fortran_vec (), m.numel (),
1816 save_as_floats); 1852 save_as_floats);
1817 } 1853 }
1818 else if (tc.is_map () || tc.is_inline_function () || tc.is_object ()) 1854 else if (tc.is_map () || tc.is_inline_function () || tc.is_object ())
1819 { 1855 {
1820 int fieldcnt = 0; 1856 int fieldcnt = 0;
1821 const Octave_map m = tc.map_value (); 1857 const Octave_map m = tc.map_value ();
1822 int nel = m.numel (); 1858 octave_idx_type nel = m.numel ();
1823 1859
1824 if (tc.is_inline_function ()) 1860 if (tc.is_inline_function ())
1825 // length of "inline" is 6 1861 // length of "inline" is 6
1826 ret += 8 + PAD (6 > max_namelen ? max_namelen : 6); 1862 ret += 8 + PAD (6 > max_namelen ? max_namelen : 6);
1827 else if (tc.is_object ()) 1863 else if (tc.is_object ())
1828 { 1864 {
1829 int classlen = tc.class_name (). length (); 1865 size_t classlen = tc.class_name (). length ();
1830 1866
1831 ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen); 1867 ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen);
1832 } 1868 }
1833 1869
1834 for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++) 1870 for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
1835 fieldcnt++; 1871 fieldcnt++;
1836 1872
1837 ret += 16 + fieldcnt * (max_namelen + 1); 1873 ret += 16 + fieldcnt * (max_namelen + 1);
1838 1874
1839 1875
1840 for (int j = 0; j < nel; j++) 1876 for (octave_idx_type j = 0; j < nel; j++)
1841 { 1877 {
1842 1878
1843 for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++) 1879 for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
1844 { 1880 {
1845 const Cell elts = m.contents (i); 1881 const Cell elts = m.contents (i);
1851 } 1887 }
1852 else 1888 else
1853 ret = -1; 1889 ret = -1;
1854 1890
1855 return ret; 1891 return ret;
1892 }
1893
1894 static void
1895 write_mat5_sparse_index_vector (std::ostream& os,
1896 const octave_idx_type *idx,
1897 octave_idx_type nel)
1898 {
1899 int tmp = sizeof (int);
1900
1901 OCTAVE_LOCAL_BUFFER (int32_t, tmp_idx, nel);
1902
1903 for (octave_idx_type i = 0; i < nel; i++)
1904 tmp_idx[i] = idx[i];
1905
1906 write_mat5_integer_data (os, tmp_idx, -tmp, nel);
1907 }
1908
1909 static void
1910 gripe_dim_too_large (const std::string& name)
1911 {
1912 warning ("save: skipping %s: dimension too large for MAT format",
1913 name.c_str ());
1856 } 1914 }
1857 1915
1858 // save the data from TC along with the corresponding NAME on stream 1916 // save the data from TC along with the corresponding NAME on stream
1859 // OS in the MatLab version 5 binary format. Return true on success. 1917 // OS in the MatLab version 5 binary format. Return true on success.
1860 1918
1862 save_mat5_binary_element (std::ostream& os, 1920 save_mat5_binary_element (std::ostream& os,
1863 const octave_value& tc, const std::string& name, 1921 const octave_value& tc, const std::string& name,
1864 bool mark_as_global, bool mat7_format, 1922 bool mark_as_global, bool mat7_format,
1865 bool save_as_floats, bool compressing) 1923 bool save_as_floats, bool compressing)
1866 { 1924 {
1867 int32_t flags=0; 1925 int32_t flags = 0;
1868 int32_t nnz=0; 1926 int32_t nnz_32 = 0;
1869 std::streampos fixup, contin;
1870 std::string cname = tc.class_name (); 1927 std::string cname = tc.class_name ();
1871 int max_namelen = (mat7_format ? 63 : 31); 1928 size_t max_namelen = (mat7_format ? 63 : 31);
1929
1930 dim_vector dv = tc.dims ();
1931 int nd = tc.ndims ();
1932 int dim_len = 4*nd;
1933
1934 static octave_idx_type max_dim_val = std::numeric_limits<int32_t>::max ();
1935
1936 for (int i = 0; i < nd; i++)
1937 {
1938 if (dv(i) > max_dim_val)
1939 {
1940 gripe_dim_too_large (name);
1941 goto skip_to_next;
1942 }
1943 }
1944
1945 if (tc.is_sparse_type ())
1946 {
1947 octave_idx_type nnz;
1948 octave_idx_type nc;
1949
1950 if (tc.is_complex_type ())
1951 {
1952 SparseComplexMatrix scm = tc.sparse_complex_matrix_value ();
1953 nnz = scm.nzmax ();
1954 nc = scm.cols ();
1955 }
1956 else
1957 {
1958 SparseMatrix sm = tc.sparse_matrix_value ();
1959 nnz = sm.nzmax ();
1960 nc = sm.cols ();
1961 }
1962
1963 if (nnz > max_dim_val || nc + 1 > max_dim_val)
1964 {
1965 gripe_dim_too_large (name);
1966 goto skip_to_next;
1967 }
1968
1969 nnz_32 = nnz;
1970 }
1971 else if (dv.numel () > max_dim_val)
1972 {
1973 gripe_dim_too_large (name);
1974 goto skip_to_next;
1975 }
1872 1976
1873 #ifdef HAVE_ZLIB 1977 #ifdef HAVE_ZLIB
1874 if (mat7_format && !compressing) 1978 if (mat7_format && !compressing)
1875 { 1979 {
1876 bool ret = false; 1980 bool ret = false;
1892 OCTAVE_LOCAL_BUFFER (char, out_buf, destLen); 1996 OCTAVE_LOCAL_BUFFER (char, out_buf, destLen);
1893 1997
1894 if (compress (reinterpret_cast<Bytef *> (out_buf), &destLen, 1998 if (compress (reinterpret_cast<Bytef *> (out_buf), &destLen,
1895 reinterpret_cast<const Bytef *> (buf_str.c_str ()), srcLen) == Z_OK) 1999 reinterpret_cast<const Bytef *> (buf_str.c_str ()), srcLen) == Z_OK)
1896 { 2000 {
1897 write_mat5_tag (os, miCOMPRESSED, static_cast<int> (destLen)); 2001 write_mat5_tag (os, miCOMPRESSED,
2002 static_cast<octave_idx_type> (destLen));
2003
1898 os.write (out_buf, destLen); 2004 os.write (out_buf, destLen);
1899 } 2005 }
1900 else 2006 else
1901 { 2007 {
1902 error ("save: error compressing data element"); 2008 error ("save: error compressing data element");
1906 2012
1907 return ret; 2013 return ret;
1908 } 2014 }
1909 #endif 2015 #endif
1910 2016
1911 // element type and length
1912 fixup = os.tellp ();
1913 write_mat5_tag (os, miMATRIX, save_mat5_element_length 2017 write_mat5_tag (os, miMATRIX, save_mat5_element_length
1914 (tc, name, save_as_floats, mat7_format)); 2018 (tc, name, save_as_floats, mat7_format));
1915 2019
1916 // array flags subelement 2020 // array flags subelement
1917 write_mat5_tag (os, miUINT32, 8); 2021 write_mat5_tag (os, miUINT32, 8);
1942 else if (cname == "uint32") 2046 else if (cname == "uint32")
1943 flags |= MAT_FILE_UINT32_CLASS; 2047 flags |= MAT_FILE_UINT32_CLASS;
1944 else if (cname == "uint64") 2048 else if (cname == "uint64")
1945 flags |= MAT_FILE_UINT64_CLASS; 2049 flags |= MAT_FILE_UINT64_CLASS;
1946 else if (tc.is_sparse_type ()) 2050 else if (tc.is_sparse_type ())
1947 { 2051 flags |= MAT_FILE_SPARSE_CLASS;
1948 flags |= MAT_FILE_SPARSE_CLASS;
1949 if (tc.is_complex_type ())
1950 {
1951 SparseComplexMatrix scm = tc.sparse_complex_matrix_value ();
1952 nnz = scm.nzmax ();
1953 }
1954 else
1955 {
1956 SparseMatrix sm = tc.sparse_matrix_value ();
1957 nnz = sm.nzmax ();
1958 }
1959 }
1960 else if (tc.is_real_scalar ()) 2052 else if (tc.is_real_scalar ())
1961 flags |= MAT_FILE_DOUBLE_CLASS; 2053 flags |= MAT_FILE_DOUBLE_CLASS;
1962 else if (tc.is_real_matrix () || tc.is_range ()) 2054 else if (tc.is_real_matrix () || tc.is_range ())
1963 flags |= MAT_FILE_DOUBLE_CLASS; 2055 flags |= MAT_FILE_DOUBLE_CLASS;
1964 else if (tc.is_complex_scalar ()) 2056 else if (tc.is_complex_scalar ())
1976 gripe_wrong_type_arg ("save", tc, false); 2068 gripe_wrong_type_arg ("save", tc, false);
1977 goto error_cleanup; 2069 goto error_cleanup;
1978 } 2070 }
1979 2071
1980 os.write (reinterpret_cast<char *> (&flags), 4); 2072 os.write (reinterpret_cast<char *> (&flags), 4);
1981 os.write (reinterpret_cast<char *> (&nnz), 4); 2073 os.write (reinterpret_cast<char *> (&nnz_32), 4);
1982 2074
1983 { 2075 write_mat5_tag (os, miINT32, dim_len);
1984 dim_vector dv = tc.dims (); 2076
1985 int nd = tc.ndims (); 2077 for (int i = 0; i < nd; i++)
1986 int dim_len = 4*nd; 2078 {
1987 2079 int32_t n = dv(i);
1988 write_mat5_tag (os, miINT32, dim_len); 2080 os.write (reinterpret_cast<char *> (&n), 4);
1989 2081 }
1990 for (int i = 0; i < nd; i++) 2082
1991 { 2083 if (PAD (dim_len) > dim_len)
1992 int32_t n = dv(i); 2084 {
1993 os.write (reinterpret_cast<char *> (&n), 4); 2085 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
1994 } 2086 os.write (buf, PAD (dim_len) - dim_len);
1995 2087 }
1996 if (PAD (dim_len) > dim_len)
1997 {
1998 static char buf[9]="\x00\x00\x00\x00\x00\x00\x00\x00";
1999 os.write (buf, PAD (dim_len) - dim_len);
2000 }
2001 }
2002 2088
2003 // array name subelement 2089 // array name subelement
2004 { 2090 {
2005 int namelen = name.length (); 2091 size_t namelen = name.length ();
2006 2092
2007 if (namelen > max_namelen) 2093 if (namelen > max_namelen)
2008 namelen = max_namelen; // only 31 or 63 char names permitted in mat file 2094 namelen = max_namelen; // only 31 or 63 char names permitted in mat file
2009 2095
2010 int paddedlength = PAD (namelen); 2096 int paddedlength = PAD (namelen);
2018 2104
2019 // data element 2105 // data element
2020 if (tc.is_string ()) 2106 if (tc.is_string ())
2021 { 2107 {
2022 charNDArray chm = tc.char_array_value (); 2108 charNDArray chm = tc.char_array_value ();
2023 int nel = chm.nelem (); 2109 octave_idx_type nel = chm.numel ();
2024 int len = nel*2; 2110 octave_idx_type len = nel*2;
2025 int paddedlength = PAD (len); 2111 octave_idx_type paddedlength = PAD (len);
2026 2112
2027 OCTAVE_LOCAL_BUFFER (int16_t, buf, nel+3); 2113 OCTAVE_LOCAL_BUFFER (int16_t, buf, nel+3);
2028 write_mat5_tag (os, miUINT16, len); 2114 write_mat5_tag (os, miUINT16, len);
2029 2115
2030 const char *s = chm.data (); 2116 const char *s = chm.data ();
2031 2117
2032 for (int i = 0; i < nel; i++) 2118 for (octave_idx_type i = 0; i < nel; i++)
2033 buf[i] = *s++ & 0x00FF; 2119 buf[i] = *s++ & 0x00FF;
2034 2120
2035 os.write (reinterpret_cast<char *> (buf), len); 2121 os.write (reinterpret_cast<char *> (buf), len);
2036 2122
2037 if (paddedlength > len) 2123 if (paddedlength > len)
2043 else if (tc.is_sparse_type ()) 2129 else if (tc.is_sparse_type ())
2044 { 2130 {
2045 if (tc.is_complex_type ()) 2131 if (tc.is_complex_type ())
2046 { 2132 {
2047 SparseComplexMatrix m = tc.sparse_complex_matrix_value (); 2133 SparseComplexMatrix m = tc.sparse_complex_matrix_value ();
2048 int nc = m.cols (); 2134 octave_idx_type nnz = m.nnz ();
2049 2135 octave_idx_type nc = m.cols ();
2050 int tmp = sizeof (int); 2136
2051 2137 write_mat5_sparse_index_vector (os, m.ridx (), nnz);
2052 write_mat5_integer_data (os, m.ridx (), -tmp, nnz); 2138 write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
2053 write_mat5_integer_data (os, m.cidx (), -tmp, nc + 1);
2054 2139
2055 NDArray buf (dim_vector (nnz, 1)); 2140 NDArray buf (dim_vector (nnz, 1));
2056 2141
2057 for (int i = 0; i < nnz; i++) 2142 for (octave_idx_type i = 0; i < nnz; i++)
2058 buf (i) = std::real (m.data (i)); 2143 buf (i) = std::real (m.data (i));
2059 2144
2060 write_mat5_array (os, buf, save_as_floats); 2145 write_mat5_array (os, buf, save_as_floats);
2061 2146
2062 for (int i = 0; i < nnz; i++) 2147 for (octave_idx_type i = 0; i < nnz; i++)
2063 buf (i) = std::imag (m.data (i)); 2148 buf (i) = std::imag (m.data (i));
2064 2149
2065 write_mat5_array (os, buf, save_as_floats); 2150 write_mat5_array (os, buf, save_as_floats);
2066 } 2151 }
2067 else 2152 else
2068 { 2153 {
2069 SparseMatrix m = tc.sparse_matrix_value (); 2154 SparseMatrix m = tc.sparse_matrix_value ();
2070 int nc = m.cols (); 2155 octave_idx_type nnz = m.nnz ();
2071 2156 octave_idx_type nc = m.cols ();
2072 int tmp = sizeof (int); 2157
2073 2158 write_mat5_sparse_index_vector (os, m.ridx (), nnz);
2074 write_mat5_integer_data (os, m.ridx (), -tmp, nnz); 2159 write_mat5_sparse_index_vector (os, m.cidx (), nc + 1);
2075 write_mat5_integer_data (os, m.cidx (), -tmp, nc + 1);
2076 2160
2077 // FIXME 2161 // FIXME
2078 // Is there a way to easily do without this buffer 2162 // Is there a way to easily do without this buffer
2079 NDArray buf (dim_vector (nnz, 1)); 2163 NDArray buf (dim_vector (nnz, 1));
2080 2164
2086 } 2170 }
2087 else if (cname == "int8") 2171 else if (cname == "int8")
2088 { 2172 {
2089 int8NDArray m = tc.int8_array_value (); 2173 int8NDArray m = tc.int8_array_value ();
2090 2174
2091 write_mat5_integer_data (os, m.fortran_vec (), -1, m.nelem ()); 2175 write_mat5_integer_data (os, m.fortran_vec (), -1, m.numel ());
2092 } 2176 }
2093 else if (cname == "int16") 2177 else if (cname == "int16")
2094 { 2178 {
2095 int16NDArray m = tc.int16_array_value (); 2179 int16NDArray m = tc.int16_array_value ();
2096 2180
2097 write_mat5_integer_data (os, m.fortran_vec (), -2, m.nelem ()); 2181 write_mat5_integer_data (os, m.fortran_vec (), -2, m.numel ());
2098 } 2182 }
2099 else if (cname == "int32") 2183 else if (cname == "int32")
2100 { 2184 {
2101 int32NDArray m = tc.int32_array_value (); 2185 int32NDArray m = tc.int32_array_value ();
2102 2186
2103 write_mat5_integer_data (os, m.fortran_vec (), -4, m.nelem ()); 2187 write_mat5_integer_data (os, m.fortran_vec (), -4, m.numel ());
2104 } 2188 }
2105 else if (cname == "int64") 2189 else if (cname == "int64")
2106 { 2190 {
2107 int64NDArray m = tc.int64_array_value (); 2191 int64NDArray m = tc.int64_array_value ();
2108 2192
2109 write_mat5_integer_data (os, m.fortran_vec (), -8, m.nelem ()); 2193 write_mat5_integer_data (os, m.fortran_vec (), -8, m.numel ());
2110 } 2194 }
2111 else if (cname == "uint8") 2195 else if (cname == "uint8")
2112 { 2196 {
2113 uint8NDArray m = tc.uint8_array_value (); 2197 uint8NDArray m = tc.uint8_array_value ();
2114 2198
2115 write_mat5_integer_data (os, m.fortran_vec (), 1, m.nelem ()); 2199 write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
2116 } 2200 }
2117 else if (cname == "uint16") 2201 else if (cname == "uint16")
2118 { 2202 {
2119 uint16NDArray m = tc.uint16_array_value (); 2203 uint16NDArray m = tc.uint16_array_value ();
2120 2204
2121 write_mat5_integer_data (os, m.fortran_vec (), 2, m.nelem ()); 2205 write_mat5_integer_data (os, m.fortran_vec (), 2, m.numel ());
2122 } 2206 }
2123 else if (cname == "uint32") 2207 else if (cname == "uint32")
2124 { 2208 {
2125 uint32NDArray m = tc.uint32_array_value (); 2209 uint32NDArray m = tc.uint32_array_value ();
2126 2210
2127 write_mat5_integer_data (os, m.fortran_vec (), 4, m.nelem ()); 2211 write_mat5_integer_data (os, m.fortran_vec (), 4, m.numel ());
2128 } 2212 }
2129 else if (cname == "uint64") 2213 else if (cname == "uint64")
2130 { 2214 {
2131 uint64NDArray m = tc.uint64_array_value (); 2215 uint64NDArray m = tc.uint64_array_value ();
2132 2216
2133 write_mat5_integer_data (os, m.fortran_vec (), 8, m.nelem ()); 2217 write_mat5_integer_data (os, m.fortran_vec (), 8, m.numel ());
2134 } 2218 }
2135 else if (tc.is_bool_type ()) 2219 else if (tc.is_bool_type ())
2136 { 2220 {
2137 uint8NDArray m (tc.bool_array_value ()); 2221 uint8NDArray m (tc.bool_array_value ());
2138 2222
2139 write_mat5_integer_data (os, m.fortran_vec (), 1, m.nelem ()); 2223 write_mat5_integer_data (os, m.fortran_vec (), 1, m.numel ());
2140 } 2224 }
2141 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()) 2225 else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ())
2142 { 2226 {
2143 NDArray m = tc.array_value (); 2227 NDArray m = tc.array_value ();
2144 2228
2161 else if (tc.is_map () || tc.is_inline_function() || tc.is_object ()) 2245 else if (tc.is_map () || tc.is_inline_function() || tc.is_object ())
2162 { 2246 {
2163 if (tc.is_inline_function () || tc.is_object ()) 2247 if (tc.is_inline_function () || tc.is_object ())
2164 { 2248 {
2165 std::string classname = tc.is_object() ? tc.class_name () : "inline"; 2249 std::string classname = tc.is_object() ? tc.class_name () : "inline";
2166 int namelen = classname.length (); 2250 size_t namelen = classname.length ();
2167 2251
2168 if (namelen > max_namelen) 2252 if (namelen > max_namelen)
2169 namelen = max_namelen; // only 31 or 63 char names permitted 2253 namelen = max_namelen; // only 31 or 63 char names permitted
2170 2254
2171 int paddedlength = PAD (namelen); 2255 int paddedlength = PAD (namelen);
2197 char buf[64]; 2281 char buf[64];
2198 int32_t maxfieldnamelength = max_namelen + 1; 2282 int32_t maxfieldnamelength = max_namelen + 1;
2199 2283
2200 octave_idx_type nf = m.nfields (); 2284 octave_idx_type nf = m.nfields ();
2201 2285
2202 int fieldcnt = nf;
2203
2204 write_mat5_tag (os, miINT32, 4); 2286 write_mat5_tag (os, miINT32, 4);
2205 os.write (reinterpret_cast<char *> (&maxfieldnamelength), 4); 2287 os.write (reinterpret_cast<char *> (&maxfieldnamelength), 4);
2206 write_mat5_tag (os, miINT8, fieldcnt*maxfieldnamelength); 2288 write_mat5_tag (os, miINT8, nf*maxfieldnamelength);
2207 2289
2208 // Iterating over the list of keys will preserve the order of 2290 // Iterating over the list of keys will preserve the order of
2209 // the fields. 2291 // the fields.
2210 string_vector keys = m.keys (); 2292 string_vector keys = m.keys ();
2211 2293
2218 // only 31 or 63 char names permitted 2300 // only 31 or 63 char names permitted
2219 strncpy (buf, key.c_str (), max_namelen); 2301 strncpy (buf, key.c_str (), max_namelen);
2220 os.write (buf, max_namelen + 1); 2302 os.write (buf, max_namelen + 1);
2221 } 2303 }
2222 2304
2223 int len = m.numel (); 2305 octave_idx_type len = m.numel ();
2224 2306
2225 // Create temporary copy of structure contents to avoid 2307 // Create temporary copy of structure contents to avoid
2226 // multiple calls of the contents method. 2308 // multiple calls of the contents method.
2227 std::vector<const octave_value *> elts (nf); 2309 std::vector<const octave_value *> elts (nf);
2228 for (octave_idx_type i = 0; i < nf; i++) 2310 for (octave_idx_type i = 0; i < nf; i++)
2229 elts[i] = m.contents (keys(i)).data (); 2311 elts[i] = m.contents (keys(i)).data ();
2230 2312
2231 for (int j = 0; j < len; j++) 2313 for (octave_idx_type j = 0; j < len; j++)
2232 { 2314 {
2233 // write the data of each element 2315 // write the data of each element
2234 2316
2235 // Iterating over the list of keys will preserve the order 2317 // Iterating over the list of keys will preserve the order
2236 // of the fields. 2318 // of the fields.
2247 } 2329 }
2248 } 2330 }
2249 else 2331 else
2250 gripe_wrong_type_arg ("save", tc, false); 2332 gripe_wrong_type_arg ("save", tc, false);
2251 2333
2252 contin = os.tellp (); 2334 skip_to_next:
2253
2254 return true; 2335 return true;
2255 2336
2256 error_cleanup: 2337 error_cleanup:
2257 error ("save: error while writing `%s' to MAT file", name.c_str ()); 2338 error ("save: error while writing `%s' to MAT file", name.c_str ());
2258 2339