1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1998-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 "dim-vector.h"
35 
36 #include "mxarray.h"
37 #include "ov-base.h"
38 #include "ov-scalar.h"
39 #include "ov-bool.h"
40 #include "ov-bool-mat.h"
41 #include "errwarn.h"
42 #include "ops.h"
43 #include "oct-locbuf.h"
44 
45 #include "oct-hdf5.h"
46 
47 #include "ov-re-sparse.h"
48 #include "ov-cx-sparse.h"
49 #include "ov-bool-sparse.h"
50 
51 #include "ov-base-sparse.h"
52 #include "ov-base-sparse.cc"
53 
54 template class OCTINTERP_API octave_base_sparse<SparseBoolMatrix>;
55 
56 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_sparse_bool_matrix,
57                                      "sparse bool matrix", "logical");
58 
59 static octave_base_value *
default_numeric_conversion_function(const octave_base_value & a)60 default_numeric_conversion_function (const octave_base_value& a)
61 {
62   const octave_sparse_bool_matrix& v
63     = dynamic_cast<const octave_sparse_bool_matrix&> (a);
64 
65   return
66     new octave_sparse_matrix (SparseMatrix (v.sparse_bool_matrix_value ()));
67 }
68 
69 octave_base_value::type_conv_info
numeric_conversion_function(void) const70 octave_sparse_bool_matrix::numeric_conversion_function (void) const
71 {
72   return octave_base_value::type_conv_info (default_numeric_conversion_function,
73                                             octave_sparse_matrix::static_type_id ());
74 }
75 
76 octave_base_value *
try_narrowing_conversion(void)77 octave_sparse_bool_matrix::try_narrowing_conversion (void)
78 {
79   octave_base_value *retval = nullptr;
80 
81   if (Vsparse_auto_mutate)
82     {
83       // Don't use numel, since it can overflow for very large matrices
84       // Note that for the second test, this means it becomes approximative
85       // since it involves a cast to double to avoid issues of overflow
86       if (matrix.rows () == 1 && matrix.cols () == 1)
87         {
88           // Const copy of the matrix, so the right version of () operator used
89           const SparseBoolMatrix tmp (matrix);
90 
91           retval = new octave_bool (tmp (0));
92         }
93       else if (matrix.cols () > 0 && matrix.rows () > 0
94                && (double (matrix.byte_size ()) > double (matrix.rows ())
95                    * double (matrix.cols ()) * sizeof (bool)))
96         retval = new octave_bool_matrix (matrix.matrix_value ());
97     }
98 
99   return retval;
100 }
101 
102 double
double_value(bool) const103 octave_sparse_bool_matrix::double_value (bool) const
104 {
105   if (isempty ())
106     err_invalid_conversion ("bool sparse matrix", "real scalar");
107 
108   if (numel () > 1)
109     warn_implicit_conversion ("Octave:array-to-scalar",
110                               "bool sparse matrix", "real scalar");
111 
112   return matrix(0, 0);
113 }
114 
115 Complex
complex_value(bool) const116 octave_sparse_bool_matrix::complex_value (bool) const
117 {
118   if (rows () == 0 || columns () == 0)
119     err_invalid_conversion ("bool sparse matrix", "complex scalar");
120 
121   if (numel () > 1)
122     warn_implicit_conversion ("Octave:array-to-scalar",
123                               "bool sparse matrix", "complex scalar");
124 
125   return Complex (matrix(0, 0), 0);
126 }
127 
128 octave_value
convert_to_str_internal(bool pad,bool force,char type) const129 octave_sparse_bool_matrix::convert_to_str_internal (bool pad, bool force,
130                                                     char type) const
131 {
132   octave_value tmp = octave_value (array_value ());
133   return tmp.convert_to_str (pad, force, type);
134 }
135 
136 // FIXME: These are inefficient ways of creating full matrices
137 
138 Matrix
matrix_value(bool) const139 octave_sparse_bool_matrix::matrix_value (bool) const
140 {
141   return Matrix (matrix.matrix_value ());
142 }
143 
144 ComplexMatrix
complex_matrix_value(bool) const145 octave_sparse_bool_matrix::complex_matrix_value (bool) const
146 {
147   return ComplexMatrix (matrix.matrix_value ());
148 }
149 
150 ComplexNDArray
complex_array_value(bool) const151 octave_sparse_bool_matrix::complex_array_value (bool) const
152 {
153   return ComplexNDArray (ComplexMatrix (matrix.matrix_value ()));
154 }
155 
156 NDArray
array_value(bool) const157 octave_sparse_bool_matrix::array_value (bool) const
158 {
159   return NDArray (Matrix (matrix.matrix_value ()));
160 }
161 
162 charNDArray
char_array_value(bool) const163 octave_sparse_bool_matrix::char_array_value (bool) const
164 {
165   charNDArray retval (dims (), 0);
166   octave_idx_type nc = matrix.cols ();
167   octave_idx_type nr = matrix.rows ();
168 
169   for (octave_idx_type j = 0; j < nc; j++)
170     for (octave_idx_type i = matrix.cidx (j); i < matrix.cidx (j+1); i++)
171       retval(matrix.ridx (i) + nr * j) = static_cast<char> (matrix.data (i));
172 
173   return retval;
174 }
175 
176 boolMatrix
bool_matrix_value(bool) const177 octave_sparse_bool_matrix::bool_matrix_value (bool) const
178 {
179   return matrix.matrix_value ();
180 }
181 
182 boolNDArray
bool_array_value(bool) const183 octave_sparse_bool_matrix::bool_array_value (bool) const
184 {
185   return boolNDArray (matrix.matrix_value ());
186 }
187 
188 SparseMatrix
sparse_matrix_value(bool) const189 octave_sparse_bool_matrix::sparse_matrix_value (bool) const
190 {
191   return SparseMatrix (this->matrix);
192 }
193 
194 SparseComplexMatrix
sparse_complex_matrix_value(bool) const195 octave_sparse_bool_matrix::sparse_complex_matrix_value (bool) const
196 {
197   return SparseComplexMatrix (this->matrix);
198 }
199 
200 octave_value
as_double(void) const201 octave_sparse_bool_matrix::as_double (void) const
202 {
203   return SparseMatrix (this->matrix);
204 }
205 
206 bool
save_binary(std::ostream & os,bool)207 octave_sparse_bool_matrix::save_binary (std::ostream& os, bool)
208 {
209   dim_vector dv = this->dims ();
210   if (dv.ndims () < 1)
211     return false;
212 
213   // Ensure that additional memory is deallocated
214   matrix.maybe_compress ();
215 
216   int nr = dv(0);
217   int nc = dv(1);
218   int nz = nnz ();
219 
220   int32_t itmp;
221   // Use negative value for ndims to be consistent with other formats
222   itmp = -2;
223   os.write (reinterpret_cast<char *> (&itmp), 4);
224 
225   itmp = nr;
226   os.write (reinterpret_cast<char *> (&itmp), 4);
227 
228   itmp = nc;
229   os.write (reinterpret_cast<char *> (&itmp), 4);
230 
231   itmp = nz;
232   os.write (reinterpret_cast<char *> (&itmp), 4);
233 
234   // add one to the printed indices to go from
235   // zero-based to one-based arrays
236   for (int i = 0; i < nc+1; i++)
237     {
238       octave_quit ();
239       itmp = matrix.cidx (i);
240       os.write (reinterpret_cast<char *> (&itmp), 4);
241     }
242 
243   for (int i = 0; i < nz; i++)
244     {
245       octave_quit ();
246       itmp = matrix.ridx (i);
247       os.write (reinterpret_cast<char *> (&itmp), 4);
248     }
249 
250   OCTAVE_LOCAL_BUFFER (char, htmp, nz);
251 
252   for (int i = 0; i < nz; i++)
253     htmp[i] = (matrix.data (i) ? 1 : 0);
254 
255   os.write (htmp, nz);
256 
257   return true;
258 }
259 
260 bool
load_binary(std::istream & is,bool swap,octave::mach_info::float_format)261 octave_sparse_bool_matrix::load_binary (std::istream& is, bool swap,
262                                         octave::mach_info::float_format /* fmt */)
263 {
264   int32_t nz, nc, nr, tmp;
265   if (! is.read (reinterpret_cast<char *> (&tmp), 4))
266     return false;
267 
268   if (swap)
269     swap_bytes<4> (&tmp);
270 
271   if (tmp != -2)
272     error ("load: only 2-D sparse matrices are supported");
273 
274   if (! is.read (reinterpret_cast<char *> (&nr), 4))
275     return false;
276   if (! is.read (reinterpret_cast<char *> (&nc), 4))
277     return false;
278   if (! is.read (reinterpret_cast<char *> (&nz), 4))
279     return false;
280 
281   if (swap)
282     {
283       swap_bytes<4> (&nr);
284       swap_bytes<4> (&nc);
285       swap_bytes<4> (&nz);
286     }
287 
288   SparseBoolMatrix m (static_cast<octave_idx_type> (nr),
289                       static_cast<octave_idx_type> (nc),
290                       static_cast<octave_idx_type> (nz));
291 
292   for (int i = 0; i < nc+1; i++)
293     {
294       octave_quit ();
295       if (! is.read (reinterpret_cast<char *> (&tmp), 4))
296         return false;
297       if (swap)
298         swap_bytes<4> (&tmp);
299       m.cidx (i) = tmp;
300     }
301 
302   for (int i = 0; i < nz; i++)
303     {
304       octave_quit ();
305       if (! is.read (reinterpret_cast<char *> (&tmp), 4))
306         return false;
307       if (swap)
308         swap_bytes<4> (&tmp);
309       m.ridx (i) = tmp;
310     }
311 
312   if (! is)
313     return false;
314 
315   OCTAVE_LOCAL_BUFFER (char, htmp, nz);
316 
317   if (! is.read (htmp, nz))
318     return false;
319 
320   for (int i = 0; i < nz; i++)
321     m.data(i) = (htmp[i] ? 1 : 0);
322 
323   if (! m.indices_ok ())
324     return false;
325 
326   matrix = m;
327 
328   return true;
329 }
330 
331 bool
save_hdf5(octave_hdf5_id loc_id,const char * name,bool)332 octave_sparse_bool_matrix::save_hdf5 (octave_hdf5_id loc_id, const char *name,
333                                       bool)
334 {
335   bool retval = false;
336 
337 #if defined (HAVE_HDF5)
338 
339   dim_vector dv = dims ();
340   int empty = save_hdf5_empty (loc_id, name, dv);
341   if (empty)
342     return (empty > 0);
343 
344   // Ensure that additional memory is deallocated
345   matrix.maybe_compress ();
346 #if defined (HAVE_HDF5_18)
347   hid_t group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT,
348                                octave_H5P_DEFAULT, octave_H5P_DEFAULT);
349 #else
350   hid_t group_hid = H5Gcreate (loc_id, name, 0);
351 #endif
352   if (group_hid < 0)
353     return false;
354 
355   hid_t space_hid, data_hid;
356   space_hid = data_hid = -1;
357   SparseBoolMatrix m = sparse_bool_matrix_value ();
358   octave_idx_type tmp;
359   hsize_t hdims[2];
360 
361   space_hid = H5Screate_simple (0, hdims, nullptr);
362   if (space_hid < 0)
363     {
364       H5Gclose (group_hid);
365       return false;
366     }
367 #if defined (HAVE_HDF5_18)
368   data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_IDX, space_hid,
369                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,
370                         octave_H5P_DEFAULT);
371 #else
372   data_hid = H5Dcreate (group_hid, "nr", H5T_NATIVE_IDX, space_hid,
373                         octave_H5P_DEFAULT);
374 #endif
375   if (data_hid < 0)
376     {
377       H5Sclose (space_hid);
378       H5Gclose (group_hid);
379       return false;
380     }
381 
382   tmp = m.rows ();
383   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL,
384                      octave_H5S_ALL, octave_H5P_DEFAULT, &tmp) >= 0;
385   H5Dclose (data_hid);
386   if (! retval)
387     {
388       H5Sclose (space_hid);
389       H5Gclose (group_hid);
390       return false;
391     }
392 
393 #if defined (HAVE_HDF5_18)
394   data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_IDX, space_hid,
395                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,
396                         octave_H5P_DEFAULT);
397 #else
398   data_hid = H5Dcreate (group_hid, "nc", H5T_NATIVE_IDX, space_hid,
399                         octave_H5P_DEFAULT);
400 #endif
401   if (data_hid < 0)
402     {
403       H5Sclose (space_hid);
404       H5Gclose (group_hid);
405       return false;
406     }
407 
408   tmp = m.cols ();
409   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
410                      octave_H5P_DEFAULT, &tmp) >= 0;
411   H5Dclose (data_hid);
412   if (! retval)
413     {
414       H5Sclose (space_hid);
415       H5Gclose (group_hid);
416       return false;
417     }
418 
419 #if defined (HAVE_HDF5_18)
420   data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_IDX, space_hid,
421                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,
422                         octave_H5P_DEFAULT);
423 #else
424   data_hid = H5Dcreate (group_hid, "nz", H5T_NATIVE_IDX, space_hid,
425                         octave_H5P_DEFAULT);
426 #endif
427   if (data_hid < 0)
428     {
429       H5Sclose (space_hid);
430       H5Gclose (group_hid);
431       return false;
432     }
433 
434   tmp = m.nnz ();
435   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
436                      octave_H5P_DEFAULT, &tmp) >= 0;
437   H5Dclose (data_hid);
438   if (! retval)
439     {
440       H5Sclose (space_hid);
441       H5Gclose (group_hid);
442       return false;
443     }
444 
445   H5Sclose (space_hid);
446 
447   hdims[0] = m.cols () + 1;
448   hdims[1] = 1;
449 
450   space_hid = H5Screate_simple (2, hdims, nullptr);
451 
452   if (space_hid < 0)
453     {
454       H5Gclose (group_hid);
455       return false;
456     }
457 
458 #if defined (HAVE_HDF5_18)
459   data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_IDX, space_hid,
460                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,
461                         octave_H5P_DEFAULT);
462 #else
463   data_hid = H5Dcreate (group_hid, "cidx", H5T_NATIVE_IDX, space_hid,
464                         octave_H5P_DEFAULT);
465 #endif
466   if (data_hid < 0)
467     {
468       H5Sclose (space_hid);
469       H5Gclose (group_hid);
470       return false;
471     }
472 
473   octave_idx_type *itmp = m.xcidx ();
474   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
475                      octave_H5P_DEFAULT, itmp) >= 0;
476   H5Dclose (data_hid);
477   if (! retval)
478     {
479       H5Sclose (space_hid);
480       H5Gclose (group_hid);
481       return false;
482     }
483 
484   H5Sclose (space_hid);
485 
486   hdims[0] = m.nnz ();
487   hdims[1] = 1;
488 
489   space_hid = H5Screate_simple (2, hdims, nullptr);
490 
491   if (space_hid < 0)
492     {
493       H5Gclose (group_hid);
494       return false;
495     }
496 
497 #if defined (HAVE_HDF5_18)
498   data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_IDX, space_hid,
499                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,
500                         octave_H5P_DEFAULT);
501 #else
502   data_hid = H5Dcreate (group_hid, "ridx", H5T_NATIVE_IDX, space_hid,
503                         octave_H5P_DEFAULT);
504 #endif
505   if (data_hid < 0)
506     {
507       H5Sclose (space_hid);
508       H5Gclose (group_hid);
509       return false;
510     }
511 
512   itmp = m.xridx ();
513   retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
514                      octave_H5P_DEFAULT, itmp) >= 0;
515   H5Dclose (data_hid);
516   if (! retval)
517     {
518       H5Sclose (space_hid);
519       H5Gclose (group_hid);
520       return false;
521     }
522 
523 #if defined (HAVE_HDF5_18)
524   data_hid = H5Dcreate (group_hid, "data", H5T_NATIVE_HBOOL, space_hid,
525                         octave_H5P_DEFAULT, octave_H5P_DEFAULT,
526                         octave_H5P_DEFAULT);
527 #else
528   data_hid = H5Dcreate (group_hid, "data", H5T_NATIVE_HBOOL, space_hid,
529                         octave_H5P_DEFAULT);
530 #endif
531   if (data_hid < 0)
532     {
533       H5Sclose (space_hid);
534       H5Gclose (group_hid);
535       return false;
536     }
537 
538   OCTAVE_LOCAL_BUFFER (hbool_t, htmp, m.nnz ());
539   for (int i = 0; i < m.nnz (); i++)
540     htmp[i] = m.xdata(i);
541 
542   retval = H5Dwrite (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
543                      octave_H5P_DEFAULT, htmp) >= 0;
544   H5Dclose (data_hid);
545   H5Sclose (space_hid);
546   H5Gclose (group_hid);
547 
548 #else
549   octave_unused_parameter (loc_id);
550   octave_unused_parameter (name);
551 
552   warn_save ("hdf5");
553 #endif
554 
555   return retval;
556 }
557 
558 bool
load_hdf5(octave_hdf5_id loc_id,const char * name)559 octave_sparse_bool_matrix::load_hdf5 (octave_hdf5_id loc_id, const char *name)
560 {
561   bool retval = false;
562 
563 #if defined (HAVE_HDF5)
564 
565   octave_idx_type nr, nc, nz;
566   hid_t group_hid, data_hid, space_hid;
567   hsize_t rank;
568 
569   dim_vector dv;
570   int empty = load_hdf5_empty (loc_id, name, dv);
571   if (empty > 0)
572     matrix.resize (dv);
573   if (empty)
574     return (empty > 0);
575 
576 #if defined (HAVE_HDF5_18)
577   group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
578 #else
579   group_hid = H5Gopen (loc_id, name);
580 #endif
581   if (group_hid < 0) return false;
582 
583 #if defined (HAVE_HDF5_18)
584   data_hid = H5Dopen (group_hid, "nr", octave_H5P_DEFAULT);
585 #else
586   data_hid = H5Dopen (group_hid, "nr");
587 #endif
588   space_hid = H5Dget_space (data_hid);
589   rank = H5Sget_simple_extent_ndims (space_hid);
590 
591   if (rank != 0)
592     {
593       H5Dclose (data_hid);
594       H5Gclose (group_hid);
595       return false;
596     }
597 
598   if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
599                octave_H5P_DEFAULT, &nr)
600       < 0)
601     {
602       H5Dclose (data_hid);
603       H5Gclose (group_hid);
604       return false;
605     }
606 
607   H5Dclose (data_hid);
608 
609 #if defined (HAVE_HDF5_18)
610   data_hid = H5Dopen (group_hid, "nc", octave_H5P_DEFAULT);
611 #else
612   data_hid = H5Dopen (group_hid, "nc");
613 #endif
614   space_hid = H5Dget_space (data_hid);
615   rank = H5Sget_simple_extent_ndims (space_hid);
616 
617   if (rank != 0)
618     {
619       H5Dclose (data_hid);
620       H5Gclose (group_hid);
621       return false;
622     }
623 
624   if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
625                octave_H5P_DEFAULT, &nc)
626       < 0)
627     {
628       H5Dclose (data_hid);
629       H5Gclose (group_hid);
630       return false;
631     }
632 
633   H5Dclose (data_hid);
634 
635 #if defined (HAVE_HDF5_18)
636   data_hid = H5Dopen (group_hid, "nz", octave_H5P_DEFAULT);
637 #else
638   data_hid = H5Dopen (group_hid, "nz");
639 #endif
640   space_hid = H5Dget_space (data_hid);
641   rank = H5Sget_simple_extent_ndims (space_hid);
642 
643   if (rank != 0)
644     {
645       H5Dclose (data_hid);
646       H5Gclose (group_hid);
647       return false;
648     }
649 
650   if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
651                octave_H5P_DEFAULT, &nz)
652       < 0)
653     {
654       H5Dclose (data_hid);
655       H5Gclose (group_hid);
656       return false;
657     }
658 
659   H5Dclose (data_hid);
660 
661   SparseBoolMatrix m (static_cast<octave_idx_type> (nr),
662                       static_cast<octave_idx_type> (nc),
663                       static_cast<octave_idx_type> (nz));
664 
665 #if defined (HAVE_HDF5_18)
666   data_hid = H5Dopen (group_hid, "cidx", octave_H5P_DEFAULT);
667 #else
668   data_hid = H5Dopen (group_hid, "cidx");
669 #endif
670   space_hid = H5Dget_space (data_hid);
671   rank = H5Sget_simple_extent_ndims (space_hid);
672 
673   if (rank != 2)
674     {
675       H5Sclose (space_hid);
676       H5Dclose (data_hid);
677       H5Gclose (group_hid);
678       return false;
679     }
680 
681   OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
682   OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
683 
684   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
685 
686   if (static_cast<int> (hdims[0]) != nc + 1
687       || static_cast<int> (hdims[1]) != 1)
688     {
689       H5Sclose (space_hid);
690       H5Dclose (data_hid);
691       H5Gclose (group_hid);
692       return false;
693     }
694 
695   octave_idx_type *itmp = m.xcidx ();
696   if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
697                octave_H5P_DEFAULT, itmp)
698       < 0)
699     {
700       H5Sclose (space_hid);
701       H5Dclose (data_hid);
702       H5Gclose (group_hid);
703       return false;
704     }
705 
706   H5Sclose (space_hid);
707   H5Dclose (data_hid);
708 
709 #if defined (HAVE_HDF5_18)
710   data_hid = H5Dopen (group_hid, "ridx", octave_H5P_DEFAULT);
711 #else
712   data_hid = H5Dopen (group_hid, "ridx");
713 #endif
714   space_hid = H5Dget_space (data_hid);
715   rank = H5Sget_simple_extent_ndims (space_hid);
716 
717   if (rank != 2)
718     {
719       H5Sclose (space_hid);
720       H5Dclose (data_hid);
721       H5Gclose (group_hid);
722       return false;
723     }
724 
725   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
726 
727   if (static_cast<int> (hdims[0]) != nz
728       || static_cast<int> (hdims[1]) != 1)
729     {
730       H5Sclose (space_hid);
731       H5Dclose (data_hid);
732       H5Gclose (group_hid);
733       return false;
734     }
735 
736   itmp = m.xridx ();
737   if (H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
738                octave_H5P_DEFAULT, itmp) < 0)
739     {
740       H5Sclose (space_hid);
741       H5Dclose (data_hid);
742       H5Gclose (group_hid);
743       return false;
744     }
745 
746   H5Sclose (space_hid);
747   H5Dclose (data_hid);
748 
749 #if defined (HAVE_HDF5_18)
750   data_hid = H5Dopen (group_hid, "data", octave_H5P_DEFAULT);
751 #else
752   data_hid = H5Dopen (group_hid, "data");
753 #endif
754   space_hid = H5Dget_space (data_hid);
755   rank = H5Sget_simple_extent_ndims (space_hid);
756 
757   if (rank != 2)
758     {
759       H5Sclose (space_hid);
760       H5Dclose (data_hid);
761       H5Gclose (group_hid);
762       return false;
763     }
764 
765   H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
766 
767   if (static_cast<int> (hdims[0]) != nz
768       || static_cast<int> (hdims[1]) != 1)
769     {
770       H5Sclose (space_hid);
771       H5Dclose (data_hid);
772       H5Gclose (group_hid);
773       return false;
774     }
775 
776   OCTAVE_LOCAL_BUFFER (hbool_t, htmp, nz);
777 
778   if (H5Dread (data_hid, H5T_NATIVE_HBOOL, octave_H5S_ALL, octave_H5S_ALL,
779                octave_H5P_DEFAULT, htmp) >= 0
780       && m.indices_ok ())
781     {
782       retval = true;
783 
784       for (int i = 0; i < nz; i++)
785         m.xdata(i) = htmp[i];
786 
787       matrix = m;
788     }
789 
790   H5Sclose (space_hid);
791   H5Dclose (data_hid);
792   H5Gclose (group_hid);
793 
794 #else
795   octave_unused_parameter (loc_id);
796   octave_unused_parameter (name);
797 
798   warn_load ("hdf5");
799 #endif
800 
801   return retval;
802 }
803 
804 mxArray *
as_mxArray(void) const805 octave_sparse_bool_matrix::as_mxArray (void) const
806 {
807   mwSize nz = nzmax ();
808   mxArray *retval = new mxArray (mxLOGICAL_CLASS, rows (), columns (),
809                                  nz, mxREAL);
810   bool *pr = static_cast<bool *> (retval->get_data ());
811   mwIndex *ir = retval->get_ir ();
812   mwIndex *jc = retval->get_jc ();
813 
814   for (mwIndex i = 0; i < nz; i++)
815     {
816       pr[i] = matrix.data (i);
817       ir[i] = matrix.ridx (i);
818     }
819 
820   for (mwIndex i = 0; i < columns () + 1; i++)
821     jc[i] = matrix.cidx (i);
822 
823   return retval;
824 }
825