c96760bd336137d17b61120dc271ef30aaab1901
[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,d10,d11,d12,d13,d14;
104
105         line >> d1 >> d2 >> d3 >> d4 >> d5 >> d6 >> d7 >> d8 >> d9 >> d10 >> d11 >> d12 >> d13 >> d14;
106
107         params.push_back( 1.0);
108
109         params.push_back( d3 );
110         params.push_back( d4 );
111         params.push_back( d5 );
112
113         params.push_back( min(d1,d2)*d1*d2 );
114         params.push_back( d1*d2 );
115
116         category = distance(d9,d10,d11,d12,d13,d14);
117
118     }
119     else if(funcname == string("angles") || funcname == string("dihedrals")){
120         double d1, d2;
121         line >> d1 >> d2;
122         params.push_back( 1.0);
123         params.push_back( d2 );
124         params.push_back( d2*d2 );
125     }
126     else if(funcname == string("integrate")){
127         double d1, d2, d3, d4, d5, d6, d7, d8;
128         line >> d1 >> d2 >> d3 >> d4 >> d5 >> d6 >> d7 >> d8;
129
130         params.push_back( 1.0);
131         params.push_back( d2 );
132         params.push_back( d2*d2 );
133     }
134     else {
135         cerr << "FATAL ERROR: Don't know how to read parameters for function " << funcname << endl;
136         throw new runtime_error("unknown function");
137     }
138
139     return make_pair(category,params);
140 }
141
142
143
144
145
146 EventInterpolator::EventInterpolator(char *table_filename, double sample_rate){
147   std::map<string,double> cycle_accurate_time_sum;
148
149   exact_matches=0;
150   exact_positive_matches=0;
151   approx_matches=0;
152   approx_positive_matches=0;
153
154   log1.open("log1");
155
156   cout << "Loading timings file: " << table_filename << endl;
157   ifstream accurateTimeTable(table_filename);
158   if(! accurateTimeTable.good() ){
159         cerr << "FATAL ERROR: Couldn't open file(perhaps it doesn't exist): " << table_filename << endl;
160         throw new runtime_error("missing file");
161   }
162
163
164   // Scan through cycle accurate time file inserting the entries into a map
165   while(accurateTimeTable.good())  {
166         string line_s;
167         getline(accurateTimeTable,line_s);
168         istringstream line(line_s);
169
170         // Expected format is:
171         // TRACEBIGSIM: event:{ eid } time:{ t } PAPI:{ list } params:{ list }
172         // params must currently come after event and time.
173
174         string funcname(""), paramstring(""), counterstring("");
175         double time = -1;
176         string temp;
177         line >> temp;
178         if(temp == string("TRACEBIGSIM:")){
179           // parse the next piece of the line
180           string field;
181           line >> field;
182           while(line.good() && accurateTimeTable.good()){
183                 if(field == string("event:{")){
184                   line >> funcname;
185                   line >> temp; // gobble up the '}'
186                   if(temp != string("}"))
187                         cerr << "ERROR: malformed entry in expected times file" << endl;
188                 } else if (field == string("time:{")){
189                   line >> time;
190                   line >> temp; // gobble up the '}'
191                   if(temp != string("}"))
192                         cerr << "ERROR: malformed entry in expected times file" << endl;
193                 } else if (field == string("PAPI:{")){
194                   counterstring = parseStreamUntilSquiggle(line);
195                 } else if (field == string("params:{")){
196                   paramstring = parseStreamUntilSquiggle(line);
197                 } else {
198                   cout << "Unknown event field: " << field  << endl;
199                 }
200                 line >> field;
201           }
202
203           if(funcname != string("") && time != -1){
204                 istringstream paramstream(paramstring);
205                 fullParams params = parseParameters(funcname,paramstream);
206                 funcIdentifier func(funcname,params.first);
207                 sample_count[func]++;
208                 cycle_accurate_time_sum[funcname] += time;
209                 accurateTimings.insert(make_pair(make_pair(func,params.second),time));
210           } else {
211                 cerr << "malformed TRACEBIGSIM: line" << endl;
212           }
213
214
215         }
216
217   }
218
219
220   std::map<string,double>::iterator cycle_i;
221   cout << "\nThe following table displays the total cycle count for each event in the \n"
222         "cycle-accurate timings file. This may be useful for back of the envelope \n"
223         "calculations for expected performance " << endl << endl;
224   cout << "\t|===============================|===================|" << endl;
225   cout << "\t|                        event  | total time (sec)  |" << endl;
226   cout << "\t|-------------------------------|-------------------|" << endl;
227   for(cycle_i= cycle_accurate_time_sum.begin();cycle_i!=cycle_accurate_time_sum.end();++cycle_i){
228         cout << "\t|";
229         assert((*cycle_i).first.length() <= 30); // the event names should be at most 30 characters
230         for(int i=0;i<30-(*cycle_i).first.length();++i)
231           cout << " ";
232         cout << (*cycle_i).first << " | ";
233         cout.width(17);
234     cout << (*cycle_i).second;
235         cout << " |" << endl;
236   }
237   cout << "\t|===============================|===================|" << endl << endl;
238
239
240
241   unsigned long sample_keep = (unsigned long) ceil(sample_rate * accurateTimings.size());
242   if (sample_rate < 1.0){
243         cout << "Randomly dropping " << (1.0-sample_rate)*100 << "% of the cycle accurate timings" << endl;
244         accurateTimings = random_select_multimap(accurateTimings, sample_keep);
245   }
246
247   analyzeExactVariances();
248
249   cout << "\nThe following table displays the number of timing samples from \n the cycle-accurate file for each event." << endl << endl;
250   cout << "\t|===================================|==========================|" << endl;
251   cout << "\t|                            event  | number of timing samples |" << endl;
252   cout << "\t|-----------------------------------|--------------------------|" << endl;
253
254
255   // Create a gsl interpolator workspace for each event/function
256   for(map<funcIdentifier,unsigned long>::iterator i=sample_count.begin(); i!=sample_count.end();++i){
257         funcIdentifier func = (*i).first;
258         unsigned long samples = (*i).second;
259
260         cout << "\t|";
261
262         for(int i=0;i<30-func.first.length();++i)
263           cout << " ";
264         cout << func.first << ",";
265         cout.width(3);
266         cout << func.second;
267
268         cout << " | ";
269         cout.width(24);
270         cout << samples << " |" << endl;
271
272
273         if(samples < numCoefficients(func.first) ){
274           cerr << "FATAL ERROR: Not enough input timing samples for " << func.first << "," << func.second << " which has " << numCoefficients(func.first) << " coefficients" << endl;
275           throw new runtime_error("samples < numCoefficients");
276         }
277         else {
278           work[func] = gsl_multifit_linear_alloc(samples,numCoefficients(func.first));
279           X[func] = gsl_matrix_alloc (samples,numCoefficients(func.first));
280           y[func] = gsl_vector_alloc (samples);
281           c[func] = gsl_vector_alloc(numCoefficients(func.first));
282           cov[func] = gsl_matrix_alloc(numCoefficients(func.first),numCoefficients(func.first));
283
284           for(int i=0;i<numCoefficients(func.first);++i){
285                 gsl_vector_set(c[func],i,1.0);
286           }
287
288         }
289   }
290   cout << "\t|===================================|==========================|" << endl << endl;
291
292   accurateTimeTable.close();
293
294
295 #ifdef WRITESTATS
296   ofstream statfile("stats-out");
297 #endif
298
299   // Fill in values for matrix X and vector Y which will be fed into the least square fit algorithm
300   // The data is currently in  accurateTimings[pair<funcIdentifier,vector<double> >(func,params.second)]=time;
301
302   //iterate through accurateTimings
303   map< pair<funcIdentifier,vector<double> >, double >::iterator itr;
304   for(itr=accurateTimings.begin();itr!=accurateTimings.end();++itr){
305         const double &time = (*itr).second;
306         const vector<double> &paramsSecond =(*itr).first.second;
307         const funcIdentifier func = (*itr).first.first;
308
309         // lookup the next unused entry in X
310         unsigned next = Xcount[func] ++;
311         gsl_matrix * x = X[func];
312
313         // copy data into array X and Y
314         for(int param_index=0;param_index<paramsSecond.size();++param_index){
315           gsl_matrix_set(x,next,param_index, paramsSecond[param_index]);
316         }
317         gsl_vector_set(y[func],next,time);
318
319   }
320
321
322 #ifdef WRITESTATS
323   statfile.close();
324 #endif
325
326   // Perform a sanity check now
327   int count1=0, count2=0;
328   for(map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i=work.begin();i!=work.end();++i){
329 #if DEBUG
330         cout << "sample count vs Xcount (" << (*i).first.first << "): " << sample_count[(*i).first] << "?=" << Xcount[(*i).first] << " " << endl;
331 #endif
332         count1 += sample_count[(*i).first];
333         count2 += Xcount[(*i).first] ;
334   }
335   cout << "Samples from cycle accurate file : " << count1 << ".  Keeping only " << count2 << " of them " << endl;
336
337   cout << "Performing Least Squared Fit to sampled time data" << endl;
338
339   //  Now do Least Square Fit: Find C where y=Xc
340   cout << "\nThe following table displays the chi^2 measure for how well the model fits the input times." << endl << endl;
341   cout << "\t|===================================|=========|=========|" << endl;
342   cout << "\t|                            event  |   chi^2 |     chi |" << endl;
343   cout << "\t|-----------------------------------|---------|---------|" << endl;
344
345   cout.setf(ios_base::scientific, ios_base::floatfield);
346   cout.precision(1);
347
348   map<funcIdentifier, gsl_multifit_linear_workspace *>::iterator i;
349   for(i=work.begin();i!=work.end();++i){
350         funcIdentifier func = (*i).first;
351         assert(! gsl_multifit_linear(X[func],y[func],c[func],cov[func],&chisqr[func],work[func]));
352         gsl_matrix_free(X[func]);
353         gsl_vector_free(y[func]);
354
355         cout << "\t|";
356
357         for(int i=0;i<30-func.first.length();++i)
358           cout << " ";
359         cout << func.first << ",";
360         cout.width(3);
361         cout << func.second;
362
363         cout << " | ";
364         cout.width(7);
365         cout << chisqr[func];
366
367         cout << " | ";
368         cout.width(7);
369         cout << sqrt(chisqr[func]) << " |" << endl;
370
371   }
372   cout << "\t|===================================|=========|=========|" << endl << endl;
373
374   // Load in Parameter File which maps event id to function name and parameters
375   cout << "Loading parameter files (May take a while)" << endl;
376
377   for(int i=0;true;++i){
378         char name[512];
379         sprintf(name,"param.%d",i);
380         ifstream parameterEventTable(name);
381
382         if(parameterEventTable.good()){
383 #ifdef DEBUG
384           cout << "     >  Loading " << name << endl;
385 #endif
386
387           while(parameterEventTable.good()){
388                 string line_s;
389                 getline(parameterEventTable,line_s);
390                 istringstream line(line_s);
391
392                 if(parameterEventTable.good()){
393                   string t1, t2;
394                   string funcname;
395                   unsigned eventid;
396
397                   line >> eventid;
398                   line >> t1 >> t2;
399                   line >> funcname;
400
401                   if(t1 == string("TRACEBIGSIM")){
402 #ifdef PRETEND_NO_ENERGY
403                         if(funcname == string("calc_pair_energy")){\
404                           funcname = "calc_pair";
405                         }
406                         else if(funcname == string("calc_self_energy")){
407                           funcname = "calc_self";
408                         }
409 #endif
410
411                         fullParams params = parseParameters(funcname,line);
412                         funcIdentifier func(funcname,params.first);
413                         Xcount[func] ++;
414                         eventparams[make_pair(i,eventid)] = make_pair(func,params.second);
415                   }
416                 }
417           }
418
419         }
420         else{ // file was no good
421           break;
422         }
423
424         parameterEventTable.close();
425   }
426 }
427
428
429 bool EventInterpolator::haveExactTime(const unsigned pe, const unsigned eventid){
430     return haveExactTime(eventparams[make_pair(pe,eventid)]);
431 }
432
433 bool EventInterpolator::haveExactTime(const pair<funcIdentifier,vector<double> > &p) {
434     return haveExactTime(p.first,p.second);
435 }
436
437 bool EventInterpolator::haveExactTime(const funcIdentifier& func, const vector<double> &p){
438   return (accurateTimings.find(make_pair(func,p)) != accurateTimings.end());
439 }
440
441 double EventInterpolator::lookupExactTime(const unsigned pe, const unsigned eventid){
442     return lookupExactTime(eventparams[make_pair(pe,eventid)]);
443 }
444
445 double EventInterpolator::lookupExactTime(const pair<funcIdentifier,vector<double> > &p) {
446     return lookupExactTime(p.first,p.second);
447 }
448
449 double EventInterpolator::lookupExactTime(const funcIdentifier& func, const vector<double> &p){
450     const  pair<funcIdentifier,vector<double> > key(func,p);
451     const int count = accurateTimings.count(key);
452
453         pair<timings_type::iterator, timings_type::iterator> itrs = accurateTimings.equal_range(key);
454         double time_sum=0;
455         for(timings_type::iterator itr=itrs.first; itr!=itrs.second; ++itr){
456           time_sum += (*itr).second;
457         }
458         double time_average = time_sum / count;
459
460     exact_matches++;
461         assert(time_average >= 0.0 );
462     return time_average;
463 }
464
465
466 /** Print out some statistics about the timings for any parameter that has multiple associated cycle-accurate timings */
467 void EventInterpolator::analyzeExactVariances(){
468
469     map< pair<funcIdentifier,vector<double> >, double > variances;
470     map< pair<funcIdentifier,vector<double> >, double > means;
471         map< funcIdentifier, double > max_std_dev;
472         map< funcIdentifier, double > associated_mean;
473
474         // Iterate through items in accurateTimings and store variances
475         timings_type::iterator itr;
476         for(itr=accurateTimings.begin();itr!=accurateTimings.end();++itr){
477           variances[(*itr).first] = lookupExactVariance( (*itr).first );
478           means[(*itr).first] = lookupExactMean( (*itr).first );
479         }
480
481         // Display the variances
482         map< pair<funcIdentifier,vector<double> >, double >::iterator vItr;
483         for(vItr = variances.begin(); vItr!=variances.end(); ++vItr){
484           double var = (*vItr).second;
485           double stddev = sqrt(var);
486           double mean = means[(*vItr).first];
487
488           if(var > 0.0){
489                 if(stddev > max_std_dev[(*vItr).first.first]){
490                   max_std_dev[(*vItr).first.first] = stddev;
491                   associated_mean[(*vItr).first.first] = mean;
492                 }
493           }
494         }
495
496         // Display the max std dev for any given event
497         cout << "\nThe following events have differing exact times for one or more parameter set.\n"
498                 "Each line corresponds to whichever parameter list produced the greatest variance\n"
499                 "(and equivalently std dev). The mean is the mean timing value associated with the\n"
500             " same parameter list of greatest variance" << endl << endl;
501
502
503         cout << "\t|===================================|=================|=================|==============|" << endl;
504         cout << "\t|                            event  |     max std dev |      mean (sec) | sd % of mean |" << endl;
505         cout << "\t|-----------------------------------|-----------------|-----------------|--------------|" << endl;
506
507 //      cout.setf(ios_base::fixed, ios_base::floatfield);
508     cout.setf(ios_base::scientific, ios_base::floatfield);
509         cout.precision(3);
510
511         int func_name_field_width=30;
512         map< funcIdentifier, double >::iterator sItr;
513         for(sItr=max_std_dev.begin(); sItr!=max_std_dev.end(); ++sItr) {
514           double stddev = (*sItr).second;
515           double mean = associated_mean[(*sItr).first];
516           cout << "\t|";
517           for(int i=0;i<func_name_field_width-(*sItr).first.first.length();++i)
518                 cout << " ";
519           cout << (*sItr).first.first ;
520           cout << ",";
521           cout.width(3);
522           cout << (*sItr).first.second;
523           cout << " | ";
524           cout.width(15);
525       cout.setf(ios_base::scientific, ios_base::floatfield);
526       cout.precision(3);
527           cout <<  stddev;
528           cout << " | ";
529       cout.width(15);
530       cout.setf(ios_base::scientific, ios_base::floatfield);
531       cout.precision(3);
532           cout << mean << " | ";
533           cout.width(9);
534       cout.setf(ios_base::fixed, ios_base::floatfield);
535       cout.precision(1);
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