text.cc (8243:63e849f0f341) text.cc (8296:be7f03723412)
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