/** * Copyright 2005-2007 ECMWF * * Licensed under the GNU Lesser General Public License which * incorporates the terms and conditions of version 3 of the GNU * General Public License. * See LICENSE and gpl-3.0.txt for details. */ /************************************** * Enrico Fucile **************************************/ #include "grib_api_internal.h" #define GRIB_EPSILON 10E-12 double grib_power(long s,long n) { double divisor = 1.0; while(s < 0) { divisor /= n; s++; } while(s > 0) { divisor *= n; s--; } return divisor; } long grib_get_binary_scale_fact(double max, double min, long bpval,int *ret) { double range = max - min; double zs = 1; long scale = 0; const long last = 127; /* Depends on edition, should be parameter */ unsigned long maxint = grib_power(bpval,2) - 1; double dmaxint=(double)maxint; *ret=0; Assert (bpval >= 1); /* printf("---- Maxint %ld range=%g\n",maxint,range); */ if(range == 0) return 0; /* range -= 1e-10; */ while( (range * zs) <= dmaxint) { scale--; zs *= 2; } while( (range * zs ) > dmaxint) { scale++; zs /= 2; } while( (unsigned long)(range * zs + 0.5) <= maxint) { scale--; zs *= 2; } while( (unsigned long)(range * zs + 0.5) > maxint) { scale++; zs /= 2; } if (scale < -last) { *ret=GRIB_UNDERFLOW; /*printf("grib_get_binary_scale_fact: max=%g min=%g\n",max,min);*/ scale = -last; } Assert(scale <= last); return scale; } long grib_get_bits_per_value(double max, double min, long binary_scale_factor) { double range = max - min; double zs = 1; long scale = 0; const long last = 127; /* Depends on edition, should be parameter */ unsigned long maxint = grib_power(binary_scale_factor,2) - 1; double dmaxint=(double)maxint; if (maxint==0) maxint=1; /* printf("---- Maxint %ld range=%g\n",maxint,range); */ if(range == 0) return 0; /* range -= 1e-10; */ while( (range * zs) <= dmaxint) { scale--;zs *= 2;} while( (range * zs ) > dmaxint) {scale++;zs /= 2;} while( (unsigned long)(range * zs + 0.5) <= maxint) { scale--; zs *= 2; } while( (unsigned long)(range * zs + 0.5) > maxint) { scale++; zs /= 2; } Assert(scale >= -last && scale <= last); /* printf("---- scale=%ld\n",scale);*/ return scale; } long grib_get_decimal_scale_fact(double max, double min, long bpval,long binary_scale) { double range = max - min; double zs = 1; long scale = 0; const long last = 127; /* Depends on edition, should be parameter */ unsigned long maxint = grib_power(bpval,2) - 1; double dmaxint=(double)maxint; range*=grib_power(-binary_scale,2); Assert (bpval >= 1); if(range == 0) return 0; while( (range * zs ) > dmaxint) { scale--; zs /= 10; } while( (range * zs) <= dmaxint) { scale++; zs *= 10; } while( (unsigned long)(range * zs + 0.5) > maxint) { scale--; zs /= 10; } while( (unsigned long)(range * zs + 0.5) <= maxint) { scale++; zs *= 10; } /* printf("grib_api: decimal_scale_fact=%ld max=%g min=%g bits_per_value=%ld binary_scale=%ld\n",scale,max,min,bpval,binary_scale); */ Assert(scale >= -last && scale <= last); return scale; }