1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 */ 30 31#if defined(__APPLE__) 32#define _GLIBCPP_USE_C99 1 33#endif 34 35#if defined(__sun) 36#include <math.h> 37#endif 38 39#include <cassert> 40#ifdef __SUNPRO_CC 41#include <math.h> 42#endif 43#include <cmath> 44#include <fstream> 45#include <iostream> 46#include <sstream> 47#include <string> 48 49#include "base/stats/info.hh" 50#include "base/stats/text.hh"
| 1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 */ 30 31#if defined(__APPLE__) 32#define _GLIBCPP_USE_C99 1 33#endif 34 35#if defined(__sun) 36#include <math.h> 37#endif 38 39#include <cassert> 40#ifdef __SUNPRO_CC 41#include <math.h> 42#endif 43#include <cmath> 44#include <fstream> 45#include <iostream> 46#include <sstream> 47#include <string> 48 49#include "base/stats/info.hh" 50#include "base/stats/text.hh"
|
51#include "base/stats/visit.hh"
| |
52#include "base/cast.hh" 53#include "base/misc.hh" 54#include "base/str.hh" 55 56using namespace std; 57 58#ifndef NAN 59float __nan(); 60/** Define Not a number. */ 61#define NAN (__nan()) 62/** Need to define __nan() */ 63#define __M5_NAN 64#endif 65 66#ifdef __M5_NAN 67float 68__nan() 69{ 70 union { 71 uint32_t ui; 72 float f; 73 } nan; 74 75 nan.ui = 0x7fc00000; 76 return nan.f; 77} 78#endif 79 80namespace Stats { 81 82std::list<Info *> &statsList(); 83 84Text::Text() 85 : mystream(false), stream(NULL), descriptions(false) 86{ 87} 88 89Text::Text(std::ostream &stream) 90 : mystream(false), stream(NULL), descriptions(false) 91{ 92 open(stream); 93} 94 95Text::Text(const std::string &file) 96 : mystream(false), stream(NULL), descriptions(false) 97{ 98 open(file); 99} 100 101 102Text::~Text() 103{ 104 if (mystream) { 105 assert(stream); 106 delete stream; 107 } 108} 109 110void 111Text::open(std::ostream &_stream) 112{ 113 if (stream) 114 panic("stream already set!"); 115 116 mystream = false; 117 stream = &_stream; 118 if (!valid()) 119 fatal("Unable to open output stream for writing\n"); 120} 121 122void 123Text::open(const std::string &file) 124{ 125 if (stream) 126 panic("stream already set!"); 127 128 mystream = true; 129 stream = new ofstream(file.c_str(), ios::trunc); 130 if (!valid()) 131 fatal("Unable to open statistics file for writing\n"); 132} 133 134bool 135Text::valid() const 136{ 137 return stream != NULL && stream->good(); 138} 139 140void
| 51#include "base/cast.hh" 52#include "base/misc.hh" 53#include "base/str.hh" 54 55using namespace std; 56 57#ifndef NAN 58float __nan(); 59/** Define Not a number. */ 60#define NAN (__nan()) 61/** Need to define __nan() */ 62#define __M5_NAN 63#endif 64 65#ifdef __M5_NAN 66float 67__nan() 68{ 69 union { 70 uint32_t ui; 71 float f; 72 } nan; 73 74 nan.ui = 0x7fc00000; 75 return nan.f; 76} 77#endif 78 79namespace Stats { 80 81std::list<Info *> &statsList(); 82 83Text::Text() 84 : mystream(false), stream(NULL), descriptions(false) 85{ 86} 87 88Text::Text(std::ostream &stream) 89 : mystream(false), stream(NULL), descriptions(false) 90{ 91 open(stream); 92} 93 94Text::Text(const std::string &file) 95 : mystream(false), stream(NULL), descriptions(false) 96{ 97 open(file); 98} 99 100 101Text::~Text() 102{ 103 if (mystream) { 104 assert(stream); 105 delete stream; 106 } 107} 108 109void 110Text::open(std::ostream &_stream) 111{ 112 if (stream) 113 panic("stream already set!"); 114 115 mystream = false; 116 stream = &_stream; 117 if (!valid()) 118 fatal("Unable to open output stream for writing\n"); 119} 120 121void 122Text::open(const std::string &file) 123{ 124 if (stream) 125 panic("stream already set!"); 126 127 mystream = true; 128 stream = new ofstream(file.c_str(), ios::trunc); 129 if (!valid()) 130 fatal("Unable to open statistics file for writing\n"); 131} 132 133bool 134Text::valid() const 135{ 136 return stream != NULL && stream->good(); 137} 138 139void
|
141Text::output()
| 140Text::begin()
|
142{ 143 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
| 141{ 142 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
|
144 list<Info *>::const_iterator i, end = statsList().end(); 145 for (i = statsList().begin(); i != end; ++i) 146 (*i)->visit(*this);
| 143} 144 145void 146Text::end() 147{
|
147 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n"); 148 stream->flush(); 149} 150 151bool 152Text::noOutput(const Info &info) 153{ 154 if (!info.flags.isSet(display)) 155 return true; 156 157 if (info.prereq && info.prereq->zero()) 158 return true; 159 160 return false; 161} 162 163string 164ValueToString(Result value, int precision) 165{ 166 stringstream val; 167 168 if (!isnan(value)) { 169 if (precision != -1) 170 val.precision(precision); 171 else if (value == rint(value)) 172 val.precision(0); 173 174 val.unsetf(ios::showpoint); 175 val.setf(ios::fixed); 176 val << value; 177 } else { 178 val << "no_value"; 179 } 180 181 return val.str(); 182} 183 184struct ScalarPrint 185{ 186 Result value; 187 string name; 188 string desc; 189 Flags flags; 190 bool descriptions; 191 int precision; 192 Result pdf; 193 Result cdf; 194 195 void update(Result val, Result total); 196 void operator()(ostream &stream) const; 197}; 198 199void 200ScalarPrint::update(Result val, Result total) 201{ 202 value = val; 203 if (total) { 204 pdf = val / total; 205 cdf += pdf; 206 } 207} 208 209void 210ScalarPrint::operator()(ostream &stream) const 211{ 212 if ((flags.isSet(nozero) && value == 0.0) || 213 (flags.isSet(nonan) && isnan(value))) 214 return; 215 216 stringstream pdfstr, cdfstr; 217 218 if (!isnan(pdf)) 219 ccprintf(pdfstr, "%.2f%%", pdf * 100.0); 220 221 if (!isnan(cdf)) 222 ccprintf(cdfstr, "%.2f%%", cdf * 100.0); 223 224 ccprintf(stream, "%-40s %12s %10s %10s", name, 225 ValueToString(value, precision), pdfstr, cdfstr); 226 227 if (descriptions) { 228 if (!desc.empty()) 229 ccprintf(stream, " # %s", desc); 230 } 231 stream << endl; 232} 233 234struct VectorPrint 235{ 236 string name; 237 string separatorString; 238 string desc; 239 vector<string> subnames; 240 vector<string> subdescs; 241 Flags flags; 242 bool descriptions; 243 int precision; 244 VResult vec; 245 Result total; 246 247 void operator()(ostream &stream) const; 248}; 249 250void 251VectorPrint::operator()(std::ostream &stream) const 252{ 253 size_type _size = vec.size(); 254 Result _total = 0.0; 255 256 if (flags.isSet(pdf | cdf)) { 257 for (off_type i = 0; i < _size; ++i) { 258 _total += vec[i]; 259 } 260 } 261 262 string base = name + separatorString; 263 264 ScalarPrint print; 265 print.name = name; 266 print.desc = desc; 267 print.precision = precision; 268 print.descriptions = descriptions; 269 print.flags = flags; 270 print.pdf = _total ? 0.0 : NAN; 271 print.cdf = _total ? 0.0 : NAN; 272 273 bool havesub = !subnames.empty(); 274 275 if (_size == 1) { 276 print.value = vec[0]; 277 print(stream); 278 return; 279 } 280 281 for (off_type i = 0; i < _size; ++i) { 282 if (havesub && (i >= subnames.size() || subnames[i].empty())) 283 continue; 284 285 print.name = base + (havesub ? subnames[i] : to_string(i)); 286 print.desc = subdescs.empty() ? desc : subdescs[i]; 287 288 print.update(vec[i], _total); 289 print(stream); 290 } 291 292 if (flags.isSet(::Stats::total)) { 293 print.pdf = NAN; 294 print.cdf = NAN; 295 print.name = base + "total"; 296 print.desc = desc; 297 print.value = total; 298 print(stream); 299 } 300} 301 302struct DistPrint 303{ 304 string name; 305 string separatorString; 306 string desc; 307 Flags flags; 308 bool descriptions; 309 int precision; 310 311 const DistData &data; 312 313 DistPrint(const Text *text, const DistInfo &info); 314 DistPrint(const Text *text, const VectorDistInfo &info, int i); 315 void init(const Text *text, const Info &info); 316 void operator()(ostream &stream) const; 317}; 318 319DistPrint::DistPrint(const Text *text, const DistInfo &info) 320 : data(info.data) 321{ 322 init(text, info); 323} 324 325DistPrint::DistPrint(const Text *text, const VectorDistInfo &info, int i) 326 : data(info.data[i]) 327{ 328 init(text, info); 329 330 name = info.name + "_" + 331 (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]); 332 333 if (!info.subdescs[i].empty()) 334 desc = info.subdescs[i]; 335} 336 337void 338DistPrint::init(const Text *text, const Info &info) 339{ 340 name = info.name; 341 separatorString = info.separatorString; 342 desc = info.desc; 343 flags = info.flags; 344 precision = info.precision; 345 descriptions = text->descriptions; 346} 347 348void 349DistPrint::operator()(ostream &stream) const 350{ 351 string base = name + separatorString; 352 353 ScalarPrint print; 354 print.precision = precision; 355 print.flags = flags; 356 print.descriptions = descriptions; 357 print.desc = desc; 358 print.pdf = NAN; 359 print.cdf = NAN; 360 361 print.name = base + "samples"; 362 print.value = data.samples; 363 print(stream); 364 365 print.name = base + "mean"; 366 print.value = data.samples ? data.sum / data.samples : NAN; 367 print(stream); 368 369 Result stdev = NAN; 370 if (data.samples) 371 stdev = sqrt((data.samples * data.squares - data.sum * data.sum) / 372 (data.samples * (data.samples - 1.0))); 373 print.name = base + "stdev"; 374 print.value = stdev; 375 print(stream); 376 377 if (data.type == Deviation) 378 return; 379 380 size_t size = data.cvec.size(); 381 382 Result total = 0.0; 383 if (data.type == Dist && data.underflow != NAN) 384 total += data.underflow; 385 for (off_type i = 0; i < size; ++i) 386 total += data.cvec[i]; 387 if (data.type == Dist && data.overflow != NAN) 388 total += data.overflow; 389 390 if (total) { 391 print.pdf = 0.0; 392 print.cdf = 0.0; 393 } 394 395 if (data.type == Dist && data.underflow != NAN) { 396 print.name = base + "underflows"; 397 print.update(data.underflow, total); 398 print(stream); 399 } 400 401 for (off_type i = 0; i < size; ++i) { 402 stringstream namestr; 403 namestr << base; 404 405 Counter low = i * data.bucket_size + data.min; 406 Counter high = ::min(low + data.bucket_size - 1.0, data.max); 407 namestr << low; 408 if (low < high) 409 namestr << "-" << high; 410 411 print.name = namestr.str(); 412 print.update(data.cvec[i], total); 413 print(stream); 414 } 415 416 if (data.type == Dist && data.overflow != NAN) { 417 print.name = base + "overflows"; 418 print.update(data.overflow, total); 419 print(stream); 420 } 421 422 print.pdf = NAN; 423 print.cdf = NAN; 424 425 if (data.type == Dist && data.min_val != NAN) { 426 print.name = base + "min_value"; 427 print.value = data.min_val; 428 print(stream); 429 } 430 431 if (data.type == Dist && data.max_val != NAN) { 432 print.name = base + "max_value"; 433 print.value = data.max_val; 434 print(stream); 435 } 436 437 print.name = base + "total"; 438 print.value = total; 439 print(stream); 440} 441 442void 443Text::visit(const ScalarInfo &info) 444{ 445 if (noOutput(info)) 446 return; 447 448 ScalarPrint print; 449 print.value = info.result(); 450 print.name = info.name; 451 print.desc = info.desc; 452 print.flags = info.flags; 453 print.descriptions = descriptions; 454 print.precision = info.precision; 455 print.pdf = NAN; 456 print.cdf = NAN; 457 458 print(*stream); 459} 460 461void 462Text::visit(const VectorInfo &info) 463{ 464 if (noOutput(info)) 465 return; 466 467 size_type size = info.size(); 468 VectorPrint print; 469 470 print.name = info.name; 471 print.separatorString = info.separatorString; 472 print.desc = info.desc; 473 print.flags = info.flags; 474 print.descriptions = descriptions; 475 print.precision = info.precision; 476 print.vec = info.result(); 477 print.total = info.total(); 478 479 if (!info.subnames.empty()) { 480 for (off_type i = 0; i < size; ++i) { 481 if (!info.subnames[i].empty()) { 482 print.subnames = info.subnames; 483 print.subnames.resize(size); 484 for (off_type i = 0; i < size; ++i) { 485 if (!info.subnames[i].empty() && 486 !info.subdescs[i].empty()) { 487 print.subdescs = info.subdescs; 488 print.subdescs.resize(size); 489 break; 490 } 491 } 492 break; 493 } 494 } 495 } 496 497 print(*stream); 498} 499 500void 501Text::visit(const Vector2dInfo &info) 502{ 503 if (noOutput(info)) 504 return; 505 506 bool havesub = false; 507 VectorPrint print; 508 509 print.subnames = info.y_subnames; 510 print.flags = info.flags; 511 print.separatorString = info.separatorString; 512 print.descriptions = descriptions; 513 print.precision = info.precision; 514 515 if (!info.subnames.empty()) { 516 for (off_type i = 0; i < info.x; ++i) 517 if (!info.subnames[i].empty()) 518 havesub = true; 519 } 520 521 VResult tot_vec(info.y); 522 Result super_total = 0.0; 523 for (off_type i = 0; i < info.x; ++i) { 524 if (havesub && (i >= info.subnames.size() || info.subnames[i].empty())) 525 continue; 526 527 off_type iy = i * info.y; 528 VResult yvec(info.y); 529 530 Result total = 0.0; 531 for (off_type j = 0; j < info.y; ++j) { 532 yvec[j] = info.cvec[iy + j]; 533 tot_vec[j] += yvec[j]; 534 total += yvec[j]; 535 super_total += yvec[j]; 536 } 537 538 print.name = info.name + "_" + 539 (havesub ? info.subnames[i] : to_string(i)); 540 print.desc = info.desc; 541 print.vec = yvec; 542 print.total = total; 543 print(*stream); 544 } 545 546 if (info.flags.isSet(::Stats::total) && (info.x > 1)) { 547 print.name = info.name; 548 print.desc = info.desc; 549 print.vec = tot_vec; 550 print.total = super_total; 551 print(*stream); 552 } 553} 554 555void 556Text::visit(const DistInfo &info) 557{ 558 if (noOutput(info)) 559 return; 560 561 DistPrint print(this, info); 562 print(*stream); 563} 564 565void 566Text::visit(const VectorDistInfo &info) 567{ 568 if (noOutput(info)) 569 return; 570 571 for (off_type i = 0; i < info.size(); ++i) { 572 DistPrint print(this, info, i); 573 print(*stream); 574 } 575} 576 577void 578Text::visit(const FormulaInfo &info) 579{ 580 visit((const VectorInfo &)info); 581} 582
| 148 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n"); 149 stream->flush(); 150} 151 152bool 153Text::noOutput(const Info &info) 154{ 155 if (!info.flags.isSet(display)) 156 return true; 157 158 if (info.prereq && info.prereq->zero()) 159 return true; 160 161 return false; 162} 163 164string 165ValueToString(Result value, int precision) 166{ 167 stringstream val; 168 169 if (!isnan(value)) { 170 if (precision != -1) 171 val.precision(precision); 172 else if (value == rint(value)) 173 val.precision(0); 174 175 val.unsetf(ios::showpoint); 176 val.setf(ios::fixed); 177 val << value; 178 } else { 179 val << "no_value"; 180 } 181 182 return val.str(); 183} 184 185struct ScalarPrint 186{ 187 Result value; 188 string name; 189 string desc; 190 Flags flags; 191 bool descriptions; 192 int precision; 193 Result pdf; 194 Result cdf; 195 196 void update(Result val, Result total); 197 void operator()(ostream &stream) const; 198}; 199 200void 201ScalarPrint::update(Result val, Result total) 202{ 203 value = val; 204 if (total) { 205 pdf = val / total; 206 cdf += pdf; 207 } 208} 209 210void 211ScalarPrint::operator()(ostream &stream) const 212{ 213 if ((flags.isSet(nozero) && value == 0.0) || 214 (flags.isSet(nonan) && isnan(value))) 215 return; 216 217 stringstream pdfstr, cdfstr; 218 219 if (!isnan(pdf)) 220 ccprintf(pdfstr, "%.2f%%", pdf * 100.0); 221 222 if (!isnan(cdf)) 223 ccprintf(cdfstr, "%.2f%%", cdf * 100.0); 224 225 ccprintf(stream, "%-40s %12s %10s %10s", name, 226 ValueToString(value, precision), pdfstr, cdfstr); 227 228 if (descriptions) { 229 if (!desc.empty()) 230 ccprintf(stream, " # %s", desc); 231 } 232 stream << endl; 233} 234 235struct VectorPrint 236{ 237 string name; 238 string separatorString; 239 string desc; 240 vector<string> subnames; 241 vector<string> subdescs; 242 Flags flags; 243 bool descriptions; 244 int precision; 245 VResult vec; 246 Result total; 247 248 void operator()(ostream &stream) const; 249}; 250 251void 252VectorPrint::operator()(std::ostream &stream) const 253{ 254 size_type _size = vec.size(); 255 Result _total = 0.0; 256 257 if (flags.isSet(pdf | cdf)) { 258 for (off_type i = 0; i < _size; ++i) { 259 _total += vec[i]; 260 } 261 } 262 263 string base = name + separatorString; 264 265 ScalarPrint print; 266 print.name = name; 267 print.desc = desc; 268 print.precision = precision; 269 print.descriptions = descriptions; 270 print.flags = flags; 271 print.pdf = _total ? 0.0 : NAN; 272 print.cdf = _total ? 0.0 : NAN; 273 274 bool havesub = !subnames.empty(); 275 276 if (_size == 1) { 277 print.value = vec[0]; 278 print(stream); 279 return; 280 } 281 282 for (off_type i = 0; i < _size; ++i) { 283 if (havesub && (i >= subnames.size() || subnames[i].empty())) 284 continue; 285 286 print.name = base + (havesub ? subnames[i] : to_string(i)); 287 print.desc = subdescs.empty() ? desc : subdescs[i]; 288 289 print.update(vec[i], _total); 290 print(stream); 291 } 292 293 if (flags.isSet(::Stats::total)) { 294 print.pdf = NAN; 295 print.cdf = NAN; 296 print.name = base + "total"; 297 print.desc = desc; 298 print.value = total; 299 print(stream); 300 } 301} 302 303struct DistPrint 304{ 305 string name; 306 string separatorString; 307 string desc; 308 Flags flags; 309 bool descriptions; 310 int precision; 311 312 const DistData &data; 313 314 DistPrint(const Text *text, const DistInfo &info); 315 DistPrint(const Text *text, const VectorDistInfo &info, int i); 316 void init(const Text *text, const Info &info); 317 void operator()(ostream &stream) const; 318}; 319 320DistPrint::DistPrint(const Text *text, const DistInfo &info) 321 : data(info.data) 322{ 323 init(text, info); 324} 325 326DistPrint::DistPrint(const Text *text, const VectorDistInfo &info, int i) 327 : data(info.data[i]) 328{ 329 init(text, info); 330 331 name = info.name + "_" + 332 (info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]); 333 334 if (!info.subdescs[i].empty()) 335 desc = info.subdescs[i]; 336} 337 338void 339DistPrint::init(const Text *text, const Info &info) 340{ 341 name = info.name; 342 separatorString = info.separatorString; 343 desc = info.desc; 344 flags = info.flags; 345 precision = info.precision; 346 descriptions = text->descriptions; 347} 348 349void 350DistPrint::operator()(ostream &stream) const 351{ 352 string base = name + separatorString; 353 354 ScalarPrint print; 355 print.precision = precision; 356 print.flags = flags; 357 print.descriptions = descriptions; 358 print.desc = desc; 359 print.pdf = NAN; 360 print.cdf = NAN; 361 362 print.name = base + "samples"; 363 print.value = data.samples; 364 print(stream); 365 366 print.name = base + "mean"; 367 print.value = data.samples ? data.sum / data.samples : NAN; 368 print(stream); 369 370 Result stdev = NAN; 371 if (data.samples) 372 stdev = sqrt((data.samples * data.squares - data.sum * data.sum) / 373 (data.samples * (data.samples - 1.0))); 374 print.name = base + "stdev"; 375 print.value = stdev; 376 print(stream); 377 378 if (data.type == Deviation) 379 return; 380 381 size_t size = data.cvec.size(); 382 383 Result total = 0.0; 384 if (data.type == Dist && data.underflow != NAN) 385 total += data.underflow; 386 for (off_type i = 0; i < size; ++i) 387 total += data.cvec[i]; 388 if (data.type == Dist && data.overflow != NAN) 389 total += data.overflow; 390 391 if (total) { 392 print.pdf = 0.0; 393 print.cdf = 0.0; 394 } 395 396 if (data.type == Dist && data.underflow != NAN) { 397 print.name = base + "underflows"; 398 print.update(data.underflow, total); 399 print(stream); 400 } 401 402 for (off_type i = 0; i < size; ++i) { 403 stringstream namestr; 404 namestr << base; 405 406 Counter low = i * data.bucket_size + data.min; 407 Counter high = ::min(low + data.bucket_size - 1.0, data.max); 408 namestr << low; 409 if (low < high) 410 namestr << "-" << high; 411 412 print.name = namestr.str(); 413 print.update(data.cvec[i], total); 414 print(stream); 415 } 416 417 if (data.type == Dist && data.overflow != NAN) { 418 print.name = base + "overflows"; 419 print.update(data.overflow, total); 420 print(stream); 421 } 422 423 print.pdf = NAN; 424 print.cdf = NAN; 425 426 if (data.type == Dist && data.min_val != NAN) { 427 print.name = base + "min_value"; 428 print.value = data.min_val; 429 print(stream); 430 } 431 432 if (data.type == Dist && data.max_val != NAN) { 433 print.name = base + "max_value"; 434 print.value = data.max_val; 435 print(stream); 436 } 437 438 print.name = base + "total"; 439 print.value = total; 440 print(stream); 441} 442 443void 444Text::visit(const ScalarInfo &info) 445{ 446 if (noOutput(info)) 447 return; 448 449 ScalarPrint print; 450 print.value = info.result(); 451 print.name = info.name; 452 print.desc = info.desc; 453 print.flags = info.flags; 454 print.descriptions = descriptions; 455 print.precision = info.precision; 456 print.pdf = NAN; 457 print.cdf = NAN; 458 459 print(*stream); 460} 461 462void 463Text::visit(const VectorInfo &info) 464{ 465 if (noOutput(info)) 466 return; 467 468 size_type size = info.size(); 469 VectorPrint print; 470 471 print.name = info.name; 472 print.separatorString = info.separatorString; 473 print.desc = info.desc; 474 print.flags = info.flags; 475 print.descriptions = descriptions; 476 print.precision = info.precision; 477 print.vec = info.result(); 478 print.total = info.total(); 479 480 if (!info.subnames.empty()) { 481 for (off_type i = 0; i < size; ++i) { 482 if (!info.subnames[i].empty()) { 483 print.subnames = info.subnames; 484 print.subnames.resize(size); 485 for (off_type i = 0; i < size; ++i) { 486 if (!info.subnames[i].empty() && 487 !info.subdescs[i].empty()) { 488 print.subdescs = info.subdescs; 489 print.subdescs.resize(size); 490 break; 491 } 492 } 493 break; 494 } 495 } 496 } 497 498 print(*stream); 499} 500 501void 502Text::visit(const Vector2dInfo &info) 503{ 504 if (noOutput(info)) 505 return; 506 507 bool havesub = false; 508 VectorPrint print; 509 510 print.subnames = info.y_subnames; 511 print.flags = info.flags; 512 print.separatorString = info.separatorString; 513 print.descriptions = descriptions; 514 print.precision = info.precision; 515 516 if (!info.subnames.empty()) { 517 for (off_type i = 0; i < info.x; ++i) 518 if (!info.subnames[i].empty()) 519 havesub = true; 520 } 521 522 VResult tot_vec(info.y); 523 Result super_total = 0.0; 524 for (off_type i = 0; i < info.x; ++i) { 525 if (havesub && (i >= info.subnames.size() || info.subnames[i].empty())) 526 continue; 527 528 off_type iy = i * info.y; 529 VResult yvec(info.y); 530 531 Result total = 0.0; 532 for (off_type j = 0; j < info.y; ++j) { 533 yvec[j] = info.cvec[iy + j]; 534 tot_vec[j] += yvec[j]; 535 total += yvec[j]; 536 super_total += yvec[j]; 537 } 538 539 print.name = info.name + "_" + 540 (havesub ? info.subnames[i] : to_string(i)); 541 print.desc = info.desc; 542 print.vec = yvec; 543 print.total = total; 544 print(*stream); 545 } 546 547 if (info.flags.isSet(::Stats::total) && (info.x > 1)) { 548 print.name = info.name; 549 print.desc = info.desc; 550 print.vec = tot_vec; 551 print.total = super_total; 552 print(*stream); 553 } 554} 555 556void 557Text::visit(const DistInfo &info) 558{ 559 if (noOutput(info)) 560 return; 561 562 DistPrint print(this, info); 563 print(*stream); 564} 565 566void 567Text::visit(const VectorDistInfo &info) 568{ 569 if (noOutput(info)) 570 return; 571 572 for (off_type i = 0; i < info.size(); ++i) { 573 DistPrint print(this, info, i); 574 print(*stream); 575 } 576} 577 578void 579Text::visit(const FormulaInfo &info) 580{ 581 visit((const VectorInfo &)info); 582} 583
|
583bool
| 584Output *
|
584initText(const string &filename, bool desc) 585{ 586 static Text text; 587 static bool connected = false; 588
| 585initText(const string &filename, bool desc) 586{ 587 static Text text; 588 static bool connected = false; 589
|
589 if (connected) 590 return false;
| 590 if (!connected) { 591 text.open(*simout.find(filename)); 592 text.descriptions = desc; 593 connected = true; 594 }
|
591
| 595
|
592 extern list<Output *> OutputList; 593 594 text.open(*simout.find(filename)); 595 text.descriptions = desc; 596 OutputList.push_back(&text); 597 connected = true; 598 599 return true;
| 596 return &text;
|
600} 601 602} // namespace Stats
| 597} 598 599} // namespace Stats
|