////////////////////////////////////////////////////////////////////////////////////// // CRUNCEP_1901_2015.H // Header file for input from a fast data archive // Created automatically by FastArchive on Mon Sep 12 18:08:07 2016 // // The following #includes should appear in your source code file: // // #include // #include // #include // #include "/data/cruncep_v7/to_fast_archive_conversion/nc_monthly_files_verJuly1//cruncep_1901_2015.h" // // Functionality to retrieve data from the archive is provided by class Cruncep_1901_2015Archive. // The following public functions are provided: // // bool open(char* filename) // Attempts to open the specified file as a fast data archive. The format must be // exactly compatible with this version of cruncep_1901_2015.h (normally the archive and // header file should have been produced together by the same program using class // CFastArchive). Returns false if the file could not be opened or had format // errors. open() with no argument is equivalent to open("cruncep_1901_2015.bin"). // // void close() // Closes the archive (if open). // // bool rewind() // Sets the file pointer to the first record in the archive file. Returns false if // no archive file is currently open. // // bool getnext(Cruncep_1901_2015& obj) // Retrieves the next record in the archive file and advances the file pointer to // the next record. Data are written to the member variables of obj. Returns false if // no archive file is currently open or if the file pointer is beyond the last // record. Use rewind() and getnext() to retrieve data sequentially from the archive. // // bool getindex(Cruncep_1901_2015& obj) // Searches the archive for a record matching the values specified for the index // items (lon and lat) in obj. If a matching record is found, the data are // written to the member variables of obj. Returns true if the archive was open and // a matching record was found, otherwise false. The search is iterative and fast. // // Sample program: // // Cruncep_1901_2015Archive ark; // Cruncep_1901_2015 data; // bool success,flag; // // // Retrieve all records in sequence and print values of lon and lat: // // success=ark.open("cruncep_1901_2015.bin"); // if (success) { // flag=ark.rewind(); // while (flag) { // flag=ark.getnext(data); // if (flag) // printf("Loaded record: lon=%g, lat=%g\n",data.lon,data.lat); // } // } // // // Look for a record with lon=-180, lat=-90: // // data.lon=-180; // data.lat=-90; // success=ark.getindex(data); // if (success) printf("Found it!\n"); // else printf("Not found\n"); // // ark.close(); struct Cruncep_1901_2015 { // Index part double lon; double lat; // Data part double mtemp[1380]; double mprec[1380]; double mswrad[1380]; double soilcode[1]; }; const long CRUNCEP_1901_2015_NRECORD=59191; const int CRUNCEP_1901_2015_DATA_LENGTH=12422; const int CRUNCEP_1901_2015_INDEX_LENGTH=7; const int CRUNCEP_1901_2015_HEADERSIZE=659; unsigned char CRUNCEP_1901_2015_HEADER[CRUNCEP_1901_2015_HEADERSIZE-4]={ 0x01,0x02,0x93,0x00,0x00,0x00,0x07,0x00,0x02,0x04,0x6C,0x6F,0x6E,0x00,0x2D,0x31,0x38,0x30,0x00,0x00, 0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95, 0xD3,0x9D,0x42,0x7F,0x00,0x00,0x31,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00, 0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x30,0x2E, 0x32,0x35,0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00, 0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x0B,0x04,0x6C,0x61,0x74,0x00,0x2D,0x39,0x30,0x00, 0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00, 0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x39,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01, 0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00, 0x30,0x2E,0x32,0x35,0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00, 0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x0A,0x00,0x00,0x30,0x86,0x00,0x04,0x06, 0x6D,0x74,0x65,0x6D,0x70,0x00,0x2D,0x31,0x30,0x30,0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00, 0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x31,0x30, 0x30,0x00,0x00,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00, 0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x30,0x2E,0x30,0x30,0x31,0x00,0x00,0x00,0xA0,0xB5, 0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F, 0x00,0x00,0x12,0x00,0x00,0x05,0x64,0x06,0x6D,0x70,0x72,0x65,0x63,0x00,0x30,0x00,0x05,0x64,0x31,0x00, 0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95, 0xD3,0x9D,0x42,0x7F,0x00,0x00,0x31,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00, 0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x30,0x2E, 0x30,0x30,0x30,0x31,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00, 0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x1B,0x00,0x00,0x05,0x64,0x07,0x6D,0x73,0x77,0x72, 0x61,0x64,0x00,0x30,0x00,0x05,0x64,0x30,0x31,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2, 0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x31,0x30,0x30,0x30,0x30, 0x30,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15, 0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x30,0x2E,0x30,0x30,0x31,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00, 0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x1B, 0x00,0x00,0x05,0x64,0x09,0x73,0x6F,0x69,0x6C,0x63,0x6F,0x64,0x65,0x00,0x30,0x00,0x05,0x64,0x31,0x00, 0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95, 0xD3,0x9D,0x42,0x7F,0x00,0x00,0x35,0x30,0x00,0x64,0x31,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00, 0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x30,0x2E, 0x31,0x00,0x31,0x00,0x00,0x00,0xA0,0xB5,0xBF,0x01,0x00,0x00,0x00,0x00,0xD2,0x00,0x41,0x00,0x00,0x00, 0x00,0x00,0x15,0x95,0xD3,0x9D,0x42,0x7F,0x00,0x00,0x09,0x00,0x00,0x00,0x01}; class Cruncep_1901_2015Archive { private: FILE* pfile; long recno; long datano; unsigned char pindex[CRUNCEP_1901_2015_INDEX_LENGTH]; unsigned char pdata[CRUNCEP_1901_2015_DATA_LENGTH]; bool iseof; long readbin(int nbyte) { unsigned char buf[4]; long mult[4]={0x1000000,0x10000,0x100,1},val; int i; fread(buf,nbyte,1,pfile); val=0; for (i=0;i>=8-nbit%8; rval+=buf*mult[i]; } } for (i=nbyte-1;i>=0;i--) { if (i>=nb) bits[i]=bits[i-nb]; else bits[i]=0; } nb=nbit%8; for (i=nbyte-1;i>=0;i--) { bits[i]>>=nb; if (i>0) { buf=bits[i-1]; buf<<=8-nb; bits[i]|=buf; } } rval=rval*scalar+offset; return rval; } void bitify(unsigned char buf[4],double fval,double offset,double scalar) { long ival = (long)((fval-offset)/scalar + 0.5); buf[0]=(unsigned char)(ival/0x1000000); ival-=buf[0]*0x1000000; buf[1]=(unsigned char)(ival/0x10000); ival-=buf[1]*0x10000; buf[2]=(unsigned char)(ival/0x100); ival-=buf[2]*0x100; buf[3]=(unsigned char)(ival); } void merge(unsigned char ptarget[3],unsigned char buf[4],int bits) { int nb=bits/8; int i; unsigned char nib; for (i=0;i<3;i++) { if (i<3-nb) ptarget[i]=ptarget[i+nb]; else ptarget[i]=0; } nb=bits%8; for (i=0;i<3;i++) { ptarget[i]<<=nb; if (i<3-1) { nib=ptarget[i+1]>>(8-nb); ptarget[i]|=nib; } } nb=bits/8; if (bits%8) nb++; for (i=1;i<=nb;i++) ptarget[3-i]|=buf[4-i]; } int compare_index(unsigned char* a,unsigned char* b) { int i; for (i=0;i<3;i++) { if (a[i]b[i]) return +1; } return 0; } bool initialise(const char* filename) { int i; unsigned char* pheader; if (pfile) fclose(pfile); pfile=fopen(filename,"rb"); if (!pfile) { printf("Could not open %s for input\n",filename); return false; } pheader=new unsigned char[CRUNCEP_1901_2015_HEADERSIZE-4]; if (!pheader) { printf("Out of memory\n"); fclose(pfile); pfile=NULL; return false; } ::rewind(pfile); fread(pheader,CRUNCEP_1901_2015_HEADERSIZE-4,1,pfile); for (i=0;i=0;i--) obj.soilcode[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,9,0.1,0); for (i=1379;i>=0;i--) obj.mswrad[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,27,0.001,0); for (i=1379;i>=0;i--) obj.mprec[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,27,0.0001,0); for (i=1379;i>=0;i--) obj.mtemp[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,18,0.001,-100); return true; } bool getindex(Cruncep_1901_2015& obj) { if (!CRUNCEP_1901_2015_NRECORD || !pfile) return false; // else unsigned char ptarget[3]={0,0,0}; unsigned char buf[4]; bitify(buf,obj.lon,-180,0.25); merge(ptarget,buf,11); bitify(buf,obj.lat,-90,0.25); merge(ptarget,buf,10); long begin = 0; long end = CRUNCEP_1901_2015_NRECORD; while (begin < end) { long middle = (begin+end)/2; getindex(middle); getdata(); int c = compare_index(pindex, ptarget); if (c < 0) { begin = middle + 1; } else if (c > 0) { end = middle; } else { for (int i=0;i>=0;i--) obj.soilcode[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,9,0.1,0); for (int i=1379;i>=0;i--) obj.mswrad[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,27,0.001,0); for (int i=1379;i>=0;i--) obj.mprec[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,27,0.0001,0); for (int i=1379;i>=0;i--) obj.mtemp[i]=popreal(pdata,CRUNCEP_1901_2015_DATA_LENGTH,18,0.001,-100); return true; } } return false; } };