h5py/1114.patch

153 lines
5.6 KiB
Diff

diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index 7d1d7a1..30746f9 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -231,6 +231,14 @@ IEEE_F128LE = IEEE_F128BE.copy()
IEEE_F128LE.set_order(H5T_ORDER_LE)
IEEE_F128LE.lock()
+LDOUBLE_LE = NATIVE_LDOUBLE.copy()
+LDOUBLE_LE.set_order(H5T_ORDER_LE)
+LDOUBLE_LE.lock()
+
+LDOUBLE_BE = NATIVE_LDOUBLE.copy()
+LDOUBLE_BE.set_order(H5T_ORDER_BE)
+LDOUBLE_BE.lock()
+
# Custom Python object pointer type
cdef hid_t H5PY_OBJ = H5Tcreate(H5T_OPAQUE, sizeof(PyObject*))
H5Tset_tag(H5PY_OBJ, "PYTHON:OBJECT")
@@ -294,6 +302,29 @@ available_ftypes = _DeprecatedMapping(available_ftypes,
"h5py. See https://github.com/h5py/h5py/pull/926 for details.")
)
+
+cdef (int, int, int) _correct_float_info(ftype_, finfo):
+ nmant = finfo.nmant
+ maxexp = finfo.maxexp
+ minexp = finfo.minexp
+ # workaround for numpy's buggy finfo on float128 on ppc64 archs
+ if ftype_ == np.longdouble and MACHINE == 'ppc64':
+ # values reported by hdf5
+ nmant = 116
+ maxexp = 1024
+ minexp = -1022
+ elif ftype_ == np.longdouble and MACHINE == 'ppc64le':
+ # values reported by hdf5
+ nmant = 52
+ maxexp = 1024
+ minexp = -1022
+ elif nmant == 63 and finfo.nexp == 15:
+ # This is an 80-bit float, correct mantissa size
+ nmant += 1
+
+ return nmant, maxexp, minexp
+
+
# === General datatype operations =============================================
@with_phil
@@ -1025,23 +1056,7 @@ cdef class TypeFloatID(TypeAtomicID):
# Handle non-standard exponent and mantissa sizes.
for ftype_, finfo, size in _available_ftypes:
- nmant = finfo.nmant
- maxexp = finfo.maxexp
- minexp = finfo.minexp
- # workaround for numpy's buggy finfo on float128 on ppc64 archs
- if ftype_ == np.longdouble and MACHINE == 'ppc64':
- # values reported by hdf5
- nmant = 116
- maxexp = 1024
- minexp = -1022
- elif ftype_ == np.longdouble and MACHINE == 'ppc64le':
- # values reported by hdf5
- nmant = 52
- maxexp = 1024
- minexp = -1022
- elif nmant == 63 and finfo.nexp == 15:
- # This is an 80-bit float, correct mantissa size
- nmant += 1
+ nmant, maxexp, minexp = _correct_float_info(ftype_, finfo)
if (size >= self.get_size() and m_size <= nmant and
(2**e_size - e_bias - 1) <= maxexp and (1 - e_bias) >= minexp):
new_dtype = np.dtype(ftype_).newbyteorder(order)
@@ -1353,29 +1368,30 @@ cdef class TypeEnumID(TypeCompositeID):
def _get_float_dtype_to_hdf5():
float_le = {}
float_be = {}
- h5_be_list = [IEEE_F16BE, IEEE_F32BE, IEEE_F64BE, IEEE_F128BE]
- h5_le_list = [IEEE_F16LE, IEEE_F32LE, IEEE_F64LE, IEEE_F128LE]
+ h5_be_list = [IEEE_F16BE, IEEE_F32BE, IEEE_F64BE, IEEE_F128BE,
+ LDOUBLE_BE]
+ h5_le_list = [IEEE_F16LE, IEEE_F32LE, IEEE_F64LE, IEEE_F128LE,
+ LDOUBLE_LE]
for ftype_, finfo, size in _available_ftypes:
+ nmant, maxexp, minexp = _correct_float_info(ftype_, finfo)
for h5type in h5_be_list:
spos, epos, esize, mpos, msize = h5type.get_fields()
ebias = h5type.get_ebias()
- if (finfo.iexp == esize and finfo.nmant == msize and
- (finfo.maxexp - 1) == ebias
+ if (finfo.iexp == esize and nmant == msize and
+ (maxexp - 1) == ebias
):
float_be[ftype_] = h5type
for h5type in h5_le_list:
spos, epos, esize, mpos, msize = h5type.get_fields()
ebias = h5type.get_ebias()
- if (finfo.iexp == esize and finfo.nmant == msize and
- (finfo.maxexp - 1) == ebias
+ if (finfo.iexp == esize and nmant == msize and
+ (maxexp - 1) == ebias
):
float_le[ftype_] = h5type
if ORDER_NATIVE == H5T_ORDER_LE:
float_nt = dict(float_le)
else:
float_nt = dict(float_be)
- if np.longdouble not in float_nt:
- float_nt[np.longdouble] = NATIVE_LDOUBLE
return float_le, float_be, float_nt
cdef dict _float_le
diff --git a/h5py/tests/hl/test_datatype.py b/h5py/tests/hl/test_datatype.py
index 51bdcb2..e718285 100644
--- a/h5py/tests/hl/test_datatype.py
+++ b/h5py/tests/hl/test_datatype.py
@@ -179,7 +179,6 @@ class TestOffsets(TestCase):
with h5py.File(fname, 'r') as f:
self.assertArrayEqual(f['data'], data)
-
def test_out_of_order_offsets(self):
dt = np.dtype({
'names' : ['f1', 'f2', 'f3'],
@@ -198,3 +197,26 @@ class TestOffsets(TestCase):
with h5py.File(fname, 'r') as fd:
self.assertArrayEqual(fd['data'], data)
+
+ def test_float_round_tripping(self):
+ dtypes = set(f for f in np.typeDict.values()
+ if (np.issubdtype(f, np.floating) or
+ np.issubdtype(f, np.complexfloating))
+ )
+
+ dtype_dset_map = {str(j): d
+ for j, d in enumerate(dtypes)}
+
+ fname = self.mktemp()
+
+ with h5py.File(fname, 'w') as f:
+ for n, d in dtype_dset_map.items():
+ data = np.arange(10,
+ dtype=d)
+
+ f.create_dataset(n, data=data)
+
+ with h5py.File(fname, 'r') as f:
+ for n, d in dtype_dset_map.items():
+ ldata = f[n][:]
+ self.assertEqual(ldata.dtype, d)