GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-range.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2023 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 <sstream>
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 "lo-utils.h"
47 
48 #include "defun.h"
49 #include "variables.h"
50 #include "errwarn.h"
51 #include "mxarray.h"
52 #include "mx-type-traits.h"
53 #include "ops.h"
54 #include "ovl.h"
55 #include "oct-hdf5.h"
56 #include "ov-range-traits.h"
57 #include "ov-range.h"
58 #include "ov-re-mat.h"
59 #include "ov-scalar.h"
60 #include "pr-output.h"
61 
62 #include "byte-swap.h"
63 #include "ls-ascii-helper.h"
64 #include "ls-hdf5.h"
65 #include "ls-utils.h"
66 
67 #if defined (HAVE_HDF5)
68 
69 template <>
71 
72 // For now, disable all but ov_range<double>.
73 
74 # if 0
75 
76 template <>
78 
79 template <>
81 
82 template <>
84 
85 template <>
87 
88 template <>
90 
91 template <>
93 
94 template <>
96 
97 template <>
99 
100 template <>
102 
103 # endif
104 
105 #else
106 
107 template <>
109 
110 // For now, disable all but ov_range<double>.
111 
112 #if 0
113 
114 template <>
116 
117 template <>
119 
120 template <>
122 
123 template <>
125 
126 template <>
128 
129 template <>
131 
132 template <>
134 
135 template <>
137 
138 template <>
140 
141 # endif
142 
143 #endif
144 
146  "double_range", "double");
147 
148 // For now, disable all but ov_range<double>.
149 
150 #if 0
151 
153  "float_range", "single");
154 
156  "int8_range", "int8");
157 
159  "int16_range", "int16");
160 
162  "int32_range", "int32");
163 
165  "int64_range", "int64");
166 
168  "uint8_range", "uint8");
169 
171  "uint16_range", "uint16");
172 
174  "uint32_range", "uint32");
175 
177  "uint64_range", "uint64");
178 
179 #endif
180 
181 template <typename T>
182 static octave_base_value *
184 {
185  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
186 
187  const ov_range<T>& v = dynamic_cast<const ov_range<T>&> (a);
188 
189  return new ov_mx_type (v.raw_array_value ());
190 }
191 
192 template <typename T>
195 {
196  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
197 
199  (default_numeric_conversion_function<T>, ov_mx_type::static_type_id ());
200 }
201 
202 template <typename T>
205 {
206  octave_base_value *retval = nullptr;
207 
208  switch (numel ())
209  {
210  case 1:
211  retval = new typename octave_value_range_traits<T>::scalar_type (m_range.elem (0));
212  break;
213 
214  case 0:
215  {
216  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
217  typename ov_mx_type::object_type m (dim_vector (1, 0));
218  retval = new ov_mx_type (m);
219  }
220  break;
221 
222  case -2:
223  // FIXME: is this case possible now? It would have to be due to
224  // conversion from Range to range<double>, but even in that case,
225  // is the invalid numel value preserved?
226  retval = new typename octave_value_range_traits<T>::matrix_type (raw_array_value ());
227  break;
228 
229  default:
230  break;
231  }
232 
233  return retval;
234 }
235 
236 template <typename T>
238 ov_range<T>::subsref (const std::string& type,
239  const std::list<octave_value_list>& idx)
240 {
241  octave_value retval;
242 
243  switch (type[0])
244  {
245  case '(':
246  retval = do_index_op (idx.front ());
247  break;
248 
249  case '{':
250  case '.':
251  {
252  std::string nm = type_name ();
253  error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
254  }
255  break;
256 
257  default:
258  panic_impossible ();
259  }
260 
261  return retval.next_subsref (type, idx);
262 }
263 
264 template <typename T>
267  bool resize_ok)
268 {
269  if (idx.length () == 1 && ! resize_ok)
270  {
271  octave_value retval;
272 
273  // The range can handle a single subscript.
274 
275  try
276  {
277  octave::idx_vector i = idx(0).index_vector ();
278 
279  if (i.is_scalar () && i(0) < numel ())
280  retval = m_range.elem (i(0));
281  else
282  retval = m_range.index (i);
283  }
284  catch (octave::index_exception& ie)
285  {
286  // More info may be added later before displaying error.
287 
288  ie.set_pos_if_unset (1, 1);
289  throw;
290  }
291 
292  return retval;
293  }
294  else
295  {
296  octave_value tmp (new typename octave_value_range_traits<T>::matrix_type (raw_array_value ()));
297 
298  return tmp.index_op (idx, resize_ok);
299  }
300 }
301 
302 template <typename T>
304 ov_range<T>::index_vector (bool require_integers) const
305 {
306  octave_value tmp (raw_array_value ());
307  return tmp.index_vector (require_integers);
308 }
309 
310 template <typename T>
311 double
313 {
314  octave_idx_type nel = numel ();
315 
316  if (nel == 0)
317  err_invalid_conversion ("range", "real scalar");
318 
319  warn_implicit_conversion ("Octave:array-to-scalar",
320  "range", "real scalar");
321 
322  return m_range.base ();
323 }
324 
325 template <typename T>
326 float
328 {
329  octave_idx_type nel = numel ();
330 
331  if (nel == 0)
332  err_invalid_conversion ("range", "real scalar");
333 
334  warn_implicit_conversion ("Octave:array-to-scalar",
335  "range", "real scalar");
336 
337  return m_range.base ();
338 }
339 
340 template <typename T>
343 {
344  const Array<T> matrix = raw_array_value ();
345  charNDArray retval (dims ());
346 
347  octave_idx_type nel = numel ();
348 
349  for (octave_idx_type i = 0; i < nel; i++)
350  retval.elem (i) = static_cast<char> (matrix.elem (i));
351 
352  return retval;
353 }
354 
355 template <typename T>
356 Complex
358 {
359  octave_idx_type nel = numel ();
360 
361  if (nel == 0)
362  err_invalid_conversion ("range", "complex scalar");
363 
364  warn_implicit_conversion ("Octave:array-to-scalar",
365  "range", "complex scalar");
366 
367  return Complex (m_range.base (), 0);
368 }
369 
370 template <typename T>
373 {
374  float tmp = lo_ieee_float_nan_value ();
375 
376  FloatComplex retval (tmp, tmp);
377 
378  octave_idx_type nel = numel ();
379 
380  if (nel == 0)
381  err_invalid_conversion ("range", "complex scalar");
382 
383  warn_implicit_conversion ("Octave:array-to-scalar",
384  "range", "complex scalar");
385 
386  retval = m_range.base ();
387 
388  return retval;
389 }
390 
391 template <typename T>
394 {
395  Array<T> matrix = raw_array_value ();
396 
397  if (warn && ! matrix.test_all (octave::is_one_or_zero<T>))
399 
400  return boolNDArray (matrix);
401 }
402 
403 template <typename T>
405 ov_range<T>::resize (const dim_vector& dv, bool fill) const
406 {
407  Array<T> retval = raw_array_value ();
408  if (fill)
409  retval.resize (dv, 0);
410  else
411  retval.resize (dv);
412  return retval;
413 }
414 
415 template <typename T>
416 octave::range<double>
418 {
419  err_wrong_type_arg ("ov_range<T>::range_value()", type_name ());
420 }
421 
422 // For now, disable all but ov_range<double>.
423 
424 #if 0
425 
426 template <typename T>
427 octave::range<float>
429 {
430  err_wrong_type_arg ("ov_range<T>::float_range_value ()", type_name ());
431 }
432 
433 template <typename T>
434 octave::range<octave_int8>
436 {
437  err_wrong_type_arg ("ov_range<T>::int8_range_value ()", type_name ());
438 }
439 
440 template <typename T>
441 octave::range<octave_int16>
443 {
444  err_wrong_type_arg ("ov_range<T>::int16_range_value ()", type_name ());
445 }
446 
447 template <typename T>
448 octave::range<octave_int32>
450 {
451  err_wrong_type_arg ("ov_range<T>::int32_range_value ()", type_name ());
452 }
453 
454 template <typename T>
455 octave::range<octave_int64>
457 {
458  err_wrong_type_arg ("ov_range<T>::int64_range_value ()", type_name ());
459 }
460 
461 template <typename T>
462 octave::range<octave_uint8>
464 {
465  err_wrong_type_arg ("ov_range<T>::uint8_range_value ()", type_name ());
466 }
467 
468 template <typename T>
469 octave::range<octave_uint16>
471 {
472  err_wrong_type_arg ("ov_range<T>::uint16_range_value ()", type_name ());
473 }
474 
475 template <typename T>
476 octave::range<octave_uint32>
478 {
479  err_wrong_type_arg ("ov_range<T>::uint32_range_value ()", type_name ());
480 }
481 
482 template <typename T>
483 octave::range<octave_uint64>
485 {
486  err_wrong_type_arg ("ov_range<T>::uint64_range_value ()", type_name ());
487 }
488 
489 #endif
490 
491 template <typename T>
493 ov_range<T>::convert_to_str_internal (bool pad, bool force, char type) const
494 {
495  octave_value tmp (raw_array_value ());
496  return tmp.convert_to_str (pad, force, type);
497 }
498 
499 // FIXME: could most of these fucntions preserve range type now?
500 
501 template <typename T>
504 {
505  return NDArray (raw_array_value ());
506 }
507 
508 template <typename T>
511 {
512  return FloatMatrix (raw_array_value ());
513 }
514 
515 template <typename T>
518 {
519  return int8NDArray (raw_array_value ());
520 }
521 
522 template <typename T>
525 {
526  return int16NDArray (raw_array_value ());
527 }
528 
529 template <typename T>
532 {
533  return int32NDArray (raw_array_value ());
534 }
535 
536 template <typename T>
539 {
540  return int64NDArray (raw_array_value ());
541 }
542 
543 template <typename T>
546 {
547  return uint8NDArray (raw_array_value ());
548 }
549 
550 template <typename T>
553 {
554  return uint16NDArray (raw_array_value ());
555 }
556 
557 template <typename T>
560 {
561  return uint32NDArray (raw_array_value ());
562 }
563 
564 template <typename T>
567 {
568  return uint64NDArray (raw_array_value ());
569 }
570 
571 template <typename T>
572 void
573 ov_range<T>::print (std::ostream& os, bool pr_as_read_syntax)
574 {
575  print_raw (os, pr_as_read_syntax);
576  newline (os);
577 }
578 
579 template <typename T>
580 void
581 ov_range<T>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
582 {
583  // FIXME: this is a potential waste of memory.
584 
585  typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
586  typename ov_mx_type::object_type tmp (raw_array_value ());
587 
588  octave_print_internal (os, tmp, pr_as_read_syntax,
589  current_print_indent_level ());
590 }
591 
592 template <typename T>
593 bool
594 ov_range<T>::print_name_tag (std::ostream& os, const std::string& name) const
595 {
596  bool retval = false;
597 
598  octave_idx_type n = numel ();
599 
600  indent (os);
601 
602  if (n == 0 || n == 1)
603  os << name << " = ";
604  else
605  {
606  os << name << " =";
607  newline (os);
608  if (! Vcompact_format)
609  newline (os);
610 
611  retval = true;
612  }
613 
614  return retval;
615 }
616 
617 template <typename T>
618 void
619 ov_range<T>::short_disp (std::ostream& os) const
620 {
622 
623  if (len == 0)
624  os << "[]";
625  else
626  {
627  os << m_range.base () << ':';
628 
629  if (len > 1)
630  {
631  if (m_range.increment () != T (1))
632  os << m_range.increment () << ':';
633 
634  os << m_range.limit ();
635  }
636  }
637 }
638 
639 // Skip white space and comments on stream IS.
640 
641 static void
642 skip_comments (std::istream& is)
643 {
644  char c = '\0';
645  while (is.get (c))
646  {
647  if (c == ' ' || c == '\t' || c == '\n')
648  ; // Skip whitespace on way to beginning of next line.
649  else
650  break;
651  }
652 
653  octave::skip_until_newline (is, false);
654 }
655 
656 template <typename T>
659 {
660  return make_format (m_range);
661 }
662 
663 template <typename T>
664 std::string
667 {
668  std::ostringstream buf;
669  octave_print_internal (buf, fmt, m_range.elem (j));
670  return buf.str ();
671 }
672 
673 template <typename T>
674 bool
675 xsave_ascii (std::ostream& os, const octave::range<T>& r,
676  const bool with_reverse)
677 {
678  T base = r.base ();
679  T limit = r.limit ();
680  T inc = r.increment ();
681  bool rev = r.reverse ();
682  octave_idx_type len = r.numel ();
683 
684  if (inc != T (0))
685  os << "# base, limit, increment";
686  else
687  os << "# base, length, increment";
688 
689  if (with_reverse)
690  os << ", reverse\n";
691  else
692  os << "\n";
693 
694  octave::write_value<T> (os, base);
695  os << ' ';
696  if (inc != T (0))
697  octave::write_value<T> (os, limit);
698  else
699  os << len;
700  os << ' ';
701  octave::write_value<T> (os, inc);
702  if (with_reverse)
703  os << ' ' << rev;
704  os << "\n";
705 
706  return true;
707 }
708 
709 template <typename T>
710 bool
711 ov_range<T>::save_ascii (std::ostream& os)
712 {
713  return xsave_ascii (os, m_range, false);
714 }
715 
716 // specialize for saving with "reverse" flag
717 
718 // For now, disable all but ov_range<double>.
719 
720 #if 0
721 
722 template <>
723 bool
724 ov_range<octave_uint8>::save_ascii (std::ostream& os)
725 {
726  return xsave_ascii (os, m_range, true);
727 }
728 
729 template <>
730 bool
731 ov_range<octave_uint16>::save_ascii (std::ostream& os)
732 {
733  return xsave_ascii (os, m_range, true);
734 }
735 
736 template <>
737 bool
738 ov_range<octave_uint32>::save_ascii (std::ostream& os)
739 {
740  return xsave_ascii (os, m_range, true);
741 }
742 
743 template <>
744 bool
745 ov_range<octave_uint64>::save_ascii (std::ostream& os)
746 {
747  return xsave_ascii (os, m_range, true);
748 }
749 
750 #endif
751 
752 template <typename T>
753 bool
754 xload_ascii (std::istream& is, octave::range<T>& r, const bool with_reverse)
755 {
756  // # base, limit, range comment added by save ().
757  skip_comments (is);
758 
759  T base, limit, inc;
760  bool rev = false;
761  is >> base >> limit >> inc;
762 
763  if (with_reverse)
764  is >> rev;
765 
766  if (! is)
767  error ("load: failed to load range constant");
768 
769  r = octave::range<T> (base, inc, limit, rev);
770 
771  return true;
772 }
773 
774 template <typename T>
775 bool
776 ov_range<T>::load_ascii (std::istream& is)
777 {
778  return xload_ascii (is, m_range, false);
779 }
780 
781 // specialize for loading with "reverse" flag
782 
783 // For now, disable all but ov_range<double>.
784 
785 #if 0
786 
787 template <>
788 bool
789 ov_range<octave_uint8>::load_ascii (std::istream& is)
790 {
791  return xload_ascii (is, m_range, true);
792 }
793 
794 template <>
795 bool
796 ov_range<octave_uint16>::load_ascii (std::istream& is)
797 {
798  return xload_ascii (is, m_range, true);
799 }
800 
801 template <>
802 bool
803 ov_range<octave_uint32>::load_ascii (std::istream& is)
804 {
805  return xload_ascii (is, m_range, true);
806 }
807 
808 template <>
809 bool
810 ov_range<octave_uint64>::load_ascii (std::istream& is)
811 {
812  return xload_ascii (is, m_range, true);
813 }
814 
815 #endif
816 
817 /*
818 %!test
819 %! a = b = 1:4;
820 %! sv_file = [tempname(), ".sav"];
821 %! unwind_protect
822 %! save (sv_file, "a", "-text");
823 %! clear a;
824 %! load (sv_file);
825 %! assert (a, b);
826 %! unwind_protect_cleanup
827 %! unlink (sv_file);
828 %! end_unwind_protect
829 
830 %!test
831 %! a = b = uint8(5):-1:0;
832 %! sv_file = [tempname(), ".sav"];
833 %! unwind_protect
834 %! save (sv_file, "a", "-text");
835 %! clear a;
836 %! load (sv_file);
837 %! assert (a, b);
838 %! unwind_protect_cleanup
839 %! unlink (sv_file);
840 %! end_unwind_protect
841 */
842 
843 template <typename T>
844 bool
845 xsave_binary (std::ostream& os, bool /* save_as_floats */,
846  const octave::range<T>& r, const bool with_reverse)
847 {
848  // FIXME: Not always double!
849 
850  char tmp = LS_DOUBLE;
851  os.write (reinterpret_cast<char *> (&tmp), 1);
852  T bas = r.base ();
853  T lim = r.limit ();
854  T inc = r.increment ();
855  if (inc == T (0))
856  lim = r.numel ();
857 
858  os.write (reinterpret_cast<char *> (&bas), sizeof (T));
859  os.write (reinterpret_cast<char *> (&lim), sizeof (T));
860  os.write (reinterpret_cast<char *> (&inc), sizeof (T));
861  if (with_reverse)
862  {
863  bool rev = r.reverse ();
864  os.write (reinterpret_cast<char *> (&rev), sizeof (bool));
865  }
866 
867  return true;
868 }
869 
870 template <typename T>
871 bool
872 ov_range<T>::save_binary (std::ostream& os, bool save_as_floats)
873 {
874  return xsave_binary (os, save_as_floats, m_range, false);
875 }
876 
877 // For now, disable all but ov_range<double>.
878 
879 #if 0
880 
881 template <>
882 bool
883 ov_range<octave_uint8>::save_binary (std::ostream& os, bool save_as_floats)
884 {
885  return xsave_binary (os, save_as_floats, m_range, true);
886 }
887 
888 template <>
889 bool
890 ov_range<octave_uint16>::save_binary (std::ostream& os, bool save_as_floats)
891 {
892  return xsave_binary (os, save_as_floats, m_range, true);
893 }
894 
895 template <>
896 bool
897 ov_range<octave_uint32>::save_binary (std::ostream& os, bool save_as_floats)
898 {
899  return xsave_binary (os, save_as_floats, m_range, true);
900 }
901 
902 template <>
903 bool
904 ov_range<octave_uint64>::save_binary (std::ostream& os, bool save_as_floats)
905 {
906  return xsave_binary (os, save_as_floats, m_range, true);
907 }
908 
909 #endif
910 
911 template <typename T>
912 bool
913 xload_binary (std::istream& is, bool swap,
915  octave::range<T>& r, const bool with_reverse)
916 {
917  // FIXME: Not always double!
918 
919  char tmp;
920  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
921  return false;
922  T bas, lim, inc;
923  if (! is.read (reinterpret_cast<char *> (&bas), sizeof (T)))
924  return false;
925  if (swap)
926  swap_bytes<sizeof (T)> (&bas);
927  if (! is.read (reinterpret_cast<char *> (&lim), sizeof (T)))
928  return false;
929  if (swap)
930  swap_bytes<sizeof (T)> (&lim);
931  if (! is.read (reinterpret_cast<char *> (&inc), sizeof (T)))
932  return false;
933  if (swap)
934  swap_bytes<sizeof (T)> (&inc);
935  bool rev = false;
936  if (with_reverse)
937  {
938  if (! is.read (reinterpret_cast<char *> (&rev), sizeof (bool)))
939  return false;
940  if (swap)
941  swap_bytes<sizeof (bool)> (&rev);
942  }
943 
944  r = octave::range<T> (bas, inc, lim, rev);
945 
946  return true;
947 }
948 
949 template <typename T>
950 bool
951 ov_range<T>::load_binary (std::istream& is, bool swap,
953 {
954  return xload_binary (is, swap, fmt, m_range, false);
955 }
956 
957 // For now, disable all but ov_range<double>.
958 
959 #if 0
960 
961 template <>
962 bool
963 ov_range<octave_uint8>::load_binary (std::istream& is, bool swap,
965 {
966  return xload_binary (is, swap, fmt, m_range, true);
967 }
968 
969 template <>
970 bool
971 ov_range<octave_uint16>::load_binary (std::istream& is, bool swap,
973 {
974  return xload_binary (is, swap, fmt, m_range, true);
975 }
976 
977 template <>
978 bool
979 ov_range<octave_uint32>::load_binary (std::istream& is, bool swap,
981 {
982  return xload_binary (is, swap, fmt, m_range, true);
983 }
984 
985 template <>
986 bool
987 ov_range<octave_uint64>::load_binary (std::istream& is, bool swap,
989 {
990  return xload_binary (is, swap, fmt, m_range, true);
991 }
992 
993 #endif
994 
995 /*
996 %!test
997 %! a = b = 1:4;
998 %! sv_file = [tempname(), ".dat"];
999 %! unwind_protect
1000 %! save (sv_file, "a", "-binary");
1001 %! clear a;
1002 %! load (sv_file);
1003 %! assert (a, b);
1004 %! unwind_protect_cleanup
1005 %! unlink (sv_file);
1006 %! end_unwind_protect
1007 
1008 %!test
1009 %! a = b = uint8(5):-1:0;
1010 %! sv_file = [tempname(), ".dat"];
1011 %! unwind_protect
1012 %! save (sv_file, "a", "-binary");
1013 %! clear a;
1014 %! load (sv_file);
1015 %! assert (a, b);
1016 %! unwind_protect_cleanup
1017 %! unlink (sv_file);
1018 %! end_unwind_protect
1019 */
1020 
1021 #if defined (HAVE_HDF5)
1022 
1023 // The following subroutines creates an HDF5 representation of the way
1024 // we will store Octave range types (triplets of floating-point numbers).
1025 // NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
1026 // H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
1027 // conversions are handled automatically by HDF5.
1028 
1029 template <typename T>
1030 static hid_t
1031 hdf5_make_range_type (hid_t num_type)
1032 {
1033  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (T) * 3);
1034 
1035  H5Tinsert (type_id, "base", 0 * sizeof (T), num_type);
1036  H5Tinsert (type_id, "limit", 1 * sizeof (T), num_type);
1037  H5Tinsert (type_id, "increment", 2 * sizeof (T), num_type);
1038 
1039  return type_id;
1040 }
1041 
1042 template <typename T>
1043 static hid_t
1045 {
1046  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (T) * 4);
1047 
1048  H5Tinsert (type_id, "base", 0 * sizeof (T), num_type);
1049  H5Tinsert (type_id, "limit", 1 * sizeof (T), num_type);
1050  H5Tinsert (type_id, "increment", 2 * sizeof (T), num_type);
1051  // FIXME: Storing "reverse" with the same width is inefficient.
1052  H5Tinsert (type_id, "reverse", 3 * sizeof (T), num_type);
1053 
1054  return type_id;
1055 }
1056 
1057 template <typename T>
1058 bool
1059 xsave_hdf5 (octave_hdf5_id loc_id, const char *name,
1060  bool /* save_as_floats */, const octave::range<T>& r,
1061  const octave_hdf5_id h5_save_type, const bool with_reverse)
1062 {
1063  bool retval = false;
1064 
1065  hsize_t dimens[3] = {0};
1066  hid_t space_hid, type_hid, data_hid;
1067  space_hid = type_hid = data_hid = -1;
1068 
1069  space_hid = H5Screate_simple (0, dimens, nullptr);
1070  if (space_hid < 0) return false;
1071 
1072  type_hid = with_reverse
1073  ? hdf5_make_range_rev_type<T> (h5_save_type)
1074  : hdf5_make_range_type<T> (h5_save_type);
1075  if (type_hid < 0)
1076  {
1077  H5Sclose (space_hid);
1078  return false;
1079  }
1080 # if defined (HAVE_HDF5_18)
1081  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,
1084 # else
1085  data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);
1086 # endif
1087  if (data_hid < 0)
1088  {
1089  H5Sclose (space_hid);
1090  H5Tclose (type_hid);
1091  return false;
1092  }
1093 
1094  T range_vals[4];
1095  range_vals[0] = r.base ();
1096  if (r.increment () != T (0))
1097  range_vals[1] = r.limit ();
1098  else
1099  range_vals[1] = r.numel ();
1100  range_vals[2] = r.increment ();
1101  range_vals[3] = r.reverse ();
1102 
1103  if (H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
1104  octave_H5P_DEFAULT, range_vals)
1105  >= 0)
1106  {
1107  octave_idx_type nel = r.numel ();
1108  retval = hdf5_add_scalar_attr (data_hid, H5T_NATIVE_IDX,
1109  "OCTAVE_RANGE_NELEM", &nel) >= 0;
1110  }
1111  else
1112  retval = false;
1113 
1114  H5Dclose (data_hid);
1115  H5Tclose (type_hid);
1116  H5Sclose (space_hid);
1117 
1118  return retval;
1119 }
1120 
1121 #endif
1122 
1123 template <typename T>
1124 bool
1125 ov_range<T>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
1126  bool save_as_floats)
1127 {
1128 #if defined (HAVE_HDF5)
1129  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1130  false);
1131 #else
1132  octave_unused_parameter (loc_id);
1133  octave_unused_parameter (name);
1134  octave_unused_parameter (save_as_floats);
1135 
1136  warn_save ("hdf5");
1137 
1138  return false;
1139 #endif
1140 }
1141 
1142 // For now, disable all but ov_range<double>.
1143 
1144 #if 0
1145 
1146 template <>
1147 bool
1148 ov_range<octave_uint8>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
1149  bool save_as_floats)
1150 {
1151 #if defined (HAVE_HDF5)
1152  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1153  true);
1154 #else
1155  octave_unused_parameter (loc_id);
1156  octave_unused_parameter (name);
1157  octave_unused_parameter (save_as_floats);
1158 
1159  warn_save ("hdf5");
1160 
1161  return false;
1162 #endif
1163 }
1164 
1165 template <>
1166 bool
1167 ov_range<octave_uint16>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
1168  bool save_as_floats)
1169 {
1170 #if defined (HAVE_HDF5)
1171  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1172  true);
1173 #else
1174  octave_unused_parameter (loc_id);
1175  octave_unused_parameter (name);
1176  octave_unused_parameter (save_as_floats);
1177 
1178  warn_save ("hdf5");
1179 
1180  return false;
1181 #endif
1182 }
1183 
1184 template <>
1185 bool
1186 ov_range<octave_uint32>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
1187  bool save_as_floats)
1188 {
1189 #if defined (HAVE_HDF5)
1190  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1191  true);
1192 #else
1193  octave_unused_parameter (loc_id);
1194  octave_unused_parameter (name);
1195  octave_unused_parameter (save_as_floats);
1196 
1197  warn_save ("hdf5");
1198 
1199  return false;
1200 #endif
1201 }
1202 
1203 template <>
1204 bool
1205 ov_range<octave_uint64>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
1206  bool save_as_floats)
1207 {
1208 #if defined (HAVE_HDF5)
1209  return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1210  true);
1211 #else
1212  octave_unused_parameter (loc_id);
1213  octave_unused_parameter (name);
1214  octave_unused_parameter (save_as_floats);
1215 
1216  warn_save ("hdf5");
1217 
1218  return false;
1219 #endif
1220 }
1221 
1222 #endif
1223 
1224 #if defined (HAVE_HDF5)
1225 
1226 template <typename T>
1227 bool
1228 xload_hdf5 (octave_hdf5_id loc_id, const char *name, octave::range<T>& r,
1229  const octave_hdf5_id h5_save_type, const bool with_reverse)
1230 {
1231  bool retval = false;
1232 
1233 # if defined (HAVE_HDF5_18)
1234  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
1235 # else
1236  hid_t data_hid = H5Dopen (loc_id, name);
1237 # endif
1238  hid_t type_hid = H5Dget_type (data_hid);
1239 
1240  hid_t range_type = with_reverse
1241  ? hdf5_make_range_rev_type<T> (h5_save_type)
1242  : hdf5_make_range_type<T> (h5_save_type);
1243 
1244  if (! hdf5_types_compatible (type_hid, range_type))
1245  {
1246  H5Tclose (range_type);
1247  H5Dclose (data_hid);
1248  return false;
1249  }
1250 
1251  hid_t space_hid = H5Dget_space (data_hid);
1252  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
1253 
1254  if (rank != 0)
1255  {
1256  H5Tclose (range_type);
1257  H5Sclose (space_hid);
1258  H5Dclose (data_hid);
1259  return false;
1260  }
1261 
1262  T rangevals[4];
1263  if (H5Dread (data_hid, range_type, octave_H5S_ALL, octave_H5S_ALL,
1264  octave_H5P_DEFAULT, rangevals)
1265  >= 0)
1266  {
1267  retval = true;
1268 
1269  // Don't use OCTAVE_RANGE_NELEM attribute, just reconstruct the range.
1270 
1271  bool rev = with_reverse ? static_cast<bool> (rangevals[3]) : false;
1272 
1273  r = octave::range<T> (rangevals[0], rangevals[2], rangevals[1], rev);
1274  }
1275 
1276  H5Tclose (range_type);
1277  H5Sclose (space_hid);
1278  H5Dclose (data_hid);
1279 
1280  return retval;
1281 }
1282 
1283 #endif
1284 
1285 template <typename T>
1286 bool
1287 ov_range<T>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1288 {
1289 #if defined (HAVE_HDF5)
1290  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, false);
1291 #else
1292  octave_unused_parameter (loc_id);
1293  octave_unused_parameter (name);
1294 
1295  warn_load ("hdf5");
1296 
1297  return false;
1298 #endif
1299 }
1300 
1301 // For now, disable all but ov_range<double>.
1302 
1303 #if 0
1304 
1305 template <>
1306 bool
1307 ov_range<octave_uint8>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1308 {
1309 #if defined (HAVE_HDF5)
1310  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1311 #else
1312  octave_unused_parameter (loc_id);
1313  octave_unused_parameter (name);
1314 
1315  warn_load ("hdf5");
1316 
1317  return false;
1318 #endif
1319 }
1320 
1321 template <>
1322 bool
1323 ov_range<octave_uint16>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1324 {
1325 #if defined (HAVE_HDF5)
1326  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1327 #else
1328  octave_unused_parameter (loc_id);
1329  octave_unused_parameter (name);
1330 
1331  warn_load ("hdf5");
1332 
1333  return false;
1334 #endif
1335 }
1336 
1337 template <>
1338 bool
1339 ov_range<octave_uint32>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1340 {
1341 #if defined (HAVE_HDF5)
1342  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1343 #else
1344  octave_unused_parameter (loc_id);
1345  octave_unused_parameter (name);
1346 
1347  warn_load ("hdf5");
1348 
1349  return false;
1350 #endif
1351 }
1352 
1353 template <>
1354 bool
1355 ov_range<octave_uint64>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
1356 {
1357 #if defined (HAVE_HDF5)
1358  return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1359 #else
1360  octave_unused_parameter (loc_id);
1361  octave_unused_parameter (name);
1362 
1363  warn_load ("hdf5");
1364 
1365  return false;
1366 #endif
1367 }
1368 
1369 #endif
1370 
1371 /*
1372 %!testif HAVE_HDF5
1373 %! a = b = 1:4;
1374 %! sv_file = [tempname(), ".h5"];
1375 %! unwind_protect
1376 %! save (sv_file, "a", "-hdf5");
1377 %! clear a;
1378 %! load (sv_file);
1379 %! assert (a, b);
1380 %! unwind_protect_cleanup
1381 %! unlink (sv_file);
1382 %! end_unwind_protect
1383 
1384 %!testif HAVE_HDF5
1385 %! a = b = uint8(5):-1:0;
1386 %! sv_file = [tempname(), ".h5"];
1387 %! unwind_protect
1388 %! save (sv_file, "a", "-hdf5");
1389 %! clear a;
1390 %! load (sv_file);
1391 %! assert (a, b);
1392 %! unwind_protect_cleanup
1393 %! unlink (sv_file);
1394 %! end_unwind_protect
1395 */
1396 
1397 template <typename T>
1398 mxArray *
1399 ov_range<T>::as_mxArray (bool interleaved) const
1400 {
1401  mxClassID mx_class = mx_type_traits<T>::mx_class;
1402 
1403  mxArray *retval = new mxArray (interleaved, mx_class, dims (), mxREAL);
1404 
1405  typedef typename mx_type_traits<T>::mx_type mx_type;
1406  mx_type *pd = static_cast<mx_type *> (retval->get_data ());
1407 
1408  mwSize nel = numel ();
1409 
1410  Array<T> matrix = raw_array_value ();
1411 
1412  const T *pdata = matrix.data ();
1413 
1414  for (mwSize i = 0; i < nel; i++)
1415  pd[i] = pdata[i];
1416 
1417  return retval;
1418 }
1419 
1420 template <typename T>
1423 {
1424  return (n < numel () ? octave_value (m_range.elem (n)) : octave_value ());
1425 }
1426 
1427 // Specializations.
1428 
1429 template <>
1430 octave::range<double>
1432 {
1433  return m_range;
1434 }
1435 
1436 // For now, disable all but ov_range<double>.
1437 
1438 #if 0
1439 
1440 template <>
1441 octave::range<float>
1443 {
1444  return m_range;
1445 }
1446 
1447 template <>
1448 octave::range<octave_int8>
1450 {
1451  return m_range;
1452 }
1453 
1454 template <>
1455 octave::range<octave_int16>
1457 {
1458  return m_range;
1459 }
1460 
1461 template <>
1462 octave::range<octave_int32>
1464 {
1465  return m_range;
1466 }
1467 
1468 template <>
1469 octave::range<octave_int64>
1471 {
1472  return m_range;
1473 }
1474 
1475 template <>
1476 octave::range<octave_uint8>
1478 {
1479  return m_range;
1480 }
1481 
1482 template <>
1483 octave::range<octave_uint16>
1485 {
1486  return m_range;
1487 }
1488 
1489 template <>
1490 octave::range<octave_uint32>
1492 {
1493  return m_range;
1494 }
1495 
1496 template <>
1497 octave::range<octave_uint64>
1499 {
1500  return m_range;
1501 }
1502 
1503 #endif
1504 
1505 template <>
1507 ov_range<double>::index_vector (bool require_integers) const
1508 {
1509  if (m_idx_cache)
1510  return *m_idx_cache;
1511 
1512  if (require_integers || m_range.all_elements_are_ints ())
1513  return set_idx_cache (octave::idx_vector (m_range));
1514 
1515  warning_with_id ("Octave:noninteger-range-as-index",
1516  "non-integer range used as index");
1517 
1518  return octave_value (matrix_value ()).round ().index_vector ();
1519 }
1520 
1521 template <>
1524 {
1525  return m_range.nnz ();
1526 }
1527 
1528 // The following specialization is also historical baggage. For double
1529 // ranges, we can produce special double-valued diagnoal matrix objects
1530 // but Octave currently provides only double and Complex diagonal matrix
1531 // objects.
1532 
1533 template <>
1536 {
1537  // FIXME: this is a potential waste of memory.
1538 
1539  return
1540  (k == 0
1541  ? octave_value (DiagMatrix (DiagArray2<double> (matrix_value ())))
1542  : octave_value (m_range.diag (k)));
1543 }
1544 
1545 template <>
1548 {
1549  Matrix mat = matrix_value ();
1550 
1551  return mat.diag (nr, nc);
1552 }
1553 
1554 template <>
1555 void
1556 ov_range<double>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
1557 {
1558  octave_print_internal (os, m_range, pr_as_read_syntax,
1559  current_print_indent_level ());
1560 }
OCTARRAY_OVERRIDABLE_FUNC_API const T * data(void) const
Size of the specified dimension.
Definition: Array.h:663
bool test_all(F fcn) const
Size of the specified dimension.
Definition: Array.h:928
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array-base.cc:1032
OCTARRAY_OVERRIDABLE_FUNC_API T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:562
Definition: dMatrix.h:42
OCTAVE_API Matrix diag(octave_idx_type k=0) const
Definition: dMatrix.cc:2407
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
void * get_data(void) const
Definition: mxarray.h:497
octave_idx_type length(void) const
Definition: ovl.h:113
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov.h:550
octave::idx_vector index_vector(bool require_integers=false) const
Definition: ov.h:579
OCTINTERP_API octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, std::size_t skip=1)
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition: ov.h:1414
OCTINTERP_API FloatComplex float_complex_value(bool=false) const
Definition: ov-range.cc:372
virtual octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-base.cc:200
OCTINTERP_API octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition: ov-range.cc:266
OCTINTERP_API octave_value fast_elem_extract(octave_idx_type n) const
Definition: ov-range.cc:1422
OCTINTERP_API octave_value as_int32(void) const
Definition: ov-range.cc:531
OCTINTERP_API type_conv_info numeric_conversion_function(void) const
Definition: ov-range.cc:194
OCTINTERP_API octave_value as_single(void) const
Definition: ov-range.cc:510
octave_value diag(octave_idx_type k=0) const
Definition: ov-range.h:226
OCTINTERP_API octave_value as_uint64(void) const
Definition: ov-range.cc:566
OCTINTERP_API bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool flag)
Definition: ov-range.cc:1125
OCTINTERP_API octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov-range.cc:405
OCTINTERP_API octave_value as_uint16(void) const
Definition: ov-range.cc:552
Array< T > raw_array_value(void) const
Definition: ov-range.h:271
OCTINTERP_API float_display_format get_edit_display_format(void) const
Definition: ov-range.cc:658
OCTINTERP_API bool load_ascii(std::istream &is)
Definition: ov-range.cc:776
OCTINTERP_API octave_value as_int16(void) const
Definition: ov-range.cc:524
OCTINTERP_API void short_disp(std::ostream &os) const
Definition: ov-range.cc:619
OCTINTERP_API void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov-range.cc:581
OCTINTERP_API bool save_ascii(std::ostream &os)
Definition: ov-range.cc:711
OCTINTERP_API std::string edit_display(const float_display_format &fmt, octave_idx_type i, octave_idx_type j) const
Definition: ov-range.cc:665
OCTINTERP_API bool save_binary(std::ostream &os, bool save_as_floats)
Definition: ov-range.cc:872
OCTINTERP_API double double_value(bool=false) const
Definition: ov-range.cc:312
OCTINTERP_API octave_value as_double(void) const
Definition: ov-range.cc:503
OCTINTERP_API octave::range< double > range_value(void) const
Definition: ov-range.cc:417
OCTINTERP_API charNDArray char_array_value(bool=false) const
Definition: ov-range.cc:342
OCTINTERP_API boolNDArray bool_array_value(bool warn=false) const
Definition: ov-range.cc:393
OCTINTERP_API octave_base_value * try_narrowing_conversion(void)
Definition: ov-range.cc:204
OCTINTERP_API float float_value(bool=false) const
Definition: ov-range.cc:327
OCTINTERP_API octave_value as_uint32(void) const
Definition: ov-range.cc:559
OCTINTERP_API octave_value as_uint8(void) const
Definition: ov-range.cc:545
OCTINTERP_API mxArray * as_mxArray(bool interleaved) const
Definition: ov-range.cc:1399
OCTINTERP_API octave_value as_int64(void) const
Definition: ov-range.cc:538
OCTINTERP_API bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-range.cc:1287
OCTINTERP_API bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition: ov-range.cc:951
OCTINTERP_API octave_value as_int8(void) const
Definition: ov-range.cc:517
OCTINTERP_API void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition: ov-range.cc:573
OCTINTERP_API octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition: ov-range.cc:493
octave_idx_type nnz(void) const
Definition: ov-range.h:135
OCTINTERP_API octave::idx_vector index_vector(bool require_integers=false) const
Definition: ov-range.cc:304
OCTINTERP_API bool print_name_tag(std::ostream &os, const std::string &name) const
Definition: ov-range.cc:594
OCTINTERP_API Complex complex_value(bool=false) const
Definition: ov-range.cc:357
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
@ LS_DOUBLE
Definition: data-conv.h:95
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1069
void error(const char *fmt,...)
Definition: error.cc:979
#define panic_impossible()
Definition: error.h:508
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_logical_conversion(void)
Definition: errwarn.cc:365
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:344
octave::idx_vector idx_vector
Definition: idx-vector.h:1039
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
void skip_until_newline(std::istream &is, bool keep_newline)
bool hdf5_types_compatible(octave_hdf5_id t1, octave_hdf5_id t2)
Definition: ls-hdf5.cc:269
octave_hdf5_err hdf5_add_scalar_attr(octave_hdf5_id loc_id, octave_hdf5_id type_id, const char *attr_name, void *buf)
Definition: ls-hdf5.cc:1205
float_format
Definition: mach-info.h:38
void mxArray
Definition: mex.h:58
class OCTAVE_API NDArray
Definition: mx-fwd.h:38
class OCTAVE_API boolNDArray
Definition: mx-fwd.h:42
class OCTAVE_API FloatMatrix
Definition: mx-fwd.h:33
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
int64_t octave_hdf5_id
#define H5T_NATIVE_IDX
Definition: oct-hdf5.h:42
T::size_type numel(const T &str)
Definition: oct-string.cc:71
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
#define DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:226
bool xsave_ascii(std::ostream &os, const octave::range< T > &r, const bool with_reverse)
Definition: ov-range.cc:675
static hid_t hdf5_make_range_rev_type(hid_t num_type)
Definition: ov-range.cc:1044
bool xsave_binary(std::ostream &os, bool, const octave::range< T > &r, const bool with_reverse)
Definition: ov-range.cc:845
static octave_base_value * default_numeric_conversion_function(const octave_base_value &a)
Definition: ov-range.cc:183
static void skip_comments(std::istream &is)
Definition: ov-range.cc:642
bool xload_binary(std::istream &is, bool swap, octave::mach_info::float_format, octave::range< T > &r, const bool with_reverse)
Definition: ov-range.cc:913
bool xsave_hdf5(octave_hdf5_id loc_id, const char *name, bool, const octave::range< T > &r, const octave_hdf5_id h5_save_type, const bool with_reverse)
Definition: ov-range.cc:1059
bool xload_hdf5(octave_hdf5_id loc_id, const char *name, octave::range< T > &r, const octave_hdf5_id h5_save_type, const bool with_reverse)
Definition: ov-range.cc:1228
bool xload_ascii(std::istream &is, octave::range< T > &r, const bool with_reverse)
Definition: ov-range.cc:754
static hid_t hdf5_make_range_type(hid_t num_type)
Definition: ov-range.cc:1031
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
Definition: pr-output.cc:1762
float_display_format make_format(const double &d)
Definition: pr-output.cc:525
bool Vcompact_format
Definition: pr-output.cc:102
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
F77_RET_T len
Definition: xerbla.cc:61