GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ov-bool-mat.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 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-bool.h"
56#include "ov-bool-mat.h"
57#include "ov-re-mat.h"
58#include "pr-output.h"
59
60#include "byte-swap.h"
61#include "ls-oct-text.h"
62#include "ls-hdf5.h"
63#include "ls-utils.h"
64
66 "bool matrix", "logical");
67
68static octave_base_value *
69default_numeric_conversion_function (const octave_base_value& a)
70{
71 const octave_bool_matrix& v = dynamic_cast<const octave_bool_matrix&> (a);
72
73 return new octave_matrix (NDArray (v.bool_array_value ()));
74}
75
78{
79 return octave_base_value::type_conv_info (default_numeric_conversion_function,
81}
82
85{
86 octave_base_value *retval = nullptr;
87
88 if (m_matrix.ndims () == 2)
89 {
91
92 octave_idx_type nr = bm.rows ();
93 octave_idx_type nc = bm.cols ();
94
95 if (nr == 1 && nc == 1)
96 retval = new octave_bool (bm (0, 0));
97 }
98
99 return retval;
100}
101
102double
104{
105 if (rows () == 0 || columns () == 0)
106 err_invalid_conversion ("bool matrix", "real scalar");
107
108 warn_implicit_conversion ("Octave:array-to-scalar",
109 "bool matrix", "real scalar");
110
111 return m_matrix(0, 0);
112}
113
114float
116{
117 if (rows () == 0 || columns () == 0)
118 err_invalid_conversion ("bool matrix", "real scalar");
119
120 warn_implicit_conversion ("Octave:array-to-scalar",
121 "bool matrix", "real scalar");
122
123 return m_matrix(0, 0);
124}
125
128{
129 if (rows () == 0 || columns () == 0)
130 err_invalid_conversion ("bool matrix", "complex scalar");
131
132 warn_implicit_conversion ("Octave:array-to-scalar",
133 "bool matrix", "complex scalar");
134
135 return Complex (m_matrix(0, 0), 0);
136}
137
140{
141 float tmp = lo_ieee_float_nan_value ();
142
143 FloatComplex retval (tmp, tmp);
144
145 if (rows () == 0 || columns () == 0)
146 err_invalid_conversion ("bool matrix", "complex scalar");
147
148 warn_implicit_conversion ("Octave:array-to-scalar",
149 "bool matrix", "complex scalar");
150
151 retval = m_matrix(0, 0);
152
153 return retval;
154}
155
158 char type) const
159{
161 return tmp.convert_to_str (pad, force, type);
162}
163
166{
167 return NDArray (m_matrix);
168}
169
172{
173 return FloatNDArray (m_matrix);
174}
175
178{
179 return int8NDArray (m_matrix);
180}
181
184{
185 return int16NDArray (m_matrix);
186}
187
190{
191 return int32NDArray (m_matrix);
192}
193
196{
197 return int64NDArray (m_matrix);
198}
199
202{
203 return uint8NDArray (m_matrix);
204}
205
208{
209 return uint16NDArray (m_matrix);
210}
211
214{
215 return uint32NDArray (m_matrix);
216}
217
220{
221 return uint64NDArray (m_matrix);
222}
223
224void
226 bool pr_as_read_syntax) const
227{
228 octave_print_internal (os, m_matrix, pr_as_read_syntax,
230}
231
232bool
234{
235 const dim_vector& dv = dims ();
236 if (dv.ndims () > 2)
237 {
238 NDArray tmp = array_value ();
239 os << "# ndims: " << dv.ndims () << "\n";
240
241 for (int i = 0; i < dv.ndims (); i++)
242 os << ' ' << dv(i);
243
244 os << "\n" << tmp;
245 }
246 else
247 {
248 // Keep this case, rather than use generic code above for backward
249 // compatibility. Makes load_ascii much more complex!!
250 os << "# rows: " << rows () << "\n"
251 << "# columns: " << columns () << "\n";
252
253 Matrix tmp = matrix_value ();
254
255 os << tmp;
256 }
257
258 return true;
259}
260
261bool
263{
264 string_vector keywords (2);
265
266 keywords[0] = "ndims";
267 keywords[1] = "rows";
268
269 std::string kw;
270 octave_idx_type val = 0;
271
272 if (! extract_keyword (is, keywords, kw, val, true))
273 error ("load: failed to extract number of rows and columns");
274
275 if (kw == "ndims")
276 {
277 int mdims = static_cast<int> (val);
278
279 if (mdims < 0)
280 error ("load: failed to extract number of dimensions");
281
282 dim_vector dv;
283 dv.resize (mdims);
284
285 for (int i = 0; i < mdims; i++)
286 is >> dv(i);
287
288 if (! is)
289 error ("load: failed to extract dimensions");
290
291 boolNDArray btmp (dv);
292
293 if (btmp.isempty ())
294 m_matrix = btmp;
295 else
296 {
297 NDArray tmp(dv);
298 is >> tmp;
299
300 if (! is)
301 error ("load: failed to load matrix constant");
302
303 for (octave_idx_type i = 0; i < btmp.numel (); i++)
304 btmp.elem (i) = (tmp.elem (i) != 0.);
305
306 m_matrix = btmp;
307 }
308 }
309 else if (kw == "rows")
310 {
311 octave_idx_type nr = val;
312 octave_idx_type nc = 0;
313
314 if (nr < 0 || ! extract_keyword (is, "columns", nc) || nc < 0)
315 error ("load: failed to extract number of rows and columns");
316
317 if (nr > 0 && nc > 0)
318 {
319 Matrix tmp (nr, nc);
320 is >> tmp;
321 if (! is)
322 error ("load: failed to load matrix constant");
323
324 boolMatrix btmp (nr, nc);
325 for (octave_idx_type j = 0; j < nc; j++)
326 for (octave_idx_type i = 0; i < nr; i++)
327 btmp.elem (i, j) = (tmp.elem (i, j) != 0.);
328
329 m_matrix = btmp;
330 }
331 else if (nr == 0 || nc == 0)
332 m_matrix = boolMatrix (nr, nc);
333 else
334 error ("unexpected dimensions in octave_bool_matrix::load_ascii - please report this bug");
335 }
336 else
337 error ("unexpected dimensions keyword (= '%s') octave_bool_matrix::load_ascii - please report this bug", kw.c_str ());
338
339 return true;
340}
341
342bool
343octave_bool_matrix::save_binary (std::ostream& os, bool /* save_as_floats */)
344{
345
346 const dim_vector& dv = dims ();
347 if (dv.ndims () < 1)
348 return false;
349
350 // Use negative value for ndims to differentiate with old format!!
351 int32_t tmp = - dv.ndims ();
352 os.write (reinterpret_cast<char *> (&tmp), 4);
353 for (int i = 0; i < dv.ndims (); i++)
354 {
355 tmp = dv(i);
356 os.write (reinterpret_cast<char *> (&tmp), 4);
357 }
358
359 const bool *mtmp = m_matrix.data ();
361 os.write (reinterpret_cast<const char *> (mtmp), nel);
362
363 return true;
364}
365
366bool
367octave_bool_matrix::load_binary (std::istream& is, bool swap,
368 octave::mach_info::float_format /* fmt */)
369{
370 int32_t mdims;
371 if (! is.read (reinterpret_cast<char *> (&mdims), 4))
372 return false;
373 if (swap)
374 swap_bytes<4> (&mdims);
375 if (mdims >= 0)
376 return false;
377
378 // mdims is negative for consistency with other matrices, where it is
379 // negative to allow the positive value to be used for rows/cols for
380 // backward compatibility
381 mdims = - mdims;
382 int32_t di;
383 dim_vector dv;
384 dv.resize (mdims);
385
386 for (int i = 0; i < mdims; i++)
387 {
388 if (! is.read (reinterpret_cast<char *> (&di), 4))
389 return false;
390 if (swap)
391 swap_bytes<4> (&di);
392 dv(i) = di;
393 }
394
395 // Convert an array with a single dimension to be a row vector.
396 // Octave should never write files like this, other software
397 // might.
398
399 if (mdims == 1)
400 {
401 mdims = 2;
402 dv.resize (mdims);
403 dv(1) = dv(0);
404 dv(0) = 1;
405 }
406
407 octave_idx_type nel = dv.numel ();
408 OCTAVE_LOCAL_BUFFER (char, htmp, nel);
409 if (! is.read (htmp, nel))
410 return false;
411 boolNDArray m(dv);
412 bool *mtmp = m.rwdata ();
413 for (octave_idx_type i = 0; i < nel; i++)
414 mtmp[i] = (htmp[i] ? 1 : 0);
415 m_matrix = m;
416
417 return true;
418}
419
420bool
422 bool /* save_as_floats */)
423{
424 bool retval = true;
425
426#if defined (HAVE_HDF5)
427
428 const dim_vector& dv = dims ();
429 int empty = save_hdf5_empty (loc_id, name, dv);
430 if (empty)
431 return (empty > 0);
432
433 int rank = dv.ndims ();
434 hid_t space_hid, data_hid;
435 space_hid = data_hid = -1;
436
437 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
438
439 // Octave uses column-major, while HDF5 uses row-major ordering
440 for (int i = 0; i < rank; i++)
441 hdims[i] = dv(rank-i-1);
442
443 space_hid = H5Screate_simple (rank, hdims, nullptr);
444 if (space_hid < 0) return false;
445#if defined (HAVE_HDF5_18)
446 data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
449#else
450 data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
452#endif
453 if (data_hid < 0)
454 {
455 H5Sclose (space_hid);
456 return false;
457 }
458
459 const bool *mtmp = m_matrix.data ();
460
461 retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
463 reinterpret_cast<const char *> (mtmp)) >= 0;
464
465 H5Dclose (data_hid);
466 H5Sclose (space_hid);
467
468#else
469 octave_unused_parameter (loc_id);
470 octave_unused_parameter (name);
471
472 warn_save ("hdf5");
473#endif
474
475 return retval;
476}
477
478bool
480{
481 bool retval = false;
482
483#if defined (HAVE_HDF5)
484
485 dim_vector dv;
486 int empty = load_hdf5_empty (loc_id, name, dv);
487 if (empty > 0)
488 m_matrix.resize (dv);
489 if (empty)
490 return (empty > 0);
491
492#if defined (HAVE_HDF5_18)
493 hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
494#else
495 hid_t data_hid = H5Dopen (loc_id, name);
496#endif
497 hid_t space_id = H5Dget_space (data_hid);
498
499 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
500
501 if (rank < 1)
502 {
503 H5Dclose (data_hid);
504 return false;
505 }
506
507 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
508 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
509
510 H5Sget_simple_extent_dims (space_id, hdims, maxdims);
511
512 // Octave uses column-major, while HDF5 uses row-major ordering
513 if (rank == 1)
514 {
515 dv.resize (2);
516 dv(0) = 1;
517 dv(1) = hdims[0];
518 }
519 else
520 {
521 dv.resize (rank);
522 for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
523 dv(j) = hdims[i];
524 }
525
526 octave_idx_type nel = dv.numel ();
527 OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
528 if (H5Dread (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
529 octave_H5P_DEFAULT, htmp)
530 >= 0)
531 {
532 retval = true;
533
534 boolNDArray btmp (dv);
535 for (octave_idx_type i = 0; i < nel; i++)
536 btmp.elem (i) = htmp[i];
537
538 m_matrix = btmp;
539 }
540
541 H5Dclose (data_hid);
542
543#else
544 octave_unused_parameter (loc_id);
545 octave_unused_parameter (name);
546
547 warn_load ("hdf5");
548#endif
549
550 return retval;
551}
552
553mxArray *
554octave_bool_matrix::as_mxArray (bool interleaved) const
555{
556 mxArray *retval = new mxArray (interleaved, mxLOGICAL_CLASS, dims (), mxREAL);
557
558 mxLogical *pd = static_cast<mxLogical *> (retval->get_data ());
559
560 mwSize nel = numel ();
561
562 const bool *pdata = m_matrix.data ();
563
564 for (mwIndex i = 0; i < nel; i++)
565 pd[i] = pdata[i];
566
567 return retval;
568}
569
571
572DEFUN (logical, args, ,
573 doc: /* -*- texinfo -*-
574@deftypefn {} {@var{TF} =} logical (@var{x})
575Convert the numeric object @var{x} to logical type.
576
577Any nonzero values will be converted to true (1) while zero values will be
578converted to false (0). The non-numeric value NaN cannot be converted and will
579produce an error.
580
581Compatibility Note: Octave accepts complex values as input, whereas @sc{matlab}
582issues an error.
583@seealso{double, single, char}
584@end deftypefn */)
585{
586 if (args.length () != 1)
587 print_usage ();
588
589 octave_value retval;
590
591 octave_value arg = args(0);
592
593 if (arg.islogical ())
594 retval = arg;
595 else if (arg.isnumeric ())
596 {
597 if (arg.issparse ())
598 retval = arg.sparse_bool_matrix_value ();
599 else if (arg.is_scalar_type ())
600 retval = arg.bool_value ();
601 else
602 retval = arg.bool_array_value ();
603 }
604 else
605 err_wrong_type_arg ("logical", arg);
606
607 return retval;
608}
609
610/*
611%!test
612%! m = eye (2) != 0;
613%! s = ! 0;
614%! c = {"double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical"};
615%! for i = 1:numel (c)
616%! assert (logical (eye (2, c{i})), m);
617%! assert (logical (eye (1, c{i})), s);
618%! endfor
619*/
620
621OCTAVE_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:563
int ndims() const
Size of the specified dimension.
Definition Array.h:679
octave_idx_type rows() const
Definition Array.h:463
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
octave_idx_type cols() const
Definition Array.h:473
bool isempty() const
Size of the specified dimension.
Definition Array.h:652
const T * data() const
Size of the specified dimension.
Definition Array.h:665
T * rwdata()
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition dim-vector.h:331
void resize(int n, int fill_value=0)
Definition dim-vector.h:268
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:253
void * get_data() const
Definition mxarray.h:482
octave_idx_type numel() const
octave_idx_type rows() const
Definition ov-base.h:384
octave_idx_type columns() const
Definition ov-base.h:391
int current_print_indent_level() const
Definition ov-base.h:945
void warn_load(const char *type) const
Definition ov-base.cc:1152
friend class octave_value
Definition ov-base.h:278
void warn_save(const char *type) const
Definition ov-base.cc:1161
FloatComplex float_complex_value(bool=false) const
octave_value as_int16() const
octave_value convert_to_str_internal(bool pad, bool force, char type) const
octave_base_value * try_narrowing_conversion()
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
float float_value(bool=false) const
octave_value as_uint8() const
boolNDArray bool_array_value(bool=false) const
octave_value as_int8() const
mxArray * as_mxArray(bool interleaved) const
type_conv_info numeric_conversion_function() const
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
NDArray array_value(bool=false) const
Complex complex_value(bool=false) const
octave_value as_single() const
octave_value as_double() const
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
bool save_binary(std::ostream &os, bool save_as_floats)
octave_value as_int64() const
double double_value(bool=false) const
bool save_ascii(std::ostream &os)
bool load_ascii(std::istream &is)
octave_value as_uint64() const
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Matrix matrix_value(bool=false) const
octave_value as_uint16() const
octave_value as_int32() const
octave_value as_uint32() const
static int static_type_id()
Definition ov-re-mat.h:249
boolNDArray bool_array_value(bool warn=false) const
Definition ov.h:900
bool bool_value(bool warn=false) const
Definition ov.h:891
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:916
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition ov.h:1322
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()
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:1003
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
intNDArray< octave_int32 > int32NDArray
intNDArray< octave_int64 > int64NDArray
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:1254
int load_hdf5_empty(octave_hdf5_id loc_id, const char *name, dim_vector &d)
Definition ls-hdf5.cc:1311
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
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:246
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
intNDArray< octave_uint16 > uint16NDArray
intNDArray< octave_uint32 > uint32NDArray
intNDArray< octave_uint64 > uint64NDArray
intNDArray< octave_uint8 > uint8NDArray