Skip to content

Commit

Permalink
Add experimental clamping filter
Browse files Browse the repository at this point in the history
add a mini filter: h5z-clamp, with a filter ID of 45678
  • Loading branch information
shaomeng authored Mar 4, 2025
2 parents 18fd6f9 + f1d35dc commit c07099a
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 3 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.14)

project(H5Z-SPERR VERSION 0.2.0 LANGUAGES C CXX DESCRIPTION "HDF5 plugin for SPERR compression")
project(H5Z-SPERR VERSION 0.2.1 LANGUAGES C CXX DESCRIPTION "HDF5 plugin for SPERR compression")

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
Expand Down Expand Up @@ -76,7 +76,7 @@ endif()
# Start installation using GNU installation rules
#
include( GNUInstallDirs )
install( TARGETS h5z-sperr LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )
install( TARGETS h5z-sperr h5z-clamp LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} )

if( BUILD_CLI_UTILITIES )
install( TARGETS generate_cd_values decode_cd_values
Expand Down
10 changes: 10 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#
# The main H5Z-SPERR filter
#
add_library( h5z-sperr h5z-sperr.c
h5zsperr_helper.cpp
icecream.c
Expand All @@ -6,3 +9,10 @@ target_include_directories( h5z-sperr PUBLIC ${HDF5_INCLUDE_DIR}
PUBLIC ${SPERR_INCLUDE_DIRS}
PUBLIC ${CMAKE_SOURCE_DIR}/include )
target_link_libraries( h5z-sperr PUBLIC ${HDF5_LIBRARIES} PUBLIC PkgConfig::SPERR )

#
# Experimental clamping filter
#
add_library( h5z-clamp h5z-clamp.c )
target_include_directories( h5z-clamp PUBLIC ${HDF5_INCLUDE_DIR} )
target_link_libraries( h5z-clamp PUBLIC ${HDF5_LIBRARIES} )
127 changes: 127 additions & 0 deletions src/h5z-clamp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* This file contains the clamp filter class definition, H5Z_clamp_class_t,
* and necessary functions required by the HDF5 plugin architecture:
* - can_apply()
* - set_local()
* - filter()
* - get_plugin_info()
* - get_plugin_type()
*/

#define H5Z_FILTER_CLAMP 45678

#include <assert.h>
#include <stdlib.h>

#include <H5PLextern.h>
#include <hdf5.h>

static htri_t H5Z_can_apply_clamp(hid_t dcpl_id, hid_t type_id, hid_t space_id)
{
/*
* dcpl_id Dataset creation property list identifier
* type_id Datatype identifier
* space_id Dataspace identifier
*/

/* Get datatype class. Fail if not floats. */
if (H5Tget_class(type_id) != H5T_FLOAT) {
H5Epush(H5E_DEFAULT, __FILE__, __func__, __LINE__, H5E_ERR_CLS, H5E_PLINE, H5E_BADTYPE,
"bad data type. Only floats are supported in H5Z-CLAMP");
return 0;
}
size_t type_size = H5Tget_size(type_id);
assert(type_size == 4 || type_size == 8);

return 1;
}

static herr_t H5Z_set_local_clamp(hid_t dcpl_id, hid_t type_id, hid_t space_id)
{
/*
* dcpl_id Dataset creation property list identifier
* type_id Datatype identifier
* space_id Dataspace identifier
*/

/* Get the datatype size. It must be 4 or 8, since the float type is verified by `can_apply`. */
unsigned int is_float = H5Tget_size(type_id) == 4 ? 1 : 0;

/*
* Assemble the meta info to be stored.
* [0] : float/double
*/
size_t cd_nelems = 1;
unsigned int cd_values[1] = {is_float};
H5Pmodify_filter(dcpl_id, H5Z_FILTER_CLAMP, H5Z_FLAG_MANDATORY, cd_nelems, cd_values);

return 1;
}

static size_t H5Z_filter_clamp(unsigned int flags,
size_t cd_nelmts,
const unsigned int cd_values[],
size_t nbytes,
size_t* buf_size,
void** buf)
{
int is_float = cd_values[0];
assert(is_float == 1 || is_float == 0);

if (flags & H5Z_FLAG_REVERSE) { /* Decompression */

if (is_float) {
if (nbytes % 4) {
H5Epush(H5E_DEFAULT, __FILE__, __func__, __LINE__, H5E_ERR_CLS, H5E_PLINE, H5E_BADSIZE,
"Decompression: input buffer len isn't right.");
return 0;
}
const size_t nelem = nbytes / 4;
float* p = (float*)(*buf);
for (size_t i = 0; i < nelem; i++) {
if (p[i] < 0.f)
p[i] = 0.f;
}
}
else {
if (nbytes % 8) {
H5Epush(H5E_DEFAULT, __FILE__, __func__, __LINE__, H5E_ERR_CLS, H5E_PLINE, H5E_BADSIZE,
"Decompression: input buffer len isn't right.");
return 0;
}
const size_t nelem = nbytes / 8;
double* p = (double*)(*buf);
for (size_t i = 0; i < nelem; i++) {
if (p[i] < 0.0)
p[i] = 0.0;
}
}

return *buf_size;

} /* Finish Decompression */
else { /* Compression */

/* Nothing to be done during compression :) */
return *buf_size;
}
}

const H5Z_class2_t H5Z_clamp_class_t = {H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_CLAMP, /* Filter id number */
1, /* encoder_present flag (set to true) */
1, /* decoder_present flag (set to true) */
"H5Z-CLAMP", /* Filter name for debugging */
H5Z_can_apply_clamp, /* The "can apply" callback */
H5Z_set_local_clamp, /* The "set local" callback */
H5Z_filter_clamp}; /* The actual filter function */

const void* H5PLget_plugin_info()
{
return &H5Z_clamp_class_t;
}

H5PL_type_t H5PLget_plugin_type()
{
return H5PL_TYPE_FILTER;
}
2 changes: 1 addition & 1 deletion src/h5z-sperr.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ static herr_t H5Z_set_local_sperr(hid_t dcpl_id, hid_t type_id, hid_t space_id)

H5Pmodify_filter(dcpl_id, H5Z_FILTER_SPERR, H5Z_FLAG_MANDATORY, cd_nelems, cd_values);

return 0;
return 1;
}

static size_t H5Z_filter_sperr(unsigned int flags,
Expand Down

0 comments on commit c07099a

Please sign in to comment.