GNU Octave 7.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-2022 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
69
71 "bool matrix", "logical");
72
73static 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
107double
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
119float
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
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
229void
231 bool pr_as_read_syntax) const
232{
233 octave_print_internal (os, matrix, pr_as_read_syntax,
235}
236
237bool
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
266bool
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
340 }
341 else
343
344 return true;
345}
346
347bool
348octave_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
377bool
378octave_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
431bool
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
493bool
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
568mxArray *
569octave_bool_matrix::as_mxArray (bool interleaved) const
570{
571 mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, dims (), mxREAL);
572
573 mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());
574
575 mwSize nel = numel ();
576
577 const bool *pdata = matrix.data ();
578
579 for (mwIndex i = 0; i < nel; i++)
580 pd[i] = pdata[i];
581
582 return retval;
583}
584
585OCTAVE_NAMESPACE_BEGIN
586
587DEFUN (logical, args, ,
588 doc: /* -*- texinfo -*-
589@deftypefn {} {} logical (@var{x})
590Convert the numeric object @var{x} to logical type.
591
592Any nonzero values will be converted to true (1) while zero values will be
593converted to false (0). The non-numeric value NaN cannot be converted and
594will produce an error.
595
596Compatibility Note: Octave accepts complex values as input, whereas
597@sc{matlab} issues an error.
598@seealso{double, single, char}
599@end deftypefn */)
600{
601 if (args.length () != 1)
602 print_usage ();
603
604 octave_value retval;
605
606 octave_value arg = args(0);
607
608 if (arg.islogical ())
609 retval = arg;
610 else if (arg.isnumeric ())
611 {
612 if (arg.issparse ())
613 retval = arg.sparse_bool_matrix_value ();
614 else if (arg.is_scalar_type ())
615 retval = arg.bool_value ();
616 else
617 retval = arg.bool_array_value ();
618 }
619 else
620 err_wrong_type_arg ("logical", arg);
621
622 return retval;
623}
624
625/*
626%!test
627%! m = eye (2) != 0;
628%! s = ! 0;
629%! c = {"double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical"};
630%! for i = 1:numel (c)
631%! assert (logical (eye (2, c{i})), m);
632%! assert (logical (eye (1, c{i})), s);
633%! endfor
634*/
635
636OCTAVE_NAMESPACE_END
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:63
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:411
octave_idx_type cols(void) const
Definition: Array.h:457
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:534
octave_idx_type rows(void) const
Definition: Array.h:449
bool isempty(void) const
Size of the specified dimension.
Definition: Array.h:607
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:616
OCTARRAY_API T * fortran_vec(void)
Size of the specified dimension.
Definition: Array.cc:1744
int ndims(void) const
Size of the specified dimension.
Definition: Array.h:627
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(void) const
Number of dimensions.
Definition: dim-vector.h:257
void * get_data(void) const
Definition: mxarray.h:497
octave_idx_type numel(void) const
Definition: ov-base-mat.h:118
dim_vector dims(void) const
Definition: ov-base-mat.h:116
octave_idx_type columns(void) const
Definition: ov-base.h:355
int current_print_indent_level(void) const
Definition: ov-base.h:893
OCTINTERP_API void warn_load(const char *type) const
Definition: ov-base.cc:1152
octave_idx_type rows(void) const
Definition: ov-base.h:348
friend class octave_value
Definition: ov-base.h:256
OCTINTERP_API void warn_save(const char *type) const
Definition: ov-base.cc:1161
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
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
mxArray * as_mxArray(bool interleaved) const
Definition: ov-bool-mat.cc:569
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:246
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:936
bool bool_value(bool warn=false) const
Definition: ov.h:930
bool issparse(void) const
Definition: ov.h:798
bool isnumeric(void) const
Definition: ov.h:795
bool is_scalar_type(void) const
Definition: ov.h:789
SparseBoolMatrix sparse_bool_matrix_value(bool warn=false) const
Definition: ov.h:952
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition: ov.h:1411
bool islogical(void) const
Definition: ov.h:780
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
OCTINTERP_API 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:980
#define panic_impossible()
Definition: error.h:411
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:116
int save_hdf5_empty(octave_hdf5_id loc_id, const char *name, const dim_vector &d)
Definition: ls-hdf5.cc:1251
int load_hdf5_empty(octave_hdf5_id loc_id, const char *name, dim_vector &d)
Definition: ls-hdf5.cc:1307
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
class OCTAVE_API NDArray
Definition: mx-fwd.h:38
class OCTAVE_API boolMatrix
Definition: mx-fwd.h:35
class OCTAVE_API FloatNDArray
Definition: mx-fwd.h:40
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:222
static octave_base_value * default_numeric_conversion_function(const octave_base_value &a)
Definition: ov-bool-mat.cc:74
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