Mercurial > hg > octave-nkf
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 |