ov-re-sparse.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2004-2012 David Bateman
00004 Copyright (C) 1998-2004 Andy Adler
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include <climits>
00029 
00030 #include <iostream>
00031 #include <vector>
00032 
00033 #include "lo-specfun.h"
00034 #include "lo-mappers.h"
00035 #include "oct-locbuf.h"
00036 
00037 #include "ov-base.h"
00038 #include "ov-scalar.h"
00039 #include "gripes.h"
00040 
00041 #include "ls-hdf5.h"
00042 
00043 #include "ov-re-sparse.h"
00044 
00045 #include "ov-base-sparse.h"
00046 #include "ov-base-sparse.cc"
00047 
00048 #include "ov-bool-sparse.h"
00049 
00050 template class OCTINTERP_API octave_base_sparse<SparseMatrix>;
00051 
00052 DEFINE_OCTAVE_ALLOCATOR (octave_sparse_matrix);
00053 
00054 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_matrix, "sparse matrix", "double");
00055 
00056 idx_vector
00057 octave_sparse_matrix::index_vector (void) const
00058 {
00059   if (matrix.numel () == matrix.nnz ())
00060     return idx_vector (array_value ());
00061   else
00062     {
00063       std::string nm = type_name ();
00064       error ("%s type invalid as index value", nm.c_str ());
00065       return idx_vector ();
00066     }
00067 }
00068 
00069 octave_base_value *
00070 octave_sparse_matrix::try_narrowing_conversion (void)
00071 {
00072   octave_base_value *retval = 0;
00073 
00074   if (Vsparse_auto_mutate)
00075     {
00076       // Don't use numel, since it can overflow for very large matrices
00077       // Note that for the second test, this means it becomes approximative
00078       // since it involves a cast to double to avoid issues of overflow
00079       if (matrix.rows () == 1 && matrix.cols () == 1)
00080         {
00081           // Const copy of the matrix, so the right version of () operator used
00082           const SparseMatrix tmp (matrix);
00083 
00084           retval = new octave_scalar (tmp (0));
00085         }
00086       else if (matrix.cols () > 0 && matrix.rows () > 0
00087                && (double (matrix.byte_size ()) > double (matrix.rows ())
00088                    * double (matrix.cols ()) * sizeof (double)))
00089         retval = new octave_matrix (matrix.matrix_value ());
00090     }
00091 
00092   return retval;
00093 }
00094 
00095 double
00096 octave_sparse_matrix::double_value (bool) const
00097 {
00098   double retval = lo_ieee_nan_value ();
00099 
00100   if (numel () > 0)
00101     {
00102       if (numel () > 1)
00103         gripe_implicit_conversion ("Octave:array-as-scalar",
00104                                    "real sparse matrix", "real scalar");
00105 
00106       retval = matrix (0, 0);
00107     }
00108   else
00109     gripe_invalid_conversion ("real sparse matrix", "real scalar");
00110 
00111   return retval;
00112 }
00113 
00114 Complex
00115 octave_sparse_matrix::complex_value (bool) const
00116 {
00117   double tmp = lo_ieee_nan_value ();
00118 
00119   Complex retval (tmp, tmp);
00120 
00121   // FIXME -- maybe this should be a function, valid_as_scalar()
00122   if (rows () > 0 && columns () > 0)
00123     {
00124       if (numel () > 1)
00125         gripe_implicit_conversion ("Octave:array-as-scalar",
00126                                    "real sparse matrix", "complex scalar");
00127 
00128       retval = matrix (0, 0);
00129     }
00130   else
00131     gripe_invalid_conversion ("real sparse matrix", "complex scalar");
00132 
00133   return retval;
00134 }
00135 
00136 Matrix
00137 octave_sparse_matrix::matrix_value (bool) const
00138 {
00139   return matrix.matrix_value ();
00140 }
00141 
00142 boolNDArray
00143 octave_sparse_matrix::bool_array_value (bool warn) const
00144 {
00145   NDArray m = matrix.matrix_value ();
00146 
00147   if (m.any_element_is_nan ())
00148     gripe_nan_to_logical_conversion ();
00149   else if (warn && m.any_element_not_one_or_zero ())
00150     gripe_logical_conversion ();
00151 
00152   return boolNDArray (m);
00153 }
00154 
00155 charNDArray
00156 octave_sparse_matrix::char_array_value (bool) const
00157 {
00158   charNDArray retval (dims (), 0);
00159   octave_idx_type nc = matrix.cols ();
00160   octave_idx_type nr = matrix.rows ();
00161 
00162   for (octave_idx_type j = 0; j < nc; j++)
00163     for (octave_idx_type i = matrix.cidx(j); i < matrix.cidx(j+1); i++)
00164       retval(matrix.ridx(i) + nr * j) = static_cast<char>(matrix.data (i));
00165 
00166   return retval;
00167 }
00168 
00169 ComplexMatrix
00170 octave_sparse_matrix::complex_matrix_value (bool) const
00171 {
00172   return ComplexMatrix (matrix.matrix_value ());
00173 }
00174 
00175 ComplexNDArray
00176 octave_sparse_matrix::complex_array_value (bool) const
00177 {
00178   return ComplexNDArray (ComplexMatrix (matrix.matrix_value ()));
00179 }
00180 
00181 NDArray
00182 octave_sparse_matrix::array_value (bool) const
00183 {
00184   return NDArray (matrix.matrix_value ());
00185 }
00186 
00187 SparseBoolMatrix
00188 octave_sparse_matrix::sparse_bool_matrix_value (bool warn) const
00189 {
00190   if (matrix.any_element_is_nan ())
00191     gripe_nan_to_logical_conversion ();
00192   else if (warn && matrix.any_element_not_one_or_zero ())
00193     gripe_logical_conversion ();
00194 
00195   return mx_el_ne (matrix, 0.0);
00196 }
00197 
00198 octave_value
00199 octave_sparse_matrix::convert_to_str_internal (bool, bool, char type) const
00200 {
00201   octave_value retval;
00202   dim_vector dv = dims ();
00203   octave_idx_type nel = dv.numel ();
00204 
00205   if (nel == 0)
00206     {
00207       char s = '\0';
00208       retval = octave_value (&s, type);
00209     }
00210   else
00211     {
00212       octave_idx_type nr = matrix.rows ();
00213       octave_idx_type nc = matrix.cols ();
00214       charNDArray chm (dv, static_cast<char> (0));
00215 
00216       bool warned = false;
00217 
00218       for (octave_idx_type j = 0; j < nc; j++)
00219         for (octave_idx_type i = matrix.cidx(j);
00220              i < matrix.cidx(j+1); i++)
00221           {
00222             octave_quit ();
00223 
00224             double d = matrix.data (i);
00225 
00226               if (xisnan (d))
00227                 {
00228                   gripe_nan_to_character_conversion ();
00229                   return retval;
00230                 }
00231               else
00232                 {
00233                   int ival = NINT (d);
00234 
00235                   if (ival < 0 || ival > UCHAR_MAX)
00236                     {
00237                       // FIXME -- is there something
00238                       // better we could do?
00239 
00240                       ival = 0;
00241 
00242                       if (! warned)
00243                         {
00244                           ::warning ("range error for conversion to character value");
00245                           warned = true;
00246                         }
00247                     }
00248 
00249                   chm (matrix.ridx(i) + j * nr) =
00250                     static_cast<char> (ival);
00251                 }
00252           }
00253 
00254       retval = octave_value (chm, type);
00255     }
00256 
00257   return retval;
00258 }
00259 
00260 bool
00261 octave_sparse_matrix::save_binary (std::ostream& os, bool&save_as_floats)
00262 {
00263   dim_vector d = this->dims ();
00264   if (d.length() < 1)
00265     return false;
00266 
00267   // Ensure that additional memory is deallocated
00268   matrix.maybe_compress ();
00269 
00270   int nr = d(0);
00271   int nc = d(1);
00272   int nz = nnz ();
00273 
00274   int32_t itmp;
00275   // Use negative value for ndims to be consistent with other formats
00276   itmp= -2;
00277   os.write (reinterpret_cast<char *> (&itmp), 4);
00278 
00279   itmp= nr;
00280   os.write (reinterpret_cast<char *> (&itmp), 4);
00281 
00282   itmp= nc;
00283   os.write (reinterpret_cast<char *> (&itmp), 4);
00284 
00285   itmp= nz;
00286   os.write (reinterpret_cast<char *> (&itmp), 4);
00287 
00288   save_type st = LS_DOUBLE;
00289   if (save_as_floats)
00290     {
00291       if (matrix.too_large_for_float ())
00292         {
00293           warning ("save: some values too large to save as floats --");
00294           warning ("save: saving as doubles instead");
00295         }
00296       else
00297         st = LS_FLOAT;
00298     }
00299   else if (matrix.nnz () > 8192) // FIXME -- make this configurable.
00300     {
00301       double max_val, min_val;
00302       if (matrix.all_integers (max_val, min_val))
00303         st = get_save_type (max_val, min_val);
00304     }
00305 
00306   // add one to the printed indices to go from
00307   // zero-based to one-based arrays
00308    for (int i = 0; i < nc+1; i++)
00309      {
00310        octave_quit ();
00311        itmp = matrix.cidx(i);
00312        os.write (reinterpret_cast<char *> (&itmp), 4);
00313      }
00314 
00315    for (int i = 0; i < nz; i++)
00316      {
00317        octave_quit ();
00318        itmp = matrix.ridx(i);
00319        os.write (reinterpret_cast<char *> (&itmp), 4);
00320      }
00321 
00322    write_doubles (os, matrix.data(), st, nz);
00323 
00324   return true;
00325 }
00326 
00327 bool
00328 octave_sparse_matrix::load_binary (std::istream& is, bool swap,
00329                                    oct_mach_info::float_format fmt)
00330 {
00331   int32_t nz, nc, nr, tmp;
00332   char ctmp;
00333 
00334   if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00335     return false;
00336 
00337   if (swap)
00338     swap_bytes<4> (&tmp);
00339 
00340   if (tmp != -2) {
00341     error ("load: only 2D sparse matrices are supported");
00342     return false;
00343   }
00344 
00345   if (! is.read (reinterpret_cast<char *> (&nr), 4))
00346     return false;
00347   if (! is.read (reinterpret_cast<char *> (&nc), 4))
00348     return false;
00349   if (! is.read (reinterpret_cast<char *> (&nz), 4))
00350     return false;
00351 
00352   if (swap)
00353     {
00354       swap_bytes<4> (&nr);
00355       swap_bytes<4> (&nc);
00356       swap_bytes<4> (&nz);
00357     }
00358 
00359   SparseMatrix m (static_cast<octave_idx_type> (nr),
00360                   static_cast<octave_idx_type> (nc),
00361                   static_cast<octave_idx_type> (nz));
00362 
00363   for (int i = 0; i < nc+1; i++)
00364     {
00365       octave_quit ();
00366       if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00367         return false;
00368       if (swap)
00369         swap_bytes<4> (&tmp);
00370       m.xcidx(i) = tmp;
00371     }
00372 
00373   for (int i = 0; i < nz; i++)
00374     {
00375       octave_quit ();
00376       if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00377         return false;
00378       if (swap)
00379         swap_bytes<4> (&tmp);
00380       m.xridx(i) = tmp;
00381     }
00382 
00383   if (! is.read (reinterpret_cast<char *> (&ctmp), 1))
00384     return false;
00385 
00386   read_doubles (is, m.xdata (), static_cast<save_type> (ctmp), nz, swap, fmt);
00387 
00388   if (error_state || ! is)
00389     return false;
00390 
00391   if (! m.indices_ok ())
00392     return false;
00393 
00394   matrix = m;
00395 
00396   return true;
00397 }
00398 
00399 #if defined (HAVE_HDF5)
00400 
00401 bool
00402 octave_sparse_matrix::save_hdf5 (hid_t loc_id, const char *name,
00403                                  bool save_as_floats)
00404 {
00405   dim_vector dv = dims ();
00406   int empty = save_hdf5_empty (loc_id, name, dv);
00407   if (empty)
00408     return (empty > 0);
00409 
00410   // Ensure that additional memory is deallocated
00411   matrix.maybe_compress ();
00412 
00413 #if HAVE_HDF5_18
00414   hid_t group_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00415 #else
00416   hid_t group_hid = H5Gcreate (loc_id, name, 0);
00417 #endif
00418   if (group_hid < 0)
00419     return false;
00420 
00421   hid_t space_hid = -1, data_hid = -1;
00422   bool retval = true;
00423   SparseMatrix m = sparse_matrix_value ();
00424   octave_idx_type tmp;
00425   hsize_t hdims[2];
00426 
00427   space_hid = H5Screate_simple (0, hdims, 0);
00428   if (space_hid < 0)
00429     {
00430       H5Gclose (group_hid);
00431       return false;
00432     }
00433 #if HAVE_HDF5_18
00434   data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_IDX, space_hid,
00435                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00436 #else
00437   data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_IDX, space_hid,
00438                         H5P_DEFAULT);
00439 #endif
00440   if (data_hid < 0)
00441     {
00442       H5Sclose (space_hid);
00443       H5Gclose (group_hid);
00444       return false;
00445     }
00446 
00447   tmp = m.rows ();
00448   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00449                      &tmp) >= 0;
00450   H5Dclose (data_hid);
00451   if (!retval)
00452     {
00453       H5Sclose (space_hid);
00454       H5Gclose (group_hid);
00455       return false;
00456     }
00457 #if HAVE_HDF5_18
00458   data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_IDX, space_hid,
00459                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00460 #else
00461   data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_IDX, space_hid,
00462                         H5P_DEFAULT);
00463 #endif
00464   if (data_hid < 0)
00465     {
00466       H5Sclose (space_hid);
00467       H5Gclose (group_hid);
00468       return false;
00469     }
00470 
00471   tmp = m.cols ();
00472   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00473                      &tmp) >= 0;
00474   H5Dclose (data_hid);
00475   if (!retval)
00476     {
00477       H5Sclose (space_hid);
00478       H5Gclose (group_hid);
00479       return false;
00480     }
00481 
00482 #if HAVE_HDF5_18
00483   data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_IDX, space_hid,
00484                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00485 #else
00486   data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_IDX, space_hid,
00487                         H5P_DEFAULT);
00488 #endif
00489   if (data_hid < 0)
00490     {
00491       H5Sclose (space_hid);
00492       H5Gclose (group_hid);
00493       return false;
00494     }
00495 
00496   tmp = m.nnz ();
00497   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00498                      &tmp) >= 0;
00499   H5Dclose (data_hid);
00500   if (!retval)
00501     {
00502       H5Sclose (space_hid);
00503       H5Gclose (group_hid);
00504       return false;
00505     }
00506 
00507   H5Sclose (space_hid);
00508 
00509   hdims[0] = m.cols() + 1;
00510   hdims[1] = 1;
00511 
00512   space_hid = H5Screate_simple (2, hdims, 0);
00513 
00514   if (space_hid < 0)
00515     {
00516       H5Gclose (group_hid);
00517       return false;
00518     }
00519 
00520 #if HAVE_HDF5_18
00521   data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_IDX, space_hid,
00522                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00523 #else
00524   data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_IDX, space_hid,
00525                         H5P_DEFAULT);
00526 #endif
00527   if (data_hid < 0)
00528     {
00529       H5Sclose (space_hid);
00530       H5Gclose (group_hid);
00531       return false;
00532     }
00533 
00534   octave_idx_type * itmp = m.xcidx ();
00535   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00536                      itmp) >= 0;
00537   H5Dclose (data_hid);
00538   if (!retval)
00539     {
00540       H5Sclose (space_hid);
00541       H5Gclose (group_hid);
00542       return false;
00543     }
00544 
00545   H5Sclose (space_hid);
00546 
00547   hdims[0] = m.nnz ();
00548   hdims[1] = 1;
00549 
00550   space_hid = H5Screate_simple (2, hdims, 0);
00551 
00552   if (space_hid < 0)
00553     {
00554       H5Gclose (group_hid);
00555       return false;
00556     }
00557 #if HAVE_HDF5_18
00558   data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_IDX, space_hid,
00559                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00560 #else
00561   data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_IDX, space_hid,
00562                         H5P_DEFAULT);
00563 #endif
00564   if (data_hid < 0)
00565     {
00566       H5Sclose (space_hid);
00567       H5Gclose (group_hid);
00568       return false;
00569     }
00570 
00571   itmp = m.xridx ();
00572   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL, H5P_DEFAULT,
00573                      itmp) >= 0;
00574   H5Dclose (data_hid);
00575   if (!retval)
00576     {
00577       H5Sclose (space_hid);
00578       H5Gclose (group_hid);
00579       return false;
00580     }
00581 
00582   hid_t save_type_hid = H5T_NATIVE_DOUBLE;
00583 
00584   if (save_as_floats)
00585     {
00586       if (m.too_large_for_float ())
00587         {
00588           warning ("save: some values too large to save as floats --");
00589           warning ("save: saving as doubles instead");
00590         }
00591       else
00592         save_type_hid = H5T_NATIVE_FLOAT;
00593     }
00594 #if HAVE_HDF5_INT2FLOAT_CONVERSIONS
00595   // hdf5 currently doesn't support float/integer conversions
00596   else
00597     {
00598       double max_val, min_val;
00599 
00600       if (m.all_integers (max_val, min_val))
00601         save_type_hid
00602           = save_type_to_hdf5 (get_save_type (max_val, min_val));
00603     }
00604 #endif /* HAVE_HDF5_INT2FLOAT_CONVERSIONS */
00605 
00606 #if HAVE_HDF5_18
00607   data_hid = H5Dcreate (group_hid, "data", save_type_hid, space_hid,
00608                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00609 #else
00610   data_hid = H5Dcreate (group_hid, "data", save_type_hid, space_hid,
00611                         H5P_DEFAULT);
00612 #endif
00613   if (data_hid < 0)
00614     {
00615       H5Sclose (space_hid);
00616       H5Gclose (group_hid);
00617       return false;
00618     }
00619 
00620   double * dtmp = m.xdata ();
00621   retval = H5Dwrite (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
00622                      H5P_DEFAULT, dtmp) >= 0;
00623   H5Dclose (data_hid);
00624   H5Sclose (space_hid);
00625   H5Gclose (group_hid);
00626 
00627   return retval;
00628 }
00629 
00630 bool
00631 octave_sparse_matrix::load_hdf5 (hid_t loc_id, const char *name)
00632 {
00633   octave_idx_type nr, nc, nz;
00634   hid_t group_hid, data_hid, space_hid;
00635   hsize_t rank;
00636 
00637   dim_vector dv;
00638   int empty = load_hdf5_empty (loc_id, name, dv);
00639   if (empty > 0)
00640     matrix.resize(dv);
00641   if (empty)
00642     return (empty > 0);
00643 
00644 #if HAVE_HDF5_18
00645   group_hid = H5Gopen (loc_id, name, H5P_DEFAULT);
00646 #else
00647   group_hid = H5Gopen (loc_id, name);
00648 #endif
00649   if (group_hid < 0) return false;
00650 
00651 #if HAVE_HDF5_18
00652   data_hid = H5Dopen (group_hid, "nr", H5P_DEFAULT);
00653 #else
00654   data_hid = H5Dopen (group_hid, "nr");
00655 #endif
00656   space_hid = H5Dget_space (data_hid);
00657   rank = H5Sget_simple_extent_ndims (space_hid);
00658 
00659   if (rank != 0)
00660     {
00661       H5Dclose (data_hid);
00662       H5Gclose (group_hid);
00663       return false;
00664     }
00665 
00666   if (H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00667                H5P_DEFAULT, &nr) < 0)
00668     {
00669       H5Dclose (data_hid);
00670       H5Gclose (group_hid);
00671       return false;
00672     }
00673 
00674   H5Dclose (data_hid);
00675 
00676 #if HAVE_HDF5_18
00677   data_hid = H5Dopen (group_hid, "nc", H5P_DEFAULT);
00678 #else
00679   data_hid = H5Dopen (group_hid, "nc");
00680 #endif
00681   space_hid = H5Dget_space (data_hid);
00682   rank = H5Sget_simple_extent_ndims (space_hid);
00683 
00684   if (rank != 0)
00685     {
00686       H5Dclose (data_hid);
00687       H5Gclose (group_hid);
00688       return false;
00689     }
00690 
00691   if (H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00692                H5P_DEFAULT, &nc) < 0)
00693     {
00694       H5Dclose (data_hid);
00695       H5Gclose (group_hid);
00696       return false;
00697     }
00698 
00699   H5Dclose (data_hid);
00700 
00701 #if HAVE_HDF5_18
00702   data_hid = H5Dopen (group_hid, "nz", H5P_DEFAULT);
00703 #else
00704   data_hid = H5Dopen (group_hid, "nz");
00705 #endif
00706   space_hid = H5Dget_space (data_hid);
00707   rank = H5Sget_simple_extent_ndims (space_hid);
00708 
00709   if (rank != 0)
00710     {
00711       H5Dclose (data_hid);
00712       H5Gclose (group_hid);
00713       return false;
00714     }
00715 
00716   if (H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00717                H5P_DEFAULT, &nz) < 0)
00718     {
00719       H5Dclose (data_hid);
00720       H5Gclose (group_hid);
00721       return false;
00722     }
00723 
00724   H5Dclose (data_hid);
00725 
00726   SparseMatrix m (static_cast<octave_idx_type> (nr),
00727                   static_cast<octave_idx_type> (nc),
00728                   static_cast<octave_idx_type> (nz));
00729 
00730 #if HAVE_HDF5_18
00731   data_hid = H5Dopen (group_hid, "cidx", H5P_DEFAULT);
00732 #else
00733   data_hid = H5Dopen (group_hid, "cidx");
00734 #endif
00735   space_hid = H5Dget_space (data_hid);
00736   rank = H5Sget_simple_extent_ndims (space_hid);
00737 
00738   if (rank != 2)
00739     {
00740       H5Sclose (space_hid);
00741       H5Dclose (data_hid);
00742       H5Gclose (group_hid);
00743       return false;
00744     }
00745 
00746   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00747   OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
00748 
00749   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
00750 
00751   if (static_cast<int> (hdims[0]) != nc + 1
00752       || static_cast<int> (hdims[1]) != 1)
00753     {
00754       H5Sclose (space_hid);
00755       H5Dclose (data_hid);
00756       H5Gclose (group_hid);
00757       return false;
00758     }
00759 
00760   octave_idx_type *itmp = m.xcidx ();
00761   if (H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00762                H5P_DEFAULT, itmp) < 0)
00763     {
00764       H5Sclose (space_hid);
00765       H5Dclose (data_hid);
00766       H5Gclose (group_hid);
00767       return false;
00768     }
00769 
00770   H5Sclose (space_hid);
00771   H5Dclose (data_hid);
00772 
00773 #if HAVE_HDF5_18
00774   data_hid = H5Dopen (group_hid, "ridx", H5P_DEFAULT);
00775 #else
00776   data_hid = H5Dopen (group_hid, "ridx");
00777 #endif
00778   space_hid = H5Dget_space (data_hid);
00779   rank = H5Sget_simple_extent_ndims (space_hid);
00780 
00781   if (rank != 2)
00782     {
00783       H5Sclose (space_hid);
00784       H5Dclose (data_hid);
00785       H5Gclose (group_hid);
00786       return false;
00787     }
00788 
00789   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
00790 
00791   if (static_cast<int> (hdims[0]) != nz || static_cast<int> (hdims[1]) != 1)
00792     {
00793       H5Sclose (space_hid);
00794       H5Dclose (data_hid);
00795       H5Gclose (group_hid);
00796       return false;
00797     }
00798 
00799   itmp = m.xridx ();
00800   if (H5Dread (data_hid, H5T_NATIVE_IDX, H5S_ALL, H5S_ALL,
00801                H5P_DEFAULT, itmp) < 0)
00802     {
00803       H5Sclose (space_hid);
00804       H5Dclose (data_hid);
00805       H5Gclose (group_hid);
00806       return false;
00807     }
00808 
00809   H5Sclose (space_hid);
00810   H5Dclose (data_hid);
00811 
00812 #if HAVE_HDF5_18
00813   data_hid = H5Dopen (group_hid, "data", H5P_DEFAULT);
00814 #else
00815   data_hid = H5Dopen (group_hid, "data");
00816 #endif
00817   space_hid = H5Dget_space (data_hid);
00818   rank = H5Sget_simple_extent_ndims (space_hid);
00819 
00820   if (rank != 2)
00821     {
00822       H5Sclose (space_hid);
00823       H5Dclose (data_hid);
00824       H5Gclose (group_hid);
00825       return false;
00826     }
00827 
00828   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
00829 
00830   if (static_cast<int> (hdims[0]) != nz || static_cast<int> (hdims[1]) != 1)
00831     {
00832       H5Sclose (space_hid);
00833       H5Dclose (data_hid);
00834       H5Gclose (group_hid);
00835       return false;
00836     }
00837 
00838   double *dtmp = m.xdata ();
00839   bool retval = false;
00840   if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL,
00841                H5P_DEFAULT, dtmp) >= 0
00842       && m.indices_ok ())
00843     {
00844       retval = true;
00845       matrix = m;
00846     }
00847 
00848   H5Sclose (space_hid);
00849   H5Dclose (data_hid);
00850   H5Gclose (group_hid);
00851 
00852   return retval;
00853 }
00854 
00855 #endif
00856 
00857 mxArray *
00858 octave_sparse_matrix::as_mxArray (void) const
00859 {
00860   mwSize nz = nzmax();
00861   mwSize nr = rows();
00862   mwSize nc = columns();
00863   mxArray *retval = new mxArray (mxDOUBLE_CLASS, nr, nc, nz, mxREAL);
00864   double *pr = static_cast<double *> (retval->get_data ());
00865   mwIndex *ir = retval->get_ir();
00866   mwIndex *jc = retval->get_jc();
00867 
00868   for (mwIndex i = 0; i < nz; i++)
00869     {
00870       pr[i] = matrix.data(i);
00871       ir[i] = matrix.ridx(i);
00872     }
00873 
00874   for (mwIndex i = 0; i < nc + 1; i++)
00875     jc[i] = matrix.cidx(i);
00876 
00877   return retval;
00878 }
00879 
00880 octave_value
00881 octave_sparse_matrix::map (unary_mapper_t umap) const
00882 {
00883   switch (umap)
00884     {
00885     case umap_imag:
00886       return SparseMatrix (matrix.rows (), matrix.cols (), 0.0);
00887 
00888     case umap_real:
00889     case umap_conj:
00890       return matrix;
00891 
00892     // Mappers handled specially.
00893 #define ARRAY_METHOD_MAPPER(UMAP, FCN) \
00894     case umap_ ## UMAP: \
00895       return octave_value (matrix.FCN ())
00896 
00897       ARRAY_METHOD_MAPPER (abs, abs);
00898 
00899 #define ARRAY_MAPPER(UMAP, TYPE, FCN) \
00900     case umap_ ## UMAP: \
00901       return octave_value (matrix.map<TYPE> (FCN))
00902 
00903       ARRAY_MAPPER (acos, Complex, rc_acos);
00904       ARRAY_MAPPER (acosh, Complex, rc_acosh);
00905       ARRAY_MAPPER (angle, double, ::arg);
00906       ARRAY_MAPPER (arg, double, ::arg);
00907       ARRAY_MAPPER (asin, Complex, rc_asin);
00908       ARRAY_MAPPER (asinh, double, ::asinh);
00909       ARRAY_MAPPER (atan, double, ::atan);
00910       ARRAY_MAPPER (atanh, Complex, rc_atanh);
00911       ARRAY_MAPPER (erf, double, ::erf);
00912       ARRAY_MAPPER (erfinv, double, ::erfinv);
00913       ARRAY_MAPPER (erfc, double, ::erfc);
00914       ARRAY_MAPPER (gamma, double, xgamma);
00915       ARRAY_MAPPER (lgamma, Complex, rc_lgamma);
00916       ARRAY_MAPPER (cbrt, double, ::cbrt);
00917       ARRAY_MAPPER (ceil, double, ::ceil);
00918       ARRAY_MAPPER (cos, double, ::cos);
00919       ARRAY_MAPPER (cosh, double, ::cosh);
00920       ARRAY_MAPPER (exp, double, ::exp);
00921       ARRAY_MAPPER (expm1, double, ::expm1);
00922       ARRAY_MAPPER (fix, double, ::fix);
00923       ARRAY_MAPPER (floor, double, ::floor);
00924       ARRAY_MAPPER (log, Complex, rc_log);
00925       ARRAY_MAPPER (log2, Complex, rc_log2);
00926       ARRAY_MAPPER (log10, Complex, rc_log10);
00927       ARRAY_MAPPER (log1p, Complex, rc_log1p);
00928       ARRAY_MAPPER (round, double, xround);
00929       ARRAY_MAPPER (roundb, double, xroundb);
00930       ARRAY_MAPPER (signum, double, ::signum);
00931       ARRAY_MAPPER (sin, double, ::sin);
00932       ARRAY_MAPPER (sinh, double, ::sinh);
00933       ARRAY_MAPPER (sqrt, Complex, rc_sqrt);
00934       ARRAY_MAPPER (tan, double, ::tan);
00935       ARRAY_MAPPER (tanh, double, ::tanh);
00936       ARRAY_MAPPER (isnan, bool, xisnan);
00937       ARRAY_MAPPER (isna, bool, octave_is_NA);
00938       ARRAY_MAPPER (isinf, bool, xisinf);
00939       ARRAY_MAPPER (finite, bool, xfinite);
00940 
00941     default: // Attempt to go via dense matrix.
00942       return octave_base_sparse<SparseMatrix>::map (umap);
00943     }
00944 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines