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