# HG changeset patch # User David Bateman # Date 1288711650 -3600 # Node ID 2271261f088ae8df22b08d6d3ad3d9d7cede3423 # Parent c0a95a5c6d2505c2be25774a0356c735c675c1a1 Address precision issue in ranges saved to HDF5 files diff -r c0a95a5c6d25 -r 2271261f088a src/ChangeLog --- a/src/ChangeLog Tue Nov 02 00:47:31 2010 +0100 +++ b/src/ChangeLog Tue Nov 02 16:27:30 2010 +0100 @@ -1,3 +1,22 @@ +2010-11-02 David Bateman + + * ls-hdf5.cc (bool hdf5_get_scalar_attr (hid_t, hid_t, + const char *, void *), herr_t hdf5_add_scalar_attr + (hid_t, hid_t, const char *, void *)): New functions. + (herr_t hdf5_add_scalar_attr (hid_t, const char *)): Remove static + definition to make this function visible externally. + * ls-hdf5.h (extern OCTINTERP_API bool hdf5_check_attr (hid_t, + const char *), extern OCTINTERP_API bool hdf5_get_scalar_attr + (hid_t, hid_t, const char *, void *buf), extern OCTINTERP_API herr_t + hdf5_add_attr (hid_t, const char *), extern OCTINTERP_API herr_t + hdf5_add_scalar_attr (hid_t, hid_t, const char *, void *)): Function + declarations. + * ov-range.cc (bool octave_range::save_hdf5 (hid_t, const char *, + bool)): Save the number of elements in the range as an HDF5 attribute. + (bool octave_range::load_hdf5 (hid_t, const char *)): If an HDF5 + attribute containing the number of elements exists use it to ensure + the correct number of elements in the range. + 2010-11-01 David Bateman * gl-render.cc (void opengl_renderer::draw_patch (const diff -r c0a95a5c6d25 -r 2271261f088a src/ls-hdf5.cc --- a/src/ls-hdf5.cc Tue Nov 02 00:47:31 2010 +0100 +++ b/src/ls-hdf5.cc Tue Nov 02 16:27:30 2010 +0100 @@ -156,7 +156,7 @@ if (attr_id >= 0) { // successful - retval = 1; + retval = true; H5Aclose (attr_id); } @@ -169,6 +169,55 @@ return retval; } +bool +hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id, + const char *attr_name, void *buf) +{ + bool retval = false; + + // we have to pull some shenanigans here to make sure + // HDF5 doesn't print out all sorts of error messages if we + // call H5Aopen for a non-existing attribute + + H5E_auto_t err_func; + void *err_func_data; + + // turn off error reporting temporarily, but save the error + // reporting function: + +#if HAVE_HDF5_18 + H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data); + H5Eset_auto (H5E_DEFAULT, 0, 0); +#else + H5Eget_auto (&err_func, &err_func_data); + H5Eset_auto (0, 0); +#endif + + hid_t attr_id = H5Aopen_name (loc_id, attr_name); + + if (attr_id >= 0) + { + hid_t space_id = H5Aget_space (attr_id); + + hsize_t rank = H5Sget_simple_extent_ndims (space_id); + + if (rank == 0) + retval = H5Aread (attr_id, type_id, buf) >= 0; + H5Aclose (attr_id); + } + + // restore error reporting: +#if HAVE_HDF5_18 + H5Eset_auto (H5E_DEFAULT, err_func, err_func_data); +#else + H5Eset_auto (err_func, err_func_data); +#endif + return retval; +} + + + + // The following subroutines creates an HDF5 representations of the way // we will store Octave complex types (pairs of floating-point numbers). // NUM_TYPE is the HDF5 numeric type to use for storage (e.g. @@ -576,7 +625,7 @@ // Add an attribute named attr_name to loc_id (a simple scalar // attribute with value 1). Return value is >= 0 on success. -static herr_t +herr_t hdf5_add_attr (hid_t loc_id, const char *attr_name) { herr_t retval = 0; @@ -611,6 +660,46 @@ return retval; } +herr_t +hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id, + const char *attr_name, void *buf) +{ + herr_t retval = 0; + + hid_t as_id = H5Screate (H5S_SCALAR); + + if (as_id >= 0) + { +#if HAVE_HDF5_18 + hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR, + as_id, H5P_DEFAULT, H5P_DEFAULT); +#else + hid_t a_id = H5Acreate (loc_id, attr_name, + H5T_NATIVE_UCHAR, as_id, H5P_DEFAULT); +#endif + if (a_id >= 0) + { + retval = H5Awrite (a_id, type_id, buf); + + H5Aclose (a_id); + } + else + retval = a_id; + + H5Sclose (as_id); + } + else + retval = as_id; + + return retval; +} + + + + + + + // Save an empty matrix, if needed. Returns // > 0 Saved empty matrix // = 0 Not an empty matrix; did nothing diff -r c0a95a5c6d25 -r 2271261f088a src/ls-hdf5.h --- a/src/ls-hdf5.h Tue Nov 02 00:47:31 2010 +0100 +++ b/src/ls-hdf5.h Tue Nov 02 16:27:30 2010 +0100 @@ -186,6 +186,21 @@ const std::string& name, const std::string& doc, bool mark_as_global, bool save_as_floats); +extern OCTINTERP_API bool +hdf5_check_attr (hid_t loc_id, const char *attr_name); + +extern OCTINTERP_API bool +hdf5_get_scalar_attr (hid_t loc_id, hid_t type_id, const char *attr_name, + void *buf); + +extern OCTINTERP_API herr_t +hdf5_add_attr (hid_t loc_id, const char *attr_name); + + +extern OCTINTERP_API herr_t +hdf5_add_scalar_attr (hid_t loc_id, hid_t type_id, + const char *attr_name, void *buf); + #ifdef IDX_TYPE_LONG #define H5T_NATIVE_IDX H5T_NATIVE_LONG #else diff -r c0a95a5c6d25 -r 2271261f088a src/ov-range.cc --- a/src/ov-range.cc Tue Nov 02 00:47:31 2010 +0100 +++ b/src/ov-range.cc Tue Nov 02 16:27:30 2010 +0100 @@ -548,8 +548,15 @@ range_vals[1] = r.inc () != 0 ? r.limit () : r.nelem (); range_vals[2] = r.inc (); - retval = H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT, - range_vals) >= 0; + if (H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, H5P_DEFAULT, + range_vals) >= 0) + { + octave_idx_type nel = r.nelem (); + retval = hdf5_add_scalar_attr (data_hid, H5T_NATIVE_IDX, + "OCTAVE_RANGE_NELEM", &nel) >= 0; + } + else + retval = false; H5Dclose (data_hid); H5Tclose (type_hid); @@ -595,11 +602,18 @@ rangevals) >= 0) { retval = true; - if (rangevals[2] != 0) - range = Range (rangevals[0], rangevals[1], rangevals[2]); + octave_idx_type nel; + if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX, + "OCTAVE_RANGE_NELEM", &nel)) + range = Range (rangevals[0], rangevals[2], nel); else - range = Range (rangevals[0], rangevals[2], - static_cast (rangevals[1])); + { + if (rangevals[2] != 0) + range = Range (rangevals[0], rangevals[1], rangevals[2]); + else + range = Range (rangevals[0], rangevals[2], + static_cast (rangevals[1])); + } } H5Tclose (range_type);