-
-
Notifications
You must be signed in to change notification settings - Fork 25
Port netcdf c 3093 #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Port netcdf c 3093 #260
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,15 @@ if (H5PL_BUILD_TESTING) | |
| target_link_libraries (h5repack_floats_bitgroom PRIVATE dl) | ||
| endif () | ||
|
|
||
| # Round-trip test for special floating-point values (NaN, +/- Inf, +/- zero). | ||
| # See the test definition lower in this file for the full description. | ||
| add_executable (h5filter_specials_bitgroom ${PROJECT_SOURCE_DIR}/h5filter_specials_bitgroom.c) | ||
| TARGET_C_PROPERTIES (h5filter_specials_bitgroom ${LIB_TYPE}) | ||
| target_link_libraries (h5filter_specials_bitgroom PRIVATE ${H5PL_HDF5_LINK_LIBS}) | ||
| if (NOT WIN32) | ||
| target_link_libraries (h5filter_specials_bitgroom PRIVATE dl) | ||
| endif () | ||
|
|
||
| macro (ADD_H5_TEST testname) | ||
| add_test ( | ||
| NAME ${testname}-clearall | ||
|
|
@@ -261,6 +270,44 @@ if (H5PL_BUILD_TESTING) | |
| if (NOT DISABLE_H5BITGROOM_ENCODER) | ||
| #UD BITGROOM | ||
| ADD_H5_UD_TEST (ud_convert 0 h5repack_floats.h5 --enable-error-stack -v -f UD=32022,0,5,3,4,0,0,0 -l CHUNK=4x8) | ||
|
|
||
| # Special-value round-trip test: writes a small chunked dataset containing | ||
| # NaN, +/- Inf, +/- zero, plus normal values; applies the BitGroom filter | ||
| # via H5Pset_filter; reads back; and asserts in C that the special values | ||
| # are preserved bit-exact while at least one normal value was quantized. | ||
| # BitGroom alternates shave (AND) on even indices and set (OR) on odd | ||
| # indices; the special values straddle both. The verdict comes from the | ||
| # program's exit code; no h5dump comparison is involved, so cross-platform | ||
| # NaN/Inf printf formatting cannot affect the result. TESTLIBDIR is | ||
| # already set by ADD_H5_UD_TEST above. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally, I feel this section is kinda jammed and has too many semicolons. A bulleted list might help with readability. |
||
| add_test ( | ||
| NAME H5BITGROOM_UD-specials-roundtrip-clearall | ||
| COMMAND ${CMAKE_COMMAND} -E remove | ||
| h5filter_specials_bitgroom.h5 | ||
| h5filter_specials_bitgroom.out | ||
| h5filter_specials_bitgroom.out.err | ||
| ) | ||
| if (NOT "${last_test}" STREQUAL "") | ||
| set_tests_properties (H5BITGROOM_UD-specials-roundtrip-clearall PROPERTIES DEPENDS ${last_test}) | ||
| endif () | ||
| set (last_test "H5BITGROOM_UD-specials-roundtrip-clearall") | ||
| add_test ( | ||
| NAME H5BITGROOM_UD-specials-roundtrip | ||
| COMMAND "${CMAKE_COMMAND}" | ||
| -D "TEST_PROGRAM=$<TARGET_FILE:h5filter_specials_bitgroom>" | ||
| -D "TEST_FOLDER=${PROJECT_BINARY_DIR}" | ||
| -D "TEST_EXPECT=0" | ||
| -D "TEST_OUTPUT=h5filter_specials_bitgroom.out" | ||
| -D "TEST_SKIP_COMPARE=1" | ||
| -D "TEST_LIBRARY_DIRECTORY=${TESTLIBDIR}" | ||
| -D "TEST_ENV_VAR=HDF5_PLUGIN_PATH" | ||
| -D "TEST_ENV_VALUE=${CMAKE_BINARY_DIR}/plugins" | ||
| -P "${H5BITGROOM_RESOURCES_DIR}/runTest.cmake" | ||
| ) | ||
| set_tests_properties (H5BITGROOM_UD-specials-roundtrip PROPERTIES | ||
| WORKING_DIRECTORY "${PROJECT_BINARY_DIR}" | ||
| DEPENDS H5BITGROOM_UD-specials-roundtrip-clearall) | ||
| set (last_test "H5BITGROOM_UD-specials-roundtrip") | ||
| endif () | ||
|
|
||
| endif () | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,228 @@ | ||
| /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | ||
| * Copyright by The HDF Group. * | ||
| * All rights reserved. * | ||
| * * | ||
| * This file is part of the HDF5 BitGroom filter plugin source. * | ||
| * The full copyright notice, including terms governing use, modification, * | ||
| * and redistribution, is contained in the file COPYING, which can be found * | ||
| * at the root of the source code distribution tree. If you do not have * | ||
| * access to this file, you may request a copy from help@hdfgroup.org. * | ||
| * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ | ||
|
|
||
| /* | ||
| * Round-trip test for special floating-point values through the BitGroom | ||
| * filter. Verifies that NaN, +Inf, -Inf, -0.0, and +0.0 are passed through | ||
| * the filter unchanged (bit-identical) on both the float and double code | ||
| * paths, and that at least one normal value is quantized (proving the | ||
| * filter actually ran). The filter is loaded dynamically via HDF5's plugin | ||
| * mechanism (HDF5_PLUGIN_PATH); no h5dump comparison is involved so cross- | ||
| * platform NaN/Inf printf formatting cannot affect the result. | ||
| * | ||
| * BitGroom alternates shave (AND-mask) on even indices and set (OR-mask) | ||
| * on odd indices; the special values are placed at both even and odd | ||
| * positions to exercise both loops. | ||
| */ | ||
|
|
||
| #include "hdf5.h" | ||
| #include <stdint.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally, standard header files should come first. |
||
|
|
||
| #define FILENAME "h5filter_specials_bitgroom.h5" | ||
| #define DSET_F32 "f32" | ||
| #define DSET_F64 "f64" | ||
| #define N 16 | ||
| #define N_SPECIALS 5 | ||
| #define H5Z_FILTER_BITGROOM 32022 | ||
|
|
||
| /* Build exact bit patterns via memcpy so the compiler cannot constant-fold | ||
| * away -0.0f or normalize a quiet NaN to a different payload. */ | ||
| static void | ||
| init_input_f32(float *buf, uint32_t *bits_out) | ||
| { | ||
| const uint32_t specials[N_SPECIALS] = { | ||
| 0x7FC00000U, /* quiet NaN */ | ||
| 0x7F800000U, /* +Inf */ | ||
| 0xFF800000U, /* -Inf */ | ||
| 0x80000000U, /* -0.0 */ | ||
| 0x00000000U, /* +0.0 */ | ||
| }; | ||
| for (int i = 0; i < N_SPECIALS; i++) | ||
| memcpy(&buf[i], &specials[i], sizeof(float)); | ||
| for (int i = N_SPECIALS; i < N; i++) | ||
| buf[i] = ((float)i - 3.7f) * 0.137f; | ||
| memcpy(bits_out, buf, N * sizeof(uint32_t)); | ||
| } | ||
|
|
||
| static void | ||
| init_input_f64(double *buf, uint64_t *bits_out) | ||
| { | ||
| const uint64_t specials[N_SPECIALS] = { | ||
| 0x7FF8000000000000ULL, /* quiet NaN */ | ||
| 0x7FF0000000000000ULL, /* +Inf */ | ||
| 0xFFF0000000000000ULL, /* -Inf */ | ||
| 0x8000000000000000ULL, /* -0.0 */ | ||
| 0x0000000000000000ULL, /* +0.0 */ | ||
| }; | ||
| for (int i = 0; i < N_SPECIALS; i++) | ||
| memcpy(&buf[i], &specials[i], sizeof(double)); | ||
| for (int i = N_SPECIALS; i < N; i++) | ||
| buf[i] = ((double)i - 3.7) * 0.137; | ||
| memcpy(bits_out, buf, N * sizeof(uint64_t)); | ||
| } | ||
|
|
||
| static int | ||
| roundtrip_f32(hid_t file_id) | ||
| { | ||
| hid_t space_id = H5I_INVALID_HID, dcpl_id = H5I_INVALID_HID, dset_id = H5I_INVALID_HID; | ||
| int ret = 1; | ||
| hsize_t dims[1] = {N}, chunk[1] = {N}; | ||
| /* NSD=3, sizeof(data)=4, has_mss_val=0, mss_val_byt_1to4=0, mss_val_byt_5to8=0 */ | ||
| const unsigned int cd_values[5] = {3, 4, 0, 0, 0}; | ||
| float input[N], output[N]; | ||
| uint32_t input_bits[N], output_bits[N]; | ||
| int any_quantized = 0; | ||
|
|
||
| init_input_f32(input, input_bits); | ||
|
|
||
| if ((space_id = H5Screate_simple(1, dims, NULL)) < 0) | ||
| goto done; | ||
| if ((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0) | ||
| goto done; | ||
| if (H5Pset_chunk(dcpl_id, 1, chunk) < 0) | ||
| goto done; | ||
| if (H5Pset_filter(dcpl_id, H5Z_FILTER_BITGROOM, H5Z_FLAG_MANDATORY, 5, cd_values) < 0) | ||
| goto done; | ||
| if ((dset_id = | ||
| H5Dcreate(file_id, DSET_F32, H5T_IEEE_F32LE, space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0) | ||
| goto done; | ||
| if (H5Dwrite(dset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, input) < 0) | ||
| goto done; | ||
| H5Dclose(dset_id); | ||
| dset_id = H5I_INVALID_HID; | ||
|
|
||
| if ((dset_id = H5Dopen(file_id, DSET_F32, H5P_DEFAULT)) < 0) | ||
| goto done; | ||
| if (H5Dread(dset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, output) < 0) | ||
| goto done; | ||
| memcpy(output_bits, output, sizeof(output_bits)); | ||
|
|
||
| for (int i = 0; i < N_SPECIALS; i++) { | ||
| if (input_bits[i] != output_bits[i]) { | ||
| fprintf(stderr, "FAIL [f32, idx %d]: special value mutated: in=0x%08x out=0x%08x\n", i, | ||
| input_bits[i], output_bits[i]); | ||
| goto done; | ||
| } | ||
| } | ||
| for (int i = N_SPECIALS; i < N; i++) { | ||
| if (input_bits[i] != output_bits[i]) { | ||
| any_quantized = 1; | ||
| break; | ||
| } | ||
| } | ||
| if (!any_quantized) { | ||
| fprintf(stderr, "FAIL [f32]: no normal value was quantized; filter did not run\n"); | ||
| goto done; | ||
| } | ||
|
|
||
| ret = 0; | ||
|
|
||
| done: | ||
| if (dset_id >= 0) | ||
| H5Dclose(dset_id); | ||
| if (dcpl_id >= 0) | ||
| H5Pclose(dcpl_id); | ||
| if (space_id >= 0) | ||
| H5Sclose(space_id); | ||
| return ret; | ||
| } | ||
|
|
||
| static int | ||
| roundtrip_f64(hid_t file_id) | ||
| { | ||
| hid_t space_id = H5I_INVALID_HID, dcpl_id = H5I_INVALID_HID, dset_id = H5I_INVALID_HID; | ||
| int ret = 1; | ||
| hsize_t dims[1] = {N}, chunk[1] = {N}; | ||
| /* NSD=3, sizeof(data)=8, has_mss_val=0, mss_val_byt_1to4=0, mss_val_byt_5to8=0 */ | ||
| const unsigned int cd_values[5] = {3, 8, 0, 0, 0}; | ||
| double input[N], output[N]; | ||
| uint64_t input_bits[N], output_bits[N]; | ||
| int any_quantized = 0; | ||
|
|
||
| init_input_f64(input, input_bits); | ||
|
|
||
| if ((space_id = H5Screate_simple(1, dims, NULL)) < 0) | ||
| goto done; | ||
| if ((dcpl_id = H5Pcreate(H5P_DATASET_CREATE)) < 0) | ||
| goto done; | ||
| if (H5Pset_chunk(dcpl_id, 1, chunk) < 0) | ||
| goto done; | ||
| if (H5Pset_filter(dcpl_id, H5Z_FILTER_BITGROOM, H5Z_FLAG_MANDATORY, 5, cd_values) < 0) | ||
| goto done; | ||
| if ((dset_id = | ||
| H5Dcreate(file_id, DSET_F64, H5T_IEEE_F64LE, space_id, H5P_DEFAULT, dcpl_id, H5P_DEFAULT)) < 0) | ||
| goto done; | ||
| if (H5Dwrite(dset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, input) < 0) | ||
| goto done; | ||
| H5Dclose(dset_id); | ||
| dset_id = H5I_INVALID_HID; | ||
|
|
||
| if ((dset_id = H5Dopen(file_id, DSET_F64, H5P_DEFAULT)) < 0) | ||
| goto done; | ||
| if (H5Dread(dset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, output) < 0) | ||
| goto done; | ||
| memcpy(output_bits, output, sizeof(output_bits)); | ||
|
|
||
| for (int i = 0; i < N_SPECIALS; i++) { | ||
| if (input_bits[i] != output_bits[i]) { | ||
| fprintf(stderr, "FAIL [f64, idx %d]: special value mutated: in=0x%016llx out=0x%016llx\n", i, | ||
| (unsigned long long)input_bits[i], (unsigned long long)output_bits[i]); | ||
| goto done; | ||
| } | ||
| } | ||
| for (int i = N_SPECIALS; i < N; i++) { | ||
| if (input_bits[i] != output_bits[i]) { | ||
| any_quantized = 1; | ||
| break; | ||
| } | ||
| } | ||
| if (!any_quantized) { | ||
| fprintf(stderr, "FAIL [f64]: no normal value was quantized; filter did not run\n"); | ||
| goto done; | ||
| } | ||
|
|
||
| ret = 0; | ||
|
|
||
| done: | ||
| if (dset_id >= 0) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be > 0 |
||
| H5Dclose(dset_id); | ||
| if (dcpl_id >= 0) | ||
| H5Pclose(dcpl_id); | ||
| if (space_id >= 0) | ||
| H5Sclose(space_id); | ||
| return ret; | ||
| } | ||
|
|
||
| int | ||
| main(void) | ||
| { | ||
| hid_t file_id; | ||
| int r_f32 = 1, r_f64 = 1; | ||
|
|
||
| file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); | ||
| if (file_id < 0) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought id should be checked against H5I_INVALID_HID instead of < 0, but when I looked in the code, it's not widely used... |
||
| fprintf(stderr, "FAIL: H5Fcreate(%s) failed\n", FILENAME); | ||
| return 1; | ||
| } | ||
|
|
||
| r_f32 = roundtrip_f32(file_id); | ||
| r_f64 = roundtrip_f64(file_id); | ||
|
|
||
| H5Fclose(file_id); | ||
|
|
||
| if (r_f32 == 0 && r_f64 == 0) { | ||
| printf("PASS: BitGroom special-value round-trip (f32 + f64)\n"); | ||
| return 0; | ||
| } | ||
| return 1; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about: "See the test definition below for the full description."?