/***************************************************************************** * * * Copyright (c) 2003-2006 Intel Corporation. * * All rights reserved. * * * ***************************************************************************** This code is covered by the Community Source License (CPL), version 1.0 as published by IBM and reproduced in the file "license.txt" in the "license" subdirectory. Redistribution in source and binary form, with or without modification, is permitted ONLY within the regulations contained in above mentioned license. Use of the name and trademark "Intel(R) MPI Benchmarks" is allowed ONLY within the regulations of the "License for Use of "Intel(R) MPI Benchmarks" Name and Trademark" as reproduced in the file "use-of-trademark-license.txt" in the "license" subdirectory. THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. EXPORT LAWS: THIS LICENSE ADDS NO RESTRICTIONS TO THE EXPORT LAWS OF YOUR JURISDICTION. It is licensee's responsibility to comply with any export regulations applicable in licensee's jurisdiction. Under CURRENT U.S. export regulations this software is eligible for export from the U.S. and can be downloaded by or otherwise exported or reexported worldwide EXCEPT to U.S. embargoed destinations which include Cuba, Iraq, Libya, North Korea, Iran, Syria, Sudan, Afghanistan and any other country to which the U.S. has embargoed goods and services. *************************************************************************** For more documentation than found here, see [1] doc/ReadMe_IMB.txt [2] Intel (R) MPI Benchmarks Users Guide and Methodology Description In doc/IMB_ug.pdf A collection of auxiliary functions ONLY for the CHECK mode of IMB =================================================================== File: IMB_chk_diff.c Implemented functions: IMB_chk_dadd; IMB_ddiff; IMB_show; IMB_err_msg; IMB_chk_diff; IMB_cmp_cat; IMB_chk_contiguous; IMB_chk_distr; IMB_chk_contained; IMB_compute_crc; ***************************************************************************/ #include "IMB_declare.h" #include "IMB_benchmark.h" #include "IMB_prototypes.h" void IMB_chk_dadd(void* AUX, int Locsize, int buf_pos, int rank0, int rank1) /* Auxiliary, only for checking mode; Creates reference accumulated values in a given buffer section, accumulated over given processor ranks Input variables: -Locsize (type int) Size of buffer section to check -buf_pos (type int) Start position of buffer section -rank0 (type int) -rank1 (type int) Process' values between rank0 and rank1 are accumulated In/out variables: -AUX (type void*) Contains accumulated values */ { /* Sum up all process' data buffers in certain window */ int i, rank; for(i=0; i 0 ) { for(i =0; i TOL ) { D=1.; *fault_pos = (i-1)*asize; } return D; } void IMB_show(char* text, struct comm_info* c_info, void* buf, int loclen, int totlen, int j_sample, POSITIONING fpos) /* Shows an excerpt of erroneous buffer if occurs in check mode Input variables: -text (type char*) Accompanying text to put out -loclen (type int) Local length of buffer -totlen (type int) Total length of buffer (for gathered or shared access buffers) -j_sample (type int) Number of sample the error occurred -fpos (type POSITIONING) File positionning (if relevant) -c_info (type struct comm_info*) Collection of all base data for MPI; see [1] for more information -buf (type void*) Given check buffer */ { int i; fprintf(unit,"Process %d: %s",c_info->rank,text); fprintf(unit,"\n"); #ifdef DEBUG int j; fprintf(dbg_file,"Process %d: %s",c_info->rank,text); fprintf(dbg_file,"\n"); #endif #ifdef MPIIO { MPI_Offset Offset; switch(fpos) { case indv_block: Offset = (MPI_Offset)(j_sample*totlen); break; case explicit: Offset = c_info->split.Offset+(MPI_Offset)(j_sample*totlen); break; case private: Offset = (MPI_Offset)(j_sample*loclen); break; case shared: Offset = (MPI_Offset)(-1); break; } if( fpos == shared ) fprintf(unit,"Overall size = %d, Portion = %d, #sample= %d\n",totlen,loclen,j_sample); else if( fpos != -1 ) fprintf(unit,"Overall size = %d, Portion = %d, Startpos = %ld\n",totlen,loclen,(long)Offset); #ifdef DEBUG if( fpos == shared ) fprintf(dbg_file,"Overall size = %d, Portion = %d, #sample= %d\n",totlen,loclen,j_sample); else if( fpos != -1 ) fprintf(dbg_file,"Overall size = %d, Portion = %d, Startpos = %ld\n",totlen,loclen,(long)Offset); #endif } #endif if( loclen < asize ) { if( loclen == 0 ) { fprintf(unit,"Buffer empty\n"); #ifdef DEBUG fprintf(dbg_file,"Buffer empty\n"); #endif } else { fprintf(unit,"Buffer in bytewise int representation: "); for (i = 0; i= 2*asize) fprintf(unit,"Buffer, 1st and last entry: "); else fprintf(unit,"Buffer entry: "); #ifdef BUFFERS_INT fprintf(unit,"%d ",((assign_type*)buf)[0]); if(loclen>=2*asize) fprintf(unit,"%d ",((assign_type*)buf)[loclen/asize-1]); #endif #ifdef BUFFERS_FLOAT fprintf(unit,"%f ",((assign_type*)buf)[0]); if(loclen>=2*asize) fprintf(unit,"%f ",((assign_type*)buf)[loclen/asize-1]); #endif fprintf(unit,"\n"); #ifdef DEBUG if(err_flag) for(j=0; jrank,text,totsize,j_sample); } #ifdef CHECK void IMB_chk_diff(char* text, struct comm_info* c_info, void* RECEIVED, int buf_pos, int Locsize, int Totalsize, int unit_size, DIRECTION mode, POSITIONING fpos, int n_sample, int j_sample, int source, double* diff ) /* Checks a received buffer against expected ref values Input variables: -text (type char*) Accompanying text -c_info (type struct comm_info*) Collection of all base data for MPI; see [1] for more information -RECEIVED (type void*) The buffer to be checked -buf_pos (type int) Beginning position (in units -> unit_size) -Locsize (type int) Local buffer size -Totalsize (type int) Total buffer size (in case of gathered buffers) -unit_size (type int) Base unit for positioning -mode (type DIRECTION) Direction of the action that took place -fpos (type POSITIONING) File positioning of the action that took place (if relevant) -n_sample (type int) # overall samples -j_sample (type int) current sample -source (type int) Sending process (if relevant) Output variables: -diff (type double*) The error against expected values */ { #ifdef MPIIO MPI_File restore; MPI_Status stat; double def_tmp; int j, j1, j2, ierr, rank, pos1, pos2, allpos; int *lenj, *rankj; #endif double defloc; int faultpos, pos; int* lengths, *all_ranks, Npos; if( err_flag ) return; defloc = 0.; faultpos = -1; if( Totalsize<= 0 ) return; #ifdef MPIIO if( mode == put ) { if( c_info -> File_rank == 0 ) { IMB_alloc_buf(c_info,"Write check",0,Totalsize); ierr = MPI_File_open(MPI_COMM_SELF, c_info->filename, c_info->amode, c_info->info, &restore); IMB_err_hand(1,ierr); if(source == -3 ) { IMB_i_alloc(&lengths,c_info->File_num_procs*n_sample+n_sample-1,"chk_diff 1"); IMB_i_alloc(&all_ranks,c_info->File_num_procs*n_sample+n_sample-1,"chk_diff 2"); } else { IMB_i_alloc(&lengths,c_info->File_num_procs,"chk_diff 1a"); IMB_i_alloc(&all_ranks,c_info->File_num_procs,"chk_diff 2a"); } lenj = lengths; rankj = all_ranks; allpos = 0; if( j_sample < 0 ) { j1=0; j2=n_sample-1; } else { j1 = j_sample; j2=j_sample; } ierr = MPI_File_seek(restore,(MPI_Offset)(j1*Totalsize),MPI_SEEK_SET); MPI_ERRHAND(ierr); for( j=j1; j<=j2 && faultpos<0 ; j++ ) { ierr = MPI_File_read (restore,c_info->r_buffer,Totalsize,c_info->etype,&stat); MPI_ERRHAND(ierr); RECEIVED = c_info->r_buffer; if( source == -3 ) { IMB_cmp_cat(c_info, RECEIVED, Totalsize, buf_pos, unit_size, 1, lenj, rankj, &Npos, &faultpos, &def_tmp); lenj += Npos; rankj += Npos; allpos+= Npos; } else { IMB_cmp_cat(c_info, RECEIVED, Totalsize, buf_pos, unit_size, 0, lenj, rankj, &Npos, &faultpos, &def_tmp); } defloc = max(defloc,def_tmp); } MPI_File_close(&restore); j_sample = j-1; IMB_free_aux(); if( faultpos >= 0 ) { IMB_err_msg(c_info,text,Totalsize,j_sample); fprintf(unit, "Error: restored buffer from output file, invalid portion starting at pos. %d\n", (j_sample*Totalsize)+faultpos); AUX = (void*)(((char*)RECEIVED)+faultpos); IMB_show("Erroneous data:",c_info,AUX,Totalsize-faultpos,Totalsize-faultpos, j_sample,-1); } else { if( source == -3 ) { IMB_chk_distr(c_info, Totalsize, n_sample, lengths, all_ranks, allpos, &def_tmp); if( def_tmp > 0. ) { IMB_err_msg(c_info,text,Totalsize,j_sample); IMB_show("restored buffer from output file, has permuted data: ", c_info,RECEIVED,Totalsize,Totalsize,j_sample,-1); } } defloc = max(defloc,def_tmp); } IMB_del_r_buf(c_info); free(lengths); free (all_ranks); } } if( mode == get ) { int file_pos; file_pos = j_sample*Totalsize; *diff=0.; IMB_alloc_aux(Totalsize," chk_diff 5"); IMB_init_file_content(AUX, file_pos, file_pos+Totalsize-1); IMB_chk_contained(RECEIVED, Locsize, AUX, Totalsize, &pos, &faultpos, &def_tmp, "Compare received portion with file Content"); IMB_get_rank_portion(c_info->File_rank,c_info->File_num_procs,Totalsize,asize, &pos1, &pos2); if( faultpos >= 0 ) { err_flag=1; defloc = 1; IMB_err_msg(c_info,text,Totalsize,j_sample); RECEIVED = (void*)((char*)RECEIVED+faultpos); fprintf(unit,"File position: %d\n",file_pos+pos+faultpos); IMB_show( "Read invalid portion: ",c_info, RECEIVED, Locsize-faultpos, Totalsize, j_sample, fpos); AUX = (void*)((char*)AUX + pos + faultpos); IMB_show( "Expected portion: ",c_info, AUX, Locsize-pos-faultpos, Locsize-pos-faultpos, j_sample, -1); MPI_Gather(&pos,1,MPI_INT,c_info->rdispl,1,MPI_INT,0,c_info->File_comm); } else { if( source == -2 && Locsize > 0 ) { IMB_get_rank_portion(c_info->File_rank,c_info->File_num_procs,Totalsize,asize, &pos1, &pos2); if( pos1 != pos ) defloc = 1; } if( source == -3 ) { /* Check permuted buffer */ MPI_Gather(&pos,1,MPI_INT,c_info->rdispl,1,MPI_INT,0,c_info->File_comm); MPI_Gather(&Locsize,1,MPI_INT,c_info->reccnt,1,MPI_INT,0,c_info->File_comm); if( c_info->File_rank == 0 ) { IMB_chk_contiguous(c_info, c_info->rdispl, c_info->reccnt, &defloc ); } else defloc=0.; } if( defloc > 0. ) IMB_err_msg(c_info,"Wrong portion ordering in read buffer",Totalsize,j_sample); } defloc = max(defloc,def_tmp); } #else if( source >= 0 ) { IMB_alloc_aux(Totalsize,"chk_diff 6"); IMB_ass_buf(AUX, source, buf_pos, buf_pos+Totalsize-1, 1); if( Totalsize < asize ) { IMB_chk_contained(RECEIVED, Totalsize, AUX, Totalsize, &pos, &faultpos, &defloc, "Compare received with expected portion"); if( faultpos>=0 ) {faultpos = 0; defloc = 1.;} } else defloc = IMB_ddiff((assign_type *)AUX, (assign_type *)RECEIVED, Totalsize/asize,&faultpos); IMB_free_aux(); } else if( source == -1 ) { IMB_alloc_aux(Locsize,"chk_diff 7"); IMB_chk_dadd(AUX,Locsize,buf_pos,0,c_info->num_procs-1); defloc = IMB_ddiff((assign_type *)AUX, (assign_type *)RECEIVED, Locsize/asize,&faultpos); IMB_free_aux(); } else { if( source == -2 ) { lengths = all_ranks = NULL; IMB_cmp_cat(c_info, RECEIVED, Totalsize, buf_pos, unit_size, 0, lengths, all_ranks, &Npos, &faultpos, &defloc); } } if( faultpos >= 0 ) { void* tmp = (void*)(((char *)RECEIVED)+faultpos); IMB_err_msg(c_info,text,Totalsize,j_sample); IMB_show( "Got invalid buffer: ",c_info, tmp, asize, asize, j_sample, -1); fprintf(unit,"pos: %d\n",faultpos); tmp = (void*)(((char *)AUX )+faultpos); IMB_show( "Expected buffer: ",c_info, tmp, asize, asize, j_sample, -1); defloc = 1; } #endif if( defloc > TOL ) err_flag = 1; *diff = max(*diff,defloc); } void IMB_cmp_cat(struct comm_info *c_info, void* RECEIVED, int size, int bufpos, int unit_size, int perm, int* lengths, int*ranks, int* Npos, int *faultpos, double* diff) /* Checks a received buffer which is a concatenation of several processes' buffers Input variables: -c_info (type struct comm_info *) Collection of all base data for MPI; see [1] for more information -RECEIVED (type void*) The buffer to be checked -size (type int) Size of the buffer -bufpos (type int) First position to check (in units -> unit_size) -unit_size (type int) Base unit of positioning -perm (type int) Logical flag: 1 iff the different rank's portions are potentially in non natural order (relevant for shared file accesses) Output variables: -lengths (type int*) An array of lengths (of a number of erroneous portions) -ranks (type int*) An array of ranks (the erroneous portions belong to) -Npos (type int*) Numer of erroneous portions found (=size of 'lengths' and 'ranks' arrays) -faultpos (type int *) Position of first found fault -diff (type double*) Diff value */ { int rank, NP, pos1, pos2, pos, rsize, rem_size; int chk_ok; assign_type *a,*r; double tmp_diff; *diff = 0.; *faultpos = -1; #ifdef MPIIO NP = c_info->File_num_procs; #else NP = c_info->num_procs; #endif rsize = (size+asize-1)/asize*asize; IMB_alloc_aux(rsize, "chk_diff 8"); r = (assign_type*)AUX; a = (assign_type*)RECEIVED; chk_ok = 0; if(perm) { *Npos = 0; pos = 0; /* Check beginning of buffer */ for( rank=0; rank=0) { if( rsize <= asize ) chk_ok=1; else { rem_size = rsize-pos; IMB_chk_contained((void*)(r+pos/asize), rem_size, RECEIVED, rem_size, &pos1, faultpos, &tmp_diff, "Check of first part of received buffer"); if( *faultpos < 0 && pos1>=0 ) { lengths[*Npos] = rem_size; ranks[*Npos] = rank; pos = rem_size; (*Npos)++; chk_ok=1; } } } } if( !chk_ok ) { *faultpos = 0; *diff = 1.; } while( (pos < size) && chk_ok ) { chk_ok = 0; for( rank=0; rank 0 ) { rem_size = min(rsize,size-pos); IMB_ass_buf(AUX, rank, 0, rsize-1, 1); IMB_chk_contained(AUX,rem_size,(void*)(a+pos/asize),rem_size,&pos1, faultpos,&tmp_diff,NULL); if( *faultpos < 0 && pos1 >= 0 ) { lengths[*Npos] = rem_size; ranks[*Npos] = rank; pos = pos+rsize; (*Npos)++; chk_ok = 1; } } /* end if(rsize>0) */ } /* end for(rank..) */ if( !chk_ok ) { *faultpos = pos; *diff = 1; } } /* end while */ } /* end if(perm) */ else { int curr=0; void* tmp; for( rank=0; rank=0 ; rank++ ) { IMB_get_rank_portion(rank, NP, size, unit_size, &pos1, &pos2); rsize = pos2-pos1+1; tmp = (void*)(((char*)RECEIVED)+curr); IMB_ass_buf(AUX, rank, bufpos, bufpos+rsize-1, 1); IMB_chk_contained(AUX,rsize,tmp,rsize,&pos1,faultpos, &tmp_diff,""); *diff = max(*diff,tmp_diff); if(*faultpos<0 && pos1>= 0 ) curr+=rsize; else { *faultpos += curr; *diff = 1; curr = -1; } } } } void IMB_chk_contiguous(struct comm_info *c_info, int* rdispl, int* sizes, double*diff) /* Checks whether arrays of displacements/sizes form a contiguous buffer Input variables: -c_info (type struct comm_info *) Collection of all base data for MPI; see [1] for more information -rdispl (type int*) Array of displacements (one for each process) -sizes (type int*) Array of sizes (one for each process) Output variables: -diff (type double*) 0 if contiguous, 1 else */ { int i, j, NP, rank, p; #ifdef MPIIO NP = c_info->File_num_procs; #else NP = c_info->num_procs; #endif for(i=0; i TOL ) { fprintf(unit,"check of contiguity of received buffer portions failed\n"); fprintf(unit,"Got the following portions/displacements:\n"); for(rank = 0; rankFile_num_procs; #else NP = c_info->num_procs; #endif for( rank=0; rankreccnt[rank]=0; } i=0; while (ireccnt[rank]++; } else if( ireccnt[rank]++; i++;} } i++; } *diff = 0.; for( rank=0; rank= pos1 && c_info->reccnt[rank] != n_sample ) *diff = 1; } if( *diff > TOL ) { fprintf(unit,"check of contiguity of received buffer portions failed\n"); fprintf(unit,"Got the following portions/from process:\n"); for(i=0; i w_size ) { *pos = 0; *fpos = 0; } else { if( p_size < asize ) { pcrc = IMB_compute_crc ((char*)part, p_size); *pos = 0; wcrc = pcrc-1; while( *pos <= w_size-p_size && wcrc != pcrc ) { void* h; h = (void*)(((char*)whole)+*pos); wcrc = IMB_compute_crc ((char*)h, p_size); if(wcrc!=pcrc) (*pos)++; } if( *pos <= w_size-p_size ) *D=0.; else {*pos=0; *fpos = 0; *D=1.;} } else { *pos = 0; w_len = w_size/asize; p_len = p_size/asize; while( *pos <= w_len-p_len && A_ABS(a_part[0] - a_whole[*pos]) > TOL ) (*pos)++; if( *pos <= w_len-p_len ) { *D = IMB_ddiff(a_part, a_whole+*pos, p_len, fpos); } else {*D=1.; *pos=0; *fpos = 0; } *pos *= asize; } } if( *fpos >= 0 ) *D=1.; } /********************* CHECKSUM ********************/ /* Most of following CRC-32 stuff is from zmodem source code */ /* I claim no copyright over the contents of this file. -- Rahul Dhesi */ /* Checksum: 951252172 (check or update this with "brik") */ #define INITCRC 0xFFFFFFFFL /* * Copyright (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. */ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static long crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; long IMB_compute_crc (register char* buf, register int size) /* In/out variables: -buf (type register char*) -size (type register int) Return value (type long) */ { long crccode = INITCRC; if( size <= 0 ) crccode = 0; else { int i; for (i = 0; i < size; i ++) { crccode = crc_32_tab[(int) ((crccode) ^ (buf[i])) & 0xff] ^ (((crccode) >> 8) & 0x00FFFFFFL); } } return(crccode); } #endif