GNU Octave  9.1.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-2024 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 *
74 default_numeric_conversion_function (const octave_base_value& a)
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 {
84  return octave_base_value::type_conv_info (default_numeric_conversion_function,
86 }
87 
90 {
91  octave_base_value *retval = nullptr;
92 
93  if (m_matrix.ndims () == 2)
94  {
95  boolMatrix bm (m_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 m_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 m_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 (m_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 = m_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 (m_matrix);
173 }
174 
177 {
178  return FloatNDArray (m_matrix);
179 }
180 
183 {
184  return int8NDArray (m_matrix);
185 }
186 
189 {
190  return int16NDArray (m_matrix);
191 }
192 
195 {
196  return int32NDArray (m_matrix);
197 }
198 
201 {
202  return int64NDArray (m_matrix);
203 }
204 
207 {
208  return uint8NDArray (m_matrix);
209 }
210 
213 {
214  return uint16NDArray (m_matrix);
215 }
216 
219 {
220  return uint32NDArray (m_matrix);
221 }
222 
225 {
226  return uint64NDArray (m_matrix);
227 }
228 
229 void
231  bool pr_as_read_syntax) const
232 {
233  octave_print_internal (os, m_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  m_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  m_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  m_matrix = btmp;
335  }
336  else if (nr == 0 || nc == 0)
337  m_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 
364  const bool *mtmp = m_matrix.data ();
365  octave_idx_type nel = m_matrix.numel ();
366  os.write (reinterpret_cast<const char *> (mtmp), nel);
367 
368  return true;
369 }
370 
371 bool
372 octave_bool_matrix::load_binary (std::istream& is, bool swap,
374 {
375  int32_t mdims;
376  if (! is.read (reinterpret_cast<char *> (&mdims), 4))
377  return false;
378  if (swap)
379  swap_bytes<4> (&mdims);
380  if (mdims >= 0)
381  return false;
382 
383  // mdims is negative for consistency with other matrices, where it is
384  // negative to allow the positive value to be used for rows/cols for
385  // backward compatibility
386  mdims = - mdims;
387  int32_t di;
388  dim_vector dv;
389  dv.resize (mdims);
390 
391  for (int i = 0; i < mdims; i++)
392  {
393  if (! is.read (reinterpret_cast<char *> (&di), 4))
394  return false;
395  if (swap)
396  swap_bytes<4> (&di);
397  dv(i) = di;
398  }
399 
400  // Convert an array with a single dimension to be a row vector.
401  // Octave should never write files like this, other software
402  // might.
403 
404  if (mdims == 1)
405  {
406  mdims = 2;
407  dv.resize (mdims);
408  dv(1) = dv(0);
409  dv(0) = 1;
410  }
411 
412  octave_idx_type nel = dv.numel ();
413  OCTAVE_LOCAL_BUFFER (char, htmp, nel);
414  if (! is.read (htmp, nel))
415  return false;
416  boolNDArray m(dv);
417  bool *mtmp = m.fortran_vec ();
418  for (octave_idx_type i = 0; i < nel; i++)
419  mtmp[i] = (htmp[i] ? 1 : 0);
420  m_matrix = m;
421 
422  return true;
423 }
424 
425 bool
427  bool /* save_as_floats */)
428 {
429  bool retval = true;
430 
431 #if defined (HAVE_HDF5)
432 
433  dim_vector dv = dims ();
434  int empty = save_hdf5_empty (loc_id, name, dv);
435  if (empty)
436  return (empty > 0);
437 
438  int rank = dv.ndims ();
439  hid_t space_hid, data_hid;
440  space_hid = data_hid = -1;
441 
442  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
443 
444  // Octave uses column-major, while HDF5 uses row-major ordering
445  for (int i = 0; i < rank; i++)
446  hdims[i] = dv(rank-i-1);
447 
448  space_hid = H5Screate_simple (rank, hdims, nullptr);
449  if (space_hid < 0) return false;
450 #if defined (HAVE_HDF5_18)
451  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
454 #else
455  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
457 #endif
458  if (data_hid < 0)
459  {
460  H5Sclose (space_hid);
461  return false;
462  }
463 
464  const bool *mtmp = m_matrix.data ();
465 
466  retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
468  reinterpret_cast<const char *> (mtmp)) >= 0;
469 
470  H5Dclose (data_hid);
471  H5Sclose (space_hid);
472 
473 #else
474  octave_unused_parameter (loc_id);
475  octave_unused_parameter (name);
476 
477  warn_save ("hdf5");
478 #endif
479 
480  return retval;
481 }
482 
483 bool
485 {
486  bool retval = false;
487 
488 #if defined (HAVE_HDF5)
489 
490  dim_vector dv;
491  int empty = load_hdf5_empty (loc_id, name, dv);
492  if (empty > 0)
493  m_matrix.resize (dv);
494  if (empty)
495  return (empty > 0);
496 
497 #if defined (HAVE_HDF5_18)
498  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
499 #else
500  hid_t data_hid = H5Dopen (loc_id, name);
501 #endif
502  hid_t space_id = H5Dget_space (data_hid);
503 
504  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
505 
506  if (rank < 1)
507  {
508  H5Dclose (data_hid);
509  return false;
510  }
511 
512  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
513  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
514 
515  H5Sget_simple_extent_dims (space_id, hdims, maxdims);
516 
517  // Octave uses column-major, while HDF5 uses row-major ordering
518  if (rank == 1)
519  {
520  dv.resize (2);
521  dv(0) = 1;
522  dv(1) = hdims[0];
523  }
524  else
525  {
526  dv.resize (rank);
527  for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
528  dv(j) = hdims[i];
529  }
530 
531  octave_idx_type nel = dv.numel ();
532  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
533  if (H5Dread (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
534  octave_H5P_DEFAULT, htmp)
535  >= 0)
536  {
537  retval = true;
538 
539  boolNDArray btmp (dv);
540  for (octave_idx_type i = 0; i < nel; i++)
541  btmp.elem (i) = htmp[i];
542 
543  m_matrix = btmp;
544  }
545 
546  H5Dclose (data_hid);
547 
548 #else
549  octave_unused_parameter (loc_id);
550  octave_unused_parameter (name);
551 
552  warn_load ("hdf5");
553 #endif
554 
555  return retval;
556 }
557 
558 mxArray *
559 octave_bool_matrix::as_mxArray (bool interleaved) const
560 {
561  mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, dims (), mxREAL);
562 
563  mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());
564 
565  mwSize nel = numel ();
566 
567  const bool *pdata = m_matrix.data ();
568 
569  for (mwIndex i = 0; i < nel; i++)
570  pd[i] = pdata[i];
571 
572  return retval;
573 }
574 
576 
577 DEFUN (logical, args, ,
578  doc: /* -*- texinfo -*-
579 @deftypefn {} {@var{TF} =} logical (@var{x})
580 Convert the numeric object @var{x} to logical type.
581 
582 Any nonzero values will be converted to true (1) while zero values will be
583 converted to false (0). The non-numeric value NaN cannot be converted and will
584 produce an error.
585 
586 Compatibility Note: Octave accepts complex values as input, whereas @sc{matlab}
587 issues an error.
588 @seealso{double, single, char}
589 @end deftypefn */)
590 {
591  if (args.length () != 1)
592  print_usage ();
593 
594  octave_value retval;
595 
596  octave_value arg = args(0);
597 
598  if (arg.islogical ())
599  retval = arg;
600  else if (arg.isnumeric ())
601  {
602  if (arg.issparse ())
603  retval = arg.sparse_bool_matrix_value ();
604  else if (arg.is_scalar_type ())
605  retval = arg.bool_value ();
606  else
607  retval = arg.bool_array_value ();
608  }
609  else
610  err_wrong_type_arg ("logical", arg);
611 
612  return retval;
613 }
614 
615 /*
616 %!test
617 %! m = eye (2) != 0;
618 %! s = ! 0;
619 %! c = {"double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical"};
620 %! for i = 1:numel (c)
621 %! assert (logical (eye (2, c{i})), m);
622 %! assert (logical (eye (1, c{i})), s);
623 %! endfor
624 */
625 
626 OCTAVE_END_NAMESPACE(octave)
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:63
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
int ndims() const
Size of the specified dimension.
Definition: Array.h:671
octave_idx_type rows() const
Definition: Array.h:459
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array-base.cc:1023
const T * data() const
Size of the specified dimension.
Definition: Array.h:663
octave_idx_type cols() const
Definition: Array.h:469
bool isempty() const
Size of the specified dimension.
Definition: Array.h:651
octave_idx_type numel() const
Number of elements in the array.
Definition: Array.h:414
Definition: dMatrix.h:42
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:335
void resize(int n, int fill_value=0)
Definition: dim-vector.h:272
octave_idx_type ndims() const
Number of dimensions.
Definition: dim-vector.h:257
void * get_data() const
Definition: mxarray.h:473
octave_idx_type numel() const
Definition: ov-base-mat.h:122
octave_idx_type rows() const
Definition: ov-base.h:374
octave_idx_type columns() const
Definition: ov-base.h:381
int current_print_indent_level() const
Definition: ov-base.h:920
void warn_load(const char *type) const
Definition: ov-base.cc:1157
friend class octave_value
Definition: ov-base.h:269
void warn_save(const char *type) const
Definition: ov-base.cc:1166
FloatComplex float_complex_value(bool=false) const
Definition: ov-bool-mat.cc:144
octave_value as_int16() const
Definition: ov-bool-mat.cc:188
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov-bool-mat.cc:162
octave_base_value * try_narrowing_conversion()
Definition: ov-bool-mat.cc:89
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov-bool-mat.cc:426
float float_value(bool=false) const
Definition: ov-bool-mat.cc:120
octave_value as_uint8() const
Definition: ov-bool-mat.cc:206
boolNDArray bool_array_value(bool=false) const
Definition: ov-bool-mat.h:183
octave_value as_int8() const
Definition: ov-bool-mat.cc:182
mxArray * as_mxArray(bool interleaved) const
Definition: ov-bool-mat.cc:559
type_conv_info numeric_conversion_function() const
Definition: ov-bool-mat.cc:82
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-bool-mat.cc:484
NDArray array_value(bool=false) const
Definition: ov-bool-mat.h:145
Complex complex_value(bool=false) const
Definition: ov-bool-mat.cc:132
octave_value as_single() const
Definition: ov-bool-mat.cc:176
octave_value as_double() 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:372
bool save_binary(std::ostream &os, bool save_as_floats)
Definition: ov-bool-mat.cc:348
octave_value as_int64() const
Definition: ov-bool-mat.cc:200
double double_value(bool=false) const
Definition: ov-bool-mat.cc:108
bool save_ascii(std::ostream &os)
Definition: ov-bool-mat.cc:238
bool load_ascii(std::istream &is)
Definition: ov-bool-mat.cc:267
octave_value as_uint64() const
Definition: ov-bool-mat.cc:224
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-bool-mat.cc:230
Matrix matrix_value(bool=false) const
Definition: ov-bool-mat.h:139
octave_value as_uint16() const
Definition: ov-bool-mat.cc:212
octave_value as_int32() const
Definition: ov-bool-mat.cc:194
octave_value as_uint32() const
Definition: ov-bool-mat.cc:218
static int static_type_id()
Definition: ov-re-mat.h:249
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:891
bool bool_value(bool warn=false) const
Definition: ov.h:885
bool is_scalar_type() const
Definition: ov.h:744
bool isnumeric() const
Definition: ov.h:750
bool issparse() const
Definition: ov.h:753
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition: ov.h:907
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition: ov.h:1307
bool islogical() const
Definition: ov.h:735
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage(void)
Definition: defun-int.h:72
#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:988
#define panic_impossible()
Definition: error.h:503
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
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()
Definition: lo-ieee.cc:116
int save_hdf5_empty(octave_hdf5_id loc_id, const char *name, const dim_vector &d)
Definition: ls-hdf5.cc:1249
int load_hdf5_empty(octave_hdf5_id loc_id, const char *name, dim_vector &d)
Definition: ls-hdf5.cc:1306
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-text.cc:84
float_format
Definition: mach-info.h:38
void mxArray
Definition: mex.h:58
T octave_idx_type m
Definition: mx-inlines.cc:781
@ mxLOGICAL_CLASS
Definition: mxtypes.h:61
int64_t mwIndex
Definition: mxtypes.h:125
@ mxREAL
Definition: mxtypes.h:80
unsigned char mxLogical
Definition: mxtypes.h:89
int64_t mwSize
Definition: mxtypes.h:124
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:235
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
Definition: pr-output.cc:1761
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