00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <Basics.H>
00023 #include <Table.H>
00024 #include <IntKey.H>
00025 #include <Generics.H>
00026 #include "StatCount.H"
00027
00028 using std::ostream;
00029 using std::endl;
00030
00031 static int IdentityMap(int x) throw ()
00032 { return x; }
00033
00034 static bool RESeqMatch(const char *string, RegExpSeq &res)
00035 {
00036 for(unsigned int i = 0; i < res.size(); i++)
00037 {
00038 Basics::RegExp *re = res.get(i);
00039 assert(re != 0);
00040 if(re->match(string))
00041 return true;
00042 }
00043 return false;
00044 }
00045
00046 StatCount::StatCount() throw ()
00047 : numVals(0), total(0), tbl( 0), histoMapName(NULL),
00048 minLoc(0), maxLoc(0),
00049 troubleEnd(troubleHigh),
00050 reportCount(0), reportCount_set(false), troubleSet()
00051 {
00052 this->histoMap = IdentityMap;
00053 }
00054
00055 void StatCount::SetHistoMap(const char *name, int (*map)(int)) throw ()
00056 {
00057 this->histoMapName = name;
00058 this->histoMap = map;
00059 }
00060
00061 void StatCount::AddTroubleEntry(int val, const Stat::Location *loc)
00062 {
00063
00064
00065 troubleSet_t::iterator placement = this->troubleSet.begin();
00066 while((placement != this->troubleSet.end()) &&
00067 this->MoreTrouble((*placement).val, val))
00068 placement++;
00069
00070
00071 this->troubleSet.insert(placement, toubleLoc_t(val, loc));
00072
00073
00074 int souceFuncCount = 0;
00075 (void) this->troubleCounts.Get(loc->get_sourceFunc(),
00076 souceFuncCount);
00077 this->troubleCounts.Put(loc->get_sourceFunc(),
00078 ++souceFuncCount);
00079 }
00080
00081 void StatCount::PruneTroubleEntries()
00082 {
00083
00084 while((this->troubleSet.size() > 0) &&
00085 (this->troubleCounts.Size() > this->reportCount))
00086 {
00087
00088 toubleLoc_t removed = this->troubleSet.back();
00089 assert(removed.loc != 0);
00090 this->troubleSet.pop_back();
00091
00092
00093
00094 int souceFuncCount;
00095 bool inTbl =
00096 this->troubleCounts.Get(removed.loc->get_sourceFunc(),
00097 souceFuncCount);
00098 assert(inTbl);
00099 souceFuncCount--;
00100 if(souceFuncCount > 0)
00101 {
00102 this->troubleCounts.Put(removed.loc->get_sourceFunc(),
00103 souceFuncCount);
00104 }
00105 else
00106 {
00107 this->troubleCounts.Delete(removed.loc->get_sourceFunc(),
00108 souceFuncCount);
00109 }
00110 }
00111 }
00112
00113 void StatCount::AddVal(int val, const Stat::Location *loc) throw ()
00114 {
00115 if (this->numVals == 0) {
00116 this->minVal = this->maxVal = val;
00117 this->minLoc = this->maxLoc = loc;
00118 } else {
00119 if (val < this->minVal) {
00120 this->minVal = val;
00121 this->minLoc = loc;
00122 } else if (val > this->maxVal) {
00123 this->maxVal = val;
00124 this->maxLoc = loc;
00125 }
00126 }
00127 this->total += val;
00128 this->numVals++;
00129 IntKey key((*(this->histoMap))(val)); int cnt;
00130 if (this->tbl.Get(key, cnt)) {
00131
00132 this->tbl.Put(key, cnt+1);
00133 } else {
00134
00135 this->tbl.Put(key, 1);
00136 }
00137
00138
00139 if(this->reportCount_set)
00140 {
00141
00142 if(!RESeqMatch(loc->get_sourceFunc().cchars(), this->troubleMasks))
00143 {
00144
00145
00146
00147
00148
00149
00150
00151 if((this->troubleCounts.Size() < this->reportCount) ||
00152 ((this->troubleSet.size() > 0) &&
00153 this->MoreTrouble(val, this->troubleSet.back().val)))
00154 {
00155
00156 AddTroubleEntry(val, loc);
00157
00158
00159 PruneTroubleEntries();
00160 }
00161 }
00162 }
00163 }
00164
00165 void StatCount::Merge(const StatCount &sc) throw ()
00166 {
00167 if (this->numVals == 0) {
00168 this->minVal = sc.minVal; this->minLoc = sc.minLoc;
00169 this->maxVal = sc.maxVal; this->maxLoc = sc.maxLoc;
00170 } else {
00171 if (sc.minVal < this->minVal) {
00172 this->minVal = sc.minVal;
00173 this->minLoc = sc.minLoc;
00174 }
00175 if (sc.maxVal > this->maxVal) {
00176 this->maxVal = sc.maxVal;
00177 this->maxLoc = sc.maxLoc;
00178 }
00179 }
00180 this->total += sc.total;
00181 this->numVals += sc.numVals;
00182 IntIntIter it(&(sc.tbl));
00183 IntKey key; int cnt, scCnt;
00184 while (it.Next( key, scCnt)) {
00185 assert(scCnt != 0);
00186 if (this->tbl.Get(key, cnt)) {
00187
00188 this->tbl.Put(key, cnt + scCnt);
00189 } else {
00190
00191 this->tbl.Put(key, scCnt);
00192 }
00193 }
00194
00195
00196 if(this->reportCount_set)
00197 {
00198
00199 for(troubleSet_t::const_iterator it = sc.troubleSet.begin();
00200 it != sc.troubleSet.end();
00201 it++)
00202 {
00203
00204 if(!RESeqMatch((*it).loc->get_sourceFunc().cchars(),
00205 this->troubleMasks))
00206 continue;
00207
00208
00209
00210
00211 if((this->troubleCounts.Size() < this->reportCount) ||
00212 ((this->troubleSet.size() > 0) &&
00213 this->MoreTrouble((*it).val, this->troubleSet.back().val)))
00214 {
00215 AddTroubleEntry((*it).val, (*it).loc);
00216 }
00217 }
00218
00219
00220 PruneTroubleEntries();
00221 }
00222 }
00223
00224 int StatCount::MinVal() const throw ()
00225 {
00226 if (this->numVals == 0) assert(false);
00227 return this->minVal;
00228 }
00229
00230 int StatCount::MaxVal() const throw ()
00231 {
00232 if (this->numVals == 0) assert(false);
00233 return this->maxVal;
00234 }
00235
00236 float StatCount::MeanVal() const throw ()
00237 {
00238 if (this->numVals == 0) assert(false);
00239 return (float)(this->total) / (float)(this->numVals);
00240 }
00241
00242 static void SC_Indent(ostream &os, int i) throw ()
00243 {
00244 for (; i > 0; i--) os << ' ';
00245 }
00246
00247 void StatCount::Print(ostream &os, int indent, bool printHisto,
00248 bool printMinLoc, bool printMaxLoc, bool printMean) const throw ()
00249 {
00250 SC_Indent(os, indent);
00251 if (this->numVals == 0) {
00252 os << "number = 0" << endl;
00253 return;
00254 } else if (!printMean && this->minVal == this->maxVal
00255 && this->numVals == this->total) {
00256
00257 os << "number = " << this->numVals << endl;
00258 return;
00259 } else {
00260 os << "number = " << this->numVals << endl;
00261 SC_Indent(os, indent);
00262 os << "min = " << this->minVal << ", mean = " <<
00263 this->MeanVal() << ", max = " << this->maxVal << endl;
00264 bool printBoth =
00265 (printMinLoc && printMaxLoc && (this->minVal == this->maxVal));
00266 if (printMinLoc && (this->minLoc != 0)) {
00267 SC_Indent(os, indent);
00268 os << (printBoth ? "Min/max" : "Min");
00269 os << " value in: " << endl;
00270 SC_Indent(os, indent+2);
00271 this->minLoc->print(os, indent+2);
00272 os << endl;
00273 }
00274 if (!printBoth && printMaxLoc && (this->maxLoc != 0)) {
00275 SC_Indent(os, indent);
00276 os << "Max value in: " << endl;
00277 SC_Indent(os, indent+2);
00278 this->maxLoc->print(os, indent+2);
00279 os << endl;
00280 }
00281 }
00282 if (printHisto) PrintHisto(os, indent);
00283 if (this->reportCount_set) PrintTrouble(os, indent);
00284 }
00285
00286 bool StatCount::MoreTrouble(int val1, int val2)
00287 {
00288 if(this->troubleEnd == troubleHigh)
00289 {
00290 return (val1 > val2);
00291 }
00292 else
00293 {
00294 return (val1 < val2);
00295 }
00296 }
00297
00298 extern "C"
00299 {
00300 static int IntCompare(const void *v1, const void *v2) throw ()
00301 {
00302 int *i1 = (int *)v1, *i2 = (int *)v2;
00303 return *i1 - *i2;
00304 }
00305 }
00306
00307 void StatCount::PrintHisto(ostream &os, int indent) const throw ()
00308 {
00309
00310 int tblSz = this->tbl.Size();
00311 int *keys = NEW_PTRFREE_ARRAY(int, tblSz);
00312
00313
00314 IntIntIter it(&(this->tbl));
00315 IntKey key; int val, i = 0;
00316 while (it.Next( key, val)) {
00317 keys[i++] = key.Val();
00318 }
00319 assert(i == tblSz);
00320
00321
00322 qsort(keys, tblSz, sizeof(*keys), IntCompare);
00323
00324
00325 int lineCnt = 0;
00326 if (this->histoMapName != NULL) {
00327 SC_Indent(os, indent);
00328 os << "Histogram mapping function: " << this->histoMapName << endl;
00329 }
00330 SC_Indent(os, indent); os << "{ ";
00331 for (i = 0; i < tblSz; i++) {
00332 IntKey key(keys[i]);
00333 bool inTbl = this->tbl.Get(key, val); assert(inTbl);
00334 if (i > 0) os << ", ";
00335 if (lineCnt >= 6) {
00336 os << endl; SC_Indent(os, indent); os << " ";
00337 lineCnt = 0;
00338 }
00339 os << keys[i] << " -> " << val;
00340 lineCnt++;
00341 }
00342 os << " }" << endl;
00343 }
00344
00345 void StatCount::PrintTrouble(ostream &os, int indent) const throw ()
00346 {
00347
00348
00349 SC_Indent(os, indent);
00350 os << ((this->troubleEnd == troubleHigh) ? "High " : "Low ")
00351 << this->reportCount << " functions:" << endl;
00352
00353 TextIntTbl not_yet_printed(&this->troubleCounts, true);
00354 for(troubleSet_t::const_iterator it = this->troubleSet.begin();
00355 it != this->troubleSet.end();
00356 it++)
00357 {
00358 const Text &sourceFunc = (*it).loc->get_sourceFunc();
00359 int unused;
00360 if(not_yet_printed.Delete(sourceFunc, unused))
00361 {
00362 SC_Indent(os, indent+2);
00363 os << sourceFunc << endl;
00364 }
00365 }
00366
00367
00368 SC_Indent(os, indent);
00369 os << "Detailed "
00370 << ((this->troubleEnd == troubleHigh) ? "high" : "low")
00371 << " cases:" << endl;
00372
00373 for(troubleSet_t::const_iterator it = this->troubleSet.begin();
00374 it != this->troubleSet.end();
00375 it++)
00376 {
00377 SC_Indent(os, indent+2);
00378 os << "value = " << (*it).val << endl;
00379 SC_Indent(os, indent+2);
00380 (*it).loc->print(os, indent+2);
00381 os << endl << endl;
00382 }
00383 }
00384