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