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