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