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