Skip to content

Commit 26046fb

Browse files
authored
Merge pull request #246 from aldanor/feature/f16
Float16 support
2 parents d1fc2c4 + 0e5aeda commit 26046fb

19 files changed

+169
-30
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
- name: Document workspace
4747
env:
4848
RUSTDOCFLAGS: "--cfg docsrs"
49-
run: cargo doc --features static,zlib,blosc,lzf
49+
run: cargo doc --features static,zlib,blosc,lzf,f16,complex
5050

5151
brew:
5252
name: brew
@@ -147,8 +147,8 @@ jobs:
147147
with: {toolchain: '${{matrix.rust}}'}
148148
- name: Build and test all crates
149149
run: cargo test --workspace -v --features hdf5-sys/static,hdf5-sys/zlib --exclude hdf5-derive
150-
- name: Build and test with filters
151-
run: cargo test --workspace -v --features hdf5-sys/static,hdf5-sys/zlib,lzf,blosc --exclude hdf5-derive
150+
- name: Build and test with filters and other features
151+
run: cargo test --workspace -v --features hdf5-sys/static,hdf5-sys/zlib,lzf,blosc,f16,complex --exclude hdf5-derive
152152
if: matrix.rust != 'stable-gnu'
153153
- name: Run examples
154154
run: |
@@ -276,7 +276,7 @@ jobs:
276276
with: {toolchain: 1.64}
277277
- name: Build and test all crates
278278
run:
279-
cargo test --workspace -vv --features=hdf5-sys/static --exclude=hdf5-derive
279+
cargo test --workspace -vv --features=hdf5-sys/static,hdf5-sys/zlib --exclude=hdf5-derive
280280

281281
wine:
282282
name: wine

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
- Add a `ByteReader` which implements `std::io::{Read, Seek}` for 1D `u8`
1010
datasets. Usage via `Dataset::as_byte_reader()`.
1111
- Add `chunk_visit` to visit all chunks in a dataset.
12-
- Implement `H5Type` for `num_complex::Complex`.
12+
- Add support for float16 values (`half::f16`), enabled via "f16" feature.
13+
- Add support for complex numbers (`num_complex::Complex`), enabled via "complex".
1314
- Adding feature `static` for the `hdf5` crate which downloads and builds a bundled HDF5.
1415

1516
### Changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ edition = "2021"
1515
[workspace.dependencies]
1616
# external
1717
cfg-if = "1.0"
18+
half = { version = "2.2", default-features = false }
1819
libc = "0.2"
1920
libz-sys = { version = "1.1", default-features = false }
2021
mpi-sys = "0.2"
22+
num-complex = { version = "0.4", default-features = false }
2123
regex = "1.8"
2224
# internal
2325
hdf5-derive = { version = "0.8.1", path = "hdf5-derive" } # !V

hdf5-sys/build.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ pub struct Header {
175175
pub have_direct: bool,
176176
pub have_parallel: bool,
177177
pub have_threadsafe: bool,
178-
pub have_zlib: bool,
179178
pub have_no_deprecated: bool,
179+
pub have_filter_deflate: bool,
180180
pub version: Version,
181181
}
182182

@@ -203,7 +203,7 @@ impl Header {
203203
} else if name == "H5_HAVE_THREADSAFE" {
204204
hdr.have_threadsafe = value > 0;
205205
} else if name == "H5_HAVE_FILTER_DEFLATE" {
206-
hdr.have_zlib = value > 0;
206+
hdr.have_filter_deflate = value > 0;
207207
} else if name == "H5_NO_DEPRECATED_SYMBOLS" {
208208
hdr.have_no_deprecated = value > 0;
209209
}
@@ -680,14 +680,18 @@ impl Config {
680680
println!("cargo:rustc-cfg=feature=\"have-threadsafe\"");
681681
println!("cargo:have_threadsafe=1");
682682
}
683+
if self.header.have_filter_deflate {
684+
println!("cargo:rustc-cfg=feature=\"have-filter-deflate\"");
685+
println!("cargo:have_filter_deflate=1");
686+
}
683687
}
684688

685689
fn check_against_features_required(&self) {
686690
let h = &self.header;
687691
for (flag, feature, native) in [
688692
(!h.have_no_deprecated, "deprecated", "HDF5_ENABLE_DEPRECATED_SYMBOLS"),
689693
(h.have_threadsafe, "threadsafe", "HDF5_ENABLE_THREADSAFE"),
690-
(h.have_zlib, "zlib", "HDF5_ENABLE_Z_LIB_SUPPORT"),
694+
(h.have_filter_deflate, "zlib", "HDF5_ENABLE_Z_LIB_SUPPORT"),
691695
] {
692696
if feature_enabled(&feature.to_ascii_uppercase()) {
693697
assert!(

hdf5-types/Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@ edition.workspace = true
1515

1616
[features]
1717
h5-alloc = []
18-
complex = ["num-complex"]
18+
complex = ["dep:num-complex"]
19+
f16 = ["dep:half"]
1920

2021
[dependencies]
2122
ascii = "1.1"
2223
cfg-if = { workspace = true }
2324
hdf5-sys = { workspace = true }
2425
libc = { workspace = true }
25-
num-complex = { version = "0.4", optional = true, default-features = false }
26+
num-complex = { workspace = true, optional = true }
27+
half = { workspace = true, optional = true }
2628

2729
[dev-dependencies]
2830
quickcheck = { version = "1.0", default-features = false }
2931
unindent = "0.2"
32+
33+
[package.metadata.docs.rs]
34+
features = ["f16", "complex"]

hdf5-types/src/dyn_value.rs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,76 @@ impl From<DynInteger> for DynValue<'_> {
115115
}
116116

117117
#[derive(Copy, Clone, PartialEq)]
118-
pub enum DynScalar {
119-
Integer(DynInteger),
118+
pub enum DynFloat {
119+
#[cfg(feature = "f16")]
120+
Float16(::half::f16),
120121
Float32(f32),
121122
Float64(f64),
123+
}
124+
125+
impl DynFloat {
126+
pub(self) fn read(buf: &[u8], size: FloatSize) -> Self {
127+
match size {
128+
#[cfg(feature = "f16")]
129+
FloatSize::U2 => Self::Float16(read_raw(buf)),
130+
FloatSize::U4 => Self::Float32(read_raw(buf)),
131+
FloatSize::U8 => Self::Float64(read_raw(buf)),
132+
}
133+
}
134+
}
135+
136+
unsafe impl DynClone for DynFloat {
137+
fn dyn_clone(&mut self, out: &mut [u8]) {
138+
match self {
139+
#[cfg(feature = "f16")]
140+
Self::Float16(x) => write_raw(out, *x),
141+
Self::Float32(x) => write_raw(out, *x),
142+
Self::Float64(x) => write_raw(out, *x),
143+
}
144+
}
145+
}
146+
147+
impl Debug for DynFloat {
148+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
149+
match *self {
150+
#[cfg(feature = "f16")]
151+
Self::Float16(x) => Debug::fmt(&x, f),
152+
Self::Float32(x) => Debug::fmt(&x, f),
153+
Self::Float64(x) => Debug::fmt(&x, f),
154+
}
155+
}
156+
}
157+
158+
impl Display for DynFloat {
159+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160+
Debug::fmt(self, f)
161+
}
162+
}
163+
164+
impl From<DynFloat> for DynScalar {
165+
fn from(value: DynFloat) -> Self {
166+
Self::Float(value)
167+
}
168+
}
169+
170+
impl From<DynFloat> for DynValue<'_> {
171+
fn from(value: DynFloat) -> Self {
172+
DynScalar::Float(value).into()
173+
}
174+
}
175+
176+
#[derive(Copy, Clone, PartialEq)]
177+
pub enum DynScalar {
178+
Integer(DynInteger),
179+
Float(DynFloat),
122180
Boolean(bool),
123181
}
124182

125183
unsafe impl DynClone for DynScalar {
126184
fn dyn_clone(&mut self, out: &mut [u8]) {
127185
match self {
128186
Self::Integer(x) => x.dyn_clone(out),
129-
Self::Float32(x) => write_raw(out, *x),
130-
Self::Float64(x) => write_raw(out, *x),
187+
Self::Float(x) => x.dyn_clone(out),
131188
Self::Boolean(x) => write_raw(out, *x),
132189
}
133190
}
@@ -137,8 +194,7 @@ impl Debug for DynScalar {
137194
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
138195
match self {
139196
Self::Integer(x) => Debug::fmt(&x, f),
140-
Self::Float32(x) => Debug::fmt(&x, f),
141-
Self::Float64(x) => Debug::fmt(&x, f),
197+
Self::Float(x) => Debug::fmt(&x, f),
142198
Self::Boolean(x) => Debug::fmt(&x, f),
143199
}
144200
}
@@ -637,8 +693,7 @@ impl<'a> DynValue<'a> {
637693

638694
match tp {
639695
Integer(size) | Unsigned(size) => DynInteger::read(buf, true, *size).into(),
640-
Float(FloatSize::U4) => DynScalar::Float32(read_raw(buf)).into(),
641-
Float(FloatSize::U8) => DynScalar::Float64(read_raw(buf)).into(),
696+
Float(size) => DynFloat::read(buf, *size).into(),
642697
Boolean => DynScalar::Boolean(read_raw(buf)).into(),
643698
Enum(ref tp) => DynEnum::new(tp, DynInteger::read(buf, tp.signed, tp.size)).into(),
644699
Compound(ref tp) => DynCompound::new(tp, buf).into(),

hdf5-types/src/h5type.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,24 @@ impl IntSize {
4040

4141
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
4242
pub enum FloatSize {
43+
#[cfg(feature = "f16")]
44+
U2 = 2,
4345
U4 = 4,
4446
U8 = 8,
4547
}
4648

4749
impl FloatSize {
4850
pub const fn from_int(size: usize) -> Option<Self> {
49-
if size == 4 {
50-
Some(Self::U4)
51-
} else if size == 8 {
52-
Some(Self::U8)
53-
} else {
54-
None
51+
#[cfg(feature = "f16")]
52+
{
53+
if size == 2 {
54+
return Some(Self::U2);
55+
}
56+
}
57+
match size {
58+
4 => Some(Self::U4),
59+
8 => Some(Self::U8),
60+
_ => None,
5561
}
5662
}
5763
}
@@ -167,6 +173,8 @@ impl Display for TypeDescriptor {
167173
TypeDescriptor::Unsigned(IntSize::U2) => write!(f, "uint16"),
168174
TypeDescriptor::Unsigned(IntSize::U4) => write!(f, "uint32"),
169175
TypeDescriptor::Unsigned(IntSize::U8) => write!(f, "uint64"),
176+
#[cfg(feature = "f16")]
177+
TypeDescriptor::Float(FloatSize::U2) => write!(f, "float16"),
170178
TypeDescriptor::Float(FloatSize::U4) => write!(f, "float32"),
171179
TypeDescriptor::Float(FloatSize::U8) => write!(f, "float64"),
172180
TypeDescriptor::Boolean => write!(f, "bool"),
@@ -251,6 +259,8 @@ impl_h5type!(u8, Unsigned, IntSize::U1);
251259
impl_h5type!(u16, Unsigned, IntSize::U2);
252260
impl_h5type!(u32, Unsigned, IntSize::U4);
253261
impl_h5type!(u64, Unsigned, IntSize::U8);
262+
#[cfg(feature = "f16")]
263+
impl_h5type!(::half::f16, Float, FloatSize::U2);
254264
impl_h5type!(f32, Float, FloatSize::U4);
255265
impl_h5type!(f64, Float, FloatSize::U8);
256266

hdf5/Cargo.toml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,21 @@ edition.workspace = true
1515

1616
[features]
1717
default = []
18-
mpio = ["dep:mpi-sys", "hdf5-sys/mpio"]
19-
lzf = ["dep:lzf-sys", "dep:errno"]
20-
blosc = ["dep:blosc-sys"]
18+
# Compile and statically link bundled HDF5 library.
2119
static = ["hdf5-sys/static"]
20+
# Enable zlib compression filter.
2221
zlib = ["hdf5-sys/zlib"]
22+
# Enable LZF compression filter.
23+
lzf = ["dep:lzf-sys", "dep:errno"]
24+
# Enable blosc compression filters.
25+
blosc = ["dep:blosc-sys"]
26+
# Enable MPI support.
27+
mpio = ["dep:mpi-sys", "hdf5-sys/mpio"]
28+
# Enable complex number type support.
29+
complex = ["hdf5-types/complex"]
30+
# Enable float16 type support.
31+
f16 = ["hdf5-types/f16"]
32+
2333
# The features with version numbers such as 1.10.3, 1.12.0 are metafeatures
2434
# and is only available when the HDF5 library is at least this version.
2535
# Features have_direct and have_parallel are also metafeatures and dependent
@@ -44,6 +54,8 @@ hdf5-sys = { workspace = true }
4454
hdf5-types = { workspace = true }
4555

4656
[dev-dependencies]
57+
half = { workspace = true }
58+
num-complex = { workspace = true }
4759
paste = "1.0"
4860
pretty_assertions = "1.3"
4961
rand = { version = "0.8", features = ["small_rng"] }
@@ -52,5 +64,5 @@ scopeguard = "1.1"
5264
tempfile = "3.6"
5365

5466
[package.metadata.docs.rs]
55-
features = ["hdf5-sys/static", "hdf5-sys/zlib", "blosc", "lzf"]
67+
features = ["static", "zlib", "blosc", "lzf", "f16", "complex"]
5668
rustdoc-args = ["--cfg", "docsrs"]

hdf5/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn main() {
99
"DEP_HDF5_HAVE_DIRECT" => print_feature("have-direct"),
1010
"DEP_HDF5_HAVE_PARALLEL" => print_feature("have-parallel"),
1111
"DEP_HDF5_HAVE_THREADSAFE" => print_feature("have-threadsafe"),
12+
"DEP_HDF5_HAVE_FILTER_DEFLATE" => print_feature("have-filter-deflate"),
1213
// internal config flags
1314
"DEP_HDF5_MSVC_DLL_INDIRECTION" => print_cfg("msvc_dll_indirection"),
1415
// public version features

hdf5/src/hl/chunks.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ mod v1_14_0 {
7272
use super::*;
7373
use hdf5_sys::h5d::H5Dchunk_iter;
7474

75-
/// Borrowed version of [ChunkInfo](crate::dataset::ChunkInfo)
75+
/// Borrowed version of [`ChunkInfo`](crate::dataset::ChunkInfo)
7676
#[derive(Clone, Debug, PartialEq, Eq)]
7777
pub struct ChunkInfoRef<'a> {
7878
pub offset: &'a [hsize_t],

hdf5/src/hl/datatype.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,16 @@ impl Datatype {
327327
Ok(string_id)
328328
}
329329

330+
#[cfg(feature = "f16")]
331+
unsafe fn f16_type() -> Result<hid_t> {
332+
use hdf5_sys::h5t::{H5Tset_ebias, H5Tset_fields};
333+
let f16_id = be_le!(H5T_IEEE_F32BE, H5T_IEEE_F32LE);
334+
h5try!(H5Tset_fields(f16_id, 15, 10, 5, 0, 10)); // cf. h5py/h5py#339
335+
h5try!(H5Tset_size(f16_id, 2));
336+
h5try!(H5Tset_ebias(f16_id, 15));
337+
Ok(f16_id)
338+
}
339+
330340
let datatype_id: Result<_> = h5lock!({
331341
match *desc {
332342
TD::Integer(size) => Ok(match size {
@@ -342,6 +352,8 @@ impl Datatype {
342352
IntSize::U8 => be_le!(H5T_STD_U64BE, H5T_STD_U64LE),
343353
}),
344354
TD::Float(size) => Ok(match size {
355+
#[cfg(feature = "f16")]
356+
FloatSize::U2 => f16_type()?,
345357
FloatSize::U4 => be_le!(H5T_IEEE_F32BE, H5T_IEEE_F32LE),
346358
FloatSize::U8 => be_le!(H5T_IEEE_I16BE, H5T_IEEE_F64LE),
347359
}),

tests/common/gen.rs renamed to hdf5/tests/common/gen.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
use std::convert::TryFrom;
2-
use std::fmt;
2+
use std::fmt::{self, Debug};
33
use std::iter;
44

55
use hdf5::types::{FixedAscii, FixedUnicode, VarLenArray, VarLenAscii, VarLenUnicode};
66
use hdf5::H5Type;
77

8+
use half::f16;
89
use ndarray::{ArrayD, SliceInfo, SliceInfoElem};
10+
use num_complex::Complex;
11+
use rand::distributions::Standard;
912
use rand::distributions::{Alphanumeric, Uniform};
13+
use rand::prelude::Distribution;
1014
use rand::prelude::{Rng, SliceRandom};
1115

1216
pub fn gen_shape<R: Rng + ?Sized>(rng: &mut R, ndim: usize) -> Vec<usize> {
@@ -93,6 +97,21 @@ macro_rules! impl_gen_tuple {
9397

9498
impl_gen_tuple! { A, B, C, D, E, F, G, H, I, J, K, L }
9599

100+
impl Gen for f16 {
101+
fn gen<R: Rng + ?Sized>(rng: &mut R) -> Self {
102+
Self::from_f32(rng.gen())
103+
}
104+
}
105+
106+
impl<T: Debug> Gen for Complex<T>
107+
where
108+
Standard: Distribution<T>,
109+
{
110+
fn gen<R: Rng + ?Sized>(rng: &mut R) -> Self {
111+
Self::new(rng.gen(), rng.gen())
112+
}
113+
}
114+
96115
pub fn gen_vec<R: Rng + ?Sized, T: Gen>(rng: &mut R, size: usize) -> Vec<T> {
97116
iter::repeat(()).map(|_| T::gen(rng)).take(size).collect()
98117
}
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)