GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-bool-mat.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2015 John W. Eaton
4 Copyright (C) 2009-2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <iostream>
29 #include <vector>
30 
31 #include "lo-ieee.h"
32 #include "mx-base.h"
33 #include "oct-locbuf.h"
34 
35 #include "defun.h"
36 #include "gripes.h"
37 #include "mxarray.h"
38 #include "oct-obj.h"
39 #include "oct-hdf5.h"
40 #include "ops.h"
41 #include "ov-base.h"
42 #include "ov-base-mat.h"
43 #include "ov-base-mat.cc"
44 #include "ov-bool.h"
45 #include "ov-bool-mat.h"
46 #include "ov-re-mat.h"
47 #include "pr-output.h"
48 
49 #include "byte-swap.h"
50 #include "ls-oct-ascii.h"
51 #include "ls-hdf5.h"
52 #include "ls-utils.h"
53 
54 template class octave_base_matrix<boolNDArray>;
55 
56 
58  "bool matrix", "logical");
59 
60 static octave_base_value *
62 {
64 
65  return new octave_matrix (NDArray (v.bool_array_value ()));
66 }
67 
70 {
73 }
74 
77 {
78  octave_base_value *retval = 0;
79 
80  if (matrix.ndims () == 2)
81  {
82  boolMatrix bm (matrix);
83 
84  octave_idx_type nr = bm.rows ();
85  octave_idx_type nc = bm.cols ();
86 
87  if (nr == 1 && nc == 1)
88  retval = new octave_bool (bm (0, 0));
89  }
90 
91  return retval;
92 }
93 
94 double
96 {
97  double retval = lo_ieee_nan_value ();
98 
99  if (rows () > 0 && columns () > 0)
100  {
101  gripe_implicit_conversion ("Octave:array-to-scalar",
102  "bool matrix", "real scalar");
103 
104  retval = matrix (0, 0);
105  }
106  else
107  gripe_invalid_conversion ("bool matrix", "real scalar");
108 
109  return retval;
110 }
111 
112 float
114 {
115  float retval = lo_ieee_float_nan_value ();
116 
117  if (rows () > 0 && columns () > 0)
118  {
119  gripe_implicit_conversion ("Octave:array-to-scalar",
120  "bool matrix", "real scalar");
121 
122  retval = matrix (0, 0);
123  }
124  else
125  gripe_invalid_conversion ("bool matrix", "real scalar");
126 
127  return retval;
128 }
129 
130 Complex
132 {
133  double tmp = lo_ieee_nan_value ();
134 
135  Complex retval (tmp, tmp);
136 
137  if (rows () > 0 && columns () > 0)
138  {
139  gripe_implicit_conversion ("Octave:array-to-scalar",
140  "bool matrix", "complex scalar");
141 
142  retval = matrix (0, 0);
143  }
144  else
145  gripe_invalid_conversion ("bool matrix", "complex scalar");
146 
147  return retval;
148 }
149 
152 {
153  float tmp = lo_ieee_float_nan_value ();
154 
155  FloatComplex retval (tmp, tmp);
156 
157  if (rows () > 0 && columns () > 0)
158  {
159  gripe_implicit_conversion ("Octave:array-to-scalar",
160  "bool matrix", "complex scalar");
161 
162  retval = matrix (0, 0);
163  }
164  else
165  gripe_invalid_conversion ("bool matrix", "complex scalar");
166 
167  return retval;
168 }
169 
172  char type) const
173 {
175  return tmp.convert_to_str (pad, force, type);
176 }
177 
178 void
180  bool pr_as_read_syntax) const
181 {
182  octave_print_internal (os, matrix, pr_as_read_syntax,
184 }
185 
186 bool
188 {
189  dim_vector d = dims ();
190  if (d.length () > 2)
191  {
192  NDArray tmp = array_value ();
193  os << "# ndims: " << d.length () << "\n";
194 
195  for (int i = 0; i < d.length (); i++)
196  os << " " << d (i);
197 
198  os << "\n" << tmp;
199  }
200  else
201  {
202  // Keep this case, rather than use generic code above for backward
203  // compatiability. Makes load_ascii much more complex!!
204  os << "# rows: " << rows () << "\n"
205  << "# columns: " << columns () << "\n";
206 
207  Matrix tmp = matrix_value ();
208 
209  os << tmp;
210  }
211 
212  return true;
213 }
214 
215 bool
217 {
218  bool success = true;
219 
221 
222  keywords[0] = "ndims";
223  keywords[1] = "rows";
224 
225  std::string kw;
226  octave_idx_type val = 0;
227 
228  if (extract_keyword (is, keywords, kw, val, true))
229  {
230  if (kw == "ndims")
231  {
232  int mdims = static_cast<int> (val);
233 
234  if (mdims >= 0)
235  {
236  dim_vector dv;
237  dv.resize (mdims);
238 
239  for (int i = 0; i < mdims; i++)
240  is >> dv(i);
241 
242  if (is)
243  {
244  boolNDArray btmp (dv);
245 
246  if (btmp.is_empty ())
247  matrix = btmp;
248  else
249  {
250  NDArray tmp(dv);
251  is >> tmp;
252 
253  if (is)
254  {
255  for (octave_idx_type i = 0; i < btmp.nelem (); i++)
256  btmp.elem (i) = (tmp.elem (i) != 0.);
257 
258  matrix = btmp;
259  }
260  else
261  {
262  error ("load: failed to load matrix constant");
263  success = false;
264  }
265  }
266  }
267  else
268  {
269  error ("load: failed to extract dimensions");
270  success = false;
271  }
272  }
273  else
274  {
275  error ("load: failed to extract number of dimensions");
276  success = false;
277  }
278  }
279  else if (kw == "rows")
280  {
281  octave_idx_type nr = val;
282  octave_idx_type nc = 0;
283 
284  if (nr >= 0 && extract_keyword (is, "columns", nc) && nc >= 0)
285  {
286  if (nr > 0 && nc > 0)
287  {
288  Matrix tmp (nr, nc);
289  is >> tmp;
290  if (is)
291  {
292  boolMatrix btmp (nr, nc);
293  for (octave_idx_type j = 0; j < nc; j++)
294  for (octave_idx_type i = 0; i < nr; i++)
295  btmp.elem (i,j) = (tmp.elem (i, j) != 0.);
296 
297  matrix = btmp;
298  }
299  else
300  {
301  error ("load: failed to load matrix constant");
302  success = false;
303  }
304  }
305  else if (nr == 0 || nc == 0)
306  matrix = boolMatrix (nr, nc);
307  else
308  panic_impossible ();
309  }
310  else
311  {
312  error ("load: failed to extract number of rows and columns");
313  success = false;
314  }
315  }
316  else
317  panic_impossible ();
318  }
319  else
320  {
321  error ("load: failed to extract number of rows and columns");
322  success = false;
323  }
324 
325  return success;
326 }
327 
328 bool
329 octave_bool_matrix::save_binary (std::ostream& os, bool& /* save_as_floats */)
330 {
331 
332  dim_vector d = dims ();
333  if (d.length () < 1)
334  return false;
335 
336  // Use negative value for ndims to differentiate with old format!!
337  int32_t tmp = - d.length ();
338  os.write (reinterpret_cast<char *> (&tmp), 4);
339  for (int i = 0; i < d.length (); i++)
340  {
341  tmp = d(i);
342  os.write (reinterpret_cast<char *> (&tmp), 4);
343  }
344 
346  bool *mtmp = m.fortran_vec ();
347  octave_idx_type nel = m.nelem ();
348  OCTAVE_LOCAL_BUFFER (char, htmp, nel);
349 
350  for (octave_idx_type i = 0; i < nel; i++)
351  htmp[i] = (mtmp[i] ? 1 : 0);
352 
353  os.write (htmp, nel);
354 
355  return true;
356 }
357 
358 bool
359 octave_bool_matrix::load_binary (std::istream& is, bool swap,
360  oct_mach_info::float_format /* fmt */)
361 {
362  int32_t mdims;
363  if (! is.read (reinterpret_cast<char *> (&mdims), 4))
364  return false;
365  if (swap)
366  swap_bytes<4> (&mdims);
367  if (mdims >= 0)
368  return false;
369 
370  // mdims is negative for consistency with other matrices, where it is
371  // negative to allow the positive value to be used for rows/cols for
372  // backward compatibility
373  mdims = - mdims;
374  int32_t di;
375  dim_vector dv;
376  dv.resize (mdims);
377 
378  for (int i = 0; i < mdims; i++)
379  {
380  if (! is.read (reinterpret_cast<char *> (&di), 4))
381  return false;
382  if (swap)
383  swap_bytes<4> (&di);
384  dv(i) = di;
385  }
386 
387  // Convert an array with a single dimension to be a row vector.
388  // Octave should never write files like this, other software
389  // might.
390 
391  if (mdims == 1)
392  {
393  mdims = 2;
394  dv.resize (mdims);
395  dv(1) = dv(0);
396  dv(0) = 1;
397  }
398 
399  octave_idx_type nel = dv.numel ();
400  OCTAVE_LOCAL_BUFFER (char, htmp, nel);
401  if (! is.read (htmp, nel))
402  return false;
403  boolNDArray m(dv);
404  bool *mtmp = m.fortran_vec ();
405  for (octave_idx_type i = 0; i < nel; i++)
406  mtmp[i] = (htmp[i] ? 1 : 0);
407  matrix = m;
408 
409  return true;
410 }
411 
412 bool
414  bool /* save_as_floats */)
415 {
416  bool retval = true;
417 
418 #if defined (HAVE_HDF5)
419 
420  dim_vector dv = dims ();
421  int empty = save_hdf5_empty (loc_id, name, dv);
422  if (empty)
423  return (empty > 0);
424 
425  int rank = dv.length ();
426  hid_t space_hid, data_hid;
427  space_hid = data_hid = -1;
429 
430  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
431 
432  // Octave uses column-major, while HDF5 uses row-major ordering
433  for (int i = 0; i < rank; i++)
434  hdims[i] = dv (rank-i-1);
435 
436  space_hid = H5Screate_simple (rank, hdims, 0);
437  if (space_hid < 0) return false;
438 #if HAVE_HDF5_18
439  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
440  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
441 #else
442  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
443  H5P_DEFAULT);
444 #endif
445  if (data_hid < 0)
446  {
447  H5Sclose (space_hid);
448  return false;
449  }
450 
451  octave_idx_type nel = m.nelem ();
452  bool *mtmp = m.fortran_vec ();
453  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
454 
455  for (octave_idx_type i = 0; i < nel; i++)
456  htmp[i] = mtmp[i];
457 
458  retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL,
459  H5P_DEFAULT, htmp) >= 0;
460 
461  H5Dclose (data_hid);
462  H5Sclose (space_hid);
463 
464 #else
465  gripe_save ("hdf5");
466 #endif
467 
468  return retval;
469 }
470 
471 bool
473 {
474  bool retval = false;
475 
476 #if defined (HAVE_HDF5)
477 
478  dim_vector dv;
479  int empty = load_hdf5_empty (loc_id, name, dv);
480  if (empty > 0)
481  matrix.resize (dv);
482  if (empty)
483  return (empty > 0);
484 
485 #if HAVE_HDF5_18
486  hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
487 #else
488  hid_t data_hid = H5Dopen (loc_id, name);
489 #endif
490  hid_t space_id = H5Dget_space (data_hid);
491 
492  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
493 
494  if (rank < 1)
495  {
496  H5Dclose (data_hid);
497  return false;
498  }
499 
500  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
501  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
502 
503  H5Sget_simple_extent_dims (space_id, hdims, maxdims);
504 
505  // Octave uses column-major, while HDF5 uses row-major ordering
506  if (rank == 1)
507  {
508  dv.resize (2);
509  dv(0) = 1;
510  dv(1) = hdims[0];
511  }
512  else
513  {
514  dv.resize (rank);
515  for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
516  dv(j) = hdims[i];
517  }
518 
519  octave_idx_type nel = dv.numel ();
520  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
521  if (H5Dread (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, H5P_DEFAULT, htmp)
522  >= 0)
523  {
524  retval = true;
525 
526  boolNDArray btmp (dv);
527  for (octave_idx_type i = 0; i < nel; i++)
528  btmp.elem (i) = htmp[i];
529 
530  matrix = btmp;
531  }
532 
533  H5Dclose (data_hid);
534 
535 #else
536  gripe_load ("hdf5");
537 #endif
538 
539  return retval;
540 }
541 
542 mxArray *
544 {
545  mxArray *retval = new mxArray (mxLOGICAL_CLASS, dims (), mxREAL);
546 
547  bool *pr = static_cast<bool *> (retval->get_data ());
548 
549  mwSize nel = numel ();
550 
551  const bool *p = matrix.data ();
552 
553  for (mwIndex i = 0; i < nel; i++)
554  pr[i] = p[i];
555 
556  return retval;
557 }
558 
559 DEFUN (logical, args, ,
560  "-*- texinfo -*-\n\
561 @deftypefn {Built-in Function} {} logical (@var{x})\n\
562 Convert the numeric object @var{x} to logical type.\n\
563 \n\
564 Any nonzero values will be converted to true (1) while zero values will be\n\
565 converted to false (0). The non-numeric value NaN cannot be converted and\n\
566 will produce an error.\n\
567 \n\
568 Compatibility Note: Octave accepts complex values as input, whereas\n\
569 @sc{matlab} issues an error.\n\
570 @seealso{double, single, char}\n\
571 @end deftypefn")
572 {
573  octave_value retval;
574 
575  if (args.length () == 1)
576  {
577  octave_value arg = args(0);
578  if (arg.is_bool_type ())
579  retval = arg;
580  else if (arg.is_numeric_type ())
581  {
582  if (arg.is_sparse_type ())
583  retval = arg.sparse_bool_matrix_value ();
584  else if (arg.is_scalar_type ())
585  retval = arg.bool_value ();
586  else
587  retval = arg.bool_array_value ();
588  }
589  else
590  gripe_wrong_type_arg ("logical", arg);
591  }
592  else
593  print_usage ();
594 
595  return retval;
596 }
597 
598 /*
599 %!test
600 %! m = eye (2) != 0;
601 %! s = !0;
602 %! c = {"double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical"};
603 %! for i = 1:numel (c)
604 %! assert (logical (eye (2, c{i})), m)
605 %! assert (logical (eye (1, c{i})), s)
606 %! endfor
607 */
void gripe_implicit_conversion(const char *id, const char *from, const char *to)
Definition: gripes.cc:180
bool is_empty(void) const
Definition: Array.h:472
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov-bool-mat.cc:171
static octave_base_value * default_numeric_conversion_function(const octave_base_value &a)
Definition: ov-bool-mat.cc:61
void gripe_wrong_type_arg(const char *name, const char *s, bool is_error)
Definition: gripes.cc:135
octave_idx_type columns(void) const
Definition: ov-base.h:301
int ndims(void) const
Definition: Array.h:487
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
void gripe_load(const char *type) const
Definition: ov-base.cc:1258
bool is_scalar_type(void) const
Definition: ov.h:657
bool is_numeric_type(void) const
Definition: ov.h:663
octave_idx_type numel(void) const
Definition: ov-base-mat.h:103
void resize(int n, int fill_value=0)
Definition: dim-vector.h:287
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
void * get_data(void) const
Definition: mxarray.h:433
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:164
void gripe_save(const char *type) const
Definition: ov-base.cc:1267
T & elem(octave_idx_type n)
Definition: Array.h:380
double lo_ieee_nan_value(void)
Definition: lo-ieee.cc:126
Complex complex_value(bool=false) const
Definition: ov-bool-mat.cc:131
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:811
octave_idx_type rows(void) const
Definition: Array.h:313
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:361
F77_RET_T const double const double double * d
int load_hdf5_empty(hid_t loc_id, const char *name, dim_vector &d)
Definition: ls-hdf5.cc:790
octave_idx_type nelem(void) const
Number of elements in the array.
Definition: Array.h:271
double double_value(bool=false) const
Definition: ov-bool-mat.cc:95
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-bool-mat.cc:179
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-ascii.cc:80
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:59
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-bool-mat.cc:472
#define CAST_CONV_ARG(t)
Definition: ops.h:83
octave_value convert_to_str(bool pad=false, bool force=false, char type= '\'') const
Definition: ov.h:1017
bool is_sparse_type(void) const
Definition: ov.h:666
bool is_bool_type(void) const
Definition: ov.h:645
static int static_type_id(void)
Definition: ov-re-mat.h:235
const T * data(void) const
Definition: Array.h:479
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition: ov.h:827
bool save_binary(std::ostream &os, bool &save_as_floats)
Definition: ov-bool-mat.cc:329
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1033
#define panic_impossible()
Definition: error.h:33
Definition: dMatrix.h:35
float lo_ieee_float_nan_value(void)
Definition: lo-ieee.cc:202
void mxArray
Definition: mex.h:53
double arg(double x)
Definition: lo-mappers.h:37
friend class octave_value
Definition: ov-base.h:206
bool save_ascii(std::ostream &os)
Definition: ov-bool-mat.cc:187
dim_vector dims(void) const
Definition: ov-base-mat.h:101
void gripe_invalid_conversion(const std::string &from, const std::string &to)
Definition: gripes.cc:99
bool bool_value(bool warn=false) const
Definition: ov.h:805
octave_base_value * try_narrowing_conversion(void)
Definition: ov-bool-mat.cc:76
int current_print_indent_level(void) const
Definition: ov-base.h:805
type_conv_info numeric_conversion_function(void) const
Definition: ov-bool-mat.cc:69
NDArray array_value(bool=false) const
Definition: ov-bool-mat.h:142
mxArray * as_mxArray(void) const
Definition: ov-bool-mat.cc:543
FloatComplex float_complex_value(bool=false) const
Definition: ov-bool-mat.cc:151
void octave_print_internal(std::ostream &, char, bool)
Definition: pr-output.cc:1715
int save_hdf5_empty(hid_t loc_id, const char *name, const dim_vector d)
Definition: ls-hdf5.cc:740
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
float float_value(bool=false) const
Definition: ov-bool-mat.cc:113
static const pair_type keywords[]
Definition: help.cc:445
std::complex< float > FloatComplex
Definition: oct-cmplx.h:30
bool load_binary(std::istream &is, bool swap, oct_mach_info::float_format fmt)
Definition: ov-bool-mat.cc:359
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-bool-mat.cc:413
Definition: mxarray.h:52
std::complex< double > Complex
Definition: oct-cmplx.h:29
const T * fortran_vec(void) const
Definition: Array.h:481
octave_idx_type cols(void) const
Definition: Array.h:321
int length(void) const
Definition: dim-vector.h:281
octave_idx_type rows(void) const
Definition: ov-base.h:294
Matrix matrix_value(bool=false) const
Definition: ov-bool-mat.h:136
boolNDArray bool_array_value(bool=false) const
Definition: ov-bool-mat.h:180
bool load_ascii(std::istream &is)
Definition: ov-bool-mat.cc:216