GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-legacy-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 "lo-ieee.h"
35 #include "lo-utils.h"
36 
37 #include "variables.h"
38 #include "error.h"
39 #include "ovl.h"
40 #include "oct-hdf5.h"
41 #include "ov-legacy-range.h"
42 #include "ov-range.h"
43 #include "ov-re-mat.h"
44 #include "ov-scalar.h"
45 #include "pr-output.h"
46 
47 #include "byte-swap.h"
48 #include "ls-ascii-helper.h"
49 #include "ls-hdf5.h"
50 #include "ls-utils.h"
51 
52 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
53 # pragma GCC diagnostic push
54 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
55 #endif
56 
58 
60  : octave_base_value (), range () { }
61 
63  : octave_base_value (), range (r)
64 {
65  if (range.numel () < 0 && range.numel () != -2)
66  error ("invalid range");
67 }
68 
69 static octave_base_value *
71 {
72  const octave_legacy_range& v = dynamic_cast<const octave_legacy_range&> (a);
73 
74  return new octave_matrix (v.matrix_value ());
75 }
76 
79 {
82 }
83 
86 {
87  octave_base_value *retval = nullptr;
88 
89  switch (range.numel ())
90  {
91  case 1:
92  retval = new octave_scalar (range.base ());
93  break;
94 
95  case 0:
96  retval = new octave_matrix (Matrix (1, 0));
97  break;
98 
99  case -2:
100  retval = new octave_matrix (range.matrix_value ());
101  break;
102 
103  default:
104  {
105  if (range.increment () == 0)
106  retval = new octave_matrix (range.matrix_value ());
107  else
108  retval = new octave_range
109  (octave::range<double> (range.base (), range.increment (),
110  range.limit (), range.numel ()));
111  }
112  break;
113  }
114 
115  return retval;
116 }
117 
118 // Skip white space and comments on stream IS.
119 
120 static void
121 skip_comments (std::istream& is)
122 {
123  char c = '\0';
124  while (is.get (c))
125  {
126  if (c == ' ' || c == '\t' || c == '\n')
127  ; // Skip whitespace on way to beginning of next line.
128  else
129  break;
130  }
131 
132  octave::skip_until_newline (is, false);
133 }
134 
135 bool
137 {
138  // # base, limit, range comment added by save ().
139  skip_comments (is);
140 
141  double base, limit, inc;
142  is >> base >> limit >> inc;
143 
144  if (! is)
145  error ("load: failed to load range constant");
146 
147  if (inc != 0)
148  range = Range (base, limit, inc);
149  else
150  range = Range (base, inc, static_cast<octave_idx_type> (limit));
151 
152  return true;
153 }
154 
155 bool
156 octave_legacy_range::load_binary (std::istream& is, bool swap,
158 {
159  char tmp;
160  if (! is.read (reinterpret_cast<char *> (&tmp), 1))
161  return false;
162  double bas, lim, inc;
163  if (! is.read (reinterpret_cast<char *> (&bas), 8))
164  return false;
165  if (swap)
166  swap_bytes<8> (&bas);
167  if (! is.read (reinterpret_cast<char *> (&lim), 8))
168  return false;
169  if (swap)
170  swap_bytes<8> (&lim);
171  if (! is.read (reinterpret_cast<char *> (&inc), 8))
172  return false;
173  if (swap)
174  swap_bytes<8> (&inc);
175  if (inc != 0)
176  range = Range (bas, lim, inc);
177  else
178  range = Range (bas, inc, static_cast<octave_idx_type> (lim));
179 
180  return true;
181 }
182 
183 #if defined (HAVE_HDF5)
184 
185 // The following subroutines creates an HDF5 representation of the way
186 // we will store Octave range types (triplets of floating-point numbers).
187 // NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
188 // H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
189 // conversions are handled automatically by HDF5.
190 
191 static hid_t
192 hdf5_make_range_type (hid_t num_type)
193 {
194  hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3);
195 
196  H5Tinsert (type_id, "base", 0 * sizeof (double), num_type);
197  H5Tinsert (type_id, "limit", 1 * sizeof (double), num_type);
198  H5Tinsert (type_id, "increment", 2 * sizeof (double), num_type);
199 
200  return type_id;
201 }
202 
203 #endif
204 
205 bool
207 {
208  bool retval = false;
209 
210 #if defined (HAVE_HDF5)
211 
212 #if defined (HAVE_HDF5_18)
213  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
214 #else
215  hid_t data_hid = H5Dopen (loc_id, name);
216 #endif
217  hid_t type_hid = H5Dget_type (data_hid);
218 
219  hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE);
220 
221  if (! hdf5_types_compatible (type_hid, range_type))
222  {
223  H5Tclose (range_type);
224  H5Dclose (data_hid);
225  return false;
226  }
227 
228  hid_t space_hid = H5Dget_space (data_hid);
229  hsize_t rank = H5Sget_simple_extent_ndims (space_hid);
230 
231  if (rank != 0)
232  {
233  H5Tclose (range_type);
234  H5Sclose (space_hid);
235  H5Dclose (data_hid);
236  return false;
237  }
238 
239  double rangevals[3];
240  if (H5Dread (data_hid, range_type, octave_H5S_ALL, octave_H5S_ALL,
241  octave_H5P_DEFAULT, rangevals)
242  >= 0)
243  {
244  retval = true;
245  octave_idx_type nel;
246  if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX,
247  "OCTAVE_RANGE_NELEM", &nel))
248  range = Range (rangevals[0], rangevals[2], nel);
249  else
250  {
251  if (rangevals[2] != 0)
252  range = Range (rangevals[0], rangevals[1], rangevals[2]);
253  else
254  range = Range (rangevals[0], rangevals[2],
255  static_cast<octave_idx_type> (rangevals[1]));
256  }
257  }
258 
259  H5Tclose (range_type);
260  H5Sclose (space_hid);
261  H5Dclose (data_hid);
262 
263 #else
264  octave_unused_parameter (loc_id);
265  octave_unused_parameter (name);
266 
267  warn_load ("hdf5");
268 #endif
269 
270  return retval;
271 }
272 
273 #if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
274 # pragma GCC diagnostic pop
275 #endif
void swap_bytes< 8 >(void *ptr)
Definition: byte-swap.h:71
Definition: dMatrix.h:42
Definition: Range.h:401
double increment(void) const
Definition: Range.h:466
double base(void) const
Definition: Range.h:463
OCTAVE_API Matrix matrix_value(void) const
Definition: Range.cc:505
double limit(void) const
Definition: Range.h:464
octave_idx_type numel(void) const
Definition: Range.h:477
OCTINTERP_API void warn_load(const char *type) const
Definition: ov-base.cc:1157
virtual Matrix matrix_value(bool=false) const
Definition: ov-base.cc:542
bool load_ascii(std::istream &is)
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
type_conv_info numeric_conversion_function(void) const
octave_base_value * try_narrowing_conversion(void)
static int static_type_id(void)
Definition: ov-re-mat.h:249
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5S_ALL
void error(const char *fmt,...)
Definition: error.cc:979
void skip_until_newline(std::istream &is, bool keep_newline)
bool hdf5_get_scalar_attr(octave_hdf5_id loc_id, octave_hdf5_id type_id, const char *attr_name, void *buf)
Definition: ls-hdf5.cc:347
bool hdf5_types_compatible(octave_hdf5_id t1, octave_hdf5_id t2)
Definition: ls-hdf5.cc:269
float_format
Definition: mach-info.h:38
T * r
Definition: mx-inlines.cc:773
int64_t octave_hdf5_id
#define H5T_NATIVE_IDX
Definition: oct-hdf5.h:42
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:229
static octave_base_value * default_numeric_conversion_function(const octave_base_value &a)
static void skip_comments(std::istream &is)
static hid_t hdf5_make_range_type(hid_t num_type)
octave_double_range octave_range
Definition: ov-range.h:620
class OCTAVE_API range
Definition: range-fwd.h:33