00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <climits>
00028
00029 #include <iostream>
00030 #include <vector>
00031
00032 #include "lo-ieee.h"
00033 #include "lo-utils.h"
00034 #include "mx-base.h"
00035 #include "quit.h"
00036 #include "oct-locbuf.h"
00037
00038 #include "defun.h"
00039 #include "gripes.h"
00040 #include "oct-obj.h"
00041 #include "oct-lvalue.h"
00042 #include "oct-stream.h"
00043 #include "ops.h"
00044 #include "ov-base.h"
00045 #include "ov-base-mat.h"
00046 #include "ov-base-mat.cc"
00047 #include "ov-base-scalar.h"
00048 #include "ov-base-scalar.cc"
00049 #include "ov-base-int.h"
00050 #include "ov-int-traits.h"
00051 #include "pr-output.h"
00052 #include "variables.h"
00053
00054 #include "byte-swap.h"
00055 #include "ls-oct-ascii.h"
00056 #include "ls-utils.h"
00057 #include "ls-hdf5.h"
00058
00059
00060
00061
00062
00063
00064 template <class T, bool is_signed = true, bool can_be_too_big = true>
00065 struct octave_base_int_helper
00066 {
00067 static bool
00068 char_value_out_of_range (T val) { return val < 0 || val > UCHAR_MAX; }
00069 };
00070
00071 template <class T>
00072 struct octave_base_int_helper<T, false, false>
00073 {
00074 static bool char_value_out_of_range (T) { return false; }
00075 };
00076
00077 template <class T>
00078 struct octave_base_int_helper<T, false, true>
00079 {
00080 static bool char_value_out_of_range (T val) { return val > UCHAR_MAX; }
00081 };
00082
00083 template <class T>
00084 struct octave_base_int_helper<T, true, false>
00085 {
00086 static bool char_value_out_of_range (T val) { return val < 0; }
00087 };
00088
00089
00090
00091
00092
00093
00094
00095 template <class T>
00096 struct octave_base_int_helper_traits
00097 {
00098 static const bool can_be_larger_than_uchar_max = true;
00099 };
00100
00101 template <>
00102 struct octave_base_int_helper_traits<char>
00103 {
00104 static const bool can_be_larger_than_uchar_max = false;
00105 };
00106
00107 template <>
00108 struct octave_base_int_helper_traits<signed char>
00109 {
00110 static const bool can_be_larger_than_uchar_max = false;
00111 };
00112
00113 template <>
00114 struct octave_base_int_helper_traits<unsigned char>
00115 {
00116 static const bool can_be_larger_than_uchar_max = false;
00117 };
00118
00119
00120 template <class T>
00121 octave_base_value *
00122 octave_base_int_matrix<T>::try_narrowing_conversion (void)
00123 {
00124 octave_base_value *retval = 0;
00125
00126 if (this->matrix.nelem () == 1)
00127 retval = new typename octave_value_int_traits<T>::scalar_type (this->matrix (0));
00128
00129 return retval;
00130 }
00131
00132 template <class T>
00133 octave_value
00134 octave_base_int_matrix<T>::convert_to_str_internal (bool, bool, char type) const
00135 {
00136 octave_value retval;
00137 dim_vector dv = this->dims ();
00138 octave_idx_type nel = dv.numel ();
00139
00140 charNDArray chm (dv);
00141
00142 bool warned = false;
00143
00144 for (octave_idx_type i = 0; i < nel; i++)
00145 {
00146 octave_quit ();
00147
00148 typename T::element_type tmp = this->matrix(i);
00149
00150 typedef typename T::element_type::val_type val_type;
00151
00152 val_type ival = tmp.value ();
00153
00154 static const bool is_signed = std::numeric_limits<val_type>::is_signed;
00155 static const bool can_be_larger_than_uchar_max
00156 = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;
00157
00158 if (octave_base_int_helper<val_type, is_signed,
00159 can_be_larger_than_uchar_max>::char_value_out_of_range (ival))
00160 {
00161
00162
00163 ival = 0;
00164
00165 if (! warned)
00166 {
00167 ::warning ("range error for conversion to character value");
00168 warned = true;
00169 }
00170 }
00171 else
00172 chm (i) = static_cast<char> (ival);
00173 }
00174
00175 retval = octave_value (chm, type);
00176
00177 return retval;
00178 }
00179
00180 template <class T>
00181 bool
00182 octave_base_int_matrix<T>::save_ascii (std::ostream& os)
00183 {
00184 dim_vector d = this->dims ();
00185
00186 os << "# ndims: " << d.length () << "\n";
00187
00188 for (int i = 0; i < d.length (); i++)
00189 os << " " << d (i);
00190
00191 os << "\n" << this->matrix;
00192
00193 return true;
00194 }
00195
00196 template <class T>
00197 bool
00198 octave_base_int_matrix<T>::load_ascii (std::istream& is)
00199 {
00200 int mdims = 0;
00201 bool success = true;
00202
00203 if (extract_keyword (is, "ndims", mdims, true))
00204 {
00205 if (mdims >= 0)
00206 {
00207 dim_vector dv;
00208 dv.resize (mdims);
00209
00210 for (int i = 0; i < mdims; i++)
00211 is >> dv(i);
00212
00213 T tmp(dv);
00214
00215 is >> tmp;
00216
00217 if (!is)
00218 {
00219 error ("load: failed to load matrix constant");
00220 success = false;
00221 }
00222
00223 this->matrix = tmp;
00224 }
00225 else
00226 {
00227 error ("load: failed to extract number of rows and columns");
00228 success = false;
00229 }
00230 }
00231 else
00232 error ("load: failed to extract number of dimensions");
00233
00234 return success;
00235 }
00236
00237 template <class T>
00238 bool
00239 octave_base_int_matrix<T>::save_binary (std::ostream& os, bool&)
00240 {
00241 dim_vector d = this->dims ();
00242 if (d.length() < 1)
00243 return false;
00244
00245
00246 int32_t tmp = - d.length();
00247 os.write (reinterpret_cast<char *> (&tmp), 4);
00248 for (int i=0; i < d.length (); i++)
00249 {
00250 tmp = d(i);
00251 os.write (reinterpret_cast<char *> (&tmp), 4);
00252 }
00253
00254 os.write (reinterpret_cast<const char *> (this->matrix.data()), this->byte_size());
00255
00256 return true;
00257 }
00258
00259 template <class T>
00260 bool
00261 octave_base_int_matrix<T>::load_binary (std::istream& is, bool swap,
00262 oct_mach_info::float_format )
00263 {
00264 int32_t mdims;
00265 if (! is.read (reinterpret_cast<char *> (&mdims), 4))
00266 return false;
00267 if (swap)
00268 swap_bytes<4> (&mdims);
00269 if (mdims >= 0)
00270 return false;
00271
00272 mdims = - mdims;
00273 int32_t di;
00274 dim_vector dv;
00275 dv.resize (mdims);
00276
00277 for (int i = 0; i < mdims; i++)
00278 {
00279 if (! is.read (reinterpret_cast<char *> (&di), 4))
00280 return false;
00281 if (swap)
00282 swap_bytes<4> (&di);
00283 dv(i) = di;
00284 }
00285
00286
00287
00288
00289
00290 if (mdims == 1)
00291 {
00292 mdims = 2;
00293 dv.resize (mdims);
00294 dv(1) = dv(0);
00295 dv(0) = 1;
00296 }
00297
00298 T m (dv);
00299
00300 if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
00301 return false;
00302
00303 if (swap)
00304 {
00305 int nel = dv.numel ();
00306 int bytes = nel / m.byte_size();
00307 for (int i = 0; i < nel; i++)
00308 switch (bytes)
00309 {
00310 case 8:
00311 swap_bytes<8> (&m(i));
00312 break;
00313 case 4:
00314 swap_bytes<4> (&m(i));
00315 break;
00316 case 2:
00317 swap_bytes<2> (&m(i));
00318 break;
00319 case 1:
00320 default:
00321 break;
00322 }
00323 }
00324
00325 this->matrix = m;
00326 return true;
00327 }
00328
00329 #if defined (HAVE_HDF5)
00330
00331 template <class T>
00332 bool
00333 octave_base_int_matrix<T>::save_hdf5 (hid_t loc_id, const char *name, bool)
00334 {
00335 hid_t save_type_hid = HDF5_SAVE_TYPE;
00336 bool retval = true;
00337 dim_vector dv = this->dims ();
00338 int empty = save_hdf5_empty (loc_id, name, dv);
00339 if (empty)
00340 return (empty > 0);
00341
00342 int rank = dv.length ();
00343 hid_t space_hid = -1, data_hid = -1;
00344 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00345
00346
00347 for (int i = 0; i < rank; i++)
00348 hdims[i] = dv (rank-i-1);
00349
00350 space_hid = H5Screate_simple (rank, hdims, 0);
00351
00352 if (space_hid < 0) return false;
00353 #if HAVE_HDF5_18
00354 data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,
00355 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00356 #else
00357 data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,
00358 H5P_DEFAULT);
00359 #endif
00360 if (data_hid < 0)
00361 {
00362 H5Sclose (space_hid);
00363 return false;
00364 }
00365
00366 retval = H5Dwrite (data_hid, save_type_hid, H5S_ALL, H5S_ALL,
00367 H5P_DEFAULT, this->matrix.data()) >= 0;
00368
00369 H5Dclose (data_hid);
00370 H5Sclose (space_hid);
00371
00372 return retval;
00373 }
00374
00375 template <class T>
00376 bool
00377 octave_base_int_matrix<T>::load_hdf5 (hid_t loc_id, const char *name)
00378 {
00379 hid_t save_type_hid = HDF5_SAVE_TYPE;
00380 bool retval = false;
00381 dim_vector dv;
00382 int empty = load_hdf5_empty (loc_id, name, dv);
00383 if (empty > 0)
00384 this->matrix.resize(dv);
00385 if (empty)
00386 return (empty > 0);
00387
00388 #if HAVE_HDF5_18
00389 hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00390 #else
00391 hid_t data_hid = H5Dopen (loc_id, name);
00392 #endif
00393 hid_t space_id = H5Dget_space (data_hid);
00394
00395 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00396
00397 if (rank < 1)
00398 {
00399 H5Sclose (space_id);
00400 H5Dclose (data_hid);
00401 return false;
00402 }
00403
00404 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00405 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
00406
00407 H5Sget_simple_extent_dims (space_id, hdims, maxdims);
00408
00409
00410 if (rank == 1)
00411 {
00412 dv.resize (2);
00413 dv(0) = 1;
00414 dv(1) = hdims[0];
00415 }
00416 else
00417 {
00418 dv.resize (rank);
00419 for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
00420 dv(j) = hdims[i];
00421 }
00422
00423 T m (dv);
00424 if (H5Dread (data_hid, save_type_hid, H5S_ALL, H5S_ALL,
00425 H5P_DEFAULT, m.fortran_vec()) >= 0)
00426 {
00427 retval = true;
00428 this->matrix = m;
00429 }
00430
00431 H5Sclose (space_id);
00432 H5Dclose (data_hid);
00433
00434 return retval;
00435 }
00436
00437 #endif
00438
00439 template <class T>
00440 void
00441 octave_base_int_matrix<T>::print_raw (std::ostream& os,
00442 bool pr_as_read_syntax) const
00443 {
00444 octave_print_internal (os, this->matrix, pr_as_read_syntax,
00445 this->current_print_indent_level ());
00446 }
00447
00448 template <class T>
00449 octave_value
00450 octave_base_int_scalar<T>::convert_to_str_internal (bool, bool, char type) const
00451 {
00452 octave_value retval;
00453
00454 T tmp = this->scalar;
00455
00456 typedef typename T::val_type val_type;
00457
00458 val_type ival = tmp.value ();
00459
00460 static const bool is_signed = std::numeric_limits<val_type>::is_signed;
00461 static const bool can_be_larger_than_uchar_max
00462 = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;
00463
00464 if (octave_base_int_helper<val_type, is_signed,
00465 can_be_larger_than_uchar_max>::char_value_out_of_range (ival))
00466 {
00467
00468
00469 ival = 0;
00470
00471 ::warning ("range error for conversion to character value");
00472 }
00473 else
00474 retval = octave_value (std::string (1, static_cast<char> (ival)), type);
00475
00476 return retval;
00477 }
00478
00479 template <class T>
00480 bool
00481 octave_base_int_scalar<T>::save_ascii (std::ostream& os)
00482 {
00483 os << this->scalar << "\n";
00484 return true;
00485 }
00486
00487 template <class T>
00488 bool
00489 octave_base_int_scalar<T>::load_ascii (std::istream& is)
00490 {
00491 is >> this->scalar;
00492 if (!is)
00493 {
00494 error ("load: failed to load scalar constant");
00495 return false;
00496 }
00497 return true;
00498 }
00499
00500 template <class T>
00501 bool
00502 octave_base_int_scalar<T>::save_binary (std::ostream& os, bool&)
00503 {
00504 os.write (reinterpret_cast<char *> (&(this->scalar)), this->byte_size());
00505 return true;
00506 }
00507
00508 template <class T>
00509 bool
00510 octave_base_int_scalar<T>::load_binary (std::istream& is, bool swap,
00511 oct_mach_info::float_format)
00512 {
00513 T tmp;
00514 if (! is.read (reinterpret_cast<char *> (&tmp), this->byte_size()))
00515 return false;
00516
00517 if (swap)
00518 switch (this->byte_size())
00519 {
00520 case 8:
00521 swap_bytes<8> (&tmp);
00522 break;
00523 case 4:
00524 swap_bytes<4> (&tmp);
00525 break;
00526 case 2:
00527 swap_bytes<2> (&tmp);
00528 break;
00529 case 1:
00530 default:
00531 break;
00532 }
00533 this->scalar = tmp;
00534 return true;
00535 }
00536
00537 #if defined (HAVE_HDF5)
00538
00539 template <class T>
00540 bool
00541 octave_base_int_scalar<T>::save_hdf5 (hid_t loc_id, const char *name, bool)
00542 {
00543 hid_t save_type_hid = HDF5_SAVE_TYPE;
00544 bool retval = true;
00545 hsize_t dimens[3];
00546 hid_t space_hid = -1, data_hid = -1;
00547
00548 space_hid = H5Screate_simple (0, dimens, 0);
00549 if (space_hid < 0) return false;
00550
00551 #if HAVE_HDF5_18
00552 data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,
00553 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00554 #else
00555 data_hid = H5Dcreate (loc_id, name, save_type_hid, space_hid,
00556 H5P_DEFAULT);
00557 #endif
00558 if (data_hid < 0)
00559 {
00560 H5Sclose (space_hid);
00561 return false;
00562 }
00563
00564 retval = H5Dwrite (data_hid, save_type_hid, H5S_ALL, H5S_ALL,
00565 H5P_DEFAULT, &(this->scalar)) >= 0;
00566
00567 H5Dclose (data_hid);
00568 H5Sclose (space_hid);
00569
00570 return retval;
00571 }
00572
00573 template <class T>
00574 bool
00575 octave_base_int_scalar<T>::load_hdf5 (hid_t loc_id, const char *name)
00576 {
00577 hid_t save_type_hid = HDF5_SAVE_TYPE;
00578 #if HAVE_HDF5_18
00579 hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00580 #else
00581 hid_t data_hid = H5Dopen (loc_id, name);
00582 #endif
00583 hid_t space_id = H5Dget_space (data_hid);
00584
00585 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00586
00587 if (rank != 0)
00588 {
00589 H5Dclose (data_hid);
00590 return false;
00591 }
00592
00593 T tmp;
00594 if (H5Dread (data_hid, save_type_hid, H5S_ALL, H5S_ALL,
00595 H5P_DEFAULT, &tmp) < 0)
00596 {
00597 H5Dclose (data_hid);
00598 return false;
00599 }
00600
00601 this->scalar = tmp;
00602
00603 H5Dclose (data_hid);
00604
00605 return true;
00606 }
00607
00608 #endif