GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ov-range.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 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-inline.h"
57#include "ov-range-traits.h"
58#include "ov-range.h"
59#include "ov-re-mat.h"
60#include "ov-scalar.h"
61#include "pr-output.h"
62
63#include "byte-swap.h"
64#include "ls-ascii-helper.h"
65#include "ls-hdf5.h"
66#include "ls-utils.h"
67
68#if defined (HAVE_HDF5)
69
70template <>
72
73// For now, enable only ov_range<double>.
74
75#else
76
77template <>
79
80// For now, enable only ov_range<double>.
81
82#endif
83
85 "double_range", "double");
86
87// For now, enable only ov_range<double>.
88
89template <typename T>
90static octave_base_value *
91default_numeric_conversion_function (const octave_base_value& a)
92{
93 typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
94
95 const ov_range<T>& v = dynamic_cast<const ov_range<T>&> (a);
96
97 return new ov_mx_type (v.raw_array_value ());
98}
99
100template <typename T>
103{
104 typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
105
107 (default_numeric_conversion_function<T>, ov_mx_type::static_type_id ());
108}
109
110template <typename T>
113{
114 octave_base_value *retval = nullptr;
115
116 switch (numel ())
117 {
118 case 1:
119 retval = new typename octave_value_range_traits<T>::scalar_type (m_range.elem (0));
120 break;
121
122 case 0:
123 {
124 typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
125 typename ov_mx_type::object_type m (dim_vector (1, 0));
126 retval = new ov_mx_type (m);
127 }
128 break;
129
130 case -2:
131 // FIXME: is this case possible now? It would have to be due to
132 // conversion from Range to range<double>, but even in that case,
133 // is the invalid numel value preserved?
134 retval = new typename octave_value_range_traits<T>::matrix_type (raw_array_value ());
135 break;
136
137 default:
138 break;
139 }
140
141 return retval;
142}
143
144template <typename T>
146ov_range<T>::subsref (const std::string& type,
147 const std::list<octave_value_list>& idx)
148{
149 octave_value retval;
150
151 switch (type[0])
152 {
153 case '(':
154 retval = do_index_op (idx.front ());
155 break;
156
157 case '{':
158 case '.':
159 {
160 std::string nm = type_name ();
161 error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
162 }
163 break;
164
165 default:
166 error ("unexpected: index not '(', '{', or '.' in ov_range<T>::subsref - please report this bug");
167 }
168
169 return retval.next_subsref (type, idx);
170}
171
172template <typename T>
175 bool resize_ok)
176{
177 if (idx.length () == 1 && ! resize_ok)
178 {
179 octave_value retval;
180
181 // The range can handle a single subscript.
182
183 try
184 {
185 octave::idx_vector i = idx(0).index_vector ();
186
187 if (i.is_scalar () && i(0) < numel ())
188 retval = m_range.elem (i(0));
189 else
190 retval = m_range.index (i);
191 }
192 catch (octave::index_exception& ie)
193 {
194 // More info may be added later before displaying error.
195
196 ie.set_pos_if_unset (1, 1);
197 throw;
198 }
199
200 return retval;
201 }
202 else
203 {
204 octave_value tmp (new typename octave_value_range_traits<T>::matrix_type (raw_array_value ()));
205
206 return tmp.index_op (idx, resize_ok);
207 }
208}
209
210template <typename T>
211octave::idx_vector
212ov_range<T>::index_vector (bool require_integers) const
213{
214 octave_value tmp (raw_array_value ());
215 return tmp.index_vector (require_integers);
216}
217
218template <typename T>
219double
221{
222 octave_idx_type nel = numel ();
223
224 if (nel == 0)
225 err_invalid_conversion ("range", "real scalar");
226
227 warn_implicit_conversion ("Octave:array-to-scalar",
228 "range", "real scalar");
229
230 return m_range.base ();
231}
232
233template <typename T>
234float
236{
237 octave_idx_type nel = numel ();
238
239 if (nel == 0)
240 err_invalid_conversion ("range", "real scalar");
241
242 warn_implicit_conversion ("Octave:array-to-scalar",
243 "range", "real scalar");
244
245 return m_range.base ();
246}
247
248template <typename T>
251{
252 const Array<T> matrix = raw_array_value ();
253 charNDArray retval (dims ());
254
255 octave_idx_type nel = numel ();
256
257 for (octave_idx_type i = 0; i < nel; i++)
258 retval.elem (i) = static_cast<char> (matrix.elem (i));
259
260 return retval;
261}
262
263template <typename T>
266{
267 octave_idx_type nel = numel ();
268
269 if (nel == 0)
270 err_invalid_conversion ("range", "complex scalar");
271
272 warn_implicit_conversion ("Octave:array-to-scalar",
273 "range", "complex scalar");
274
275 return Complex (m_range.base (), 0);
276}
277
278template <typename T>
281{
282 float tmp = lo_ieee_float_nan_value ();
283
284 FloatComplex retval (tmp, tmp);
285
286 octave_idx_type nel = numel ();
287
288 if (nel == 0)
289 err_invalid_conversion ("range", "complex scalar");
290
291 warn_implicit_conversion ("Octave:array-to-scalar",
292 "range", "complex scalar");
293
294 retval = m_range.base ();
295
296 return retval;
297}
298
299template <typename T>
302{
303 Array<T> matrix = raw_array_value ();
304
305 if (warn && ! matrix.test_all (octave::is_one_or_zero<T>))
307
308 return boolNDArray (matrix);
309}
310
311template <typename T>
313ov_range<T>::resize (const dim_vector& dv, bool fill) const
314{
315 Array<T> retval = raw_array_value ();
316 if (fill)
317 retval.resize (dv, 0);
318 else
319 retval.resize (dv);
320 return retval;
321}
322
323template <typename T>
324octave::range<double>
326{
327 err_wrong_type_arg ("ov_range<T>::range_value()", type_name ());
328}
329
330// For now, enable only ov_range<double>.
331
332template <typename T>
334ov_range<T>::convert_to_str_internal (bool pad, bool force, char type) const
335{
336 octave_value tmp (raw_array_value ());
337 return tmp.convert_to_str (pad, force, type);
338}
339
340// FIXME: could most of these fucntions preserve range type now?
341
342template <typename T>
345{
346 return NDArray (raw_array_value ());
347}
348
349template <typename T>
352{
353 return FloatMatrix (raw_array_value ());
354}
355
356template <typename T>
359{
360 return int8NDArray (raw_array_value ());
361}
362
363template <typename T>
366{
367 return int16NDArray (raw_array_value ());
368}
369
370template <typename T>
373{
374 return int32NDArray (raw_array_value ());
375}
376
377template <typename T>
380{
381 return int64NDArray (raw_array_value ());
382}
383
384template <typename T>
387{
388 return uint8NDArray (raw_array_value ());
389}
390
391template <typename T>
394{
395 return uint16NDArray (raw_array_value ());
396}
397
398template <typename T>
401{
402 return uint32NDArray (raw_array_value ());
403}
404
405template <typename T>
408{
409 return uint64NDArray (raw_array_value ());
410}
411
412template <typename T>
413void
414ov_range<T>::print (std::ostream& os, bool pr_as_read_syntax)
415{
416 print_raw (os, pr_as_read_syntax);
417 newline (os);
418}
419
420template <typename T>
421void
422ov_range<T>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
423{
424 // FIXME: this is a potential waste of memory.
425
426 typedef typename octave_value_range_traits<T>::matrix_type ov_mx_type;
427 typename ov_mx_type::object_type tmp (raw_array_value ());
428
429 octave_print_internal (os, tmp, pr_as_read_syntax,
430 current_print_indent_level ());
431}
432
433template <typename T>
434bool
435ov_range<T>::print_name_tag (std::ostream& os, const std::string& name) const
436{
437 bool retval = false;
438
439 octave_idx_type n = numel ();
440
441 indent (os);
442
443 if (n == 0 || n == 1)
444 os << name << " = ";
445 else
446 {
447 os << name << " =";
448 newline (os);
449 if (! Vcompact_format)
450 newline (os);
451
452 retval = true;
453 }
454
455 return retval;
456}
457
458template <typename T>
459void
460ov_range<T>::short_disp (std::ostream& os) const
461{
463
464 if (len == 0)
465 os << "[]";
466 else
467 {
468 os << m_range.base () << ':';
469
470 if (len > 1)
471 {
472 if (m_range.increment () != T (1))
473 os << m_range.increment () << ':';
474
475 os << m_range.limit ();
476 }
477 }
478}
479
480// Skip white space and comments on stream IS.
481
482static void
483skip_comments (std::istream& is)
484{
485 char c = '\0';
486 while (is.get (c))
487 {
488 if (c == ' ' || c == '\t' || c == '\n')
489 ; // Skip whitespace on way to beginning of next line.
490 else
491 break;
492 }
493
494 octave::skip_until_newline (is, false);
495}
496
497template <typename T>
500{
501 return make_format (m_range);
502}
503
504template <typename T>
505std::string
508{
509 std::ostringstream buf;
510 octave_print_internal (buf, fmt, m_range.elem (j));
511 return buf.str ();
512}
513
514template <typename T>
515bool
516xsave_ascii (std::ostream& os, const octave::range<T>& r,
517 const bool with_reverse)
518{
519 T base = r.base ();
520 T limit = r.limit ();
521 T inc = r.increment ();
522 bool rev = r.reverse ();
523 octave_idx_type len = r.numel ();
524
525 if (inc != T (0))
526 os << "# base, limit, increment";
527 else
528 os << "# base, length, increment";
529
530 if (with_reverse)
531 os << ", reverse\n";
532 else
533 os << "\n";
534
535 octave::write_value<T> (os, base);
536 os << ' ';
537 if (inc != T (0))
538 octave::write_value<T> (os, limit);
539 else
540 os << len;
541 os << ' ';
542 octave::write_value<T> (os, inc);
543 if (with_reverse)
544 os << ' ' << rev;
545 os << "\n";
546
547 return true;
548}
549
550template <typename T>
551bool
552ov_range<T>::save_ascii (std::ostream& os)
553{
554 return xsave_ascii (os, m_range, false);
555}
556
557// specialize for saving with "reverse" flag
558
559// For now, enable only ov_range<double>.
560
561template <typename T>
562bool
563xload_ascii (std::istream& is, octave::range<T>& r, const bool with_reverse)
564{
565 // # base, limit, range comment added by save ().
566 skip_comments (is);
567
568 T base, limit, inc;
569 bool rev = false;
570 is >> base >> limit >> inc;
571
572 if (with_reverse)
573 is >> rev;
574
575 if (! is)
576 error ("load: failed to load range constant");
577
578 r = octave::range<T> (base, inc, limit, rev);
579
580 return true;
581}
582
583template <typename T>
584bool
585ov_range<T>::load_ascii (std::istream& is)
586{
587 return xload_ascii (is, m_range, false);
588}
589
590// specialize for loading with "reverse" flag
591
592// For now, enable only ov_range<double>.
593
594/*
595%!test
596%! a = b = 1:4;
597%! sv_file = [tempname(), ".sav"];
598%! unwind_protect
599%! save (sv_file, "a", "-text");
600%! clear a;
601%! load (sv_file);
602%! assert (a, b);
603%! unwind_protect_cleanup
604%! unlink (sv_file);
605%! end_unwind_protect
606
607%!test
608%! a = b = uint8(5):-1:0;
609%! sv_file = [tempname(), ".sav"];
610%! unwind_protect
611%! save (sv_file, "a", "-text");
612%! clear a;
613%! load (sv_file);
614%! assert (a, b);
615%! unwind_protect_cleanup
616%! unlink (sv_file);
617%! end_unwind_protect
618*/
619
620template <typename T>
621bool
622xsave_binary (std::ostream& os, bool /* save_as_floats */,
623 const octave::range<T>& r, const bool with_reverse)
624{
625 // FIXME: Not always double!
626
627 char tmp = LS_DOUBLE;
628 os.write (reinterpret_cast<char *> (&tmp), 1);
629 T bas = r.base ();
630 T lim = r.limit ();
631 T inc = r.increment ();
632 if (inc == T (0))
633 lim = r.numel ();
634
635 os.write (reinterpret_cast<char *> (&bas), sizeof (T));
636 os.write (reinterpret_cast<char *> (&lim), sizeof (T));
637 os.write (reinterpret_cast<char *> (&inc), sizeof (T));
638 if (with_reverse)
639 {
640 bool rev = r.reverse ();
641 os.write (reinterpret_cast<char *> (&rev), sizeof (bool));
642 }
643
644 return true;
645}
646
647template <typename T>
648bool
649ov_range<T>::save_binary (std::ostream& os, bool save_as_floats)
650{
651 return xsave_binary (os, save_as_floats, m_range, false);
652}
653
654// For now, enable only ov_range<double>.
655
656template <typename T>
657bool
658xload_binary (std::istream& is, bool swap,
659 octave::mach_info::float_format /* fmt */,
660 octave::range<T>& r, const bool with_reverse)
661{
662 // FIXME: Not always double!
663
664 char tmp;
665 if (! is.read (reinterpret_cast<char *> (&tmp), 1))
666 return false;
667 T bas, lim, inc;
668 if (! is.read (reinterpret_cast<char *> (&bas), sizeof (T)))
669 return false;
670 if (swap)
671 swap_bytes<sizeof (T)> (&bas);
672 if (! is.read (reinterpret_cast<char *> (&lim), sizeof (T)))
673 return false;
674 if (swap)
675 swap_bytes<sizeof (T)> (&lim);
676 if (! is.read (reinterpret_cast<char *> (&inc), sizeof (T)))
677 return false;
678 if (swap)
679 swap_bytes<sizeof (T)> (&inc);
680 bool rev = false;
681 if (with_reverse)
682 {
683 if (! is.read (reinterpret_cast<char *> (&rev), sizeof (bool)))
684 return false;
685 if (swap)
686 swap_bytes<sizeof (bool)> (&rev);
687 }
688
689 r = octave::range<T> (bas, inc, lim, rev);
690
691 return true;
692}
693
694template <typename T>
695bool
696ov_range<T>::load_binary (std::istream& is, bool swap,
697 octave::mach_info::float_format fmt)
698{
699 return xload_binary (is, swap, fmt, m_range, false);
700}
701
702// For now, enable only ov_range<double>.
703
704/*
705%!test
706%! a = b = 1:4;
707%! sv_file = [tempname(), ".dat"];
708%! unwind_protect
709%! save (sv_file, "a", "-binary");
710%! clear a;
711%! load (sv_file);
712%! assert (a, b);
713%! unwind_protect_cleanup
714%! unlink (sv_file);
715%! end_unwind_protect
716
717%!test
718%! a = b = uint8(5):-1:0;
719%! sv_file = [tempname(), ".dat"];
720%! unwind_protect
721%! save (sv_file, "a", "-binary");
722%! clear a;
723%! load (sv_file);
724%! assert (a, b);
725%! unwind_protect_cleanup
726%! unlink (sv_file);
727%! end_unwind_protect
728*/
729
730#if defined (HAVE_HDF5)
731
732// The following subroutines creates an HDF5 representation of the way
733// we will store Octave range types (triplets of floating-point numbers).
734// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
735// H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
736// conversions are handled automatically by HDF5.
737
738template <typename T>
739static hid_t
740hdf5_make_range_type (hid_t num_type)
741{
742 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (T) * 3);
743
744 H5Tinsert (type_id, "base", 0 * sizeof (T), num_type);
745 H5Tinsert (type_id, "limit", 1 * sizeof (T), num_type);
746 H5Tinsert (type_id, "increment", 2 * sizeof (T), num_type);
747
748 return type_id;
749}
750
751template <typename T>
752static hid_t
753hdf5_make_range_rev_type (hid_t num_type)
754{
755 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (T) * 4);
756
757 H5Tinsert (type_id, "base", 0 * sizeof (T), num_type);
758 H5Tinsert (type_id, "limit", 1 * sizeof (T), num_type);
759 H5Tinsert (type_id, "increment", 2 * sizeof (T), num_type);
760 // FIXME: Storing "reverse" with the same width is inefficient.
761 H5Tinsert (type_id, "reverse", 3 * sizeof (T), num_type);
762
763 return type_id;
764}
765
766template <typename T>
767bool
768xsave_hdf5 (octave_hdf5_id loc_id, const char *name,
769 bool /* save_as_floats */, const octave::range<T>& r,
770 const octave_hdf5_id h5_save_type, const bool with_reverse)
771{
772 bool retval = false;
773
774 hsize_t dimens[3] = {0};
775 hid_t space_hid, type_hid, data_hid;
776 space_hid = type_hid = data_hid = -1;
777
778 space_hid = H5Screate_simple (0, dimens, nullptr);
779 if (space_hid < 0) return false;
780
781 type_hid = with_reverse
782 ? hdf5_make_range_rev_type<T> (h5_save_type)
783 : hdf5_make_range_type<T> (h5_save_type);
784 if (type_hid < 0)
785 {
786 H5Sclose (space_hid);
787 return false;
788 }
789# if defined (HAVE_HDF5_18)
790 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid,
793# else
794 data_hid = H5Dcreate (loc_id, name, type_hid, space_hid, octave_H5P_DEFAULT);
795# endif
796 if (data_hid < 0)
797 {
798 H5Sclose (space_hid);
799 H5Tclose (type_hid);
800 return false;
801 }
802
803 T range_vals[4];
804 range_vals[0] = r.base ();
805 if (r.increment () != T (0))
806 range_vals[1] = r.limit ();
807 else
808 range_vals[1] = r.numel ();
809 range_vals[2] = r.increment ();
810 range_vals[3] = r.reverse ();
811
812 if (H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
813 octave_H5P_DEFAULT, range_vals)
814 >= 0)
815 {
816 octave_idx_type nel = r.numel ();
817 retval = hdf5_add_scalar_attr (data_hid, H5T_NATIVE_IDX,
818 "OCTAVE_RANGE_NELEM", &nel) >= 0;
819 }
820 else
821 retval = false;
822
823 H5Dclose (data_hid);
824 H5Tclose (type_hid);
825 H5Sclose (space_hid);
826
827 return retval;
828}
829
830#endif
831
832template <typename T>
833bool
834ov_range<T>::save_hdf5 (octave_hdf5_id loc_id, const char *name,
835 bool save_as_floats)
836{
837#if defined (HAVE_HDF5)
838 return xsave_hdf5 (loc_id, name, save_as_floats, m_range, hdf5_save_type,
839 false);
840#else
841 octave_unused_parameter (loc_id);
842 octave_unused_parameter (name);
843 octave_unused_parameter (save_as_floats);
844
845 warn_save ("hdf5");
846
847 return false;
848#endif
849}
850
851// For now, enable only ov_range<double>.
852
853#if defined (HAVE_HDF5)
854
855template <typename T>
856bool
857xload_hdf5 (octave_hdf5_id loc_id, const char *name, octave::range<T>& r,
858 const octave_hdf5_id h5_save_type, const bool with_reverse)
859{
860 bool retval = false;
861
862# if defined (HAVE_HDF5_18)
863 hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
864# else
865 hid_t data_hid = H5Dopen (loc_id, name);
866# endif
867 hid_t type_hid = H5Dget_type (data_hid);
868
869 hid_t range_type = with_reverse
870 ? hdf5_make_range_rev_type<T> (h5_save_type)
871 : hdf5_make_range_type<T> (h5_save_type);
872
873 if (! hdf5_types_compatible (type_hid, range_type))
874 {
875 H5Tclose (range_type);
876 H5Dclose (data_hid);
877 return false;
878 }
879
880 hid_t space_hid = H5Dget_space (data_hid);
881 hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
882
883 if (rank != 0)
884 {
885 H5Tclose (range_type);
886 H5Sclose (space_hid);
887 H5Dclose (data_hid);
888 return false;
889 }
890
891 T rangevals[4];
892 if (H5Dread (data_hid, range_type, octave_H5S_ALL, octave_H5S_ALL,
893 octave_H5P_DEFAULT, rangevals)
894 >= 0)
895 {
896 retval = true;
897
898 // Don't use OCTAVE_RANGE_NELEM attribute, just reconstruct the range.
899
900 bool rev = with_reverse ? static_cast<bool> (rangevals[3]) : false;
901
902 r = octave::range<T> (rangevals[0], rangevals[2], rangevals[1], rev);
903 }
904
905 H5Tclose (range_type);
906 H5Sclose (space_hid);
907 H5Dclose (data_hid);
908
909 return retval;
910}
911
912#endif
913
914template <typename T>
915bool
916ov_range<T>::load_hdf5 (octave_hdf5_id loc_id, const char *name)
917{
918#if defined (HAVE_HDF5)
919 return xload_hdf5 (loc_id, name, m_range, hdf5_save_type, false);
920#else
921 octave_unused_parameter (loc_id);
922 octave_unused_parameter (name);
923
924 warn_load ("hdf5");
925
926 return false;
927#endif
928}
929
930// For now, enable only ov_range<double>.
931
932/*
933%!testif HAVE_HDF5
934%! a = b = 1:4;
935%! sv_file = [tempname(), ".h5"];
936%! unwind_protect
937%! save (sv_file, "a", "-hdf5");
938%! clear a;
939%! load (sv_file);
940%! assert (a, b);
941%! unwind_protect_cleanup
942%! unlink (sv_file);
943%! end_unwind_protect
944
945%!testif HAVE_HDF5
946%! a = b = uint8(5):-1:0;
947%! sv_file = [tempname(), ".h5"];
948%! unwind_protect
949%! save (sv_file, "a", "-hdf5");
950%! clear a;
951%! load (sv_file);
952%! assert (a, b);
953%! unwind_protect_cleanup
954%! unlink (sv_file);
955%! end_unwind_protect
956*/
957
958template <typename T>
959mxArray *
960ov_range<T>::as_mxArray (bool interleaved) const
961{
962 mxClassID mx_class = mx_type_traits<T>::mx_class;
963
964 mxArray *retval = new mxArray (interleaved, mx_class, dims (), mxREAL);
965
966 typedef typename mx_type_traits<T>::mx_type mx_type;
967 mx_type *pd = static_cast<mx_type *> (retval->get_data ());
968
969 mwSize nel = numel ();
970
971 Array<T> matrix = raw_array_value ();
972
973 const T *pdata = matrix.data ();
974
975 for (mwSize i = 0; i < nel; i++)
976 pd[i] = pdata[i];
977
978 return retval;
979}
980
982 "trivial range", "double");
983
984template <typename T>
985bool
987
988template <>
989bool
991{
992 octave_idx_type n = m_range.numel ();
993 if (n > std::numeric_limits<int>::max())
994 return false;
995 if (n <= 1)
996 return false;
997
998 if (m_range.final_value () > std::numeric_limits<int>::max ()
999 || m_range.final_value () < std::numeric_limits<int>::min ())
1000 return false;
1001 if (m_range.increment () > std::numeric_limits<int>::max ()
1002 || m_range.increment () < std::numeric_limits<int>::min ())
1003 return false;
1004 if (m_range.base () > std::numeric_limits<int>::max ()
1005 || m_range.base () < std::numeric_limits<int>::min ())
1006 return false;
1007 if (m_range.limit () > std::numeric_limits<int>::max ()
1008 || m_range.limit () < std::numeric_limits<int>::min ())
1009 return false;
1010
1011 if (std::isnan (m_range.final_value ()))
1012 return false;
1013 if (std::isnan (m_range.increment ()))
1014 return false;
1015 if (std::isnan (m_range.base ()))
1016 return false;
1017 if (std::isnan (m_range.limit ()))
1018 return false;
1019
1020 if (static_cast<int> (m_range.final_value ()) != m_range.final_value ())
1021 return false;
1022 if (static_cast<int> (m_range.increment ()) != m_range.increment ())
1023 return false;
1024 if (static_cast<int> (m_range.base ()) != m_range.base ())
1025 return false;
1026 if (static_cast<int> (m_range.limit ()) != m_range.limit ())
1027 return false;
1028
1029 if (m_range.reverse ())
1030 return false;
1031
1032 return true;
1033}
1034
1035template <typename T>
1038{
1039 error ("Type error returning trivial range");
1040}
1041
1042template <>
1045{
1046 return octave_value (new octave_trivial_range (m_range.numel (), m_range.base (), m_range.increment ()));
1047}
1048
1049template <typename T>
1052{
1053 return (n < numel () ? octave_value (m_range.elem (n)) : octave_value ());
1054}
1055
1056// Specializations.
1057
1058template <>
1059octave::range<double>
1061{
1062 return m_range;
1063}
1064
1065template <typename T>
1068{
1069 octave_value ov = octave_value_factory::make (m_range.elem (n));
1070
1071 return ov.as_double_or_copy ();
1072}
1073
1074template <>
1077{
1078 octave_value ov = octave_value_factory::make (m_range.elem (n));
1079
1080 return ov;
1081}
1082
1083// For now, enable only ov_range<double>.
1084
1085template <>
1086octave::idx_vector
1087ov_range<double>::index_vector (bool require_integers) const
1088{
1089 if (m_idx_cache)
1090 return *m_idx_cache;
1091
1092 if (require_integers || m_range.all_elements_are_ints ())
1093 return set_idx_cache (octave::idx_vector (m_range));
1094
1095 warning_with_id ("Octave:noninteger-range-as-index",
1096 "non-integer range used as index");
1097
1098 return octave_value (matrix_value ()).round ().index_vector ();
1099}
1100
1101template <>
1104{
1105 return m_range.nnz ();
1106}
1107
1108// The following specialization is also historical baggage. For double
1109// ranges, we can produce special double-valued diagnoal matrix objects
1110// but Octave currently provides only double and Complex diagonal matrix
1111// objects.
1112
1113template <>
1116{
1117 // FIXME: this is a potential waste of memory.
1118
1119 return
1120 (k == 0
1121 ? octave_value (DiagMatrix (DiagArray2<double> (matrix_value ())))
1122 : octave_value (m_range.diag (k)));
1123}
1124
1125template <>
1128{
1129 Matrix mat = matrix_value ();
1130
1131 return mat.diag (nr, nc);
1132}
1133
1134template <>
1135void
1136ov_range<double>::print_raw (std::ostream& os, bool pr_as_read_syntax) const
1137{
1138 octave_print_internal (os, m_range, pr_as_read_syntax,
1139 current_print_indent_level ());
1140}
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
bool test_all(F fcn) const
Size of the specified dimension.
Definition Array.h:924
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition Array.h:563
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
const T * data() const
Size of the specified dimension.
Definition Array.h:665
Matrix diag(octave_idx_type k=0) const
Definition dMatrix.cc:2407
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
void * get_data() const
Definition mxarray.h:482
static octave_value make(double d)
Definition ov-inline.h:47
octave_idx_type length() const
Definition ovl.h:111
octave_value index_op(const octave_value_list &idx, bool resize_ok=false)
Definition ov.h:504
octave::idx_vector index_vector(bool require_integers=false) const
Definition ov.h:534
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:1322
octave_value round() const
Definition ov.h:1499
octave_value as_double_or_copy() const
Definition ov.h:442
FloatComplex float_complex_value(bool=false) const
Definition ov-range.cc:280
octave_value do_index_op(const octave_value_list &idx, bool resize_ok=false)
Definition ov-range.cc:174
octave_value fast_elem_extract(octave_idx_type n) const
Definition ov-range.cc:1051
octave_value as_int64() const
Definition ov-range.cc:379
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition ov-range.cc:146
octave_value diag(octave_idx_type k=0) const
Definition ov-range.h:271
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool flag)
Definition ov-range.cc:834
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition ov-range.cc:313
octave_value as_uint32() const
Definition ov-range.cc:400
Array< T > raw_array_value() const
Definition ov-range.h:316
octave_value as_uint16() const
Definition ov-range.cc:393
bool could_be_trivial_range()
Definition ov-range.cc:986
bool load_ascii(std::istream &is)
Definition ov-range.cc:585
void short_disp(std::ostream &os) const
Definition ov-range.cc:460
octave_value as_single() const
Definition ov-range.cc:351
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition ov-range.cc:422
bool save_ascii(std::ostream &os)
Definition ov-range.cc:552
std::string edit_display(const float_display_format &fmt, octave_idx_type i, octave_idx_type j) const
Definition ov-range.cc:506
bool save_binary(std::ostream &os, bool save_as_floats)
Definition ov-range.cc:649
double double_value(bool=false) const
Definition ov-range.cc:220
octave_value as_uint64() const
Definition ov-range.cc:407
float_display_format get_edit_display_format() const
Definition ov-range.cc:499
octave_idx_type nnz() const
Definition ov-range.h:178
octave_value as_int8() const
Definition ov-range.cc:358
octave_value as_int16() const
Definition ov-range.cc:365
charNDArray char_array_value(bool=false) const
Definition ov-range.cc:250
octave_value vm_extract_forloop_value(octave_idx_type idx)
Definition ov-range.cc:1067
boolNDArray bool_array_value(bool warn=false) const
Definition ov-range.cc:301
type_conv_info numeric_conversion_function() const
Definition ov-range.cc:102
float float_value(bool=false) const
Definition ov-range.cc:235
mxArray * as_mxArray(bool interleaved) const
Definition ov-range.cc:960
octave_value as_trivial_range()
Definition ov-range.cc:1037
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition ov-range.cc:916
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition ov-range.cc:696
octave_value as_double() const
Definition ov-range.cc:344
octave::range< double > range_value() const
Definition ov-range.cc:325
void print(std::ostream &os, bool pr_as_read_syntax=false)
Definition ov-range.cc:414
octave_value convert_to_str_internal(bool pad, bool force, char type) const
Definition ov-range.cc:334
octave_base_value * try_narrowing_conversion()
Definition ov-range.cc:112
octave_value as_uint8() const
Definition ov-range.cc:386
octave::idx_vector index_vector(bool require_integers=false) const
Definition ov-range.cc:212
bool print_name_tag(std::ostream &os, const std::string &name) const
Definition ov-range.cc:435
octave_value as_int32() const
Definition ov-range.cc:372
Complex complex_value(bool=false) const
Definition ov-range.cc:265
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
@ LS_DOUBLE
Definition data-conv.h:93
void warning_with_id(const char *id, const char *fmt,...)
Definition error.cc:1093
void error(const char *fmt,...)
Definition error.cc:1003
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()
Definition errwarn.cc:365
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition errwarn.cc:344
intNDArray< octave_int16 > int16NDArray
intNDArray< octave_int32 > int32NDArray
intNDArray< octave_int64 > int64NDArray
intNDArray< octave_int8 > int8NDArray
Definition int8NDArray.h:36
float lo_ieee_float_nan_value()
Definition lo-ieee.cc:116
bool hdf5_types_compatible(octave_hdf5_id t1, octave_hdf5_id t2)
Definition ls-hdf5.cc:274
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:1210
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:74
#define DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition ov-base.h:243
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition ov-base.h:246
bool xsave_ascii(std::ostream &os, const octave::range< T > &r, const bool with_reverse)
Definition ov-range.cc:516
bool xsave_binary(std::ostream &os, bool, const octave::range< T > &r, const bool with_reverse)
Definition ov-range.cc:622
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:658
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:768
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:857
bool xload_ascii(std::istream &is, octave::range< T > &r, const bool with_reverse)
Definition ov-range.cc:563
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
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
intNDArray< octave_uint32 > uint32NDArray
intNDArray< octave_uint64 > uint64NDArray
intNDArray< octave_uint8 > uint8NDArray
F77_RET_T len
Definition xerbla.cc:61