GNU Octave 7.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-2022 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
69template <>
71
72// For now, disable all but ov_range<double>.
73
74# if 0
75
76template <>
78
79template <>
81
82template <>
84
85template <>
87
88template <>
90
91template <>
93
94template <>
96
97template <>
99
100template <>
102
103# endif
104
105#else
106
107template <>
109
110// For now, disable all but ov_range<double>.
111
112#if 0
113
114template <>
116
117template <>
119
120template <>
122
123template <>
125
126template <>
128
129template <>
131
132template <>
134
135template <>
137
138template <>
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
181template <typename T>
182static 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
192template <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
202template <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
236template <typename T>
238ov_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:
259 }
260
261 return retval.next_subsref (type, idx);
262}
263
264template <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
302template <typename T>
304ov_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
310template <typename T>
311double
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
325template <typename T>
326float
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
340template <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
355template <typename T>
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
370template <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
391template <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
403template <typename T>
405ov_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
415template <typename T>
416octave::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
426template <typename T>
427octave::range<float>
429{
430 err_wrong_type_arg ("ov_range<T>::float_range_value ()", type_name ());
431}
432
433template <typename T>
434octave::range<octave_int8>
436{
437 err_wrong_type_arg ("ov_range<T>::int8_range_value ()", type_name ());
438}
439
440template <typename T>
441octave::range<octave_int16>
443{
444 err_wrong_type_arg ("ov_range<T>::int16_range_value ()", type_name ());
445}
446
447template <typename T>
448octave::range<octave_int32>
450{
451 err_wrong_type_arg ("ov_range<T>::int32_range_value ()", type_name ());
452}
453
454template <typename T>
455octave::range<octave_int64>
457{
458 err_wrong_type_arg ("ov_range<T>::int64_range_value ()", type_name ());
459}
460
461template <typename T>
462octave::range<octave_uint8>
464{
465 err_wrong_type_arg ("ov_range<T>::uint8_range_value ()", type_name ());
466}
467
468template <typename T>
469octave::range<octave_uint16>
471{
472 err_wrong_type_arg ("ov_range<T>::uint16_range_value ()", type_name ());
473}
474
475template <typename T>
476octave::range<octave_uint32>
478{
479 err_wrong_type_arg ("ov_range<T>::uint32_range_value ()", type_name ());
480}
481
482template <typename T>
483octave::range<octave_uint64>
485{
486 err_wrong_type_arg ("ov_range<T>::uint64_range_value ()", type_name ());
487}
488
489#endif
490
491template <typename T>
493ov_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
501template <typename T>
504{
505 return NDArray (raw_array_value ());
506}
507
508template <typename T>
511{
512 return FloatMatrix (raw_array_value ());
513}
514
515template <typename T>
518{
519 return int8NDArray (raw_array_value ());
520}
521
522template <typename T>
525{
526 return int16NDArray (raw_array_value ());
527}
528
529template <typename T>
532{
533 return int32NDArray (raw_array_value ());
534}
535
536template <typename T>
539{
540 return int64NDArray (raw_array_value ());
541}
542
543template <typename T>
546{
547 return uint8NDArray (raw_array_value ());
548}
549
550template <typename T>
553{
554 return uint16NDArray (raw_array_value ());
555}
556
557template <typename T>
560{
561 return uint32NDArray (raw_array_value ());
562}
563
564template <typename T>
567{
568 return uint64NDArray (raw_array_value ());
569}
570
571template <typename T>
572void
573ov_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
579template <typename T>
580void
581ov_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
592template <typename T>
593bool
594ov_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
617template <typename T>
618void
619ov_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
641static void
642skip_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
656template <typename T>
659{
660 return make_format (m_range);
661}
662
663template <typename T>
664std::string
667{
668 std::ostringstream buf;
669 octave_print_internal (buf, fmt, m_range.elem (j));
670 return buf.str ();
671}
672
673template <typename T>
674bool
675xsave_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
709template <typename T>
710bool
711ov_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
722template <>
723bool
724ov_range<octave_uint8>::save_ascii (std::ostream& os)
725{
726 return xsave_ascii (os, m_range, true);
727}
728
729template <>
730bool
732{
733 return xsave_ascii (os, m_range, true);
734}
735
736template <>
737bool
739{
740 return xsave_ascii (os, m_range, true);
741}
742
743template <>
744bool
746{
747 return xsave_ascii (os, m_range, true);
748}
749
750#endif
751
752template <typename T>
753bool
754xload_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
774template <typename T>
775bool
776ov_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
787template <>
788bool
789ov_range<octave_uint8>::load_ascii (std::istream& is)
790{
791 return xload_ascii (is, m_range, true);
792}
793
794template <>
795bool
797{
798 return xload_ascii (is, m_range, true);
799}
800
801template <>
802bool
804{
805 return xload_ascii (is, m_range, true);
806}
807
808template <>
809bool
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
843template <typename T>
844bool
845xsave_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
870template <typename T>
871bool
872ov_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
881template <>
882bool
883ov_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
888template <>
889bool
890ov_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
895template <>
896bool
897ov_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
902template <>
903bool
904ov_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
911template <typename T>
912bool
913xload_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
949template <typename T>
950bool
951ov_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
961template <>
962bool
963ov_range<octave_uint8>::load_binary (std::istream& is, bool swap,
965{
966 return xload_binary (is, swap, fmt, m_range, true);
967}
968
969template <>
970bool
971ov_range<octave_uint16>::load_binary (std::istream& is, bool swap,
973{
974 return xload_binary (is, swap, fmt, m_range, true);
975}
976
977template <>
978bool
979ov_range<octave_uint32>::load_binary (std::istream& is, bool swap,
981{
982 return xload_binary (is, swap, fmt, m_range, true);
983}
984
985template <>
986bool
987ov_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
1029template <typename T>
1030static hid_t
1031hdf5_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
1042template <typename T>
1043static 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
1057template <typename T>
1058bool
1059xsave_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,
1083# else
1084 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);
1085# endif
1086 if (data_hid < 0)
1087 {
1088 H5Sclose (space_hid);
1089 H5Tclose (type_hid);
1090 return false;
1091 }
1092
1093 T range_vals[4];
1094 range_vals[0] = r.base ();
1095 if (r.increment () != T (0))
1096 range_vals[1] = r.limit ();
1097 else
1098 range_vals[1] = r.numel ();
1099 range_vals[2] = r.increment ();
1100 range_vals[3] = r.reverse ();
1101
1102 if (H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
1103 octave_H5P_DEFAULT, range_vals)
1104 >= 0)
1105 {
1106 octave_idx_type nel = r.numel ();
1107 retval = hdf5_add_scalar_attr (data_hid, H5T_NATIVE_IDX,
1108 "OCTAVE_RANGE_NELEM", &nel) >= 0;
1109 }
1110 else
1111 retval = false;
1112
1113 H5Dclose (data_hid);
1114 H5Tclose (type_hid);
1115 H5Sclose (space_hid);
1116
1117 return retval;
1118}
1119
1120#endif
1121
1122template <typename T>
1123bool
1125 bool save_as_floats)
1126{
1127#if defined (HAVE_HDF5)
1128 return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1129 false);
1130#else
1131 octave_unused_parameter (loc_id);
1132 octave_unused_parameter (name);
1133 octave_unused_parameter (save_as_floats);
1134
1135 warn_save ("hdf5");
1136
1137 return false;
1138#endif
1139}
1140
1141// For now, disable all but ov_range<double>.
1142
1143#if 0
1144
1145template <>
1146bool
1148 bool save_as_floats)
1149{
1150#if defined (HAVE_HDF5)
1151 return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1152 true);
1153#else
1154 octave_unused_parameter (loc_id);
1155 octave_unused_parameter (name);
1156 octave_unused_parameter (save_as_floats);
1157
1158 warn_save ("hdf5");
1159
1160 return false;
1161#endif
1162}
1163
1164template <>
1165bool
1167 bool save_as_floats)
1168{
1169#if defined (HAVE_HDF5)
1170 return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1171 true);
1172#else
1173 octave_unused_parameter (loc_id);
1174 octave_unused_parameter (name);
1175 octave_unused_parameter (save_as_floats);
1176
1177 warn_save ("hdf5");
1178
1179 return false;
1180#endif
1181}
1182
1183template <>
1184bool
1186 bool save_as_floats)
1187{
1188#if defined (HAVE_HDF5)
1189 return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1190 true);
1191#else
1192 octave_unused_parameter (loc_id);
1193 octave_unused_parameter (name);
1194 octave_unused_parameter (save_as_floats);
1195
1196 warn_save ("hdf5");
1197
1198 return false;
1199#endif
1200}
1201
1202template <>
1203bool
1205 bool save_as_floats)
1206{
1207#if defined (HAVE_HDF5)
1208 return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
1209 true);
1210#else
1211 octave_unused_parameter (loc_id);
1212 octave_unused_parameter (name);
1213 octave_unused_parameter (save_as_floats);
1214
1215 warn_save ("hdf5");
1216
1217 return false;
1218#endif
1219}
1220
1221#endif
1222
1223#if defined (HAVE_HDF5)
1224
1225template <typename T>
1226bool
1227xload_hdf5 (octave_hdf5_id loc_id, const char *name, octave::range<T>& r,
1228 const octave_hdf5_id h5_save_type, const bool with_reverse)
1229{
1230 bool retval = false;
1231
1232# if defined (HAVE_HDF5_18)
1233 hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
1234# else
1235 hid_t data_hid = H5Dopen (loc_id, name);
1236# endif
1237 hid_t type_hid = H5Dget_type (data_hid);
1238
1239 hid_t range_type = with_reverse
1240 ? hdf5_make_range_rev_type<T> (h5_save_type)
1241 : hdf5_make_range_type<T> (h5_save_type);
1242
1243 if (! hdf5_types_compatible (type_hid, range_type))
1244 {
1245 H5Tclose (range_type);
1246 H5Dclose (data_hid);
1247 return false;
1248 }
1249
1250 hid_t space_hid = H5Dget_space (data_hid);
1251 hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
1252
1253 if (rank != 0)
1254 {
1255 H5Tclose (range_type);
1256 H5Sclose (space_hid);
1257 H5Dclose (data_hid);
1258 return false;
1259 }
1260
1261 T rangevals[4];
1262 if (H5Dread (data_hid, range_type, octave_H5S_ALL, octave_H5S_ALL,
1263 octave_H5P_DEFAULT, rangevals)
1264 >= 0)
1265 {
1266 retval = true;
1267
1268 // Don't use OCTAVE_RANGE_NELEM attribute, just reconstruct the range.
1269
1270 bool rev = with_reverse ? static_cast<bool> (rangevals[3]) : false;
1271
1272 r = octave::range<T> (rangevals[0], rangevals[2], rangevals[1], rev);
1273 }
1274
1275 H5Tclose (range_type);
1276 H5Sclose (space_hid);
1277 H5Dclose (data_hid);
1278
1279 return retval;
1280}
1281
1282#endif
1283
1284template <typename T>
1285bool
1287{
1288#if defined (HAVE_HDF5)
1289 return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, false);
1290#else
1291 octave_unused_parameter (loc_id);
1292 octave_unused_parameter (name);
1293
1294 warn_load ("hdf5");
1295
1296 return false;
1297#endif
1298}
1299
1300// For now, disable all but ov_range<double>.
1301
1302#if 0
1303
1304template <>
1305bool
1307{
1308#if defined (HAVE_HDF5)
1309 return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1310#else
1311 octave_unused_parameter (loc_id);
1312 octave_unused_parameter (name);
1313
1314 warn_load ("hdf5");
1315
1316 return false;
1317#endif
1318}
1319
1320template <>
1321bool
1323{
1324#if defined (HAVE_HDF5)
1325 return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1326#else
1327 octave_unused_parameter (loc_id);
1328 octave_unused_parameter (name);
1329
1330 warn_load ("hdf5");
1331
1332 return false;
1333#endif
1334}
1335
1336template <>
1337bool
1339{
1340#if defined (HAVE_HDF5)
1341 return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1342#else
1343 octave_unused_parameter (loc_id);
1344 octave_unused_parameter (name);
1345
1346 warn_load ("hdf5");
1347
1348 return false;
1349#endif
1350}
1351
1352template <>
1353bool
1355{
1356#if defined (HAVE_HDF5)
1357 return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, true);
1358#else
1359 octave_unused_parameter (loc_id);
1360 octave_unused_parameter (name);
1361
1362 warn_load ("hdf5");
1363
1364 return false;
1365#endif
1366}
1367
1368#endif
1369
1370/*
1371%!testif HAVE_HDF5
1372%! a = b = 1:4;
1373%! sv_file = [tempname(), ".h5"];
1374%! unwind_protect
1375%! save (sv_file, "a", "-hdf5");
1376%! clear a;
1377%! load (sv_file);
1378%! assert (a, b);
1379%! unwind_protect_cleanup
1380%! unlink (sv_file);
1381%! end_unwind_protect
1382
1383%!testif HAVE_HDF5
1384%! a = b = uint8(5):-1:0;
1385%! sv_file = [tempname(), ".h5"];
1386%! unwind_protect
1387%! save (sv_file, "a", "-hdf5");
1388%! clear a;
1389%! load (sv_file);
1390%! assert (a, b);
1391%! unwind_protect_cleanup
1392%! unlink (sv_file);
1393%! end_unwind_protect
1394*/
1395
1396template <typename T>
1397mxArray *
1398ov_range<T>::as_mxArray (bool interleaved) const
1399{
1400 mxClassID mx_class = mx_type_traits<T>::mx_class;
1401
1402 mxArray *retval = new mxArray (interleaved, mx_class, dims (), mxREAL);
1403
1404 typedef typename mx_type_traits<T>::mx_type mx_type;
1405 mx_type *pd = static_cast<mx_type *> (retval->get_data ());
1406
1407 mwSize nel = numel ();
1408
1409 Array<T> matrix = raw_array_value ();
1410
1411 const T *pdata = matrix.data ();
1412
1413 for (mwSize i = 0; i < nel; i++)
1414 pd[i] = pdata[i];
1415
1416 return retval;
1417}
1418
1419template <typename T>
1422{
1423 return (n < numel () ? octave_value (m_range.elem (n)) : octave_value ());
1424}
1425
1426// Specializations.
1427
1428template <>
1429octave::range<double>
1431{
1432 return m_range;
1433}
1434
1435// For now, disable all but ov_range<double>.
1436
1437#if 0
1438
1439template <>
1440octave::range<float>
1442{
1443 return m_range;
1444}
1445
1446template <>
1447octave::range<octave_int8>
1449{
1450 return m_range;
1451}
1452
1453template <>
1454octave::range<octave_int16>
1456{
1457 return m_range;
1458}
1459
1460template <>
1461octave::range<octave_int32>
1463{
1464 return m_range;
1465}
1466
1467template <>
1468octave::range<octave_int64>
1470{
1471 return m_range;
1472}
1473
1474template <>
1475octave::range<octave_uint8>
1477{
1478 return m_range;
1479}
1480
1481template <>
1482octave::range<octave_uint16>
1484{
1485 return m_range;
1486}
1487
1488template <>
1489octave::range<octave_uint32>
1491{
1492 return m_range;
1493}
1494
1495template <>
1496octave::range<octave_uint64>
1498{
1499 return m_range;
1500}
1501
1502#endif
1503
1504template <>
1506ov_range<double>::index_vector (bool require_integers) const
1507{
1508 if (m_idx_cache)
1509 return *m_idx_cache;
1510
1511 if (require_integers || m_range.all_elements_are_ints ())
1512 return set_idx_cache (octave::idx_vector (m_range));
1513
1514 warning_with_id ("Octave:noninteger-range-as-index",
1515 "non-integer range used as index");
1516
1517 return octave_value (matrix_value ()).round ().index_vector ();
1518}
1519
1520template <>
1523{
1524 return m_range.nnz ();
1525}
1526
1527// The following specialization is also historical baggage. For double
1528// ranges, we can produce special double-valued diagnoal matrix objects
1529// but Octave currently provides only double and Complex diagonal matrix
1530// objects.
1531
1532template <>
1535{
1536 // FIXME: this is a potential waste of memory.
1537
1538 return
1539 (k == 0
1540 ? octave_value (DiagMatrix (DiagArray2<double> (matrix_value ())))
1541 : octave_value (m_range.diag (k)));
1542}
1543
1544template <>
1547{
1548 Matrix mat = matrix_value ();
1549
1550 return mat.diag (nr, nc);
1551}
1552
1553template <>
1554void
1555ov_range<double>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
1556{
1557 octave_print_internal (os, m_range, pr_as_read_syntax,
1558 current_print_indent_level ());
1559}
bool test_all(F fcn) const
Size of the specified dimension.
Definition: Array.h:862
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:534
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
const T * data(void) const
Size of the specified dimension.
Definition: Array.h:616
Definition: dMatrix.h:42
OCTAVE_API Matrix diag(octave_idx_type k=0) const
Definition: dMatrix.cc:2402
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
void * get_data(void) const
Definition: mxarray.h:497
bool is_scalar(void) const
Definition: idx-vector.h:559
void set_pos_if_unset(octave_idx_type nd_arg, octave_idx_type dim_arg)
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:1411
OCTINTERP_API FloatComplex float_complex_value(bool=false) const
Definition: ov-range.cc:372
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:1421
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 subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-range.cc:238
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:1124
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
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
Array< T > raw_array_value(void) const
Definition: ov-range.h:271
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:1398
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:1286
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:1070
void error(const char *fmt,...)
Definition: error.cc:980
#define panic_impossible()
Definition: error.h:411
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
QString name
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
OCTAVE_NAMESPACE_BEGIN 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:1207
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
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:219
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:1227
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