diff options
author | Pedro Vicente Nunes <pvn@hdfgroup.org> | 2008-03-04 19:03:05 (GMT) |
---|---|---|
committer | Pedro Vicente Nunes <pvn@hdfgroup.org> | 2008-03-04 19:03:05 (GMT) |
commit | ab30541dbff26f59e3f22da48c4e7bbd7595e977 (patch) | |
tree | 332546d237732d8ab16f8b779f912d35320d1459 /tools | |
parent | 3a92e3a69be3f4831c06e797dae0920ea9c1f069 (diff) | |
download | hdf5-ab30541dbff26f59e3f22da48c4e7bbd7595e977.zip hdf5-ab30541dbff26f59e3f22da48c4e7bbd7595e977.tar.gz hdf5-ab30541dbff26f59e3f22da48c4e7bbd7595e977.tar.bz2 |
[svn-r14698] #606 (B1) h5diff: Add ability to handle NaN values
Added 2 sets of datasets to the h5 files, that contain NaNs. There is no automated test to test NaN, since the output varies from platform to platform
tested: windows, linux, solaris
Diffstat (limited to 'tools')
-rw-r--r-- | tools/h5diff/h5diffgentest.c | 285 | ||||
-rw-r--r-- | tools/lib/h5diff_array.c | 1097 | ||||
-rw-r--r-- | tools/testfiles/h5diff_17.txt | 4 | ||||
-rw-r--r-- | tools/testfiles/h5diff_basic1.h5 | bin | 8296 -> 9712 bytes | |||
-rw-r--r-- | tools/testfiles/h5diff_basic2.h5 | bin | 4240 -> 4240 bytes |
5 files changed, 1045 insertions, 341 deletions
diff --git a/tools/h5diff/h5diffgentest.c b/tools/h5diff/h5diffgentest.c index 460d9db..cbb7fee 100644 --- a/tools/h5diff/h5diffgentest.c +++ b/tools/h5diff/h5diffgentest.c @@ -77,24 +77,30 @@ static int write_dset(hid_t loc_id,int rank,hsize_t *dims,const char *name,hid_t int main(void) { - test_basic (FILE1,FILE2); - test_types (FILE3); - test_datatypes(FILE4); - - /* generate 2 files, the second call creates a similar file with differences */ - test_attributes(FILE5,0); - test_attributes(FILE6,1); - - /* generate 2 files, the second call creates a similar file with differences */ - test_datasets(FILE7,0); - test_datasets(FILE8,1); - - /* generate 2 files, the second call creates a similar file with differences */ - test_hyperslab(FILE9,0); - test_hyperslab(FILE10,1); - return 0; + if ( test_basic (FILE1,FILE2) < 0 ) + goto out; + + test_types (FILE3); + test_datatypes(FILE4); + + /* generate 2 files, the second call creates a similar file with differences */ + test_attributes(FILE5,0); + test_attributes(FILE6,1); + + /* generate 2 files, the second call creates a similar file with differences */ + test_datasets(FILE7,0); + test_datasets(FILE8,1); + + /* generate 2 files, the second call creates a similar file with differences */ + test_hyperslab(FILE9,0); + test_hyperslab(FILE10,1); + return 0; + +out: + return 1; } +#if 0 /*------------------------------------------------------------------------- * Function: test_basic * @@ -235,6 +241,253 @@ TOOLTEST h5diff_191.txt file1.h5 file1.h5 -v -p 0.02 g1/dset5 g1/dset6 TOOLTEST h5diff_192.txt file1.h5 file1.h5 -v -p 0.02 g1/dset7 g1/dset8 */ +#endif + +/*------------------------------------------------------------------------- + * Function: test_basic + * + * Purpose: basic tests + * + *------------------------------------------------------------------------- + */ + +static +int test_basic(const char *fname1, + const char *fname2) +{ + hid_t fid1, fid2; + hid_t gid1, gid2, gid3; + hsize_t dims1[1] = { 6 }; + hsize_t dims2[2] = { 3,2 }; + + /*------------------------------------------------------------------------- + * create two files + *------------------------------------------------------------------------- + */ + + if (( fid1 = H5Fcreate (fname1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0 ) + goto out; + if (( fid2 = H5Fcreate (fname2, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0 ) + goto out; + + /*------------------------------------------------------------------------- + * create groups + *------------------------------------------------------------------------- + */ + + gid1 = H5Gcreate(fid1, "g1", 0); + gid2 = H5Gcreate(fid2, "g1", 0); + gid3 = H5Gcreate(fid2, "g2", 0); + + /*------------------------------------------------------------------------- + * tests: + * # 1.1 normal mode + * # 1.2 normal mode with objects + * # 1.3 report mode + * # 1.4 report mode with objects + * # 1.5 with -d + *------------------------------------------------------------------------- + */ + + { + double data1[3][2] = {{1,1}, {1,1}, {0,0}}; + double data2[3][2] = {{0,1.1},{1.01,1.001},{0,1}}; + double data3[3][2] = {{100,100},{100,100},{100,100}}; + double data4[3][2] = {{105,120},{160,95},{80,40}}; + + write_dset(gid1,2,dims2,"dset1",H5T_NATIVE_DOUBLE,data1); + write_dset(gid2,2,dims2,"dset2",H5T_NATIVE_DOUBLE,data2); + write_dset(gid1,2,dims2,"dset3",H5T_NATIVE_DOUBLE,data3); + write_dset(gid2,2,dims2,"dset4",H5T_NATIVE_DOUBLE,data4); + write_dset(gid2,2,dims2,"dset1",H5T_NATIVE_DOUBLE,data2); + + } + /*------------------------------------------------------------------------- + * relative error, compare divide by zero, both zero + * # 1.6.1 with -p (int) + *------------------------------------------------------------------------- + */ + { + int data5[3][2] = {{100,100},{100,0},{0,100}}; + int data6[3][2] = {{120,80}, {0,100},{0,50}}; + + write_dset(gid1,2,dims2,"dset5",H5T_NATIVE_INT,data5); + write_dset(gid1,2,dims2,"dset6",H5T_NATIVE_INT,data6); + + } + + /*------------------------------------------------------------------------- + * relative error, compare divide by zero, both zero + * # 1.6.2 with -p (unsigned long_long) + *------------------------------------------------------------------------- + */ + { + unsigned long_long data7[3][2] = {{100,100},{100,0},{0,100}}; + unsigned long_long data8[3][2] = {{120,80}, {0,100},{0,50}}; + + write_dset(gid1,2,dims2,"dset7",H5T_NATIVE_ULLONG,data7); + write_dset(gid1,2,dims2,"dset8",H5T_NATIVE_ULLONG,data8); + + } + + /*------------------------------------------------------------------------- + * relative error, compare divide by zero, both zero + * # 1.6.3 with -p (double) + * + * A B 1-B/A % + * 100 120 0.2 20 + * 100 80 0.2 20 + * 100 0 1 100 + * 0 100 #DIV/0! #DIV/0! + * 0 0 #DIV/0! #DIV/0! + * 100 50 0.5 50 + *------------------------------------------------------------------------- + */ + { + double data9[3][2] = {{100,100},{100,0},{0,100}}; + double data10[3][2] ={{120,80}, {0,100},{0,50}}; + + write_dset(gid1,2,dims2,"dset9",H5T_NATIVE_DOUBLE,data9); + write_dset(gid1,2,dims2,"dset10",H5T_NATIVE_DOUBLE,data10); + + } + + + /*------------------------------------------------------------------------- + * test floating point comparison + *------------------------------------------------------------------------- + */ + { + /* epsilon = 0.00001 */ + float data11[3][2] ={{0.00000f,0.00001f},{0.00001f, 0.00000f},{0.00001f,0.00001f}}; + float data12[3][2] ={{0.00000f,0.00002f},{0.000009f,0.00001f},{0.00000f,0.00001f}}; + double data13[3][2] ={{0.000000000,0.000000001},{0.000000001, 0.000000000},{0.000000001,0.000000001}}; + double data14[3][2] ={{0.000000000,0.000000002},{0.0000000009,0.000000001},{0.000000000,0.000000001}}; + + write_dset(gid1,2,dims2,"fp1",H5T_NATIVE_FLOAT,data11); + write_dset(gid1,2,dims2,"fp2",H5T_NATIVE_FLOAT,data12); + write_dset(gid1,2,dims2,"d1",H5T_NATIVE_DOUBLE,data13); + write_dset(gid1,2,dims2,"d2",H5T_NATIVE_DOUBLE,data14); + + } + + + /*------------------------------------------------------------------------- + * NaNs in H5T_NATIVE_FLOAT + *------------------------------------------------------------------------- + */ + { + +#if 1 + float data15[6]; + float data16[6]; + + data15[0] = (float) sqrt( (double)-1 ); + data15[1] = 1; + data15[2] = (float) sqrt( (double)-1 ); + data15[3] = 1; + data15[4] = 1; + data15[5] = 1; + + data16[0] = (float) sqrt( (double)-1 ); + data16[1] = (float) sqrt( (double)-1 ); + data16[2] = 1; + data16[3] = 1; + data16[4] = 1; + data16[5] = 1; + + write_dset(gid1,1,dims1,"fp15",H5T_NATIVE_FLOAT,data15); + write_dset(gid1,1,dims1,"fp16",H5T_NATIVE_FLOAT,data16); +#else + +#define NU_ELMTS 1000000 + + hsize_t i; + + hsize_t dims2[1] = { NU_ELMTS }; + + float *data15 = malloc (NU_ELMTS * sizeof(float) ); + float *data16 = malloc (NU_ELMTS * sizeof(float) ); + + data15[0] = (float) sqrt( (double)-1 ); + data15[1] = 1; + data15[2] = (float) sqrt( (double)-1 ); + data15[3] = 1; + data15[4] = 1; + data15[5] = 1; + + data16[0] = (float) sqrt( (double)-1 ); + data16[1] = (float) sqrt( (double)-1 ); + data16[2] = 1; + data16[3] = 1; + data16[4] = 1; + data16[5] = 1; + + for ( i = 6; i < NU_ELMTS; i++ ) + { + data15[i] = /*data15[0];*/ 2; + data16[i] = 1; + } + + write_dset(gid1,1,dims2,"fp15",H5T_NATIVE_FLOAT,data15); + write_dset(gid1,1,dims2,"fp16",H5T_NATIVE_FLOAT,data16); + + free( data15 ); + free( data16 ); +#endif + + } + + + + /*------------------------------------------------------------------------- + * NaNs in H5T_NATIVE_DOUBLE + *------------------------------------------------------------------------- + */ + { + + double data17[6]; + double data18[6]; + + data17[0] = sqrt( (double)-1 ); + data17[1] = 1; + data17[2] = sqrt( (double)-1 ); + data17[3] = 1; + data17[4] = 1; + data17[5] = 1; + + data18[0] = (float) sqrt( (double)-1 ); + data18[1] = (float) sqrt( (double)-1 ); + data18[2] = 1; + data18[3] = 1; + data18[4] = 1; + data18[5] = 1; + + write_dset(gid1,1,dims1,"fp17",H5T_NATIVE_DOUBLE,data17); + write_dset(gid1,1,dims1,"fp18",H5T_NATIVE_DOUBLE,data18); + + } + + + + + /*------------------------------------------------------------------------- + * close + *------------------------------------------------------------------------- + */ + H5Gclose(gid1); + H5Gclose(gid2); + H5Gclose(gid3); + H5Fclose(fid1); + H5Fclose(fid2); + return SUCCEED; + +out: + + return FAIL; +} + + /*------------------------------------------------------------------------- * Function: test_types diff --git a/tools/lib/h5diff_array.c b/tools/lib/h5diff_array.c index d520990..e2861b8 100644 --- a/tools/lib/h5diff_array.c +++ b/tools/lib/h5diff_array.c @@ -17,6 +17,16 @@ #include "h5diff.h" #include "H5private.h" +#include <sys/timeb.h> +#include <time.h> + +#if 0 +#define H5DIFF_DO_TIME +#endif +#if 1 +#define H5DIFF_DO_NAN +#endif + /*------------------------------------------------------------------------- * printf formatting *------------------------------------------------------------------------- @@ -56,9 +66,6 @@ #define H5DIFF_FLT_EPSILON .00001 #define H5DIFF_DBL_EPSILON .000000001 -static hbool_t equal_float(float value, float expected); -static hbool_t equal_double(double value, double expected); - /*------------------------------------------------------------------------- * -p relative error formula * @@ -119,12 +126,29 @@ static int not_comparable; * local prototypes *------------------------------------------------------------------------- */ + static void close_obj(H5G_obj_t1 obj_type, hid_t obj_id); static hsize_t diff_region(hid_t obj1_id, hid_t obj2_id,hid_t region1_id, hid_t region2_id, diff_opt_t *options); static hbool_t all_zero(const void *_mem, size_t size); static hsize_t character_compare(unsigned char *mem1,unsigned char *mem2,hsize_t i,int rank,hsize_t *dims,hsize_t *acc,hsize_t *pos,diff_opt_t *options,const char *obj1,const char *obj2,int *ph); static hsize_t character_compare_opt(unsigned char *mem1,unsigned char *mem2,hsize_t i,int rank,hsize_t *dims,hsize_t *acc,hsize_t *pos,diff_opt_t *options,const char *obj1,const char *obj2,int *ph); +static hbool_t equal_float(float value, float expected); +static hbool_t equal_double(double value, double expected); + + +/*------------------------------------------------------------------------- + * NaN detection + *------------------------------------------------------------------------- + */ +typedef enum dtype_t +{ + FLT_FLOAT, FLT_DOUBLE, +#if H5_SIZEOF_LONG_DOUBLE !=0 + FLT_LDOUBLE, +#endif +} dtype_t; +static int my_isnan(dtype_t type, void *val); /*------------------------------------------------------------------------- * @@ -667,40 +691,10 @@ hsize_t diff_datum(void *_mem1, break; /*------------------------------------------------------------------------- - * H5T_VLEN + * H5T_REFERENCE *------------------------------------------------------------------------- */ - case H5T_VLEN: - - /* get the VL sequences's base datatype for each element */ - memb_type = H5Tget_super(m_type); - size = H5Tget_size(memb_type); - - /* get the number of sequence elements */ - nelmts = ((hvl_t *)mem1)->len; - - for (j = 0; j < (int)nelmts; j++) - nfound+=diff_datum( - ((char *)(((hvl_t *)mem1)->p)) + j * size, - ((char *)(((hvl_t *)mem2)->p)) + j * size, /* offset */ - memb_type, - i, /* index position */ - rank, - dims, - acc, - pos, - options, - obj1, - obj2, - container1_id, - container2_id, - ph); - - H5Tclose(memb_type); - - break; - case H5T_REFERENCE: @@ -814,9 +808,49 @@ hsize_t diff_datum(void *_mem1, break; + /*------------------------------------------------------------------------- + * H5T_VLEN + *------------------------------------------------------------------------- + */ - case H5T_INTEGER: + case H5T_VLEN: + + /* get the VL sequences's base datatype for each element */ + memb_type = H5Tget_super(m_type); + size = H5Tget_size(memb_type); + /* get the number of sequence elements */ + nelmts = ((hvl_t *)mem1)->len; + + for (j = 0; j < (int)nelmts; j++) + nfound+=diff_datum( + ((char *)(((hvl_t *)mem1)->p)) + j * size, + ((char *)(((hvl_t *)mem2)->p)) + j * size, /* offset */ + memb_type, + i, /* index position */ + rank, + dims, + acc, + pos, + options, + obj1, + obj2, + container1_id, + container2_id, + ph); + + H5Tclose(memb_type); + + break; + + + + /*------------------------------------------------------------------------- + * H5T_INTEGER + *------------------------------------------------------------------------- + */ + + case H5T_INTEGER: /*------------------------------------------------------------------------- * H5T_NATIVE_SCHAR @@ -1785,238 +1819,357 @@ hsize_t diff_datum(void *_mem1, break; /* H5T_INTEGER class */ - case H5T_FLOAT: + + /*------------------------------------------------------------------------- + * H5T_FLOAT + *------------------------------------------------------------------------- + */ + + case H5T_FLOAT: + + + + /*------------------------------------------------------------------------- + * H5T_NATIVE_FLOAT + *------------------------------------------------------------------------- + */ + if (H5Tequal(m_type, H5T_NATIVE_FLOAT)) + { + float temp1_float; + float temp2_float; + int isnan1; + int isnan2; - /*------------------------------------------------------------------------- - * H5T_NATIVE_FLOAT - *------------------------------------------------------------------------- - */ + assert(type_size==sizeof(float)); - if (H5Tequal(m_type, H5T_NATIVE_FLOAT)) - { - float temp1_float; - float temp2_float; - assert(type_size==sizeof(float)); - memcpy(&temp1_float, mem1, sizeof(float)); - memcpy(&temp2_float, mem2, sizeof(float)); - - /* -d and !-p */ - if (options->d && !options->p) - { - if (ABS(temp1_float-temp2_float) > options->delta) - { - if ( print_data(options) ) - { - print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); - } - nfound++; - } - } - /* !-d and -p */ - else if (!options->d && options->p) - { + memcpy(&temp1_float, mem1, sizeof(float)); + memcpy(&temp2_float, mem2, sizeof(float)); - PER(temp1_float,temp2_float); - - if (not_comparable && !both_zero) /* not comparable */ - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); - } - options->not_cmp=1; - nfound++; - } - - else - - if ( per > options->percent && ABS(temp1_float-temp2_float) > options->delta ) - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P,temp1_float,temp2_float, - ABS(temp1_float-temp2_float), - ABS(1-temp2_float/temp1_float)); - } - nfound++; - } - } - - /* -d and -p */ - else if ( options->d && options->p) - { - - PER(temp1_float,temp2_float); - - if (not_comparable && !both_zero) /* not comparable */ - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float, - ABS(temp1_float-temp2_float)); - } - options->not_cmp=1; - nfound++; - } - - else - - if ( per > options->percent ) - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P,temp1_float,temp2_float, - ABS(temp1_float-temp2_float), - ABS(1-temp2_float/temp1_float)); - } - nfound++; - } - } - - else if (equal_float(temp1_float,temp2_float)==FALSE) - { - - if ( print_data(options) ) - { - print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); - } - nfound++; - } - - } /*H5T_NATIVE_FLOAT*/ + /* logic for detecting NaNs is different with options -d, -p and no options */ - /*------------------------------------------------------------------------- - * H5T_NATIVE_DOUBLE - *------------------------------------------------------------------------- - */ + /*------------------------------------------------------------------------- + * -d and !-p + *------------------------------------------------------------------------- + */ + if (options->d && !options->p) + { + + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_FLOAT,&temp1_float); + isnan2 = my_isnan(FLT_FLOAT,&temp2_float); + + if ( !isnan1 && !isnan2) + { + + if (ABS(temp1_float-temp2_float) > options->delta) + { + if ( print_data(options) ) + { + print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); + } + nfound++; + } + + } /* NaN */ + } + /*------------------------------------------------------------------------- + * !-d and -p + *------------------------------------------------------------------------- + */ + else if (!options->d && options->p) + { + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_FLOAT,&temp1_float); + isnan2 = my_isnan(FLT_FLOAT,&temp2_float); + + if ( !isnan1 && !isnan2) + { + + PER(temp1_float,temp2_float); + + if (not_comparable && !both_zero) /* not comparable */ + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); + } + options->not_cmp=1; + nfound++; + } + + else + + if ( per > options->percent && ABS(temp1_float-temp2_float) > options->delta ) + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P,temp1_float,temp2_float, + ABS(temp1_float-temp2_float), + ABS(1-temp2_float/temp1_float)); + } + nfound++; + } + + } /* NaN */ + } - else if (H5Tequal(m_type, H5T_NATIVE_DOUBLE)) - { - double temp1_double; - double temp2_double; - assert(type_size==sizeof(double)); - - memcpy(&temp1_double, mem1, sizeof(double)); - memcpy(&temp2_double, mem2, sizeof(double)); - /* -d and !-p */ - if (options->d && !options->p) - { - if (ABS(temp1_double-temp2_double) > options->delta) - { - if ( print_data(options) ) - { - print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT,temp1_double,temp2_double,ABS(temp1_double-temp2_double)); - } - nfound++; - } - } - /* !-d and -p */ - else if (!options->d && options->p) - { - - PER(temp1_double,temp2_double); - - if (not_comparable && !both_zero) /* not comparable */ - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P_NOTCOMP,temp1_double,temp2_double, - ABS(temp1_double-temp2_double)); - } - options->not_cmp=1; - nfound++; - } - - else - - if ( per > options->percent ) - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P,temp1_double,temp2_double, - ABS(temp1_double-temp2_double), - ABS(1-temp2_double/temp1_double)); - } - nfound++; - } - } - - - /* -d and -p */ - else if ( options->d && options->p) - { - - PER(temp1_double,temp2_double); - - if (not_comparable && !both_zero) /* not comparable */ - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P_NOTCOMP,temp1_double,temp2_double, - ABS(temp1_double-temp2_double)); - } - options->not_cmp=1; - nfound++; - } - - else - - if ( per > options->percent && - ABS(temp1_double-temp2_double) > options->delta ) - { - if ( print_data(options) ) - { - print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P,temp1_double,temp2_double, - ABS(temp1_double-temp2_double), - ABS(1-temp2_double/temp1_double)); - } - nfound++; - } - } + /*------------------------------------------------------------------------- + * -d and -p + *------------------------------------------------------------------------- + */ + + else if ( options->d && options->p) + { + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_FLOAT,&temp1_float); + isnan2 = my_isnan(FLT_FLOAT,&temp2_float); + + if ( !isnan1 && !isnan2) + { + + PER(temp1_float,temp2_float); + + if (not_comparable && !both_zero) /* not comparable */ + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float, + ABS(temp1_float-temp2_float)); + } + options->not_cmp=1; + nfound++; + } + + else + + if ( per > options->percent ) + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P,temp1_float,temp2_float, + ABS(temp1_float-temp2_float), + ABS(1-temp2_float/temp1_float)); + } + nfound++; + } + + } /* NaN */ + } + + /*------------------------------------------------------------------------- + * no -d and -p + *------------------------------------------------------------------------- + */ + else if (equal_float(temp1_float,temp2_float)==FALSE) + { + + if ( print_data(options) ) + { + print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); + } + nfound++; + } + } /*H5T_NATIVE_FLOAT*/ - else if (equal_double(temp1_double,temp2_double)==FALSE) - { - if ( print_data(options) ) - { - print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT,temp1_double,temp2_double,ABS(temp1_double-temp2_double)); - } - nfound++; - } - } /*H5T_NATIVE_DOUBLE*/ + /*------------------------------------------------------------------------- + * H5T_NATIVE_DOUBLE + *------------------------------------------------------------------------- + */ + + else if (H5Tequal(m_type, H5T_NATIVE_DOUBLE)) + { + double temp1_double; + double temp2_double; + int isnan1; + int isnan2; - break; /* H5T_FLOAT class */ + assert(type_size==sizeof(double)); + + memcpy(&temp1_double, mem1, sizeof(double)); + memcpy(&temp2_double, mem2, sizeof(double)); - } /* switch */ + /* logic for detecting NaNs is different with options -d, -p and no options */ - return nfound; + /*------------------------------------------------------------------------- + * -d and !-p + *------------------------------------------------------------------------- + */ + if (options->d && !options->p) + { -} + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_DOUBLE,&temp1_double); + isnan2 = my_isnan(FLT_DOUBLE,&temp2_double); + + if ( !isnan1 && !isnan2) + { + + if (ABS(temp1_double-temp2_double) > options->delta) + { + if ( print_data(options) ) + { + print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT,temp1_double,temp2_double,ABS(temp1_double-temp2_double)); + } + nfound++; + } + + } /* NaN */ + } + /*------------------------------------------------------------------------- + * !-d and -p + *------------------------------------------------------------------------- + */ + else if (!options->d && options->p) + { + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_DOUBLE,&temp1_double); + isnan2 = my_isnan(FLT_DOUBLE,&temp2_double); + + if ( !isnan1 && !isnan2) + { + + PER(temp1_double,temp2_double); + + if (not_comparable && !both_zero) /* not comparable */ + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P_NOTCOMP,temp1_double,temp2_double, + ABS(temp1_double-temp2_double)); + } + options->not_cmp=1; + nfound++; + } + + else + + if ( per > options->percent ) + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P,temp1_double,temp2_double, + ABS(temp1_double-temp2_double), + ABS(1-temp2_double/temp1_double)); + } + nfound++; + } + + } /* NaN */ + } + + /*------------------------------------------------------------------------- + * -d and -p + *------------------------------------------------------------------------- + */ + else if ( options->d && options->p) + { + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_DOUBLE,&temp1_double); + isnan2 = my_isnan(FLT_DOUBLE,&temp2_double); + + if ( !isnan1 && !isnan2) + { + + PER(temp1_double,temp2_double); + + if (not_comparable && !both_zero) /* not comparable */ + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P_NOTCOMP,temp1_double,temp2_double, + ABS(temp1_double-temp2_double)); + } + options->not_cmp=1; + nfound++; + } + + else + + if ( per > options->percent && + ABS(temp1_double-temp2_double) > options->delta ) + { + if ( print_data(options) ) + { + print_pos(ph,1,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P,temp1_double,temp2_double, + ABS(temp1_double-temp2_double), + ABS(1-temp2_double/temp1_double)); + } + nfound++; + } + + } /* NaN */ + } + + /*------------------------------------------------------------------------- + * no -d and -p + *------------------------------------------------------------------------- + */ + else if (equal_double(temp1_double,temp2_double)==FALSE) + { + if ( print_data(options) ) + { + print_pos(ph,0,i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT,temp1_double,temp2_double,ABS(temp1_double-temp2_double)); + } + nfound++; + } + } /*H5T_NATIVE_DOUBLE*/ + + + break; /* H5T_FLOAT class */ + + } /* switch */ + + return nfound; +} /*------------------------------------------------------------------------- * Function: all_zero @@ -2030,13 +2183,13 @@ hsize_t diff_datum(void *_mem1, static hbool_t all_zero(const void *_mem, size_t size) { - const unsigned char *mem = (const unsigned char *)_mem; + const unsigned char *mem = (const unsigned char *)_mem; - while (size-- > 0) - if (mem[size]) - return FALSE; + while(size-- > 0) + if(mem[size]) + return FALSE; - return TRUE; + return TRUE; } /*------------------------------------------------------------------------- @@ -2485,34 +2638,53 @@ hsize_t diff_float(unsigned char *mem1, hsize_t i; double per; int both_zero; + int isnan1; + int isnan2; - - /* -d and !-p */ + + /*------------------------------------------------------------------------- + * -d and !-p + *------------------------------------------------------------------------- + */ + if (options->d && !options->p) { for ( i = 0; i < nelmts; i++) { memcpy(&temp1_float, mem1, sizeof(float)); memcpy(&temp2_float, mem2, sizeof(float)); - - if (ABS(temp1_float-temp2_float) > options->delta) - { - if ( print_data(options) ) + + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_FLOAT,&temp1_float); + isnan2 = my_isnan(FLT_FLOAT,&temp2_float); + + if ( !isnan1 && !isnan2) + { + if (ABS(temp1_float-temp2_float) > options->delta) { - print_pos(ph,0,hyper_start+i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); + if ( print_data(options) ) + { + print_pos(ph,0,hyper_start+i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT,temp1_float,temp2_float,ABS(temp1_float-temp2_float)); + } + nfound++; } - nfound++; - } + } /* NaN */ mem1+=sizeof(float); mem2+=sizeof(float); if (options->n && nfound>=options->count) return nfound; - } + } /* i */ } - - /* !-d and -p */ + + /*------------------------------------------------------------------------- + * !-d and -p + *------------------------------------------------------------------------- + */ else if (!options->d && options->p) { for ( i = 0; i < nelmts; i++) @@ -2520,43 +2692,57 @@ hsize_t diff_float(unsigned char *mem1, memcpy(&temp1_float, mem1, sizeof(float)); memcpy(&temp2_float, mem2, sizeof(float)); - PER(temp1_float,temp2_float); - - if (not_comparable && !both_zero) /* not comparable */ - { - if ( print_data(options) ) - { - print_pos(ph,1,hyper_start+i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float, - ABS(temp1_float-temp2_float)); - } - options->not_cmp=1; - nfound++; - } + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_FLOAT,&temp1_float); + isnan2 = my_isnan(FLT_FLOAT,&temp2_float); - else + if ( !isnan1 && !isnan2) + { - if ( per > options->percent ) + PER(temp1_float,temp2_float); + + if (not_comparable && !both_zero) /* not comparable */ { if ( print_data(options) ) { print_pos(ph,1,hyper_start+i,acc,pos,rank,dims,obj1,obj2); printf(SPACES); - printf(F_FORMAT_P,temp1_float,temp2_float, - ABS(temp1_float-temp2_float), - ABS(1-temp2_float/temp1_float)); + printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float, + ABS(temp1_float-temp2_float)); } + options->not_cmp=1; nfound++; } - mem1+=sizeof(float); - mem2+=sizeof(float); - if (options->n && nfound>=options->count) - return nfound; - } + + else + + if ( per > options->percent ) + { + if ( print_data(options) ) + { + print_pos(ph,1,hyper_start+i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P,temp1_float,temp2_float, + ABS(temp1_float-temp2_float), + ABS(1-temp2_float/temp1_float)); + } + nfound++; + } + } /* NaN */ + mem1+=sizeof(float); + mem2+=sizeof(float); + if (options->n && nfound>=options->count) + return nfound; + } /* i */ } - /* -d and -p */ + /*------------------------------------------------------------------------- + * -d and -p + *------------------------------------------------------------------------- + */ else if ( options->d && options->p) { @@ -2565,48 +2751,81 @@ hsize_t diff_float(unsigned char *mem1, memcpy(&temp1_float, mem1, sizeof(float)); memcpy(&temp2_float, mem2, sizeof(float)); - PER(temp1_float,temp2_float); - - if (not_comparable && !both_zero) /* not comparable */ - { - if ( print_data(options) ) - { - print_pos(ph,1,hyper_start+i,acc,pos,rank,dims,obj1,obj2); - printf(SPACES); - printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float, - ABS(temp1_float-temp2_float)); - } - options->not_cmp=1; - nfound++; - } + /*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + isnan1 = my_isnan(FLT_FLOAT,&temp1_float); + isnan2 = my_isnan(FLT_FLOAT,&temp2_float); - else + if ( !isnan1 && !isnan2) + { + + PER(temp1_float,temp2_float); - if ( per > options->percent && ABS(temp1_float-temp2_float) > options->delta ) + if (not_comparable && !both_zero) /* not comparable */ { if ( print_data(options) ) { print_pos(ph,1,hyper_start+i,acc,pos,rank,dims,obj1,obj2); printf(SPACES); - printf(F_FORMAT_P,temp1_float,temp2_float, - ABS(temp1_float-temp2_float), - ABS(1-temp2_float/temp1_float)); + printf(F_FORMAT_P_NOTCOMP,temp1_float,temp2_float, + ABS(temp1_float-temp2_float)); } + options->not_cmp=1; nfound++; } - mem1+=sizeof(float); - mem2+=sizeof(float); - if (options->n && nfound>=options->count) - return nfound; - } + + else + + if ( per > options->percent && ABS(temp1_float-temp2_float) > options->delta ) + { + if ( print_data(options) ) + { + print_pos(ph,1,hyper_start+i,acc,pos,rank,dims,obj1,obj2); + printf(SPACES); + printf(F_FORMAT_P,temp1_float,temp2_float, + ABS(temp1_float-temp2_float), + ABS(1-temp2_float/temp1_float)); + } + nfound++; + } + + } /* NaN */ + mem1+=sizeof(float); + mem2+=sizeof(float); + if (options->n && nfound>=options->count) + return nfound; + } /* i */ } + + /*------------------------------------------------------------------------- + * no -d and -p + *------------------------------------------------------------------------- + */ else { + +#if defined (H5DIFF_DO_TIME) + int time; + + #if defined (WIN32) + struct _timeb *tbstart = malloc(sizeof(struct _timeb)); + struct _timeb *tbstop = malloc(sizeof(struct _timeb)); + _ftime( tbstart); + #else + struct timeb *tbstart = malloc(sizeof(struct timeb)); + struct timeb *tbstop = malloc(sizeof(struct timeb)); + ftime( tbstart); + #endif + +#endif for ( i = 0; i < nelmts; i++) { memcpy(&temp1_float, mem1, sizeof(float)); memcpy(&temp2_float, mem2, sizeof(float)); + if (equal_float(temp1_float,temp2_float)==FALSE) { @@ -2623,7 +2842,24 @@ hsize_t diff_float(unsigned char *mem1, mem2+=sizeof(float); if (options->n && nfound>=options->count) return nfound; + } /* nelmts */ + + + +#if defined (H5DIFF_DO_TIME) + + #if defined (WIN32) + _ftime( tbstop ); + #else + ftime( tbstop ); + #endif + + time = tbstop->time - tbstart->time; + printf(" TIME = %d sec\n", time ); + +#endif + } @@ -4543,7 +4779,7 @@ hsize_t diff_ullong(unsigned char *mem1, } /*------------------------------------------------------------------------- - * Function: equal_float, equal_double + * Function: equal_double * * Purpose: use a relative error formula to deal with floating point * uncertainty @@ -4552,6 +4788,7 @@ hsize_t diff_ullong(unsigned char *mem1, * October 24, 2006 * * Modifications: + * 8/1/2007. handle NaNs * *------------------------------------------------------------------------- */ @@ -4561,6 +4798,40 @@ hbool_t equal_double(double value, double expected) int both_zero; int is_zero; +#if defined (H5DIFF_DO_NAN) + +/*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + int isnan1 = my_isnan(FLT_DOUBLE,&value); + int isnan2 = my_isnan(FLT_DOUBLE,&expected); + + /*------------------------------------------------------------------------- + * we consider NaN == NaN to be true + *------------------------------------------------------------------------- + */ + if ( isnan1 && isnan2 ) + { + return TRUE; + } + + /*------------------------------------------------------------------------- + * one is a NaN, do not compare but assume difference + *------------------------------------------------------------------------- + */ + if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + { + return FALSE; + } + + /*------------------------------------------------------------------------- + * both are not NaNs, compare + *------------------------------------------------------------------------- + */ + +#endif + BOTH_ZERO(value,expected) if (both_zero) return TRUE; @@ -4576,13 +4847,60 @@ hbool_t equal_double(double value, double expected) } - +/*------------------------------------------------------------------------- + * Function: equal_float + * + * Purpose: use a relative error formula to deal with floating point + * uncertainty + * + * Programmer: pvn + * October 24, 2006 + * + * Modifications: + * 8/1/2007. handle NaNs + * + *------------------------------------------------------------------------- + */ static hbool_t equal_float(float value, float expected) { int both_zero; int is_zero; +#if defined (H5DIFF_DO_NAN) + +/*------------------------------------------------------------------------- + * detect NaNs + *------------------------------------------------------------------------- + */ + int isnan1 = my_isnan(FLT_FLOAT,&value); + int isnan2 = my_isnan(FLT_FLOAT,&expected); + + /*------------------------------------------------------------------------- + * we consider NaN == NaN to be true + *------------------------------------------------------------------------- + */ + if ( isnan1 && isnan2 ) + { + return TRUE; + } + + /*------------------------------------------------------------------------- + * one is a NaN, do not compare but assume difference + *------------------------------------------------------------------------- + */ + if ( (isnan1 && !isnan2) || ( !isnan1 && isnan2 ) ) + { + return FALSE; + } + + /*------------------------------------------------------------------------- + * both are not NaNs, compare + *------------------------------------------------------------------------- + */ + +#endif + BOTH_ZERO(value,expected) if (both_zero) return TRUE; @@ -4598,3 +4916,132 @@ hbool_t equal_float(float value, float expected) } + + +/*------------------------------------------------------------------------- + * Function: my_isnan + * + * Purpose: Determines whether VAL points to NaN. + * + * Return: TRUE or FALSE + * + * Programmer: Robb Matzke + * Monday, July 6, 1998 + * + * Modifications: + * Pedro Vicente, 12 October 2007. + * Add a string detection type for WIN32 + * + *------------------------------------------------------------------------- + */ +static int +my_isnan(dtype_t type, void *val) +{ + int retval = 0; + char s[256]; + + if (FLT_FLOAT==type) + { + float x; + HDmemcpy(&x, val, sizeof(float)); + retval = (x!=x); + + + + } + else if (FLT_DOUBLE==type) + { + double x; + HDmemcpy(&x, val, sizeof(double)); + retval = (x!=x); +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE && H5_SIZEOF_LONG_DOUBLE!=0 + } + else if (FLT_LDOUBLE==type) + { + long double x; + HDmemcpy(&x, val, sizeof(long double)); + retval = (x!=x); +#endif + } + else + { + return 0; + } + + /* + * Sometimes NaN==NaN (e.g., DEC Alpha) so we try to print it and see if + * the result contains a NaN string. + */ + if (!retval) + { + if (FLT_FLOAT==type) + { + float x; + HDmemcpy(&x, val, sizeof(float)); + sprintf(s, "%g", x); + + + } + else if (FLT_DOUBLE==type) + { + double x; + HDmemcpy(&x, val, sizeof(double)); + sprintf(s, "%g", x); +#if H5_SIZEOF_LONG_DOUBLE!=H5_SIZEOF_DOUBLE && H5_SIZEOF_LONG_DOUBLE!=0 + } + else if (FLT_LDOUBLE==type) + { + long double x; + HDmemcpy(&x, val, sizeof(long double)); + sprintf(s, "%Lg", x); +#endif + } + else + { + return 0; + } + + + if ( HDstrstr(s, "NaN") || + HDstrstr(s, "NAN") || + HDstrstr(s, "nan") || + HDstrstr(s, "-1.#IND") /* WIN32 */ + ) + { + + retval = 1; + } + + + + + } + +#ifdef H5_VMS + /* For "float" and "double" on OpenVMS/Alpha, NaN is + * actually a valid value of maximal value.*/ + if(!retval) + { + if (FLT_FLOAT==type) + { + float x; + HDmemcpy(&x, val, sizeof(float)); + retval = (x==FLT_MAX || x==-FLT_MAX); + } else if (FLT_DOUBLE==type) { + double x; + HDmemcpy(&x, val, sizeof(double)); + retval = (x==DBL_MAX || x==-DBL_MAX); + } else + { + return 0; + } + } +#endif /*H5_VMS*/ + + return retval; +} + + + + + diff --git a/tools/testfiles/h5diff_17.txt b/tools/testfiles/h5diff_17.txt index 1187a9b..3045d26 100644 --- a/tools/testfiles/h5diff_17.txt +++ b/tools/testfiles/h5diff_17.txt @@ -18,6 +18,10 @@ file1 file2 x /g1/dset8 x /g1/dset9 x /g1/fp1 + x /g1/fp15 + x /g1/fp16 + x /g1/fp17 + x /g1/fp18 x /g1/fp2 x /g2 diff --git a/tools/testfiles/h5diff_basic1.h5 b/tools/testfiles/h5diff_basic1.h5 Binary files differindex 4eb0faa..a228f94 100644 --- a/tools/testfiles/h5diff_basic1.h5 +++ b/tools/testfiles/h5diff_basic1.h5 diff --git a/tools/testfiles/h5diff_basic2.h5 b/tools/testfiles/h5diff_basic2.h5 Binary files differindex 463e0da..46285cf 100644 --- a/tools/testfiles/h5diff_basic2.h5 +++ b/tools/testfiles/h5diff_basic2.h5 |