/* * (C) Copyright 2005- ECMWF. * * This software is licensed under the terms of the Apache Licence Version 2.0 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. * * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction. */ #include #include #include #include "grib_api_internal.h" #define NO_PRINT 1 #define PRINT_ALL (1<<1) #define PRINT_ROUND_ERRORS (1<<2) #define PRINT_TRUNCATION (1<<3) #define NO_NEAREST_SMALLER_IBM_FLOAT (1<<4) void test_bits(double x,unsigned long mode) { double y=0,z=0,w=0,t=0; double dy=0,dz=0,dw=0,dt=0; unsigned long i=0,j=0,k=0,l=0; i=grib_ibm_to_long(x); y=grib_long_to_ibm(i); dy=y-x; z=grib_long_to_ibm(j); dz=z-x; k=grib_ibm_nearest_smaller_to_long(x); w=grib_long_to_ibm(k); dw=w-x; if ( !(mode & NO_NEAREST_SMALLER_IBM_FLOAT) ) { t=grib_nearest_smaller_ibm_float(x); l=grib_ibm_to_long(y); dt=t-x; } if (mode & PRINT_ALL) { printf("x=%.20e \n",x); printf("grib_ibm_to_long %lu (0x%lx) -> %.20e diff=%.20e\n",i,i,y,dy); printf("grib_nearest_smaller_ibm_float %lu (0x%lx) -> %.20e diff=%.20e\n",l,l,t,dt); printf("grib_ibm_nearest_smaller_to_long %lu (0x%lx) -> %.20e diff=%.20e\n",k,k,w,dw); } if (fabs(dz) < fabs(dy) && ( (mode & PRINT_ROUND_ERRORS )| (mode & PRINT_ALL ) )) { printf("!!!!!!!!!!-------------- Rounding error \n"); printf("x=%.20e \n",x); printf("grib_ibm_to_long %lu (0x%lx) -> %.20e diff=%.20e\n",i,i,y,dy); printf("grib_ibm_to_long_trunc %lu (0x%lx) -> %.20e diff=%.20e\n",j,j,z,dz); printf("grib_nearest_smaller_ibm_float %lu (0x%lx) -> %.20e diff=%.20e\n",l,l,t,dt); printf("grib_ibm_nearest_smaller_to_long %lu (0x%lx) -> %.20e diff=%.20e\n",k,k,w,dw); } if (( w != t) && ( (mode & PRINT_TRUNCATION ) | ( mode & PRINT_ALL ) ) ) { printf("!!!!!!!!!!--------------- Different nearest smaller \n"); printf("x=%.20e \n",x); printf("grib_ibm_to_long %lu (0x%lx) -> %.20e diff=%.20e\n",i,i,y,dy); printf("grib_ibm_to_long_trunc %lu (0x%lx) -> %.20e diff=%.20e\n",j,j,z,dz); printf("grib_nearest_smaller_ibm_float %lu (0x%lx) -> %.20e diff=%.20e\n",l,l,t,dt); printf("grib_ibm_nearest_smaller_to_long %lu (0x%lx) -> %.20e diff=%.20e\n",k,k,w,dw); } } void print_machine_parameters() { int ibeta=0, it=0, irnd=0, ngrd=0, machep=0, negep=0, iexp=0, minexp=0, maxexp=0; float eps=0, epsneg=0, xmin=0, xmax=0; printf("-- Machine parameters ---\n"); printf("ibeta=%d\n",ibeta); printf("it=%d\n",it); printf("irnd=%d\n",irnd); printf("ngrd=%d\n",ngrd); printf("machep=%d\n",machep); printf("negep=%d\n",negep); printf("iexp=%d\n",iexp); printf("minexp=%d\n",minexp); printf("maxexp=%d\n",maxexp); printf("eps=%g\n",eps); printf("epsneg=%g\n",epsneg); printf("xmin=%.20e\n",xmin); printf("xmax=%.20e\n",xmax); printf("-------------------------\n\n"); } int main(int argc, char *argv[]) { double x,y,z,w,d,eps,epst,epsh; double dt=0; unsigned long i,j,n,nc,c,m; unsigned long seed=123; unsigned char ibm[4]; float xf=0; int r; unsigned long iminp=0x00100000, imaxp=0x7fffffff; unsigned long iminn=0x80100000, imaxn=0xffffffff; double dminp=0,dmaxp=0,dminn=0,dmaxn=0; double dminpn=0,dmaxpp=0,dminnn=0,dmaxnp=0; unsigned long A; long e; int k,cc; dminp=grib_long_to_ibm(iminp); dminpn=grib_long_to_ibm(iminp+1); dmaxp=grib_long_to_ibm(imaxp); dmaxpp=grib_long_to_ibm(imaxp-1); dminn=grib_long_to_ibm(iminn); dminnn=grib_long_to_ibm(iminn+1); dmaxn=grib_long_to_ibm(imaxn); dmaxnp=grib_long_to_ibm(imaxn-1); x=-1.33642013258103330000e-83; i=grib_ibm_to_long(x); j=grib_ibm_nearest_smaller_to_long(x); printf("grib_ibm_to_long(%.20e)=0x%lX grib_long_to_ibm(0x%lX)=%.20e grib_ibm_nearest_smaller_to_long(%.20e)=0x%lX\n", x,i,i,grib_long_to_ibm(i),x,j); printf("grib_long_to_ibm(grib_ibm_nearest_smaller_to_long(%.20e))=%.20e\n",x,grib_long_to_ibm(j)); exit(0); /* if (argc > 1 ) { x=atof(argv[1]); test_bits(x,PRINT_ALL); printf("-----------------\n"); exit(0); } */ /* i=0x49800000; x=grib_long_to_ibm(i); j=grib_ibm_to_long(x); printf(" grib_long_to_ibm(0x%lX)=%.8e grib_ibm_to_long(grib_long_to_ibm(0x%lX))=0x%lX\n",i,x,i,j); exit(0); */ printf("-------------------------------- ibm float -------------------------------\n"); printf("Min positive 0x%lX -> %.8e ",iminp,dminp); printf("-- next 0x%lX -> %.8e diff=%.3e\n",iminp+1,dminpn,dminp-dminpn); printf("Max positive 0x%lX -> %.8e ",imaxp,dmaxp); printf("-- prev 0x%lX -> %.8e diff= %.3e\n",imaxp-1,dmaxpp,dmaxp-dmaxpp); printf("Min negative 0x%lX -> %.8e ",iminn,dminn); printf("-- next 0x%lX -> %.8e diff= %.3e\n",iminn+1,dminnn,dminn-dminnn); printf("Max negative 0x%lX -> %.8e ",imaxn,dmaxn); printf("-- prev 0x%lX -> %.8e diff=%.3e\n",imaxn-1,dmaxnp,dmaxn-dmaxnp); printf("%lu negative values, %lu positive values\n",(imaxn-iminn),(imaxp-iminp)); printf("--------------------------------------------------------------------------\n"); fflush(stdout); #if 0 if (0) { printf("---- Test --------- ibm_to_long(long_to_ibm()) ---------------------------\n"); nc=((imaxn-iminp))/100; c=0; for (i=iminp;i=nc) { printf("%d - %lu 0x%lX\n",cc,i-iminp,i);fflush(stdout); c=0;cc++; } A = (i & 0x7f000000) >> 24; e = A-70; eps=1; m = (i & 0xffffff); /* printf("---m=0x%lX\n",m); */ eps=grib_ibm_table_e(A); epsh=eps/2; epst=eps/3; y=grib_long_to_ibm(i); if (grib_ibm_to_long(y) != i) { printf("------ grib_long_to_ibm(grib_ibm_to_long()) Failure -----------------\n"); printf("i=0x%lX\n",i); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i,grib_long_to_ibm(i)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i-1,grib_long_to_ibm(i-1)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i+1,grib_long_to_ibm(i+1)); printf("eps=%.20e\n",eps); printf("y=%.20e grib_ibm_to_long(y)=0x%lX grib_long_to_ibm(grib_ibm_to_long(y))=%.20e\n",y,j,z); printf("fabs(grib_long_to_ibm(grib_ibm_to_long(y))-y)=%.20e \n",d); printf("--------------------------------------------------------\n"); fflush(stdout); exit(1); } for (k=1;k<3;k++) { if (i == 0x7FFFFFFF) continue; if (y>0) y+=epst; else y-=epst; /* rounding test */ j=grib_ibm_to_long(y); z=grib_long_to_ibm(j); d=fabs(z-y); if ( d > epsh ) { printf("---------------- Rounding Failure ----------------------\n"); printf("i=0x%lX\n",i); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i,grib_long_to_ibm(i)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i-1,grib_long_to_ibm(i-1)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i+1,grib_long_to_ibm(i+1)); printf("eps=%.20e\n",eps); printf("y=%.20e grib_ibm_to_long(y)=0x%lX grib_long_to_ibm(grib_ibm_to_long(y))=%.20e\n",y,j,z); printf("fabs(grib_long_to_ibm(grib_ibm_to_long(y))-y)=%.20e \n",d); printf("--------------------------------------------------------\n"); fflush(stdout); exit(1); } /* nearest smaller test */ j=grib_ibm_nearest_smaller_to_long(y); z=grib_long_to_ibm(j); d=z-y; if ( d > 0 ) { printf("---------------- Nearest smaller Failure ---------------\n"); printf("i=0x%lX\n",i); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i-1,grib_long_to_ibm(i-1)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i,grib_long_to_ibm(i)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i+1,grib_long_to_ibm(i+1)); printf("eps=%.20e d=%.20e\n",eps,d); printf(" y=%.20e grib_ibm_nearest_smaller_to_long(y)=0x%lX\n",y,j); printf("grib_long_to_ibm(0x%lX)=%.20e\n",j,z); printf("--------------------------------------------------------\n"); fflush(stdout); exit(1); } if ( abs(d) > eps ) { printf("---------------- Nearest smaller warning ---------------\n"); printf("i=0x%lX\n",i); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i-1,grib_long_to_ibm(i-1)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i,grib_long_to_ibm(i)); printf("grib_long_to_ibm(0x%lX)=%.20e \n", i+1,grib_long_to_ibm(i+1)); printf("eps=%.20e d=%.20e\n",eps,d); printf(" y=%.20e grib_ibm_nearest_smaller_to_long(y)=0x%lX\n",y,j); printf("grib_long_to_ibm(0x%lX)=%.20e\n",j,z); printf("--------------------------------------------------------\n"); fflush(stdout); } } c++; } printf("\n--- test finished ---------------------------------\n"); return 0; }