Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

binarysave.c

Go to the documentation of this file.
00001 
00007 #include <stdio.h>     
00008 #include <time.h>
00009 #include <sys/types.h> /* for clock routines */
00010 
00011 #include "binarysave.h"
00012 #include "ipc.h"
00013 #include "cmdparam.h"
00014 #include "globals.h"
00015 #include "kernel.h"
00016 #define NO_ANALYZE
00017 
00018 
00019 
00020 /******************************************************************************/
00021 /* Static variables                                                           */
00022 /******************************************************************************/
00023 
00024 Tristate LISSOMBinaryStateSaver::save_afferent_weights_only=False;
00025 Tristate LISSOMBinaryStateSaver::save_all_lateral_weights=False;
00026 Tristate LISSOMBinaryStateSaver::load_afferent_weights_only=False;
00027 
00028 
00029 
00030 /******************************************************************************/
00031 /* Defines and typedefs                                                       */
00032 /******************************************************************************/
00033 
00034 /* Enable faster file reads by assuming order of data stored in file
00035    matches the current configuration of PEs
00036 */
00037 /* #define ASSUME_FIXED_PE_CONFIGURATION */
00038 
00039 /* Turns on file debugging messages when defined */
00040 /* #define LF_DEBUG_FILE */
00041 
00043 #define LF_BUFFER_VERIFY
00044 
00045 
00046 
00048 typedef f32 LFFloatType;
00049 #define LF_FLOAT_SIZE sizeof(LFFloatType)
00050 
00051 
00052 /* Binary file tokens */
00053 #define SMALLEST_LFTOK            1
00054 #define LFTOK_NO_TOKEN            0
00055 #define LFTOK_SNAPSHOT_HEADER     1
00056 #define LFTOK_ROW_HEADER          2
00057 #define LFTOK_NEURON_HEADER_ORIG  3
00058 #define LFTOK_AFF_WEIGHTS         4
00059 #define LFTOK_LEXC_WEIGHTS_OLD    5
00060 #define LFTOK_LINH_WEIGHT_CHUNK   6
00061 #define LFTOK_NEURON_TRAILER      7
00062 #define LFTOK_SNAPSHOT_TRAILER    8
00063 #define LFTOK_LEXC_WEIGHTS        9
00064 #define LFTOK_NEURON_HEADER_BUG  10 /* So named because some files using it reported an incorrect token length, confusing printTokens */
00065 #define LARGEST_LFTOK            10
00066 
00068 #define LF_UNUSED   0x00
00069 
00070 #define LF_ALL_EYES   99
00071 
00072 
00073 
00074 #define LF_FLOAT_TOLERANCE 0.0000001
00075 
00076 /* Error handling */
00077 #define LF_NO_ERROR 0
00078 #define LF_ERROR   -1
00079 
00080 #define LF_MAXWARNINGS 5
00081 
00082 
00083 /******************************************************************************/
00084 /* Initialization hook                                                        */
00085 /******************************************************************************/
00086 
00087 
00088 void  LISSOMBinaryStateSaver::binarysave_init_hook( void )
00089 {
00090   PARAM_I(PARAM_3BOOL,  load_afferent_weights_only,False,True,
00091           "If true, when loading weights, load only the afferent ones. This allows\n"
00092           "a machine with little memory to read in a file created on a much larger one,\n"
00093           "though all it can do is compute initial activations and map values which\n"
00094           "depend on them.");
00095   
00096   PARAM_I(PARAM_3BOOL,  save_afferent_weights_only,False,True,
00097           "If true, when saving weights, save only the afferent ones. This results\n"
00098           "in a much smaller file, but the resulting network is of only limited use.");
00099 
00100   PARAM_I(PARAM_3BOOL,  save_all_lateral_weights,False,True,
00101           "If true, when saving weights, save all lateral weights whether\n"
00102           "they are negative or not.");
00103 }
00104 
00105 
00106 
00107 /******************************************************************************/
00108 /* File processing routines                                                   */
00109 /******************************************************************************/
00110 
00111 
00113 int LISSOMBinaryStateSaver::binaryWeightsFileWrite( FILE *file )
00114 { 
00115   int current_local_row;
00116   int part_of_row;
00117   time_t start_time, end_time;
00118 
00119   /* reset everything */
00120   tokensWritten = 0;
00121   status = 0;
00122   errorsEncountered = 0;
00123   
00124   /* The last PE is in charge of writing */
00125   if (AMYOUNGESTPE) {
00126     start_time = time(NULL);
00127     ipc_notify(IPC_ALL,IPC_STD,"Weight file saving started %.24s", ctime(&start_time));
00128 
00129     /* write LFTOK_SNAPSHOT_HEADER */
00130     writeToken(   file, makeToken( LFTOK_SNAPSHOT_HEADER, 2+1, lm.N, lm.perows));
00131     writeInteger( file, iteration);
00132   }
00133 
00134   /* dump data for each row */
00135   for (current_local_row=0; current_local_row <lm.perows; current_local_row++) {
00136     for (part_of_row=0; part_of_row <parts_per_row; part_of_row++) {
00137     
00138       const int current_map_row = MAPROW(current_local_row);
00139       LFBufferClear( &binaryBuffer );
00140       binaryWeightsBufferFill( &binaryBuffer, current_map_row, current_local_row, part_of_row );
00141       if (status != 0) return status;
00142       
00143       /* verify contents of buffer */
00144 #ifdef LF_BUFFER_VERIFY
00145         tokensRead = 0;
00146         binaryWeightsBufferProcess( &binaryBuffer, True);
00147         if(status != 0) return status;
00148 #endif
00149 
00150       /* synchronize all processors before writing each PE's part-row of data */
00151       ipc_barrier();
00152       
00153       /* The last PE writes this part-row from all of the PEs */
00154       if (AMYOUNGESTPE) {
00155         int pe;
00156         
00157         for(pe=(NPEs-1); pe>=0; pe--){
00158           
00159           if (!PEISME(pe))
00160             LFBufferGet(&binaryBuffer, pe);
00161           
00162           /* determine and write row number and length */
00163           writeToken(  file, makeToken( LFTOK_ROW_HEADER, 2 + 1, 
00164                                         ARBITRARY_MAPROW(current_local_row,pe), LF_UNUSED));
00165           writeInteger(file, LFBufferLength(&binaryBuffer));
00166           
00167           /* dump part-row in buffer to file */
00168           LFBufferWrite(&binaryBuffer,file);
00169         }
00170       }
00171     
00172       /* synchronize all processors before computing the next part-row of data */
00173       ipc_barrier();
00174     }
00175   }
00176 
00177   if (AMYOUNGESTPE) {
00178     
00179     /* write LFTOK_SNAPSHOT_TRAILER */
00180     writeToken(  file, makeToken( LFTOK_SNAPSHOT_TRAILER, 2 + 1, LF_UNUSED, LF_UNUSED));
00181     writeInteger(file, iteration);
00182 
00183     end_time = time(NULL);  
00184   
00185     /* Show elapsed time */
00186     ipc_notify(IPC_ALL,IPC_STD,"Weight saving took %g seconds, completing %.24s",
00187                (double)difftime(end_time, start_time),
00188                ctime(&end_time));
00189   }
00190 
00191   if (errorsEncountered != 0) {
00192     ipc_notify(IPC_ALL,IPC_ERROR,"There were %d non-fatal errors during saving",errorsEncountered);
00193     ipc_notify(IPC_ALL,IPC_ERROR,"Consult the log file for more information");
00194   }
00195 
00196   return LF_NO_ERROR;
00197 }
00198 
00199 
00200 
00202 int LISSOMBinaryStateSaver::binaryWeightsBufferFill( LFBuffer *buffer, int current_map_row, 
00203                             int current_local_row, int part_of_row )
00204 { 
00205   int current_j;
00206   int which_eye;
00207   
00208   int start_j =  part_of_row      * (lm.N/parts_per_row);
00209   int end_j   = (part_of_row + 1) * (lm.N/parts_per_row);
00210 
00211   /* Check that N is evenly divisible by parts_per_row) */
00212   if (lm.N%parts_per_row != 0){
00213     ipc_notify(IPC_ALL,IPC_ERROR,"N must be divisible by parts_per_row: %d%%%d != 0",
00214               (int)lm.N, (int)parts_per_row);
00215     return LF_ERROR;
00216     /* ipc_notify(IPC_ALL,IPC_STD,"After"); */
00217   }
00218   
00219   /* write data for each neuron in this part of row */
00220   for (current_j =start_j; current_j <end_j; current_j++){
00221     
00222     if(status != 0) return status;
00223 
00224     /* write LFTOK_NEURON_HEADER */
00225     LFBufferWriteToken(buffer, 
00226                        makeToken( LFTOK_NEURON_HEADER_ORIG, 2 + 2, current_map_row, current_j));
00227     
00228     LFBufferWriteInteger(buffer, lm.cortex_map[current_map_row][current_j].centerx);
00229     LFBufferWriteInteger(buffer, lm.cortex_map[current_map_row][current_j].centery);
00230     
00231     /* write LFTOK_AFF_WEIGHTS */
00232     {
00233       const int rf_width = 1 + 2*lm.rf_radius;  /* always odd */
00234 
00235       /* Wts in file are always scaled for num_eyes=2, regardless of num_eyes */
00236       const double wt_scale = lm.num_aff_inputs()/2.0;
00237 
00238       int x,y;
00239       
00240       /* writes all afferent weights, even those which may be outside the 
00241          retina boundaries for this receptive field.  Assuming a reasonable 
00242          lm.rf_radius (e.g. 5), this should not waste a significant amount of space. 
00243          */
00244       
00245       /* write one afferent weight token for each eye */
00246       for (which_eye = 0; which_eye < lm.num_aff_inputs(); which_eye++) {
00247         LFBufferWriteToken(buffer, makeToken( LFTOK_AFF_WEIGHTS, 
00248                                               2 + rf_width*rf_width,
00249                                               rf_width, which_eye)); 
00250         
00251         for (x=0; x<rf_width; x++)
00252           for (y=0; y<rf_width; y++)
00253             LFBufferWriteFloat(buffer, wt_scale * 
00254                                lm.wts[current_local_row][current_j].weights[which_eye][x][y]);
00255         
00256       }
00257     }
00258     
00259 
00260     /* Save lateral weights if needed */
00261     if (!save_afferent_weights_only) {
00262       
00263       /* write LFTOK_LEXC_WEIGHTS */
00264       binaryWeightsBufferWriteLatWeights( buffer, LFTOK_LEXC_WEIGHTS,
00265                                           current_map_row, current_j,
00266                                           lm.exc_rad, lm.exc_array_width,
00267                                           &(lm.wts[current_local_row][current_j].lat_exc_wts[0]));
00268       
00269       /* write LFTOK_LINH_WEIGHT_CHUNKs */
00270       {
00271         int start_index=0, end_index=-1, i;
00272         int dynamic_lat_inh_dimension = (2*lm.inh_rad + 1)*(2*lm.inh_rad + 1);
00273         f64 live_threshold = 1.5 * DEATH_FLAG;
00274 
00275         if (save_all_lateral_weights)
00276                 live_threshold = -1.0E30;
00277 
00278         if (dynamic_lat_inh_dimension != lm.lat_inh_dimension)
00279           ipc_notify(IPC_ONE,IPC_ERROR,"Lateral inhibitory radius changed; not supported by binarysave.c");
00280 
00281         /* infinite loop -- find and write each chunk of live weights */
00282         /* this is ugly, but I can't figure out a better way */
00283         for (;;) {
00284             /* Looks at all lateral inhibitory weights, even those which may be 
00285                outside the cortex boundaries for this neuron.  This is fine 
00286                as long as the weights outside were initialized to zero or 
00287                DEATH_FLAG, since they will not be considered alive anyway.  
00288                */
00289 
00290             /* skip over empty connections to find start of chunk */
00291             for (start_index = end_index+1; 
00292                  ((start_index <= dynamic_lat_inh_dimension-1) &&
00293                   (lm.wts[current_local_row][current_j].lat_inh_wts[start_index]   < live_threshold));
00294                  start_index++);
00295           
00296             /* done if at end of array */
00297             if (start_index >= dynamic_lat_inh_dimension) 
00298               break;
00299           
00300             /* chunk lasts until two or three dead connections found in a row */
00301             /* skips by two, so might end up with one dead connection included */
00302             for (end_index=start_index; 
00303                  ((end_index < dynamic_lat_inh_dimension - 2)  &&
00304                   !((lm.wts[current_local_row][current_j].lat_inh_wts[end_index+1] < live_threshold) &&
00305                     (lm.wts[current_local_row][current_j].lat_inh_wts[end_index+2] < live_threshold)));
00306                  end_index +=2);
00307           
00308             /* ensure that array bounds are respected and last few connections are saved */
00309             if (end_index >= (dynamic_lat_inh_dimension-2))
00310               end_index = dynamic_lat_inh_dimension - 1;
00311           
00312           
00313             /* remove last dead connection, if any */
00314             /* delete this statement if 8-byte multiples are needed */
00315             if (lm.wts[current_local_row][current_j].lat_inh_wts[end_index] < live_threshold)
00316               end_index--;
00317 
00318             /* make and write token for this chunk */
00319             LFBufferWriteToken(buffer, makeToken( LFTOK_LINH_WEIGHT_CHUNK, 
00320                                                         2 + (end_index - start_index + 1), 
00321                                                         start_index, end_index));
00322           
00323             /* write weights */
00324             for (i=start_index; i<=end_index; i++)
00325               LFBufferWriteFloat(buffer, lm.wts[current_local_row][current_j].lat_inh_wts[i]);
00326           
00327           };
00328       }
00329     }
00330 
00331     /* write LFTOK_NEURON_TRAILER */
00332     LFBufferWriteToken(buffer, makeToken( LFTOK_NEURON_TRAILER, 2, current_map_row, current_j));
00333     
00334   }
00335 
00336   return LF_NO_ERROR;
00337 }
00338 
00339 
00340 
00342 int LISSOMBinaryStateSaver::binaryWeightsFileRead( FILE *file )
00343 { 
00344   LFTokenType thisToken; /* most recently read token */
00345 
00346   time_t start_time, end_time;
00347 
00348   /* reset everything */
00349   tokensRead = 0;
00350   status = 0;
00351   errorsEncountered = 0;
00352   LFBufferClear( &binaryBuffer );
00353 
00354   /* The first PE does the actual file reading */
00355   if (AMPARENTPE){
00356     
00357     start_time = time(NULL);
00358     ipc_notify(IPC_ALL,IPC_STD,"Weight file loading started %.24s", ctime(&start_time));
00359 
00360     /* read LFTOK_SNAPSHOT_HEADER */
00361     thisToken = readTokenExpecting(LFTOK_SNAPSHOT_HEADER, file);
00362     compareParameter(tokenInfoa(thisToken), lm.N,     "N"    );
00363 #ifdef ASSUME_FIXED_PE_CONFIGURATION
00364     compareParameter(tokenInfob(thisToken), lm.perows, "perows");
00365 #endif
00366     
00367     /* Read iteration to PE0; value won't propagate to other PEs until later */
00368     iteration = readInteger(file);
00369   }
00370 
00371 #ifdef ASSUME_FIXED_PE_CONFIGURATION
00372   ipc_notify(IPC_ONE,IPC_VERBOSE,"Assuming fixed order of rows in binary weights file");
00373   binaryWeightsFileReadInFixedOrder(file, &binaryBuffer);
00374 #else
00375   binaryWeightsFileReadInArbitraryOrder(file, &binaryBuffer);
00376 #endif
00377   
00378   /* read LFTOK_SNAPSHOT_TRAILER */
00379   if (AMPARENTPE){
00380     thisToken = readTokenExpecting(LFTOK_SNAPSHOT_TRAILER, file);
00381     if (readInteger(file) != iteration)
00382       ipc_notify(IPC_ALL,IPC_ERROR,"File truncated: End of SNAPSHOT_TRAILER missing");
00383 
00384     end_time = time(NULL);  
00385 
00386     /* Show elapsed time */
00387     ipc_notify(IPC_ALL,IPC_STD,"Weight loading took %g seconds, completing %.24s",
00388                (double)(difftime(end_time, start_time)),
00389                ctime(&end_time));
00390 
00391   }
00392 
00393   if (errorsEncountered != 0) {
00394     ipc_notify(IPC_ALL,IPC_ERROR,"There were %d non-fatal errors during loading",errorsEncountered);
00395     ipc_notify(IPC_ALL,IPC_ERROR,"Consult the runfile for more information");
00396   }
00397   
00398   return LF_NO_ERROR;
00399 }
00400 
00401 
00402 
00403 int LISSOMBinaryStateSaver::binaryWeightsBufferWriteLatWeights( LFBuffer *buffer, int token_name,
00404                                         int i, int j, int radius, int array_width,
00405                                         l_weight *weights)
00406 {
00407   const int lowk  = MAX(i-radius,0     );
00408   const int highk = MIN(i+radius,lm.N-1);
00409   const int lowl  = MAX(j-radius,0     );
00410   const int highl = MIN(j+radius,lm.N-1);
00411   const int num   = (highk-lowk+1)*(highl-lowl+1);
00412     
00413   int k,l;
00414   
00415   LFBufferWriteToken(buffer, makeToken( token_name, 2+num, num, 0));
00416   
00417   for(k=lowk; k<= highk; k++) {
00418     const int partial_idx = PARTIAL_LAT_INDEX(i,j,k,radius,array_width);
00419     for (l=lowl; l<=highl; l++) {
00420       const int idx = FULL_LAT_INDEX(partial_idx,l);
00421       
00422       LFBufferWriteFloat(buffer, weights[idx]);
00423     }
00424   }
00425   
00426   return LF_NO_ERROR;
00427 }
00428 
00429 
00430 
00431 int LISSOMBinaryStateSaver::binaryWeightsBufferReadLatWeights(  LFBuffer *buffer, LFTokenType token,
00432                                         int i, int j, int radius, int array_width,
00433                                         l_weight *weights, int verify, const char *description)
00434 {
00435   const int lowk  = MAX(i-radius,0     );
00436   const int highk = MIN(i+radius,lm.N-1);
00437   const int lowl  = MAX(j-radius,0     );
00438   const int highl = MIN(j+radius,lm.N-1);
00439   const int num   = (highk-lowk+1)*(highl-lowl+1);
00440   
00441   int k,l;
00442 
00443   if (load_afferent_weights_only) {
00444     /* Discard lateral weights */
00445     int idx;
00446     for(idx=0; idx<tokenInfoa(token); idx++) 
00447       LFBufferReadFloat(buffer);
00448     return LF_NO_ERROR;
00449   }
00450 
00451   /* Discard data if bogus */
00452   if (num != tokenInfoa(token)) {
00453     const  int maxwarnings=10;
00454     static int warnings = 0;
00455     /* ipc_abort(IPC_EXIT_FILE_PROBLEM, */
00456     warnings++;
00457     if (warnings < maxwarnings) {
00458       ipc_notify(IPC_ALL,IPC_ERROR,
00459                  "Problem with lateral weight encoding (at neuron (%d,%d): file %d != computed %d); current parameters may not match file",
00460                  i,j,tokenInfoa(token),num);
00461     }
00462     else if (warnings == maxwarnings)
00463       ipc_notify(IPC_ALL,IPC_ERROR,
00464                  "Maximum number of lateral weight warnings reached (%d); the rest will be discarded",
00465                  maxwarnings);
00466     
00467     for (k=tokenInfoa(token); k>0; k--)
00468       LFBufferReadFloat(buffer);
00469   } else
00470     
00471   for(k=lowk; k<= highk; k++) {
00472     const int partial_idx = PARTIAL_LAT_INDEX(i,j,k,radius,array_width);
00473     for (l=lowl; l<=highl; l++) {
00474       const int idx = FULL_LAT_INDEX(partial_idx,l);
00475       const l_weight aFloat = LFBufferReadFloat(buffer);
00476       
00477       compareOrSet_l_weight(&weights[idx], aFloat, verify, description);
00478     }
00479   }
00480 
00481   return LF_NO_ERROR;
00482 }
00483 
00484 
00485 
00492 int LISSOMBinaryStateSaver::binaryWeightsFileReadInFixedOrder(FILE *file, LFBuffer *buffer)
00493 {
00494   int current_map_row;
00495   int current_local_row;
00496   int part_of_row;
00497   int row_length;
00498   LFTokenType thisToken; /* most recently read token */
00499   
00500   /* read data for each pe, one part of one row at a time */
00501   for (current_local_row =0; current_local_row <lm.perows; current_local_row++) {
00502     for (part_of_row=0; part_of_row <parts_per_row; part_of_row++) {
00503 
00504       if (AMPARENTPE){
00505         int pe; 
00506         int rowsRead = 0;
00507         
00508         /* Read LFTOK_ROW_HEADERs and data for each part-row until data is found for this PE */
00509         do
00510           {
00511             thisToken = readTokenExpecting(LFTOK_ROW_HEADER, file);
00512             
00513             current_map_row  = tokenInfoa(thisToken);
00514             row_length = readInteger(file);
00515             LFBufferClear( buffer );
00516             LFBufferRead(  buffer, file, row_length);
00517             
00518             if ( current_local_row != LOCALROW(current_map_row)) {
00519                 status = LF_ERROR;
00520                 ipc_notify(IPC_ALL,IPC_ERROR,"Rows are not in the correct major order in file");
00521             }
00522             pe = PEFORROW(current_map_row);
00523             if (!PEISME(pe))
00524               LFBufferPut( buffer, pe);
00525 
00526             rowsRead++;
00527             
00528           }  while (!PEISME(pe));
00529         
00530         if ( rowsRead != NPEs) {
00531           status = LF_ERROR;
00532           ipc_notify(IPC_ALL,IPC_ERROR,"Rows are not in the correct minor order in file");
00533         }
00534       }
00535 
00536       
00537       /* ensure that every pe that had data in the file has gotten it */
00538       ipc_barrier();
00539 
00540 #ifdef CRAY      
00541 #pragma _CRI suppress (buffer) /* Force data to be loaded from memory   */
00542 #endif
00543       
00544       /* process the tokens in this PE's buffer */
00545       binaryWeightsBufferProcess( buffer, False);
00546       
00547       /* ensure that every pe is done with its data before continuing */
00548       ipc_barrier();
00549 
00550       if(status != 0) return status;
00551     }
00552   }
00553 
00554   return LF_NO_ERROR;
00555 }
00556 
00557 
00558 
00559 int LISSOMBinaryStateSaver::binaryWeightsFileReadInArbitraryOrder(FILE *file, LFBuffer *buffer)
00560 {
00561   static int done;
00562   done=0;
00563   
00564   while (!done) {
00565 
00566     /* Ensure all PEs are ready to receive any data that might be sent to them */
00567     ipc_barrier();
00568     
00569     /* One PE reads all data initially, then moves it to appropriate PE
00570        for processing. */
00571     if (AMPARENTPE) {
00572       LFTokenType nextToken;
00573       int i, ownerpe, pe_has_data[NPES];
00574       
00575       /* Initially, no PE's buffer contains data, since all have read theirs */
00576       for (i=0; i<NPEs; i++)
00577         pe_has_data[i]=False;
00578 
00579       /* Determine what the next batch of data will be */
00580       nextToken  = peekToken(file);
00581       ownerpe    = PEFORROW(tokenInfoa(nextToken));
00582       done       = (tokenName(nextToken) !=  LFTOK_ROW_HEADER);
00583 
00584       /* Read rows, if any, until one found that would overwrite a full buffer */
00585       while (!done && !pe_has_data[ownerpe]) {
00586         int row_length;
00587         
00588         readTokenExpecting(LFTOK_ROW_HEADER,file); /* Discard known token */
00589         row_length = readInteger(file);
00590         
00591         LFBufferRead(  buffer, file, row_length);
00592         pe_has_data[ownerpe]=True;
00593         
00594         if (!PEISME(ownerpe)) {
00595           LFBufferPut( buffer, ownerpe);
00596           LFBufferClear( buffer );
00597         }
00598 
00599         nextToken  = peekToken(file);
00600         ownerpe    = PEFORROW(tokenInfoa(nextToken));
00601         done       = (tokenName(nextToken) !=  LFTOK_ROW_HEADER);
00602       }
00603     }
00604     
00605     /* ensure that data is ready at parent PE before continuing */
00606     ipc_barrier();
00607     ipc_get( &done, IPC_INT, 1, PARENTPE);
00608     
00609     /* process any tokens that may be in this PEs buffer */
00610 #ifdef CRAY
00611 #pragma _CRI suppress (buffer) /* Force data to be loaded from memory   */
00612 #endif
00613     if (LFBufferLength(buffer)!=0)
00614       binaryWeightsBufferProcess(buffer, False);
00615   }
00616 
00617   if(status != 0) return status;
00618   return LF_NO_ERROR;
00619 }
00620 
00621 
00622 
00623 #define MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE                          \
00624   if (current_map_row == Uninitialized || current_j == Uninitialized) {  \
00625     ipc_notify(IPC_ALL,IPC_ERROR,"Missing neuron header");                           \
00626     return LF_ERROR;                                                       \
00627   }
00628 
00629 
00630 
00632 int LISSOMBinaryStateSaver::binaryWeightsBufferProcess( LFBuffer *buffer, int verify)
00633 { 
00634   LFTokenType thisToken; /* most recently read token */
00635   int max_eye_data_found=-1;
00636 
00637 #ifdef LF_DEBUG_FILE
00638   int offset;
00639 #endif
00640 
00641   int current_local_row = Uninitialized;
00642   int current_map_row   = Uninitialized;
00643   int current_j         = Uninitialized;
00644 
00645   /* Snapshot buffer at start for later restoration if just verifying */
00646   /* (Slight encapsulation violation, but...) */
00647   int bufferStart = buffer->start;
00648   int bufferEnd   = buffer->end;
00649 
00650   /* process each token in this buffer */
00651   do
00652     {
00653       if(status != LF_NO_ERROR) return status;
00654 
00655 #ifdef LF_DEBUG_FILE
00656       offset = buffer->start;
00657 #endif      
00658       thisToken = LFBufferReadToken(buffer);
00659 #ifdef LF_DEBUG_FILE
00660         printToken( thisToken, offset );      
00661 #endif
00662       
00663       switch(tokenName(thisToken)){
00664         
00665       case LFTOK_NEURON_HEADER_ORIG:
00666       case LFTOK_NEURON_HEADER_BUG:
00667         
00668         if (current_map_row != Uninitialized || current_j != Uninitialized) {
00669           ipc_notify(IPC_ALL,IPC_ERROR,"Missing neuron trailer");
00670           return LF_ERROR;
00671         }
00672         
00673         current_map_row   = tokenInfoa(thisToken);
00674         current_j         = tokenInfob(thisToken);
00675         current_local_row = LOCALROW(current_map_row);
00676         
00677         compareOrSetInt(&lm.cortex_map[current_map_row][current_j].centerx, 
00678                         LFBufferReadInteger(buffer),
00679                         verify, "centerx");
00680         compareOrSetInt(&lm.cortex_map[current_map_row][current_j].centery, 
00681                         LFBufferReadInteger(buffer),
00682                         verify, "centery");
00683 
00684         max_eye_data_found=-1;
00685 
00686         if (tokenName(thisToken)==LFTOK_NEURON_HEADER_BUG) {
00687           int which_eye;
00688           for (which_eye = 0; which_eye < lm.num_aff_inputs(); which_eye++) {
00689 #ifdef NO_ANALYZE      
00690             LFBufferReadInteger(buffer);
00691 #else
00692             compareOrSetInt(&or_pref[which_eye][current_map_row][current_j], 
00693                             LFBufferReadInteger(buffer),
00694                             verify, "orientation preference");
00695 #endif
00696           }
00697         }
00698           
00699         break;
00700       
00701       case LFTOK_AFF_WEIGHTS:         
00702         {
00703           int x,y,eye;
00704           const int rf_width  = tokenInfoa(thisToken);  /* always odd */
00705           const int which_eye = tokenInfob(thisToken);
00706           const int eye_start = (which_eye==LF_ALL_EYES ?        0 : which_eye);
00707           const int eye_bound = (which_eye==LF_ALL_EYES ? lm.num_aff_inputs() : which_eye+1);
00708           const double wt_scale = 2.0/lm.num_aff_inputs(); /* Wts in file are always scaled as if num_eyes=2 */
00709 
00710           if (which_eye!=LF_ALL_EYES)
00711             max_eye_data_found = MAX(max_eye_data_found,which_eye);
00712           
00713           compareParameter((rf_width-1)/2, lm.rf_radius,     "rf_radius"    );
00714           
00715           MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;
00716           
00717           for (x=0; x<rf_width; x++)
00718             for (y=0; y<rf_width; y++) {
00719               a_weight aFloat = wt_scale * LFBufferReadFloat(buffer);
00720               
00721               for (eye=eye_start; eye<eye_bound; eye++)
00722                 compareOrSet_a_weight(&lm.wts[current_local_row][current_j].weights[eye][x][y],
00723                                       aFloat, verify, "afferent weight");
00724             }
00725         }
00726         break;
00727         
00728         
00729       case LFTOK_LEXC_WEIGHTS:
00730         MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;   
00731         binaryWeightsBufferReadLatWeights( buffer, thisToken,
00732                                            current_map_row, current_j,
00733                                            lm.exc_rad, lm.exc_array_width,
00734                                            &(lm.wts[current_local_row][current_j].lat_exc_wts[0]),
00735                                            verify,"lateral excitatory weight");
00736         break;
00737         
00738       case LFTOK_LEXC_WEIGHTS_OLD:
00739         {
00740           int start_index, end_index, i;
00741           static int ignoring_weights = False;
00742           
00743           start_index  = tokenInfoa(thisToken);
00744           end_index    = tokenInfob(thisToken);
00745           
00746           MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;        
00747           
00748           for (i=start_index; i<=end_index; i++) {
00749             l_weight aFloat = LFBufferReadFloat(buffer);
00750             
00751             if (!ignoring_weights && (end_index > lm.lat_exc_dimension)) {
00752               if (!load_afferent_weights_only)
00753                 ipc_notify(IPC_ALL,IPC_WARNING,"Not enough space for the lateral excitatory weights; ignoring them");
00754               ignoring_weights = True;
00755             }
00756 
00757             if (!ignoring_weights && !load_afferent_weights_only)
00758               compareOrSet_l_weight(&lm.wts[current_local_row][current_j].lat_exc_wts[i],
00759                                     aFloat, verify, "lateral excitatory weight");
00760           }
00761         }
00762         break;
00763         
00764         
00765       case LFTOK_LINH_WEIGHT_CHUNK:   
00766         {
00767           int i;
00768           int start_index, end_index;
00769           static int ignoring_weights = False;
00770           
00771           start_index  = tokenInfoa(thisToken);  /* first index (from left to right) */
00772           end_index    = tokenInfob(thisToken);  /* last index */
00773           
00774           MAKE_SURE_NEURON_HEADER_INFO_AVAILABLE;
00775           
00776           for (i=start_index; i<=end_index; i++) {
00777             l_weight aFloat = LFBufferReadFloat(buffer);
00778             
00779             if (!ignoring_weights && (end_index > lm.lat_inh_dimension)) {
00780               if (!load_afferent_weights_only)
00781                 ipc_notify(IPC_ALL,IPC_WARNING,"Not enough space for the lateral inhibitory weights; ignoring them");
00782               ignoring_weights = True;
00783             }
00784             
00785             if (!ignoring_weights && !load_afferent_weights_only)
00786               compareOrSet_l_weight(&lm.wts[current_local_row][current_j].lat_inh_wts[i],
00787                                     aFloat, verify, "lateral inhibitory weight");
00788           }
00789         }
00790         break;
00791         
00792         
00793       case LFTOK_NEURON_TRAILER:
00794         if ((tokenInfoa(thisToken) != current_map_row) ||
00795             (tokenInfob(thisToken) != current_j)) {
00796           status = LF_ERROR;
00797           ipc_notify(IPC_ALL,IPC_ERROR,"File format error -- neuron trailer");
00798         }
00799 
00800         /* If there are currently more eyes than were defined in the file,
00801            copy data to remaining eyes */
00802         if (max_eye_data_found >= 0 && lm.num_aff_inputs() < max_eye_data_found+1) {
00803           static int warned=False;
00804           if (!warned) {
00805             ipc_notify(IPC_ONE,IPC_CAUTION,"Data in file was for %d eyes; ignoring eyes larger than %d",
00806                        max_eye_data_found+1,lm.num_aff_inputs()-1);
00807             warned=True;
00808           }
00809         }
00810         
00811         if (max_eye_data_found >= 0 && lm.num_aff_inputs() > max_eye_data_found+1) {
00812           int x,y,eye;
00813           static int warned=False;
00814           
00815           if (!warned) {
00816             ipc_notify(IPC_ONE,IPC_CAUTION,"Data in file was for %d eyes; extending to %d eyes",
00817                        max_eye_data_found+1,lm.num_aff_inputs());
00818             warned=True;
00819           }
00820           
00821           for (x=0; x<1+lm.rf_radius*2; x++)
00822             for (y=0; y<1+lm.rf_radius*2; y++)
00823               for (eye=max_eye_data_found+1; eye<lm.num_aff_inputs(); eye++)
00824                 lm.wts[current_local_row][current_j].weights[eye][x][y] =
00825                   lm.wts[current_local_row][current_j].weights[max_eye_data_found][x][y];
00826         }
00827         
00828         current_map_row   = Uninitialized;
00829         current_local_row = Uninitialized;
00830         current_j         = Uninitialized;
00831         break;
00832         
00833         
00834       default:
00835         status = LF_ERROR;
00836         ipc_notify(IPC_ALL,IPC_ERROR,"Error in input file -- unknown token: %ld",
00837                   (long)tokenName(thisToken));
00838       }
00839     } while (LFBufferLength(buffer) > 0);
00840 
00841   /* Reset buffer to start and end at the beginning, since circular buffer hasn't been implemented */
00842   LFBufferClear( buffer ); 
00843   
00844   /* restore buffer to previous state */
00845   if (verify){
00846     buffer->start = bufferStart;
00847     buffer->end   = bufferEnd;
00848   }
00849 
00850   return LF_NO_ERROR;
00851 }
00852 
00853 
00854 
00856 void LISSOMBinaryStateSaver::printTokens( FILE *file )
00857 {
00858   int offset;
00859   LFTokenType token;
00860   f32 float32;
00861   i32 int32;
00862   int i;
00863 
00864   /* The first PE does the actual file reading */
00865   if (AMPARENTPE)
00866     do {
00867       offset = ftell(file);
00868   
00869       token = readToken(file);
00870   
00871       printToken( token, offset );
00872   
00873       if ( (tokenName(token) >= SMALLEST_LFTOK) && (tokenName(token) <= LARGEST_LFTOK) )
00874         for(i=2; i<tokenLength(token); i++) {
00875           offset = ftell(file);
00876           int32 = (i32)readInteger(file);
00877           fseek(file, offset, SEEK_SET); /* Reset file offset */
00878           float32 = (f32)readFloat(file);
00879           
00880           ipc_notify(IPC_ALL,IPC_STD,"Offset: %#6x     Hex: %10x  Int: %11d  Float: %e",
00881                      (int)offset,(int)int32,(int)int32,(double)float32);
00882         }
00883     }
00884   while (tokenName(token) != LFTOK_SNAPSHOT_TRAILER);
00885 }
00886 
00887 
00888 
00889 void LISSOMBinaryStateSaver::printTokensInBuffer( LFBuffer *buffer )
00890 {
00891   int offset;
00892   LFTokenType token;
00893   f32 float32;
00894   i32 int32;
00895   int i;
00896   int bufferStart = buffer->start;
00897   int bufferEnd = buffer->end;
00898 
00899   /* The first PE does the actual file reading */
00900   if (AMPARENTPE)
00901     do {
00902       offset = buffer->start;
00903   
00904       token = LFBufferReadToken(buffer);
00905   
00906       printToken( token, offset );
00907   
00908       if ( (tokenName(token) >= SMALLEST_LFTOK) && (tokenName(token) <= LARGEST_LFTOK) )
00909         for(i=2; i<tokenLength(token); i++) {
00910           offset = buffer->start;
00911           int32 = (i32)LFBufferReadInteger(buffer);
00912           buffer->start = offset; /* Reset buffer offset */
00913           float32 = (f32)LFBufferReadFloat(buffer);
00914           
00915           ipc_notify(IPC_ALL,IPC_STD,"Offset: %#6x     Hex: %10x  Int: %11d  Float: %e",
00916                      (int)offset,(int)int32,(int)int32,(double)float32);
00917         }
00918     }
00919   while (LFBufferLength(buffer)>0);
00920 
00921   buffer->start = bufferStart;
00922   buffer->end   = bufferEnd;
00923 }
00924 
00925 
00926 
00927 /******************************************************************************/
00928 /* Token handling primitives                                                  */
00929 /******************************************************************************/
00930 
00935 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::makeToken(int name, int length, int infoa, int infob )
00936 {
00937   LFTokenType temp;
00938   temp.right=
00939     ( ((i32)infob   & 0xFFFF)      ) |
00940     ( ((i32)infoa   & 0xFFFF) << 16);
00941   
00942   temp.left=
00943     ( ((i32)length  & 0xFFFF)      ) |
00944     ( ((i32)name    & 0xFFFF) << 16);
00945 
00946   return temp;
00947 }
00948 
00949 
00950 
00951 /* Return the indicated field of the given token. */
00952 int LISSOMBinaryStateSaver::tokenName(   LFTokenType token )   {  return (int)((token.left  >> 16)         );  }
00953 int LISSOMBinaryStateSaver::tokenLength( LFTokenType token )   {  return (int)((token.left       ) & 0xFFFF);  }
00954 int LISSOMBinaryStateSaver::tokenInfoa(  LFTokenType token )   {  return (int)((token.right >> 16) & 0xFFFF);  }
00955 int LISSOMBinaryStateSaver::tokenInfob(  LFTokenType token )   {  return (int)((token.right      ) & 0xFFFF);  }
00956 
00957 
00958 
00959 const char* LISSOMBinaryStateSaver::tokenNameString(LFTokenType token)
00960 {
00961   static char buf[20];
00962     
00963   switch (tokenName(token)) {
00964   case LFTOK_SNAPSHOT_HEADER:   return("SNAPSHOT_HEADER");    
00965   case LFTOK_ROW_HEADER:        return("ROW_HEADER");         
00966   case LFTOK_NEURON_HEADER_ORIG:return("NEURON_HEADER_ORIG");
00967   case LFTOK_NEURON_HEADER_BUG: return("NEURON_HEADER_BUG");
00968   case LFTOK_AFF_WEIGHTS:       return("AFF_WEIGHTS");        
00969   case LFTOK_LEXC_WEIGHTS_OLD:  return("LEXC_WEIGHTS_OLD");
00970   case LFTOK_LEXC_WEIGHTS:      return("LEXC_WEIGHTS");       
00971   case LFTOK_LINH_WEIGHT_CHUNK: return("LINH_WEIGHT_CHUNK");  
00972   case LFTOK_NEURON_TRAILER:    return("NEURON_TRAILER");     
00973   case LFTOK_SNAPSHOT_TRAILER:  return("SNAPSHOT_TRAILER");       
00974   default:
00975     sprintf(buf,"Token: %4d", (int)tokenName(token));
00976     return buf;
00977   }
00978 }  
00979 
00980 
00981 
00982 void LISSOMBinaryStateSaver::printToken( LFTokenType token, int offset )
00983 {
00984   ipc_notify(IPC_ALL,IPC_STD,"Offset: %#6x  %-18s  Length: %3d  Infoa: %3d  Infob: %3d",
00985              offset,tokenNameString(token),(int)tokenLength(token),
00986              (int)tokenInfoa(token),(int)tokenInfob(token));
00987 }
00988 
00989 
00990 
00991 /******************************************************************************/
00992 /* Buffer handling primitives                                                 */
00993 /******************************************************************************/
00994 
00996 void LISSOMBinaryStateSaver::LFBufferGet( LFBuffer *buffer, int pe )
00997 {
00998   ipc_get64(&(buffer->start),   1, pe);
00999   ipc_get64(&(buffer->end),     1, pe);
01000   ipc_get32(&(buffer->data[0]), buffer->end + 1, pe);
01001 }
01002 
01003 
01004 
01006 void LISSOMBinaryStateSaver::LFBufferPut( LFBuffer *buffer, int pe )
01007 {  
01008   /* Should fix this; would need to provide a static area for copying data
01009      or at least broadcasting the addresses */
01010   /* Warning is here because this is the most dangerous spot, but LFBufferGet
01011      will also retrieve trash. */
01012 #if (NPES>1)
01013   ipc_notify(IPC_ONE,IPC_ERROR,
01014              "Binary file saving is currently not supported on multi-PE architectures"),
01015 #else    
01016   ipc_put64(&(buffer->start),   1, pe);
01017   ipc_put64(&(buffer->end),     1, pe);
01018   ipc_put32(&(buffer->data[0]), buffer->end + 1, pe);
01019 #endif  
01020 }
01021 
01022 
01023 
01025 void LISSOMBinaryStateSaver::LFBufferClear( LFBuffer *buffer )
01026 {  
01027   buffer->start =  0;  
01028   buffer->end   = -1;  
01029 }
01030 
01031 
01032 
01034 int LISSOMBinaryStateSaver::LFBufferLength( LFBuffer *buffer )
01035 { return buffer->length(); }
01036 
01037 
01038 
01040 int LISSOMBinaryStateSaver::LFBufferWrite( LFBuffer *buffer, FILE *file )
01041 {
01042   buffer->start += fwrite(&(buffer->data[buffer->start]), sizeof(buffer->data[0]),
01043                           LFBufferLength(buffer), file);
01044 
01045   if ((buffer->end - buffer->start + 1) !=0){
01046     ipc_notify(IPC_ALL,IPC_ERROR,"Cannot write buffer to file -- Disk or quota full?");
01047     return LF_ERROR;
01048   }
01049   
01050   return LF_NO_ERROR;
01051 }
01052 
01053 
01054 
01058 int LISSOMBinaryStateSaver::LFBufferRead( LFBuffer *buffer, FILE *file, int length)
01059 {
01060   buffer->ensure_space_available(length);
01061   buffer->end += fread( &buffer->data[buffer->end + 1], 
01062                         sizeof(buffer->data[0]), length, file);  
01063 
01064   return LF_NO_ERROR;
01065 }
01066 
01067 
01068 
01070 int LISSOMBinaryStateSaver::LFBufferWriteToken(LFBuffer *buffer, LFTokenType token )
01071 {
01072   i32 words[2];
01073   words[0] = token.left;
01074   words[1] = token.right;
01075 
01076   if (!bigendian) {
01077     words[0] = i32_swap_endian(words[0]);
01078     words[1] = i32_swap_endian(words[1]);
01079   }
01080 
01081   buffer->ensure_space_available(3);
01082   buffer->data[++buffer->end] = words[0];
01083   buffer->data[++buffer->end] = words[1];
01084 
01085   tokensWritten++;
01086 
01087   return LF_NO_ERROR;
01088 }
01089 
01090 
01091 
01093 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::LFBufferReadToken(LFBuffer *buffer )
01094 {
01095   LFTokenType token;
01096   i32 words[2];
01097   
01098   /*  ipc_notify(IPC_ALL,IPC_STD,"Buffer start:%08x  end:%08x",
01099       buffer->start, buffer->end); */
01100 
01101   if ((buffer->end - buffer-> start) < 1)
01102     ipc_notify(IPC_ALL,IPC_ERROR,"Buffer is empty -- cannot read token");
01103 
01104   words[0] = buffer->data[buffer->start++];
01105   words[1] = buffer->data[buffer->start++];
01106   if (!bigendian) {
01107     words[0] = i32_swap_endian(words[0]);
01108     words[1] = i32_swap_endian(words[1]);
01109   }
01110   
01111   token.left  = words[0];
01112   token.right = words[1];
01113 
01114   tokensRead++;
01115 
01116   if ( (tokenName(token) < SMALLEST_LFTOK) || (tokenName(token) > LARGEST_LFTOK) )
01117     ipc_notify(IPC_ALL,IPC_WARNING,"Unknown token: %08x %08x", (int)token.left, (int)token.right); 
01118   
01119   return token;
01120 }
01121 
01122 
01124 int LISSOMBinaryStateSaver::LFBufferWriteItem(LFBuffer *buffer, void *itemptr)
01125 {
01126   /* Get item */
01127   LFBufferDataType item = *(LFBufferDataType *)itemptr;
01128   if (!bigendian)
01129     item = LFBufferDataType_swap_endian(item);
01130 
01131   /* Put item in buffer */
01132   buffer->ensure_space_available(1);
01133   buffer->data[++buffer->end] = item;
01134   return LF_NO_ERROR;
01135 }
01136 
01137      
01138 
01140 LISSOMBinaryStateSaver::LFBufferDataType LISSOMBinaryStateSaver::LFBufferReadItem(LFBuffer *buffer)
01141 {
01142   LFBufferDataType item;
01143 
01144   /* Check for data available */
01145   if ((buffer->end - buffer->start) < 0){
01146     ipc_notify(IPC_ALL,IPC_ERROR,"Buffer is empty -- cannot read integer");
01147     return 0;    
01148   }
01149 
01150   /* Get item */
01151   item = buffer->data[buffer->start++];
01152   if (!bigendian)
01153     item = LFBufferDataType_swap_endian(item);
01154 
01155   /* Return item */
01156   return item;
01157 }
01158 
01159 
01160 
01163 int LISSOMBinaryStateSaver::LFBufferWriteFloat(LFBuffer *buffer, f32 aFloat )
01164 {
01165   assert(sizeof(f32)==sizeof(LFBufferDataType));
01166   return LFBufferWriteItem(buffer,&aFloat);
01167 }
01168 
01169 
01170 
01172 f32 LISSOMBinaryStateSaver::LFBufferReadFloat(LFBuffer *buffer)
01173 {
01174   LFBufferDataType item = LFBufferReadItem(buffer);
01175   assert(sizeof(f32)==sizeof(LFBufferDataType));
01176   return *(f32 * )(void *)(&item);
01177 }
01178 
01179 
01180 
01183 int LISSOMBinaryStateSaver::LFBufferWriteInteger(LFBuffer *buffer, int anInteger )
01184 {
01185   i32 output=(i32)anInteger;
01186   assert(sizeof(i32)==sizeof(LFBufferDataType));
01187   return LFBufferWriteItem(buffer,&output);
01188 }
01189 
01190 
01191 
01193 int LISSOMBinaryStateSaver::LFBufferReadInteger(LFBuffer *buffer)
01194 {  return (int) LFBufferReadItem(buffer);  }
01195 
01196 
01197 
01198 /******************************************************************************/
01199 /* Direct file handling primitives                                            */
01200 /******************************************************************************/
01201 
01203 int LISSOMBinaryStateSaver::writeToken(FILE *file, LFTokenType token )
01204 {
01205   i32 words[2];
01206   words[0] = token.left;
01207   words[1] = token.right;
01208 
01209   if (!bigendian) {
01210     words[0] = i32_swap_endian(words[0]);
01211     words[1] = i32_swap_endian(words[1]);
01212   }
01213 
01214   if (2 != fwrite( &words, sizeof(words[0]), 2, file)){
01215     ipc_notify(IPC_ALL,IPC_ERROR,"Cannot write to file");
01216     return LF_ERROR;
01217   }
01218   tokensWritten++;
01219 
01220   return LF_NO_ERROR;
01221 }
01222 
01223 
01224 
01226 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::readToken(FILE *file )
01227 {
01228   LFTokenType token;
01229   i32 words[2];
01230 
01231   if (2 != fread( &words, sizeof(words[0]),    2, file))
01232     ipc_notify(IPC_ALL,IPC_ERROR,"Cannot read token from file");
01233 
01234   tokensRead++;
01235 
01236   if (!bigendian) {
01237     words[0] = i32_swap_endian(words[0]);
01238     words[1] = i32_swap_endian(words[1]);
01239   }
01240   
01241   token.left  = words[0];
01242   token.right = words[1];
01243 
01244   if ( (tokenName(token) < SMALLEST_LFTOK) || (tokenName(token) > LARGEST_LFTOK) )
01245     ipc_notify(IPC_ALL,IPC_WARNING,"Unknown token: %08x %08x", (int)token.left, (int)token.right); 
01246   
01247   return token;
01248 }
01249 
01250 
01251 
01253 LISSOMBinaryStateSaver::LFTokenType LISSOMBinaryStateSaver::peekToken(FILE *file )
01254 {
01255   LFTokenType token;
01256   i32 words[2];
01257   long position = ftell(file);
01258 
01259   if (2 != fread( &words, sizeof(words[0]),    2, file))
01260     ipc_notify(IPC_ALL,IPC_ERROR,"Cannot read token from file");
01261 
01262   fseek(file, position, SEEK_SET); /* Reset file offset */
01263 
01264   if (!bigendian) {
01265     words[0] = i32_swap_endian(words[0]);
01266     words[1] = i32_swap_endian(words[1]);
01267   }
01268   
01269   token.left  = words[0];
01270   token.right = words[1];
01271 
01272   if ( (tokenName(token) < SMALLEST_LFTOK) || (tokenName(token) > LARGEST_LFTOK) )
01273     ipc_notify(IPC_ALL,IPC_WARNING,"Unknown token: %08x %08x", (int)token.left, (int)token.right); 
01274 
01275   return token;
01276 }
01277 
01278 
01279 
01281 LISSOMBinaryStateSaver::LFTokenType
01282 LISSOMBinaryStateSaver::readTokenExpecting(int tokenNameExpected, FILE *file)
01283 {
01284   int offset = ftell(file);
01285   LFTokenType token;
01286   token=readToken(file);
01287 
01288 #ifdef LF_DEBUG_FILE
01289   printToken( token, offset );
01290 #endif
01291   
01292   if (tokenName(token) != tokenNameExpected)
01293     ipc_notify(IPC_ALL,IPC_ERROR,"Expected token %s at offset %d but found %d. (Full token: 0x%08x %08x)", 
01294               tokenNameString(makeToken(tokenNameExpected,0,0,0)), offset, (int)tokenName(token),
01295               (int)token.left, (int)token.right);
01296   
01297   return token;
01298 }
01299 
01300 
01301 
01303 int LISSOMBinaryStateSaver::writeItem(FILE *file, void *itemptr)
01304 {
01305   static int warningprinted = False;
01306   LFBufferDataType item = *(LFBufferDataType *)itemptr;
01307 
01308   if (!bigendian)
01309     item = LFBufferDataType_swap_endian(item);
01310 
01311   if (1 != fwrite( &item, sizeof(item), 1, file))
01312     if (!warningprinted) {
01313       ipc_notify(IPC_ALL,IPC_ERROR,"Cannot write to file");
01314       warningprinted=True;
01315     }
01316 
01317   return LF_NO_ERROR;
01318 }
01319 
01320      
01321 
01323 LISSOMBinaryStateSaver::LFBufferDataType
01324 LISSOMBinaryStateSaver::readItem(FILE* file)
01325 {
01326   LFBufferDataType item;
01327   static int warningprinted = False;
01328   
01329   if (1 != fread( &item, sizeof(item), 1, file))
01330     if (!warningprinted) {
01331       ipc_notify(IPC_ALL,IPC_ERROR,"Cannot read from file");
01332       warningprinted=True;
01333     }
01334   
01335   if (!bigendian)
01336     item = LFBufferDataType_swap_endian(item);
01337   
01338   return item;
01339 }
01340 
01341 
01342 
01345 int LISSOMBinaryStateSaver::writeFloat(FILE *file, f32 aFloat )
01346 {
01347   assert(sizeof(f32)==sizeof(LFBufferDataType));
01348   return writeItem(file,&aFloat);
01349 }
01350 
01351 
01352 
01354 f32 LISSOMBinaryStateSaver::readFloat(FILE *file)
01355 {
01356   LFBufferDataType item = readItem(file);
01357   assert(sizeof(f32)==sizeof(LFBufferDataType));
01358   return *(f32 * )(void *)(&item);
01359 }
01360 
01361 
01362 
01365 int LISSOMBinaryStateSaver::writeInteger(FILE *file, int anInteger )
01366 {
01367   i32 output=(i32)anInteger;
01368   assert(sizeof(i32)==sizeof(LFBufferDataType));
01369   return writeItem(file,&output);
01370 }
01371 
01372 
01373 
01375 int LISSOMBinaryStateSaver::readInteger(FILE *file)
01376 {  return (int)readItem(file);  }
01377 
01378 
01379 
01380 /******************************************************************************/
01381 /* Other utility routines                                                     */
01382 /******************************************************************************/
01383 
01384 
01386 int LISSOMBinaryStateSaver::compareParameter(int weight_file_parameter, int param_file_parameter, const char *description)
01387 {
01388   if (weight_file_parameter != param_file_parameter) {
01389     ipc_notify(IPC_ALL,IPC_ERROR,"Value for %s in weight file (%d) differs from value in param file (%d)", 
01390               description, (int)weight_file_parameter, (int)param_file_parameter);
01391     return LF_ERROR;
01392   }
01393 
01394   return LF_NO_ERROR;
01395 }
01396 
01397 
01398 
01400 int LISSOMBinaryStateSaver::compareOrSetInt(int *destination, int value, int verify, const char *description)
01401 {
01402   if (!verify) 
01403     *destination = value;
01404   else if (*destination != value) {
01405     static int warnings=0;
01406     warnings++;
01407     if (warnings < LF_MAXWARNINGS) 
01408       ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSetInt: Value for %s stored in buffer (%d) differs from value in memory (%d)", 
01409                 description, (int)value, (int)*destination);
01410     else if (warnings == LF_MAXWARNINGS) 
01411       ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSetInt: Maximum number of warnings reached (%d)",warnings);
01412   }
01413 
01414   return *destination;
01415 }
01416 
01417 
01418 
01422 #define compareOrSet_proc(type)                                                                 \
01423 LISSOMBinaryStateSaver::type LISSOMBinaryStateSaver::compareOrSet_ ## type (type *destination, type value, int verify, const char *description) \
01424 {                                                                                               \
01425   if (!verify)                                                                                  \
01426     *destination = value;                                                                       \
01427   else                                                                                          \
01428     /* ensure that the number is "pretty close" to real value, even if zero */                  \
01429     if ((*destination == 0 && ((*destination - value)                 > LF_FLOAT_TOLERANCE ))|| \
01430         (*destination != 0 && ((*destination - value)/(*destination)) > LF_FLOAT_TOLERANCE ) ) {\
01431       static int warnings=0;                                                                    \
01432       warnings++;                                                                               \
01433       if (warnings < LF_MAXWARNINGS)                                                            \
01434         ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" #type ": Value for %s stored in buffer (%e) differs from value in memory (%e)",    \
01435                   description, (double)value, (double)(*destination));                          \
01436       else if (warnings == LF_MAXWARNINGS)                                                      \
01437         ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" #type ": Maximum number of warnings reached (%d)",warnings);       \
01438     }                                                                                           \
01439                                                                                                 \
01440   return *destination;                                                                          \
01441 }
01442 
01443 
01444 
01445 compareOrSet_proc(a_weight)
01446 compareOrSet_proc(l_weight)
01447 
01448      
01449 
01450 /* For debugging, the routines below are what the macros above currently expand to 
01451 
01452 //a_weight LISSOMBinaryStateSaver::compareOrSet_a_weight ( a_weight *destination, a_weight value, int verify, const char *description)
01453 //{
01454 //  if (!verify)
01455 //    *destination = value;
01456 //  else if ((*destination == 0 && ((*destination - value) > 0.0000001 ))
01457 //           || (*destination != 0 && ((*destination - value)/(*destination)) > 0.0000001 ) ) {
01458 //    static int warnings=0;
01459 //    warnings++;
01460 //    if (warnings < 5 )
01461 //      ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" "a_weight" ": Value for %s stored in buffer (%e) differs from value in memory (%e)",
01462 //                description, (double)value, (double)(*destination));
01463 //    else if (warnings == 5 )
01464 //      ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" "a_weight" ": Maximum number of warnings reached (%d)",warnings);
01465 //  }
01466 // 
01467 //  return *destination;
01468 //} 
01469 // 
01470 //l_weight LISSOMBinaryStateSaver::compareOrSet_l_weight ( l_weight *destination, l_weight value, int verify, const char *description)
01471 //{
01472 //  if (!verify)
01473 //    *destination = value;
01474 //  else if ((*destination == 0 && ((*destination - value) > 0.0000001 )) ||
01475 //           (*destination != 0 && ((*destination - value)/(*destination)) > 0.0000001 ) ) {
01476 //    static int warnings=0;
01477 //    warnings++;
01478 //    if (warnings < 5 )
01479 //      ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" "l_weight" ": Value for %s stored in buffer (%e) differs from value in memory (%e)",
01480 //                description, (double)value, (double)(*destination));
01481 //    else if (warnings == 5 )
01482 //      ipc_notify(IPC_ALL,IPC_ERROR,"compareOrSet_" "l_weight" ": Maximum number of warnings reached (%d)",warnings);
01483 //  }
01484 // 
01485 //  return *destination;
01486 //}
01487 
01488 */
01489 

Generated on Mon Jan 20 02:35:43 2003 for RF-LISSOM by doxygen1.3-rc2