Skip to content

Commit 115cea2

Browse files
author
Andy Ferris
committed
Added support for Float16
* Saving and loading Float16 values is now supported * Float16 is no longer an "opaque" type. * Added some more wrapper functions relating to setting and getting floating-point datatype fields * `H5T_FLOAT16` needs to be created dynamically. Attempts at making the list of natively supported types dynamically modifiable by the user is blocked by the fact that `HDF5BitsKind` is used for dispatch everywhere... * Unit test
1 parent d2eddaf commit 115cea2

File tree

2 files changed

+65
-11
lines changed

2 files changed

+65
-11
lines changed

src/plain.jl

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,16 @@ const H5T_NATIVE_DOUBLE = read_const(:H5T_NATIVE_DOUBLE_g)
226226
# Library versions
227227
const H5F_LIBVER_EARLIEST = 0
228228
const H5F_LIBVER_LATEST = 1
229+
# Constructed types (occurs at runtime)
230+
function make_float16()
231+
FLOAT16 = h5t_copy(H5T_NATIVE_FLOAT)
232+
h5t_set_fields(FLOAT16, 15, 10, 5, 0, 10)
233+
h5t_set_size(FLOAT16, 2)
234+
h5t_set_ebias(FLOAT16, 15)
235+
h5t_lock(FLOAT16)
236+
return FLOAT16
237+
end
238+
# const H5T_FLOAT16 = make_float16() (in `__init__()`)
229239

230240
## Conversion between Julia types and HDF5 atomic types
231241
hdf5_type_id(::Type{Int8}) = H5T_NATIVE_INT8
@@ -236,10 +246,11 @@ hdf5_type_id(::Type{Int32}) = H5T_NATIVE_INT32
236246
hdf5_type_id(::Type{UInt32}) = H5T_NATIVE_UINT32
237247
hdf5_type_id(::Type{Int64}) = H5T_NATIVE_INT64
238248
hdf5_type_id(::Type{UInt64}) = H5T_NATIVE_UINT64
249+
#hdf5_type_id(::Type{Float16}) = H5T_FLOAT16 (in `__init__()`)
239250
hdf5_type_id(::Type{Float32}) = H5T_NATIVE_FLOAT
240251
hdf5_type_id(::Type{Float64}) = H5T_NATIVE_DOUBLE
241252

242-
@compat typealias HDF5BitsKind Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64}
253+
@compat typealias HDF5BitsKind Union{Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float16, Float32, Float64}
243254
@compat typealias BitsKindOrString Union{HDF5BitsKind, String}
244255

245256
# It's not safe to use particular id codes because these can change, so we use characteristics of the type.
@@ -252,6 +263,7 @@ const hdf5_type_map = @compat Dict(
252263
(H5T_INTEGER, H5T_SGN_NONE, convert(Csize_t, 2)) => UInt16,
253264
(H5T_INTEGER, H5T_SGN_NONE, convert(Csize_t, 4)) => UInt32,
254265
(H5T_INTEGER, H5T_SGN_NONE, convert(Csize_t, 8)) => UInt64,
266+
(H5T_FLOAT, nothing, convert(Csize_t, 2)) => Float16,
255267
(H5T_FLOAT, nothing, convert(Csize_t, 4)) => Float32,
256268
(H5T_FLOAT, nothing, convert(Csize_t, 8)) => Float64,
257269
)
@@ -1797,17 +1809,30 @@ function hdf5_to_julia_eltype(objtype)
17971809
error("character set ", cset, " not recognized")
17981810
end
17991811
elseif class_id == H5T_INTEGER || class_id == H5T_FLOAT
1800-
native_type = h5t_get_native_type(objtype.id)
1801-
try
1802-
native_size = h5t_get_size(native_type)
1803-
if class_id == H5T_INTEGER
1804-
is_signed = h5t_get_sign(native_type)
1805-
else
1806-
is_signed = nothing
1812+
# First look in the type last for a match
1813+
# otherwise fall back to a native datatype
1814+
# Allows for users to dynamically add types to the typemap
1815+
t_size = h5t_get_size(objtype)
1816+
if class_id == H5T_INTEGER
1817+
is_signed = h5t_get_sign(objtype)
1818+
else
1819+
is_signed = nothing # probably should include the mantissa size, etc...
1820+
end
1821+
if haskey(hdf5_type_map, (class_id, is_signed, t_size))
1822+
T = hdf5_type_map[(class_id, is_signed, t_size)]
1823+
else
1824+
native_type = h5t_get_native_type(objtype.id)
1825+
try
1826+
native_size = h5t_get_size(native_type)
1827+
if class_id == H5T_INTEGER
1828+
is_signed = h5t_get_sign(native_type)
1829+
else
1830+
is_signed = nothing
1831+
end
1832+
T = hdf5_type_map[(class_id, is_signed, native_size)]
1833+
finally
1834+
h5t_close(native_type)
18071835
end
1808-
T = hdf5_type_map[(class_id, is_signed, native_size)]
1809-
finally
1810-
h5t_close(native_type)
18111836
end
18121837
elseif class_id == H5T_ENUM
18131838
super_type = h5t_get_super(objtype.id)
@@ -1990,7 +2015,10 @@ for (jlname, h5name, outtype, argtypes, argsyms, msg) in
19902015
(:h5s_select_hyperslab, :H5Sselect_hyperslab, Herr, (Hid, Cint, Ptr{Hsize}, Ptr{Hsize}, Ptr{Hsize}, Ptr{Hsize}), (:dspace_id, :seloper, :start, :stride, :count, :block), "Error selecting hyperslab"),
19912016
(:h5t_commit, :H5Tcommit2, Herr, (Hid, Ptr{UInt8}, Hid, Hid, Hid, Hid), (:loc_id, :name, :dtype_id, :lcpl_id, :tcpl_id, :tapl_id), "Error committing type"),
19922017
(:h5t_close, :H5Tclose, Herr, (Hid,), (:dtype_id,), "Error closing datatype"),
2018+
(:h5t_lock, :H5Tlock, Herr, (Hid,), (:dtype_id,), "Error locking datatype"),
19932019
(:h5t_set_cset, :H5Tset_cset, Herr, (Hid, Cint), (:dtype_id, :cset), "Error setting character set in datatype"),
2020+
(:h5t_set_ebias, :H5Tset_ebias, Herr, (Hid, Csize_t), (:dtype_id, :ebias), "Error setting exponential bias of floating-point type"),
2021+
(:h5t_set_fields, :H5Tset_fields, Herr, (Hid, Csize_t, Csize_t, Csize_t, Csize_t, Csize_t), (:dtype_id, :spos, :epos, :esize, :mpos, :msize), "Error setting floating-point type fields"),
19942022
(:h5t_set_size, :H5Tset_size, Herr, (Hid, Csize_t), (:dtype_id, :sz), "Error setting size of datatype"),
19952023
)
19962024

@@ -2076,6 +2104,7 @@ for (jlname, h5name, outtype, argtypes, argsyms, ex_error) in
20762104
(:h5t_get_array_ndims, :H5Tget_array_ndims, Cint, (Hid,), (:dtype_id,), :(error("Error getting ndims of array"))),
20772105
(:h5t_get_class, :H5Tget_class, Cint, (Hid,), (:dtype_id,), :(error("Error getting class"))),
20782106
(:h5t_get_cset, :H5Tget_cset, Cint, (Hid,), (:dtype_id,), :(error("Error getting character set encoding"))),
2107+
(:h5t_get_ebias, :H5Tget_ebias, Csize_t, (Hid,), (:dtype_id,), :(error("Error getting exponential bias"))),
20792108
(:h5t_get_member_class, :H5Tget_member_class, Cint, (Hid, Cuint), (:dtype_id, :index), :(error("Error getting class of compound datatype member #", index))),
20802109
(:h5t_get_member_index, :H5Tget_member_index, Cint, (Hid, Ptr{UInt8}), (:dtype_id, :membername), :(error("Error getting index of compound datatype member \"", membername, "\""))),
20812110
(:h5t_get_member_offset, :H5Tget_member_offset, Csize_t, (Hid, Cuint), (:dtype_id, :index), :(error("Error getting offset of compound datatype member #", index))),
@@ -2166,6 +2195,21 @@ function h5s_get_simple_extent_dims(space_id::Hid)
21662195
h5s_get_simple_extent_dims(space_id, dims, maxdims)
21672196
return tuple(reverse!(dims)...), tuple(reverse!(maxdims)...)
21682197
end
2198+
function h5t_get_fields(type_id::Hid)
2199+
spos = Ref{Csize_t}()
2200+
epos = Ref{Csize_t}()
2201+
esize = Ref{Csize_t}()
2202+
mpos = Ref{Csize_t}()
2203+
msize = Ref{Csize_t}()
2204+
herr = ccall((:H5Tget_fields, libhdf5),
2205+
Herr,
2206+
(Hid, Ptr{Csize_t}, Ptr{Csize_t}, Ptr{Csize_t}, Ptr{Csize_t}, Ptr{Csize_t}),
2207+
type_id, spos, epos, esize, mpos, msize)
2208+
if herr < 0
2209+
error("Error getting fields of floating-point datatype")
2210+
end
2211+
return (spos[], epos[], esize[], mpos[], msize[])
2212+
end
21692213
function h5t_get_member_name(type_id::Hid, index::Integer)
21702214
pn = ccall((:H5Tget_member_name, libhdf5),
21712215
Ptr{UInt8},
@@ -2399,6 +2443,10 @@ function __init__()
23992443
UTF8_ATTRIBUTE_PROPERTIES[] = p_create(H5P_ATTRIBUTE_CREATE)
24002444
h5p_set_char_encoding(UTF8_ATTRIBUTE_PROPERTIES[].id, H5T_CSET_UTF8)
24012445

2446+
# Set up Float16 (must occur at runtime)
2447+
eval(:(const H5T_FLOAT16 = make_float16()))
2448+
eval(:(hdf5_type_id(::Type{Float16}) = H5T_FLOAT16))
2449+
24022450
rehash!(hdf5_type_map, length(hdf5_type_map.keys))
24032451
rehash!(hdf5_prop_get_set, length(hdf5_prop_get_set.keys))
24042452

test/plain.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,9 @@ h5open(fn, "r", "libver_bounds",
314314
intarray = read(fid, "intarray")
315315
@test intarray == [1,2,3]
316316
end
317+
318+
arr_float16 = Float16[1.0, 0.25, 0.5, 8.0]
319+
h5write("test_float16.h5", "x", arr_float16)
320+
arr_float16_2 = h5read("test_float16.h5", "x")
321+
@test isa(arr_float16_2, Vector{Float16})
322+
@test arr_float16_2 == arr_float16

0 commit comments

Comments
 (0)