ov-bool-mat.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2009-2010 VZLU Prague
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 <iostream>
00029 #include <vector>
00030 
00031 #include "lo-ieee.h"
00032 #include "mx-base.h"
00033 #include "oct-locbuf.h"
00034 
00035 #include "defun.h"
00036 #include "gripes.h"
00037 #include "oct-obj.h"
00038 #include "ops.h"
00039 #include "ov-base.h"
00040 #include "ov-base-mat.h"
00041 #include "ov-base-mat.cc"
00042 #include "ov-bool.h"
00043 #include "ov-bool-mat.h"
00044 #include "ov-re-mat.h"
00045 #include "pr-output.h"
00046 
00047 #include "byte-swap.h"
00048 #include "ls-oct-ascii.h"
00049 #include "ls-hdf5.h"
00050 #include "ls-utils.h"
00051 
00052 template class octave_base_matrix<boolNDArray>;
00053 
00054 DEFINE_OCTAVE_ALLOCATOR (octave_bool_matrix);
00055 
00056 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_bool_matrix,
00057                                      "bool matrix", "logical");
00058 
00059 static octave_base_value *
00060 default_numeric_conversion_function (const octave_base_value& a)
00061 {
00062   CAST_CONV_ARG (const octave_bool_matrix&);
00063 
00064   return new octave_matrix (NDArray (v.bool_array_value ()));
00065 }
00066 
00067 octave_base_value::type_conv_info
00068 octave_bool_matrix::numeric_conversion_function (void) const
00069 {
00070   return octave_base_value::type_conv_info (default_numeric_conversion_function,
00071                                             octave_matrix::static_type_id ());
00072 }
00073 
00074 octave_base_value *
00075 octave_bool_matrix::try_narrowing_conversion (void)
00076 {
00077   octave_base_value *retval = 0;
00078 
00079   if (matrix.ndims () == 2)
00080     {
00081       boolMatrix bm = matrix.matrix_value ();
00082 
00083       octave_idx_type nr = bm.rows ();
00084       octave_idx_type nc = bm.cols ();
00085 
00086       if (nr == 1 && nc == 1)
00087         retval = new octave_bool (bm (0, 0));
00088     }
00089 
00090   return retval;
00091 }
00092 
00093 double
00094 octave_bool_matrix::double_value (bool) const
00095 {
00096   double retval = lo_ieee_nan_value ();
00097 
00098   if (rows () > 0 && columns () > 0)
00099     {
00100       gripe_implicit_conversion ("Octave:array-as-scalar",
00101                                  "bool matrix", "real scalar");
00102 
00103       retval = matrix (0, 0);
00104     }
00105   else
00106     gripe_invalid_conversion ("bool matrix", "real scalar");
00107 
00108   return retval;
00109 }
00110 
00111 float
00112 octave_bool_matrix::float_value (bool) const
00113 {
00114   float retval = lo_ieee_float_nan_value ();
00115 
00116   if (rows () > 0 && columns () > 0)
00117     {
00118       gripe_implicit_conversion ("Octave:array-as-scalar",
00119                                  "bool matrix", "real scalar");
00120 
00121       retval = matrix (0, 0);
00122     }
00123   else
00124     gripe_invalid_conversion ("bool matrix", "real scalar");
00125 
00126   return retval;
00127 }
00128 
00129 Complex
00130 octave_bool_matrix::complex_value (bool) const
00131 {
00132   double tmp = lo_ieee_nan_value ();
00133 
00134   Complex retval (tmp, tmp);
00135 
00136   if (rows () > 0 && columns () > 0)
00137     {
00138       gripe_implicit_conversion ("Octave:array-as-scalar",
00139                                  "bool matrix", "complex scalar");
00140 
00141       retval = matrix (0, 0);
00142     }
00143   else
00144     gripe_invalid_conversion ("bool matrix", "complex scalar");
00145 
00146   return retval;
00147 }
00148 
00149 FloatComplex
00150 octave_bool_matrix::float_complex_value (bool) const
00151 {
00152   float tmp = lo_ieee_float_nan_value ();
00153 
00154   FloatComplex retval (tmp, tmp);
00155 
00156   if (rows () > 0 && columns () > 0)
00157     {
00158       gripe_implicit_conversion ("Octave:array-as-scalar",
00159                                  "bool matrix", "complex scalar");
00160 
00161       retval = matrix (0, 0);
00162     }
00163   else
00164     gripe_invalid_conversion ("bool matrix", "complex scalar");
00165 
00166   return retval;
00167 }
00168 
00169 octave_value
00170 octave_bool_matrix::convert_to_str_internal (bool pad, bool force,
00171                                              char type) const
00172 {
00173   octave_value tmp = octave_value (array_value ());
00174   return tmp.convert_to_str (pad, force, type);
00175 }
00176 
00177 void
00178 octave_bool_matrix::print_raw (std::ostream& os,
00179                                bool pr_as_read_syntax) const
00180 {
00181   octave_print_internal (os, matrix, pr_as_read_syntax,
00182                          current_print_indent_level ());
00183 }
00184 
00185 bool
00186 octave_bool_matrix::save_ascii (std::ostream& os)
00187 {
00188   dim_vector d = dims ();
00189   if (d.length () > 2)
00190     {
00191       NDArray tmp = array_value ();
00192       os << "# ndims: " << d.length () << "\n";
00193 
00194       for (int i = 0; i < d.length (); i++)
00195         os << " " << d (i);
00196 
00197       os << "\n" << tmp;
00198     }
00199   else
00200     {
00201       // Keep this case, rather than use generic code above for backward
00202       // compatiability. Makes load_ascii much more complex!!
00203       os << "# rows: " << rows () << "\n"
00204          << "# columns: " << columns () << "\n";
00205 
00206       Matrix tmp = matrix_value ();
00207 
00208       os << tmp;
00209     }
00210 
00211   return true;
00212 }
00213 
00214 bool
00215 octave_bool_matrix::load_ascii (std::istream& is)
00216 {
00217   bool success = true;
00218 
00219   string_vector keywords (2);
00220 
00221   keywords[0] = "ndims";
00222   keywords[1] = "rows";
00223 
00224   std::string kw;
00225   octave_idx_type val = 0;
00226 
00227   if (extract_keyword (is, keywords, kw, val, true))
00228     {
00229       if (kw == "ndims")
00230         {
00231           int mdims = static_cast<int> (val);
00232 
00233           if (mdims >= 0)
00234             {
00235               dim_vector dv;
00236               dv.resize (mdims);
00237 
00238               for (int i = 0; i < mdims; i++)
00239                 is >> dv(i);
00240 
00241               if (is)
00242                 {
00243                   boolNDArray btmp (dv);
00244 
00245                   if (btmp.is_empty ())
00246                     matrix = btmp;
00247                   else
00248                     {
00249                       NDArray tmp(dv);
00250                       is >> tmp;
00251 
00252                       if (is)
00253                         {
00254                           for (octave_idx_type i = 0; i < btmp.nelem (); i++)
00255                             btmp.elem (i) = (tmp.elem (i) != 0.);
00256 
00257                           matrix = btmp;
00258                         }
00259                       else
00260                         {
00261                           error ("load: failed to load matrix constant");
00262                           success = false;
00263                         }
00264                     }
00265                 }
00266               else
00267                 {
00268                   error ("load: failed to extract dimensions");
00269                   success = false;
00270                 }
00271             }
00272           else
00273             {
00274               error ("load: failed to extract number of dimensions");
00275               success = false;
00276             }
00277         }
00278       else if (kw == "rows")
00279         {
00280           octave_idx_type nr = val;
00281           octave_idx_type nc = 0;
00282 
00283           if (nr >= 0 && extract_keyword (is, "columns", nc) && nc >= 0)
00284             {
00285               if (nr > 0 && nc > 0)
00286                 {
00287                   Matrix tmp (nr, nc);
00288                   is >> tmp;
00289                   if (is)
00290                     {
00291                       boolMatrix btmp (nr, nc);
00292                       for (octave_idx_type j = 0; j < nc; j++)
00293                         for (octave_idx_type i = 0; i < nr; i++)
00294                           btmp.elem (i,j) = (tmp.elem (i, j) != 0.);
00295 
00296                       matrix = btmp;
00297                     }
00298                   else
00299                     {
00300                       error ("load: failed to load matrix constant");
00301                       success = false;
00302                     }
00303                 }
00304               else if (nr == 0 || nc == 0)
00305                 matrix = boolMatrix (nr, nc);
00306               else
00307                 panic_impossible ();
00308             }
00309           else
00310             {
00311               error ("load: failed to extract number of rows and columns");
00312               success = false;
00313             }
00314         }
00315       else
00316         panic_impossible ();
00317     }
00318   else
00319     {
00320       error ("load: failed to extract number of rows and columns");
00321       success = false;
00322     }
00323 
00324   return success;
00325 }
00326 
00327 bool
00328 octave_bool_matrix::save_binary (std::ostream& os, bool& /* save_as_floats */)
00329 {
00330 
00331   dim_vector d = dims ();
00332   if (d.length() < 1)
00333     return false;
00334 
00335   // Use negative value for ndims to differentiate with old format!!
00336   int32_t tmp = - d.length();
00337   os.write (reinterpret_cast<char *> (&tmp), 4);
00338   for (int i = 0; i < d.length (); i++)
00339     {
00340       tmp = d(i);
00341       os.write (reinterpret_cast<char *> (&tmp), 4);
00342     }
00343 
00344   boolNDArray m = bool_array_value ();
00345   bool *mtmp = m.fortran_vec ();
00346   octave_idx_type nel = m.nelem ();
00347   OCTAVE_LOCAL_BUFFER (char, htmp, nel);
00348 
00349   for (octave_idx_type i = 0; i < nel; i++)
00350     htmp[i] = (mtmp[i] ? 1 : 0);
00351 
00352   os.write (htmp, nel);
00353 
00354   return true;
00355 }
00356 
00357 bool
00358 octave_bool_matrix::load_binary (std::istream& is, bool swap,
00359                                  oct_mach_info::float_format /* fmt */)
00360 {
00361   int32_t mdims;
00362   if (! is.read (reinterpret_cast<char *> (&mdims), 4))
00363     return false;
00364   if (swap)
00365     swap_bytes<4> (&mdims);
00366   if (mdims >= 0)
00367     return false;
00368 
00369   // mdims is negative for consistency with other matrices, where it is
00370   // negative to allow the positive value to be used for rows/cols for
00371   // backward compatibility
00372   mdims = - mdims;
00373   int32_t di;
00374   dim_vector dv;
00375   dv.resize (mdims);
00376 
00377   for (int i = 0; i < mdims; i++)
00378     {
00379       if (! is.read (reinterpret_cast<char *> (&di), 4))
00380         return false;
00381       if (swap)
00382         swap_bytes<4> (&di);
00383       dv(i) = di;
00384     }
00385 
00386   // Convert an array with a single dimension to be a row vector.
00387   // Octave should never write files like this, other software
00388   // might.
00389 
00390   if (mdims == 1)
00391     {
00392       mdims = 2;
00393       dv.resize (mdims);
00394       dv(1) = dv(0);
00395       dv(0) = 1;
00396     }
00397 
00398   octave_idx_type nel = dv.numel ();
00399   OCTAVE_LOCAL_BUFFER (char, htmp, nel);
00400   if (! is.read (htmp, nel))
00401     return false;
00402   boolNDArray m(dv);
00403   bool *mtmp = m.fortran_vec ();
00404   for (octave_idx_type i = 0; i < nel; i++)
00405     mtmp[i] = (htmp[i] ? 1 : 0);
00406   matrix = m;
00407 
00408   return true;
00409 }
00410 
00411 #if defined (HAVE_HDF5)
00412 
00413 bool
00414 octave_bool_matrix::save_hdf5 (hid_t loc_id, const char *name,
00415                                bool /* save_as_floats */)
00416 {
00417   dim_vector dv = dims ();
00418   int empty = save_hdf5_empty (loc_id, name, dv);
00419   if (empty)
00420     return (empty > 0);
00421 
00422   int rank = dv.length ();
00423   hid_t space_hid = -1, data_hid = -1;
00424   bool retval = true;
00425   boolNDArray m = bool_array_value ();
00426 
00427   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00428 
00429   // Octave uses column-major, while HDF5 uses row-major ordering
00430   for (int i = 0; i < rank; i++)
00431     hdims[i] = dv (rank-i-1);
00432 
00433   space_hid = H5Screate_simple (rank, hdims, 0);
00434   if (space_hid < 0) return false;
00435 #if HAVE_HDF5_18
00436   data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
00437                         H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00438 #else
00439   data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
00440                         H5P_DEFAULT);
00441 #endif
00442   if (data_hid < 0)
00443     {
00444       H5Sclose (space_hid);
00445       return false;
00446     }
00447 
00448   octave_idx_type nel = m.nelem ();
00449   bool *mtmp = m.fortran_vec ();
00450   OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
00451 
00452   for (octave_idx_type i = 0; i < nel; i++)
00453     htmp[i] = mtmp[i];
00454 
00455   retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL,
00456                      H5P_DEFAULT, htmp) >= 0;
00457 
00458   H5Dclose (data_hid);
00459   H5Sclose (space_hid);
00460 
00461   return retval;
00462 }
00463 
00464 bool
00465 octave_bool_matrix::load_hdf5 (hid_t loc_id, const char *name)
00466 {
00467   bool retval = false;
00468 
00469   dim_vector dv;
00470   int empty = load_hdf5_empty (loc_id, name, dv);
00471   if (empty > 0)
00472     matrix.resize(dv);
00473   if (empty)
00474     return (empty > 0);
00475 
00476 #if HAVE_HDF5_18
00477   hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
00478 #else
00479   hid_t data_hid = H5Dopen (loc_id, name);
00480 #endif
00481   hid_t space_id = H5Dget_space (data_hid);
00482 
00483   hsize_t rank = H5Sget_simple_extent_ndims (space_id);
00484 
00485   if (rank < 1)
00486     {
00487       H5Dclose (data_hid);
00488       return false;
00489     }
00490 
00491   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
00492   OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
00493 
00494   H5Sget_simple_extent_dims (space_id, hdims, maxdims);
00495 
00496   // Octave uses column-major, while HDF5 uses row-major ordering
00497   if (rank == 1)
00498     {
00499       dv.resize (2);
00500       dv(0) = 1;
00501       dv(1) = hdims[0];
00502     }
00503   else
00504     {
00505       dv.resize (rank);
00506       for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
00507         dv(j) = hdims[i];
00508     }
00509 
00510   octave_idx_type nel = dv.numel ();
00511   OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
00512   if (H5Dread (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, H5P_DEFAULT, htmp) >= 0)
00513     {
00514       retval = true;
00515 
00516       boolNDArray btmp (dv);
00517       for (octave_idx_type i = 0; i < nel; i++)
00518           btmp.elem (i) = htmp[i];
00519 
00520       matrix = btmp;
00521     }
00522 
00523   H5Dclose (data_hid);
00524 
00525   return retval;
00526 }
00527 
00528 #endif
00529 
00530 mxArray *
00531 octave_bool_matrix::as_mxArray (void) const
00532 {
00533   mxArray *retval = new mxArray (mxLOGICAL_CLASS, dims (), mxREAL);
00534 
00535   bool *pr = static_cast<bool *> (retval->get_data ());
00536 
00537   mwSize nel = numel ();
00538 
00539   const bool *p = matrix.data ();
00540 
00541   for (mwIndex i = 0; i < nel; i++)
00542     pr[i] = p[i];
00543 
00544   return retval;
00545 }
00546 
00547 DEFUN (logical, args, ,
00548   "-*- texinfo -*-\n\
00549 @deftypefn {Built-in Function} {} logical (@var{x})\n\
00550 Convert @var{x} to logical type.\n\
00551 @seealso{double, single, char}\n\
00552 @end deftypefn")
00553 {
00554   octave_value retval;
00555 
00556   if (args.length () == 1)
00557     {
00558       octave_value arg = args(0);
00559       if (arg.is_bool_type ())
00560         retval = arg;
00561       else if (arg.is_numeric_type ())
00562         {
00563           if (arg.is_sparse_type ())
00564             retval = arg.sparse_bool_matrix_value ();
00565           else if (arg.is_scalar_type ())
00566             retval = arg.bool_value ();
00567           else
00568             retval = arg.bool_array_value ();
00569         }
00570       else
00571         gripe_wrong_type_arg ("logical", arg);
00572     }
00573   else
00574     print_usage ();
00575 
00576   return retval;
00577 }
00578 
00579 /*
00580 %!shared m, s, c
00581 %! m = eye (2) != 0;
00582 %! s = !0;
00583 %! c = {"double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical"};
00584 %!test
00585 %! for i = 1:numel (c)
00586 %!   assert (logical (eye (2, c{i})), m)
00587 %!   assert (logical (eye (1, c{i})), s)
00588 %! endfor
00589 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines