GNU Octave  3.8.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-2013 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 "ops.h"
40 #include "ov-base.h"
41 #include "ov-base-mat.h"
42 #include "ov-base-mat.cc"
43 #include "ov-bool.h"
44 #include "ov-bool-mat.h"
45 #include "ov-re-mat.h"
46 #include "pr-output.h"
47 
48 #include "byte-swap.h"
49 #include "ls-oct-ascii.h"
50 #include "ls-hdf5.h"
51 #include "ls-utils.h"
52 
53 template class octave_base_matrix<boolNDArray>;
54 
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  {
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 #if defined (HAVE_HDF5)
413 
414 bool
415 octave_bool_matrix::save_hdf5 (hid_t loc_id, const char *name,
416  bool /* save_as_floats */)
417 {
418  dim_vector dv = dims ();
419  int empty = save_hdf5_empty (loc_id, name, dv);
420  if (empty)
421  return (empty > 0);
422 
423  int rank = dv.length ();
424  hid_t space_hid = -1, data_hid = -1;
425  bool retval = true;
427 
428  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
429 
430  // Octave uses column-major, while HDF5 uses row-major ordering
431  for (int i = 0; i < rank; i++)
432  hdims[i] = dv (rank-i-1);
433 
434  space_hid = H5Screate_simple (rank, hdims, 0);
435  if (space_hid < 0) return false;
436 #if HAVE_HDF5_18
437  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
438  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
439 #else
440  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_HBOOL, space_hid,
441  H5P_DEFAULT);
442 #endif
443  if (data_hid < 0)
444  {
445  H5Sclose (space_hid);
446  return false;
447  }
448 
449  octave_idx_type nel = m.nelem ();
450  bool *mtmp = m.fortran_vec ();
451  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
452 
453  for (octave_idx_type i = 0; i < nel; i++)
454  htmp[i] = mtmp[i];
455 
456  retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL,
457  H5P_DEFAULT, htmp) >= 0;
458 
459  H5Dclose (data_hid);
460  H5Sclose (space_hid);
461 
462  return retval;
463 }
464 
465 bool
466 octave_bool_matrix::load_hdf5 (hid_t loc_id, const char *name)
467 {
468  bool retval = false;
469 
470  dim_vector dv;
471  int empty = load_hdf5_empty (loc_id, name, dv);
472  if (empty > 0)
473  matrix.resize (dv);
474  if (empty)
475  return (empty > 0);
476 
477 #if HAVE_HDF5_18
478  hid_t data_hid = H5Dopen (loc_id, name, H5P_DEFAULT);
479 #else
480  hid_t data_hid = H5Dopen (loc_id, name);
481 #endif
482  hid_t space_id = H5Dget_space (data_hid);
483 
484  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
485 
486  if (rank < 1)
487  {
488  H5Dclose (data_hid);
489  return false;
490  }
491 
492  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
493  OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
494 
495  H5Sget_simple_extent_dims (space_id, hdims, maxdims);
496 
497  // Octave uses column-major, while HDF5 uses row-major ordering
498  if (rank == 1)
499  {
500  dv.resize (2);
501  dv(0) = 1;
502  dv(1) = hdims[0];
503  }
504  else
505  {
506  dv.resize (rank);
507  for (hsize_t i = 0, j = rank - 1; i < rank; i++, j--)
508  dv(j) = hdims[i];
509  }
510 
511  octave_idx_type nel = dv.numel ();
512  OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nel);
513  if (H5Dread (data_hid, H5T_NATIVE_HBOOL, H5S_ALL, H5S_ALL, H5P_DEFAULT, htmp)
514  >= 0)
515  {
516  retval = true;
517 
518  boolNDArray btmp (dv);
519  for (octave_idx_type i = 0; i < nel; i++)
520  btmp.elem (i) = htmp[i];
521 
522  matrix = btmp;
523  }
524 
525  H5Dclose (data_hid);
526 
527  return retval;
528 }
529 
530 #endif
531 
532 mxArray *
534 {
535  mxArray *retval = new mxArray (mxLOGICAL_CLASS, dims (), mxREAL);
536 
537  bool *pr = static_cast<bool *> (retval->get_data ());
538 
539  mwSize nel = numel ();
540 
541  const bool *p = matrix.data ();
542 
543  for (mwIndex i = 0; i < nel; i++)
544  pr[i] = p[i];
545 
546  return retval;
547 }
548 
549 DEFUN (logical, args, ,
550  "-*- texinfo -*-\n\
551 @deftypefn {Built-in Function} {} logical (@var{x})\n\
552 Convert @var{x} to logical type.\n\
553 @seealso{double, single, char}\n\
554 @end deftypefn")
555 {
556  octave_value retval;
557 
558  if (args.length () == 1)
559  {
560  octave_value arg = args(0);
561  if (arg.is_bool_type ())
562  retval = arg;
563  else if (arg.is_numeric_type ())
564  {
565  if (arg.is_sparse_type ())
566  retval = arg.sparse_bool_matrix_value ();
567  else if (arg.is_scalar_type ())
568  retval = arg.bool_value ();
569  else
570  retval = arg.bool_array_value ();
571  }
572  else
573  gripe_wrong_type_arg ("logical", arg);
574  }
575  else
576  print_usage ();
577 
578  return retval;
579 }
580 
581 /*
582 %!test
583 %! m = eye (2) != 0;
584 %! s = !0;
585 %! c = {"double", "single", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "logical"};
586 %! for i = 1:numel (c)
587 %! assert (logical (eye (2, c{i})), m)
588 %! assert (logical (eye (1, c{i})), s)
589 %! endfor
590 */