Better Formatting
[charm.git] / examples / bigsim / tools / rewritelog / EventInterpolator.C
1 #include <EventInterpolator.h>
2
3 //#define DEBUG
4 #define PRETEND_NO_ENERGY
5
6 using namespace std;
7
8
9 /** Create a vector such that "count" items out of "length" in the vector are set to true */
10 vector<bool> random_select(int count, int length){
11   vector<bool> v(length);
12   int c=0;
13   // Initialize all to false
14   for(int i=0;i<length;++i)
15         v[i] = false;
16   while(c < count){
17         // find a random entry int the vector
18         int r = rand() % length;
19         // mark it as true, incrementing c if this is the first time we mark it
20         if(v[r] == false){
21           c++;
22           v[r] = true;
23         }
24   }
25   return v;
26 }
27
28 template <typename T, typename T2>
29 multimap<T,T2> random_select_multimap(multimap<T,T2> input_map , int count){
30     assert(input_map.size() >= count);
31     vector<bool> which_to_keep = random_select(count, input_map.size());
32     multimap<T,T2> output_map;
33     int len = which_to_keep.size();
34     typename multimap<T, T2>::iterator itr=input_map.begin();
35     for(int i=0; i<len; ++i, ++itr){
36         if(which_to_keep[i] == true){
37           // Do something like this to keep them around:
38             output_map.insert(make_pair((*itr).first, (*itr).second));
39         }
40     }
41 //     assert(output_map.size()==count);
42     return output_map;
43 }
44
45 int EventInterpolator::numCoefficients(const string &funcname){
46 // We create a dummy input stringstream and pass it to parseParameters.
47 // Then we count how many parameters that function creates
48     string temp("0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0");
49     istringstream temp2(temp);
50     return parseParameters(funcname,temp2).second.size();
51 }
52
53
54 int distance(int i1, int i2, int i3, int i4, int i5, int i6){
55     int x1 =(abs(13+i1-i4)%13)*4;
56     int x2 =(abs(13+i4-i1)%13)*4;
57     int x = min(x1,x2);
58
59     int y1 =(abs(6+i2-i5)%6)*2;
60     int y2 =(abs(6+i5-i2)%6)*2;
61     int y = min(y1,y2);
62
63     int z1 =(abs(4+i3-i6)%4)*1;
64     int z2 =(abs(4+i6-i3)%4)*1;
65     int z = min(z1,z2);
66
67     return x+y+z;
68
69 }
70
71 string parseStreamUntilSquiggle(istream &in){
72   string temp;
73   ostringstream out;
74   in >> temp;
75   while(temp != string("}") && in.good()){
76
77         out << temp << " "; 
78
79         in >> temp;
80   }
81
82   return out.str();
83 }
84
85
86
87 /** First parameter is a category or subclass for a particular timed region. For example, we wish to consider computation for adjacent patches differently than patches that are neighbors of adjacent patches. This allows a single timed region to be broken out and treated as a number of different cases. */
88 pair<int,vector<double> > EventInterpolator::parseParameters(const string &funcname, istringstream &line){
89     vector<double> params;
90     int category=0;
91
92     if( funcname == string("calc_self_energy_merge_fullelect") ||
93         funcname == string("calc_pair_energy_merge_fullelect") ||
94                 funcname == string("calc_self_energy_fullelect") ||
95         funcname == string("calc_pair_energy_fullelect") ||
96         funcname == string("calc_self_merge_fullelect") ||
97         funcname == string("calc_pair_merge_fullelect") ||
98         funcname == string("calc_self") ||
99         funcname == string("calc_pair") ||
100         funcname == string("calc_self_energy") ||
101         funcname == string("calc_pair_energy") ){
102
103         double d1,d2,d3,d4,d5,d6,d7,d8,d9;
104         int i1,i2,i3,i4,i5,i6;
105
106         line >> d1 >> d2 >> i1 >> i2 >> i3 >> i4 >> i5 >> i6 >>
107                 d3 >> d4 >> d5 >> d6 >> d7 >> d8;
108
109         params.push_back( 1.0);
110
111 //         params.push_back( 1.0 / distance );
112         params.push_back( d3 );
113         params.push_back( d4 );
114         params.push_back( d5 );
115                 //        params.push_back( d2 );
116                 //        params.push_back( d3 );
117                 //        params.push_back( d4 );
118         params.push_back( min(d1,d2)*d1*d2 );
119         params.push_back( d1*d2 );
120
121         category = distance(i1,i2,i3,i4,i5,i6 );
122
123     }
124     else if(funcname == string("angles") || funcname == string("dihedrals")){
125         double d1, d2;
126         line >> d1 >> d2;
127
128         params.push_back( 1.0);
129         params.push_back( d2 );
130         params.push_back( d2*d2 );
131     }
132     else if(funcname == string("integrate")){
133         double d1, d2, d3, d4, d5, d6, d7, d8;
134         line >> d1 >> d2 >> d3 >> d4 >> d5 >> d6 >> d7 >> d8;
135
136         params.push_back( 1.0);
137         params.push_back( d2 );
138         params.push_back( d2*d2 );
139     }
140     else {
141         cerr << "FATAL ERROR: Don't know how to read parameters for function " << funcname << endl;
142         throw new runtime_error("unknown function");
143     }
144
145     return make_pair(category,params);
146 }
147
148
149
150
151
152 EventInterpolator::EventInterpolator(char *table_filename, double sample_rate){
153   std::map<string,double> cycle_accurate_time_sum;
154   
155   exact_matches=0;
156   exact_positive_matches=0;
157   approx_matches=0;
158   approx_positive_matches=0;
159   
160   log1.open("log1");
161   
162   cout << "Loading timings file: " << table_filename << endl;
163   ifstream accurateTimeTable(table_filename);
164   if(! accurateTimeTable.good() ){
165         cerr << "FATAL ERROR: Couldn't open file(perhaps it doesn't exist): " << table_filename << endl;
166         throw new runtime_error("missing file");
167   }
168
169
170   // Scan through cycle accurate time file inserting the entries into a map
171   while(accurateTimeTable.good())  {
172         string line_s;
173         getline(accurateTimeTable,line_s);
174         istringstream line(line_s);
175
176         // Expected format is:
177         // TRACEBIGSIM: event:{ eid } time:{ t } PAPI:{ list } params:{ list }
178         // params must currently come after event and time.
179
180         string funcname(""), paramstring(""), counterstring("");
181         double time = -1;
182         string temp;
183         line >> temp;
184         if(temp == string("TRACEBIGSIM:")){
185           // parse the next piece of the line
186           string field;
187           line >> field;
188           while(line.good() && accurateTimeTable.good()){
189                 if(field == string("event:{")){
190                   line >> funcname;
191                   line >> temp; // gobble up the '}'
192                   if(temp != string("}"))
193                         cerr << "ERROR: malformed entry in expected times file" << endl;
194                 } else if (field == string("time:{")){
195                   line >> time;
196                   line >> temp; // gobble up the '}'
197                   if(temp != string("}"))
198                         cerr << "ERROR: malformed entry in expected times file" << endl;
199                 } else if (field == string("PAPI:{")){
200                   counterstring = parseStreamUntilSquiggle(line);
201                 } else if (field == string("params:{")){
202                   paramstring = parseStreamUntilSquiggle(line);
203                 } else {
204                   cout << "Unknown event field: " << field  << endl;
205                 }
206                 line >> field;
207           }
208           
209           if(funcname != string("") && time != -1){
210                 istringstream paramstream(paramstring);
211                 fullParams params = parseParameters(funcname,paramstream);
212                 funcIdentifier func(funcname,params.first);
213                 sample_count[func]++;
214                 cycle_accurate_time_sum[funcname] += time;
215                 accurateTimings.insert(make_pair(make_pair(func,params.second),time));
216           } else {
217                 cerr << "malformed TRACEBIGSIM: line" << endl;
218           }
219
220
221         }
222
223   }
224
225
226   std::map<string,double>::iterator cycle_i;
227   cout << "\nThe following table displays the total cycle count for each event in the \n" 
228         "cycle-accurate timings file. This may be useful for back of the envelope \n"
229         "calculations for expected performance " << endl << endl;
230   cout << "\t|===============================|===================|" << endl;
231   cout << "\t|                        event  | total cycle count |" << endl;
232   cout << "\t|-------------------------------|-------------------|" << endl;
233   for(cycle_i= cycle_accurate_time_sum.begin();cycle_i!=cycle_accurate_time_sum.end();++cycle_i){
234         cout << "\t|";
235         assert((*cycle_i).first.length() <= 30); // the event names should be at most 30 characters
236         for(int i=0;i<30-(*cycle_i).first.length();++i) 
237           cout << " ";
238         cout << (*cycle_i).first << " | ";
239         cout.width(17);
240         cout << (*cycle_i).second;
241         cout << " |" << endl;
242   }     
243   cout << "\t|===============================|===================|" << endl << endl;
244
245
246
247   unsigned long sample_keep = (unsigned long) ceil(sample_rate * accurateTimings.size());
248   if (sample_rate < 1.0){
249         cout << "Randomly dropping " << (1.0-sample_rate)*100 << "% of the cycle accurate timings" << endl;
250         accurateTimings = random_select_multimap(accurateTimings, sample_keep);
251   }
252
253   analyzeExactVariances();
254
255   cout << "\nThe following table displays the number of timing samples from \n the cycle-accurate file for each event." << endl << endl;
256   cout << "\t|===================================|==========================|" << endl;
257   cout << "\t|                            event  | number of timing samples |" << endl;
258   cout << "\t|-----------------------------------|--------------------------|" << endl;
259
260
261   // Create a gsl interpolator workspace for each event/function
262   for(map<funcIdentifier,unsigned long>::iterator i=sample_count.begin(); i!=sample_count.end();++i){
263         funcIdentifier func = (*i).first;
264         unsigned long samples = (*i).second;
265                 
266         cout << "\t|";
267                 
268         for(int i=0;i<30-func.first.length();++i)
269           cout << " ";
270         cout << func.first << ",";
271         cout.width(3);
272         cout << func.second;
273                 
274         cout << " | ";
275         cout.width(24);
276         cout << samples << " |" << endl;
277
278
279         if(samples < numCoefficients(func.first) ){
280           cerr << "FATAL ERROR: Not enough input timing samples for " << func.first << "," << func.second << " which has " << numCoefficients(func.first) << " coefficients" << endl;
281           throw new runtime_error("samples < numCoefficients");
282         }
283         else {
284           work[func] = gsl_multifit_linear_alloc(samples,numCoefficients(func.first));
285           X[func] = gsl_matrix_alloc (samples,numCoefficients(func.first));
286           y[func] = gsl_vector_alloc (samples);
287           c[func] = gsl_vector_alloc(numCoefficients(func.first));
288           cov[func] = gsl_matrix_alloc(numCoefficients(func.first),numCoefficients(func.first));
289
290           for(int i=0;i<numCoefficients(func.first);++i){
291                 gsl_vector_set(c[func],i,1.0);
292           }
293
294         }
295   }
296   cout << "\t|===================================|==========================|" << endl << endl;
297
298   accurateTimeTable.close();
299
300
301 #ifdef WRITESTATS
302   ofstream statfile("stats-out");
303 #endif
304
305   // Fill in values for matrix X and vector Y which will be fed into the least square fit algorithm
306   // The data is currently in  accurateTimings[pair<funcIdentifier,vector<double> >(func,params.second)]=time;
307
308   //iterate through accurateTimings
309   cout << "accurateTimings.size() = " << accurateTimings.size() << endl;
310   map< pair<funcIdentifier,vector<double> >, double >::iterator itr;
311   for(itr=accurateTimings.begin();itr!=accurateTimings.end();++itr){
312         const double &time = (*itr).second;
313         const vector<double> &paramsSecond =(*itr).first.second;
314         const funcIdentifier func = (*itr).first.first;
315
316         // lookup the next unused entry in X
317         unsigned next = Xcount[func] ++;
318         gsl_matrix * x = X[func];
319
320         // copy data into array X and Y
321         for(int param_index=0;param_index<paramsSecond.size();++param_index){
322           gsl_matrix_set(x,next,param_index, paramsSecond[param_index]);
323         }
324         gsl_vector_set(y[func],next,time);
325
326   }
327
328
329 #ifdef WRITESTATS
330   statfile.close();
331 #endif
332
333   // Perform a sanity check now
334   int count1=0, count2=0;
335   for(map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i=work.begin();i!=work.end();++i){
336 #if DEBUG
337         cout << "sample count vs Xcount (" << (*i).first.first << "): " << sample_count[(*i).first] << "?=" << Xcount[(*i).first] << " " << endl;
338 #endif
339         count1 += sample_count[(*i).first];
340         count2 += Xcount[(*i).first] ;
341   }
342   cout << "Samples from cycle accurate file : " << count1 << ".  Keeping only " << count2 << " of them " << endl;
343
344   cout << "Performing Least Squared Fit to sampled time data" << endl;
345
346   //  Now do Least Square Fit: Find C where y=Xc
347   cout << "\nThe following table displays the chi^2 measure for how well the model fits the input times." << endl << endl;
348   cout << "\t|===================================|=========|=========|" << endl;
349   cout << "\t|                            event  |   chi^2 |     chi |" << endl;
350   cout << "\t|-----------------------------------|---------|---------|" << endl;
351
352   cout.setf(ios_base::scientific, ios_base::floatfield);
353   cout.precision(1);
354
355   map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i;
356   for(i=work.begin();i!=work.end();++i){
357         funcIdentifier func = (*i).first;
358         assert(! gsl_multifit_linear(X[func],y[func],c[func],cov[func],&chisqr[func],work[func]));
359         gsl_matrix_free(X[func]);
360         gsl_vector_free(y[func]);
361
362         cout << "\t|";
363                 
364         for(int i=0;i<30-func.first.length();++i)
365           cout << " ";
366         cout << func.first << ",";
367         cout.width(3);
368         cout << func.second;
369                 
370         cout << " | ";
371         cout.width(7);
372         cout << chisqr[func];
373
374         cout << " | ";
375         cout.width(7);
376         cout << sqrt(chisqr[func]) << " |" << endl;
377
378   }
379   cout << "\t|===================================|=========|=========|" << endl << endl;
380
381   // Load in Parameter File which maps event id to function name and parameters
382   cout << "Loading parameter files" << endl;
383
384   for(int i=0;i<102400;++i){
385         char name[512];
386         sprintf(name,"param.%d",i);
387         ifstream parameterEventTable(name);
388
389         if(parameterEventTable.good()){
390 #ifdef DEBUG
391           cout << "     >  Loading " << name << endl;
392 #endif
393
394           while(parameterEventTable.good()){
395                 string line_s;
396                 getline(parameterEventTable,line_s);
397                 istringstream line(line_s);
398
399                 if(parameterEventTable.good()){
400                   string t1, t2;
401                   string funcname;
402                   unsigned eventid;
403
404                   line >> eventid;
405                   line >> t1 >> t2;
406                   line >> funcname;
407
408                   if(t1 == string("TRACEBIGSIM")){
409 #ifdef PRETEND_NO_ENERGY
410                         if(funcname == string("calc_pair_energy")){\
411                           funcname = "calc_pair";
412                         }
413                         else if(funcname == string("calc_self_energy")){
414                           funcname = "calc_self";
415                         }
416 #endif
417
418                         fullParams params = parseParameters(funcname,line);
419                         funcIdentifier func(funcname,params.first);
420                         Xcount[func] ++;
421                         eventparams[make_pair(i,eventid)] = make_pair(func,params.second);
422                   }
423                 }
424           }
425
426         }
427         else{ // file was no good
428           break;
429         }
430
431         parameterEventTable.close();
432   }
433 }
434
435
436 bool EventInterpolator::haveExactTime(const unsigned pe, const unsigned eventid){
437     return haveExactTime(eventparams[make_pair(pe,eventid)]);
438 }
439
440 bool EventInterpolator::haveExactTime(const pair<funcIdentifier,vector<double> > &p) {
441     return haveExactTime(p.first,p.second);
442 }
443
444 bool EventInterpolator::haveExactTime(const funcIdentifier& func, const vector<double> &p){
445   return (accurateTimings.find(make_pair(func,p)) != accurateTimings.end());
446 }
447
448 double EventInterpolator::lookupExactTime(const unsigned pe, const unsigned eventid){
449     return lookupExactTime(eventparams[make_pair(pe,eventid)]);
450 }
451
452 double EventInterpolator::lookupExactTime(const pair<funcIdentifier,vector<double> > &p) {
453     return lookupExactTime(p.first,p.second);
454 }
455
456 double EventInterpolator::lookupExactTime(const funcIdentifier& func, const vector<double> &p){
457     const  pair<funcIdentifier,vector<double> > key(func,p);
458     const int count = accurateTimings.count(key);
459
460         pair<timings_type::iterator, timings_type::iterator> itrs = accurateTimings.equal_range(key);
461         double time_sum=0;
462         for(timings_type::iterator itr=itrs.first; itr!=itrs.second; ++itr){
463           time_sum += (*itr).second;
464         }
465         double time_average = time_sum / count;
466
467     exact_matches++;
468         assert(time_average >= 0.0 );
469     return time_average;
470 }
471
472
473 /** Print out some statistics about the timings for any parameter that has multiple associated cycle-accurate timings */
474 void EventInterpolator::analyzeExactVariances(){
475
476     map< pair<funcIdentifier,vector<double> >, double > variances;
477     map< pair<funcIdentifier,vector<double> >, double > means;
478         map< funcIdentifier, double > max_std_dev;
479         map< funcIdentifier, double > associated_mean;
480
481         // Iterate through items in accurateTimings and store variances
482         timings_type::iterator itr;
483         for(itr=accurateTimings.begin();itr!=accurateTimings.end();++itr){
484           variances[(*itr).first] = lookupExactVariance( (*itr).first );
485           means[(*itr).first] = lookupExactMean( (*itr).first );
486         }
487
488         // Display the variances
489         map< pair<funcIdentifier,vector<double> >, double >::iterator vItr;
490         for(vItr = variances.begin(); vItr!=variances.end(); ++vItr){
491           double var = (*vItr).second;
492           double stddev = sqrt(var);
493           double mean = means[(*vItr).first];
494
495           if(var > 0.0){
496                 if(stddev > max_std_dev[(*vItr).first.first]){
497                   max_std_dev[(*vItr).first.first] = stddev;
498                   associated_mean[(*vItr).first.first] = mean;
499                 }
500           }
501         }
502         
503         // Display the max std dev for any given event
504         cout << "\nThe following events have differing exact times for one or more parameter set.\n"
505                 "Each line corresponds to whichever parameter list produced the greatest variance\n"
506                 "(and equivalently std dev). The mean is the mean timing value associated with the\n"
507             " same parameter list of greatest variance" << endl << endl;
508
509
510         cout << "\t|===================================|=================|=================|==============|" << endl;
511         cout << "\t|                            event  |     max std dev |            mean | sd % of mean |" << endl;
512         cout << "\t|-----------------------------------|-----------------|-----------------|--------------|" << endl;
513
514         cout.setf(ios_base::fixed, ios_base::floatfield);
515         cout.precision(1);
516
517         int func_name_field_width=30;
518         map< funcIdentifier, double >::iterator sItr;
519         for(sItr=max_std_dev.begin(); sItr!=max_std_dev.end(); ++sItr) {
520           double stddev = (*sItr).second;
521           double mean = associated_mean[(*sItr).first];
522           cout << "\t|";
523           for(int i=0;i<func_name_field_width-(*sItr).first.first.length();++i) 
524                 cout << " ";
525           cout << (*sItr).first.first ;
526           cout << ",";
527           cout.width(3);
528           cout << (*sItr).first.second;
529           cout << " | ";
530           cout.width(15);
531           cout <<  stddev;
532           cout << " | ";
533           cout.width(15);
534           cout << mean << " | ";
535           cout.width(9);
536           cout << (stddev * 100.0 / mean) << "    | " << endl;
537         }
538         cout.setf(ios_base::fmtflags(0), ios_base::floatfield);
539         cout << "\t|===================================|=================|=================|==============|" << endl << endl;
540
541 }
542
543 /** Lookup the average timing for a given event and parameter list */
544 double EventInterpolator::lookupExactVariance(const unsigned pe, const unsigned eventid){
545     return lookupExactVariance(eventparams[make_pair(pe,eventid)]);
546 }
547
548 /** Lookup the variance in the timings for a given event and parameter list */
549 double EventInterpolator::lookupExactVariance(const pair<funcIdentifier,vector<double> > &p) {
550     return lookupExactVariance(p.first,p.second);
551 }
552
553 /** Lookup the variance in the timings for a given event and parameter list */
554 double EventInterpolator::lookupExactVariance(const funcIdentifier& func, const vector<double> &p){
555     const  pair<funcIdentifier,vector<double> > key(func,p);
556     const int count = accurateTimings.count(key);
557
558         // Compute mean
559         pair<timings_type::iterator, timings_type::iterator> itrs = accurateTimings.equal_range(key);
560         double time_sum=0;
561         for(timings_type::iterator itr=itrs.first; itr!=itrs.second; ++itr){
562           time_sum += (*itr).second;
563         }
564         const double time_average = time_sum / count;
565
566         // Compute Variance
567         double V_sum=0;
568         for(timings_type::iterator itr=itrs.first; itr!=itrs.second; ++itr){
569           const double d = (*itr).second-time_average;
570           V_sum += d*d;
571         }
572         const double Var = V_sum / count;
573
574     return Var;
575 }
576
577 /** Lookup the average timing for a given event and parameter list */
578 double EventInterpolator::lookupExactMean(const unsigned pe, const unsigned eventid){
579     return lookupExactMean(eventparams[make_pair(pe,eventid)]);
580 }
581 /** Lookup the average timing for a given event and parameter list */
582 double EventInterpolator::lookupExactMean(const pair<funcIdentifier,vector<double> > &p) {
583     return lookupExactMean(p.first,p.second);
584 }
585 /** Lookup the average timing for a given event and parameter list */
586 double EventInterpolator::lookupExactMean(const funcIdentifier& func, const vector<double> &p){
587     const  pair<funcIdentifier,vector<double> > key(func,p);
588     const int count = accurateTimings.count(key);
589
590         // Compute mean
591         pair<timings_type::iterator, timings_type::iterator> itrs = accurateTimings.equal_range(key);
592         double time_sum=0;
593         for(timings_type::iterator itr=itrs.first; itr!=itrs.second; ++itr){
594           time_sum += (*itr).second;
595         }
596         return time_sum / count;
597 }
598
599
600 /** If we have a parameterfile entry for the requested pe,eventid pair */
601 double EventInterpolator::haveNewTiming(const unsigned pe, const unsigned eventid) {
602     return eventparams.find( make_pair(pe,eventid) ) != eventparams.end();
603 }
604
605 double EventInterpolator::predictTime(const unsigned pe, const unsigned eventid) {
606     return predictTime(eventparams[make_pair(pe,eventid)]);
607 }
608
609 double EventInterpolator::predictTime(const pair<funcIdentifier,vector<double> > &p) {
610     return predictTime(p.first,p.second);
611 }
612
613 bool EventInterpolator::canInterpolateFunc(const funcIdentifier& func){
614     return (work.find(func) != work.end());
615 }
616
617
618 double EventInterpolator::getNewTiming(const unsigned pe, const unsigned eventid){
619   if(haveExactTime(pe,eventid) )
620         return lookupExactTime(pe,eventid);
621   else
622         return predictTime(pe,eventid);
623 }
624
625 double EventInterpolator::predictTime(const funcIdentifier &func, const vector<double> &params) {
626
627     // check name
628     if(!canInterpolateFunc(func)){
629         cerr << "FATAL ERROR: function name not found in cycle accurate timing file: " << func.first << "," << func.second << endl;
630        throw new runtime_error("function name not found");
631     }
632
633     // Estimate time for a given set of parameters p
634     gsl_vector *desired_params;
635
636     desired_params = gsl_vector_alloc(numCoefficients(func.first));
637     assert(numCoefficients(func.first)==params.size());
638
639     for(int i=0;i<params.size();++i){
640         gsl_vector_set(desired_params,i,params[i]);
641     }
642
643     double desired_time, desired_time_err;
644     assert(c[func]);
645     assert(cov[func]);
646     assert(! gsl_multifit_linear_est(desired_params,c[func],cov[func],&desired_time,&desired_time_err));
647
648     gsl_vector_free(desired_params);
649
650
651     if(min_interpolated_time.find(func) == min_interpolated_time.end())
652         min_interpolated_time[func] = desired_time;
653     else
654         min_interpolated_time[func] = min( min_interpolated_time[func], desired_time);
655
656     if(max_interpolated_time.find(func) == max_interpolated_time.end())
657         max_interpolated_time[func] = desired_time;
658     else
659         max_interpolated_time[func] = max( max_interpolated_time[func], desired_time);
660
661
662     approx_matches++;
663     if(desired_time>=0.0)
664         approx_positive_matches++;
665
666 //    gsl_vector_free(desired_params);
667
668
669     return desired_time;
670 }
671
672
673 void EventInterpolator::printMinInterpolatedTimes(){
674
675     cout << "The following functions were interpolated(as opposed to approximated:" << endl;
676
677     for(map<funcIdentifier,double>::iterator i=min_interpolated_time.begin();i!=min_interpolated_time.end();++i){
678         cout << "   > min predicted/interpolated time for function " << (*i).first.first << "," << (*i).first.second << " is " << (*i).second << " cycles " << endl;
679     }
680     for(map<funcIdentifier,double>::iterator i=max_interpolated_time.begin();i!=max_interpolated_time.end();++i){
681         cout << "   > max predicted/interpolated time for function " << (*i).first.first << "," << (*i).first.second << " is " << (*i).second << " cycles " << endl;
682     }
683
684     cout << endl;
685 }
686
687 void EventInterpolator::printMatches(){
688     cout << "    > Exact lookup = " << exact_matches << " (" << exact_positive_matches << " positive)" << endl;
689     cout << "    > Approximated = " << approx_matches << " (" << approx_positive_matches << " positive)" << endl;
690     cout << "    > Total        = " << approx_matches+exact_matches <<  " (" << exact_positive_matches+approx_positive_matches << " positive)" << endl;
691 }
692
693 void EventInterpolator::printCoefficients(){
694
695     for(map<funcIdentifier,gsl_vector*>::iterator i=c.begin();i!=c.end();++i){
696         cout << "    > Coefficients for function " << (*i).first.first << "," << (*i).first.second << " :" << endl;
697         for(int j=0; j < ((*i).second)->size; ++j){
698             cout << "    >    " << j << " is " << gsl_vector_get ((*i).second, j) << endl;
699         }
700     }
701
702 }
703
704
705
706
707 /** Free the gsl arrays and workspaces */
708 EventInterpolator::~EventInterpolator(){
709     map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i;
710     for(i=work.begin();i!=work.end();++i){
711         const funcIdentifier &func = (*i).first;
712         gsl_multifit_linear_free(work[func]);
713         gsl_matrix_free(cov[func]);
714         gsl_vector_free(c[func]);
715     }
716         log1.close();
717 }
718
719
720
721