text.cc (5598:345ef3bda3d2) text.cc (5599:5bad83cddb8c)
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 <iostream>
40#include <sstream>
41#include <fstream>
42#include <string>
43
44#include "base/misc.hh"
45#include "base/statistics.hh"
46#include "base/stats/statdb.hh"
47#include "base/stats/text.hh"
48#include "base/stats/visit.hh"
49
50using namespace std;
51
52#ifndef NAN
53float __nan();
54/** Define Not a number. */
55#define NAN (__nan())
56/** Need to define __nan() */
57#define __M5_NAN
58#endif
59
60#ifdef __M5_NAN
61float
62__nan()
63{
64 union {
65 uint32_t ui;
66 float f;
67 } nan;
68
69 nan.ui = 0x7fc00000;
70 return nan.f;
71}
72#endif
73
74namespace Stats {
75
76Text::Text()
77 : mystream(false), stream(NULL), compat(false), descriptions(false)
78{
79}
80
81Text::Text(std::ostream &stream)
82 : mystream(false), stream(NULL), compat(false), descriptions(false)
83{
84 open(stream);
85}
86
87Text::Text(const std::string &file)
88 : mystream(false), stream(NULL), compat(false), descriptions(false)
89{
90 open(file);
91}
92
93
94Text::~Text()
95{
96 if (mystream) {
97 assert(stream);
98 delete stream;
99 }
100}
101
102void
103Text::open(std::ostream &_stream)
104{
105 if (stream)
106 panic("stream already set!");
107
108 mystream = false;
109 stream = &_stream;
110 if (!valid())
111 fatal("Unable to open output stream for writing\n");
112}
113
114void
115Text::open(const std::string &file)
116{
117 if (stream)
118 panic("stream already set!");
119
120 mystream = true;
121 stream = new ofstream(file.c_str(), ios::trunc);
122 if (!valid())
123 fatal("Unable to open statistics file for writing\n");
124}
125
126bool
127Text::valid() const
128{
129 return stream != NULL && stream->good();
130}
131
132void
133Text::output()
134{
135 using namespace Database;
136
137 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
138 stat_list_t::const_iterator i, end = stats().end();
139 for (i = stats().begin(); i != end; ++i)
140 (*i)->visit(*this);
141 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
142 stream->flush();
143}
144
145bool
146Text::noOutput(const StatData &data)
147{
148 if (!(data.flags & print))
149 return true;
150
151 if (data.prereq && data.prereq->zero())
152 return true;
153
154 return false;
155}
156
157string
158ValueToString(Result value, int precision, bool compat)
159{
160 stringstream val;
161
162 if (!isnan(value)) {
163 if (precision != -1)
164 val.precision(precision);
165 else if (value == rint(value))
166 val.precision(0);
167
168 val.unsetf(ios::showpoint);
169 val.setf(ios::fixed);
170 val << value;
171 } else {
172 val << (compat ? "<err: div-0>" : "no value");
173 }
174
175 return val.str();
176}
177
178struct ScalarPrint
179{
180 Result value;
181 string name;
182 string desc;
183 StatFlags flags;
184 bool compat;
185 bool descriptions;
186 int precision;
187 Result pdf;
188 Result cdf;
189
190 void operator()(ostream &stream) const;
191};
192
193void
194ScalarPrint::operator()(ostream &stream) const
195{
196 if ((flags & nozero && value == 0.0) ||
197 (flags & nonan && isnan(value)))
198 return;
199
200 stringstream pdfstr, cdfstr;
201
202 if (!isnan(pdf))
203 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
204
205 if (!isnan(cdf))
206 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
207
208 if (compat && flags & __substat) {
209 ccprintf(stream, "%32s %12s %10s %10s", name,
210 ValueToString(value, precision, compat), pdfstr, cdfstr);
211 } else {
212 ccprintf(stream, "%-40s %12s %10s %10s", name,
213 ValueToString(value, precision, compat), pdfstr, cdfstr);
214 }
215
216 if (descriptions) {
217 if (!desc.empty())
218 ccprintf(stream, " # %s", desc);
219 }
220 stream << endl;
221}
222
223struct VectorPrint
224{
225 string name;
226 string desc;
227 vector<string> subnames;
228 vector<string> subdescs;
229 StatFlags flags;
230 bool compat;
231 bool descriptions;
232 int precision;
233 VResult vec;
234 Result total;
235
236 void operator()(ostream &stream) const;
237};
238
239void
240VectorPrint::operator()(std::ostream &stream) const
241{
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 <iostream>
40#include <sstream>
41#include <fstream>
42#include <string>
43
44#include "base/misc.hh"
45#include "base/statistics.hh"
46#include "base/stats/statdb.hh"
47#include "base/stats/text.hh"
48#include "base/stats/visit.hh"
49
50using namespace std;
51
52#ifndef NAN
53float __nan();
54/** Define Not a number. */
55#define NAN (__nan())
56/** Need to define __nan() */
57#define __M5_NAN
58#endif
59
60#ifdef __M5_NAN
61float
62__nan()
63{
64 union {
65 uint32_t ui;
66 float f;
67 } nan;
68
69 nan.ui = 0x7fc00000;
70 return nan.f;
71}
72#endif
73
74namespace Stats {
75
76Text::Text()
77 : mystream(false), stream(NULL), compat(false), descriptions(false)
78{
79}
80
81Text::Text(std::ostream &stream)
82 : mystream(false), stream(NULL), compat(false), descriptions(false)
83{
84 open(stream);
85}
86
87Text::Text(const std::string &file)
88 : mystream(false), stream(NULL), compat(false), descriptions(false)
89{
90 open(file);
91}
92
93
94Text::~Text()
95{
96 if (mystream) {
97 assert(stream);
98 delete stream;
99 }
100}
101
102void
103Text::open(std::ostream &_stream)
104{
105 if (stream)
106 panic("stream already set!");
107
108 mystream = false;
109 stream = &_stream;
110 if (!valid())
111 fatal("Unable to open output stream for writing\n");
112}
113
114void
115Text::open(const std::string &file)
116{
117 if (stream)
118 panic("stream already set!");
119
120 mystream = true;
121 stream = new ofstream(file.c_str(), ios::trunc);
122 if (!valid())
123 fatal("Unable to open statistics file for writing\n");
124}
125
126bool
127Text::valid() const
128{
129 return stream != NULL && stream->good();
130}
131
132void
133Text::output()
134{
135 using namespace Database;
136
137 ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
138 stat_list_t::const_iterator i, end = stats().end();
139 for (i = stats().begin(); i != end; ++i)
140 (*i)->visit(*this);
141 ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
142 stream->flush();
143}
144
145bool
146Text::noOutput(const StatData &data)
147{
148 if (!(data.flags & print))
149 return true;
150
151 if (data.prereq && data.prereq->zero())
152 return true;
153
154 return false;
155}
156
157string
158ValueToString(Result value, int precision, bool compat)
159{
160 stringstream val;
161
162 if (!isnan(value)) {
163 if (precision != -1)
164 val.precision(precision);
165 else if (value == rint(value))
166 val.precision(0);
167
168 val.unsetf(ios::showpoint);
169 val.setf(ios::fixed);
170 val << value;
171 } else {
172 val << (compat ? "<err: div-0>" : "no value");
173 }
174
175 return val.str();
176}
177
178struct ScalarPrint
179{
180 Result value;
181 string name;
182 string desc;
183 StatFlags flags;
184 bool compat;
185 bool descriptions;
186 int precision;
187 Result pdf;
188 Result cdf;
189
190 void operator()(ostream &stream) const;
191};
192
193void
194ScalarPrint::operator()(ostream &stream) const
195{
196 if ((flags & nozero && value == 0.0) ||
197 (flags & nonan && isnan(value)))
198 return;
199
200 stringstream pdfstr, cdfstr;
201
202 if (!isnan(pdf))
203 ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
204
205 if (!isnan(cdf))
206 ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
207
208 if (compat && flags & __substat) {
209 ccprintf(stream, "%32s %12s %10s %10s", name,
210 ValueToString(value, precision, compat), pdfstr, cdfstr);
211 } else {
212 ccprintf(stream, "%-40s %12s %10s %10s", name,
213 ValueToString(value, precision, compat), pdfstr, cdfstr);
214 }
215
216 if (descriptions) {
217 if (!desc.empty())
218 ccprintf(stream, " # %s", desc);
219 }
220 stream << endl;
221}
222
223struct VectorPrint
224{
225 string name;
226 string desc;
227 vector<string> subnames;
228 vector<string> subdescs;
229 StatFlags flags;
230 bool compat;
231 bool descriptions;
232 int precision;
233 VResult vec;
234 Result total;
235
236 void operator()(ostream &stream) const;
237};
238
239void
240VectorPrint::operator()(std::ostream &stream) const
241{
242 int _size = vec.size();
242 size_type _size = vec.size();
243 Result _total = 0.0;
244
245 if (flags & (pdf | cdf)) {
243 Result _total = 0.0;
244
245 if (flags & (pdf | cdf)) {
246 for (int i = 0; i < _size; ++i) {
246 for (off_type i = 0; i < _size; ++i) {
247 _total += vec[i];
248 }
249 }
250
251 string base = name + (compat ? "_" : "::");
252
253 ScalarPrint print;
254 print.name = name;
255 print.desc = desc;
256 print.compat = compat;
257 print.precision = precision;
258 print.descriptions = descriptions;
259 print.flags = flags;
260 print.pdf = NAN;
261 print.cdf = NAN;
262
263 bool havesub = !subnames.empty();
264
265 if (_size == 1) {
266 print.value = vec[0];
267 print(stream);
268 } else if (!compat) {
247 _total += vec[i];
248 }
249 }
250
251 string base = name + (compat ? "_" : "::");
252
253 ScalarPrint print;
254 print.name = name;
255 print.desc = desc;
256 print.compat = compat;
257 print.precision = precision;
258 print.descriptions = descriptions;
259 print.flags = flags;
260 print.pdf = NAN;
261 print.cdf = NAN;
262
263 bool havesub = !subnames.empty();
264
265 if (_size == 1) {
266 print.value = vec[0];
267 print(stream);
268 } else if (!compat) {
269 for (int i = 0; i < _size; ++i) {
269 for (off_type i = 0; i < _size; ++i) {
270 if (havesub && (i >= subnames.size() || subnames[i].empty()))
271 continue;
272
273 print.name = base + (havesub ? subnames[i] : to_string(i));
274 print.desc = subdescs.empty() ? desc : subdescs[i];
275 print.value = vec[i];
276
277 if (_total && (flags & pdf)) {
278 print.pdf = vec[i] / _total;
279 print.cdf += print.pdf;
280 }
281
282 print(stream);
283 }
284
285 if (flags & ::Stats::total) {
286 print.name = base + "total";
287 print.desc = desc;
288 print.value = total;
289 print(stream);
290 }
291 } else {
292 if (flags & ::Stats::total) {
293 print.value = total;
294 print(stream);
295 }
296
297 Result _pdf = 0.0;
298 Result _cdf = 0.0;
299 if (flags & dist) {
300 ccprintf(stream, "%s.start_dist\n", name);
270 if (havesub && (i >= subnames.size() || subnames[i].empty()))
271 continue;
272
273 print.name = base + (havesub ? subnames[i] : to_string(i));
274 print.desc = subdescs.empty() ? desc : subdescs[i];
275 print.value = vec[i];
276
277 if (_total && (flags & pdf)) {
278 print.pdf = vec[i] / _total;
279 print.cdf += print.pdf;
280 }
281
282 print(stream);
283 }
284
285 if (flags & ::Stats::total) {
286 print.name = base + "total";
287 print.desc = desc;
288 print.value = total;
289 print(stream);
290 }
291 } else {
292 if (flags & ::Stats::total) {
293 print.value = total;
294 print(stream);
295 }
296
297 Result _pdf = 0.0;
298 Result _cdf = 0.0;
299 if (flags & dist) {
300 ccprintf(stream, "%s.start_dist\n", name);
301 for (int i = 0; i < _size; ++i) {
301 for (off_type i = 0; i < _size; ++i) {
302 print.name = havesub ? subnames[i] : to_string(i);
303 print.desc = subdescs.empty() ? desc : subdescs[i];
304 print.flags |= __substat;
305 print.value = vec[i];
306
307 if (_total) {
308 _pdf = vec[i] / _total;
309 _cdf += _pdf;
310 }
311
312 if (flags & pdf)
313 print.pdf = _pdf;
314 if (flags & cdf)
315 print.cdf = _cdf;
316
317 print(stream);
318 }
319 ccprintf(stream, "%s.end_dist\n", name);
320 } else {
302 print.name = havesub ? subnames[i] : to_string(i);
303 print.desc = subdescs.empty() ? desc : subdescs[i];
304 print.flags |= __substat;
305 print.value = vec[i];
306
307 if (_total) {
308 _pdf = vec[i] / _total;
309 _cdf += _pdf;
310 }
311
312 if (flags & pdf)
313 print.pdf = _pdf;
314 if (flags & cdf)
315 print.cdf = _cdf;
316
317 print(stream);
318 }
319 ccprintf(stream, "%s.end_dist\n", name);
320 } else {
321 for (int i = 0; i < _size; ++i) {
321 for (off_type i = 0; i < _size; ++i) {
322 if (havesub && subnames[i].empty())
323 continue;
324
325 print.name = base;
326 print.name += havesub ? subnames[i] : to_string(i);
327 print.desc = subdescs.empty() ? desc : subdescs[i];
328 print.value = vec[i];
329
330 if (_total) {
331 _pdf = vec[i] / _total;
332 _cdf += _pdf;
333 } else {
334 _pdf = _cdf = NAN;
335 }
336
337 if (flags & pdf) {
338 print.pdf = _pdf;
339 print.cdf = _cdf;
340 }
341
342 print(stream);
343 }
344 }
345 }
346}
347
348struct DistPrint
349{
350 string name;
351 string desc;
352 StatFlags flags;
353 bool compat;
354 bool descriptions;
355 int precision;
356
357 Result min_val;
358 Result max_val;
359 Result underflow;
360 Result overflow;
361 VResult vec;
362 Result sum;
363 Result squares;
364 Result samples;
365
366 Counter min;
367 Counter max;
368 Counter bucket_size;
322 if (havesub && subnames[i].empty())
323 continue;
324
325 print.name = base;
326 print.name += havesub ? subnames[i] : to_string(i);
327 print.desc = subdescs.empty() ? desc : subdescs[i];
328 print.value = vec[i];
329
330 if (_total) {
331 _pdf = vec[i] / _total;
332 _cdf += _pdf;
333 } else {
334 _pdf = _cdf = NAN;
335 }
336
337 if (flags & pdf) {
338 print.pdf = _pdf;
339 print.cdf = _cdf;
340 }
341
342 print(stream);
343 }
344 }
345 }
346}
347
348struct DistPrint
349{
350 string name;
351 string desc;
352 StatFlags flags;
353 bool compat;
354 bool descriptions;
355 int precision;
356
357 Result min_val;
358 Result max_val;
359 Result underflow;
360 Result overflow;
361 VResult vec;
362 Result sum;
363 Result squares;
364 Result samples;
365
366 Counter min;
367 Counter max;
368 Counter bucket_size;
369 int size;
369 size_type size;
370 bool fancy;
371
372 void operator()(ostream &stream) const;
373};
374
375void
376DistPrint::operator()(ostream &stream) const
377{
378 if (fancy) {
379 ScalarPrint print;
380 string base = name + (compat ? "_" : "::");
381
382 print.precision = precision;
383 print.flags = flags;
384 print.compat = compat;
385 print.descriptions = descriptions;
386 print.desc = desc;
387 print.pdf = NAN;
388 print.cdf = NAN;
389
390 print.name = base + "mean";
391 print.value = samples ? sum / samples : NAN;
392 print(stream);
393
394 print.name = base + "stdev";
395 print.value = samples ? sqrt((samples * squares - sum * sum) /
396 (samples * (samples - 1.0))) : NAN;
397 print(stream);
398
399 print.name = "**Ignore: " + base + "TOT";
400 print.value = samples;
401 print(stream);
402 return;
403 }
404
405 assert(size == vec.size());
406
407 Result total = 0.0;
408
409 total += underflow;
370 bool fancy;
371
372 void operator()(ostream &stream) const;
373};
374
375void
376DistPrint::operator()(ostream &stream) const
377{
378 if (fancy) {
379 ScalarPrint print;
380 string base = name + (compat ? "_" : "::");
381
382 print.precision = precision;
383 print.flags = flags;
384 print.compat = compat;
385 print.descriptions = descriptions;
386 print.desc = desc;
387 print.pdf = NAN;
388 print.cdf = NAN;
389
390 print.name = base + "mean";
391 print.value = samples ? sum / samples : NAN;
392 print(stream);
393
394 print.name = base + "stdev";
395 print.value = samples ? sqrt((samples * squares - sum * sum) /
396 (samples * (samples - 1.0))) : NAN;
397 print(stream);
398
399 print.name = "**Ignore: " + base + "TOT";
400 print.value = samples;
401 print(stream);
402 return;
403 }
404
405 assert(size == vec.size());
406
407 Result total = 0.0;
408
409 total += underflow;
410 for (int i = 0; i < size; ++i)
410 for (off_type i = 0; i < size; ++i)
411 total += vec[i];
412 total += overflow;
413
414 string base = name + (compat ? "." : "::");
415
416 ScalarPrint print;
417 print.desc = compat ? "" : desc;
418 print.flags = flags;
419 print.compat = compat;
420 print.descriptions = descriptions;
421 print.precision = precision;
422 print.pdf = NAN;
423 print.cdf = NAN;
424
425 if (compat) {
426 ccprintf(stream, "%-42s", base + "start_dist");
427 if (descriptions && !desc.empty())
428 ccprintf(stream, " # %s", desc);
429 stream << endl;
430 }
431
432 print.name = base + "samples";
433 print.value = samples;
434 print(stream);
435
436 print.name = base + "min_value";
437 print.value = min_val;
438 print(stream);
439
440 if (!compat || underflow > 0.0) {
441 print.name = base + "underflows";
442 print.value = underflow;
443 if (!compat && total) {
444 print.pdf = underflow / total;
445 print.cdf += print.pdf;
446 }
447 print(stream);
448 }
449
450 if (!compat) {
411 total += vec[i];
412 total += overflow;
413
414 string base = name + (compat ? "." : "::");
415
416 ScalarPrint print;
417 print.desc = compat ? "" : desc;
418 print.flags = flags;
419 print.compat = compat;
420 print.descriptions = descriptions;
421 print.precision = precision;
422 print.pdf = NAN;
423 print.cdf = NAN;
424
425 if (compat) {
426 ccprintf(stream, "%-42s", base + "start_dist");
427 if (descriptions && !desc.empty())
428 ccprintf(stream, " # %s", desc);
429 stream << endl;
430 }
431
432 print.name = base + "samples";
433 print.value = samples;
434 print(stream);
435
436 print.name = base + "min_value";
437 print.value = min_val;
438 print(stream);
439
440 if (!compat || underflow > 0.0) {
441 print.name = base + "underflows";
442 print.value = underflow;
443 if (!compat && total) {
444 print.pdf = underflow / total;
445 print.cdf += print.pdf;
446 }
447 print(stream);
448 }
449
450 if (!compat) {
451 for (int i = 0; i < size; ++i) {
451 for (off_type i = 0; i < size; ++i) {
452 stringstream namestr;
453 namestr << name;
454
455 Counter low = i * bucket_size + min;
456 Counter high = ::min(low + bucket_size, max);
457 namestr << low;
458 if (low < high)
459 namestr << "-" << high;
460
461 print.name = namestr.str();
462 print.value = vec[i];
463 if (total) {
464 print.pdf = vec[i] / total;
465 print.cdf += print.pdf;
466 }
467 print(stream);
468 }
469 } else {
470 Counter _min;
471 Result _pdf;
472 Result _cdf = 0.0;
473
474 print.flags = flags | __substat;
475
452 stringstream namestr;
453 namestr << name;
454
455 Counter low = i * bucket_size + min;
456 Counter high = ::min(low + bucket_size, max);
457 namestr << low;
458 if (low < high)
459 namestr << "-" << high;
460
461 print.name = namestr.str();
462 print.value = vec[i];
463 if (total) {
464 print.pdf = vec[i] / total;
465 print.cdf += print.pdf;
466 }
467 print(stream);
468 }
469 } else {
470 Counter _min;
471 Result _pdf;
472 Result _cdf = 0.0;
473
474 print.flags = flags | __substat;
475
476 for (int i = 0; i < size; ++i) {
476 for (off_type i = 0; i < size; ++i) {
477 if ((flags & nozero && vec[i] == 0.0) ||
478 (flags & nonan && isnan(vec[i])))
479 continue;
480
481 _min = i * bucket_size + min;
482 _pdf = vec[i] / total * 100.0;
483 _cdf += _pdf;
484
485
486 print.name = ValueToString(_min, 0, compat);
487 print.value = vec[i];
488 print.pdf = (flags & pdf) ? _pdf : NAN;
489 print.cdf = (flags & cdf) ? _cdf : NAN;
490 print(stream);
491 }
492
493 print.flags = flags;
494 }
495
496 if (!compat || overflow > 0.0) {
497 print.name = base + "overflows";
498 print.value = overflow;
499 if (!compat && total) {
500 print.pdf = overflow / total;
501 print.cdf += print.pdf;
502 } else {
503 print.pdf = NAN;
504 print.cdf = NAN;
505 }
506 print(stream);
507 }
508
509 print.pdf = NAN;
510 print.cdf = NAN;
511
512 if (!compat) {
513 print.name = base + "total";
514 print.value = total;
515 print(stream);
516 }
517
518 print.name = base + "max_value";
519 print.value = max_val;
520 print(stream);
521
522 if (!compat && samples != 0) {
523 print.name = base + "mean";
524 print.value = sum / samples;
525 print(stream);
526
527 print.name = base + "stdev";
528 print.value = sqrt((samples * squares - sum * sum) /
529 (samples * (samples - 1.0)));
530 print(stream);
531 }
532
533 if (compat)
534 ccprintf(stream, "%send_dist\n\n", base);
535}
536
537void
538Text::visit(const ScalarData &data)
539{
540 if (noOutput(data))
541 return;
542
543 ScalarPrint print;
544 print.value = data.result();
545 print.name = data.name;
546 print.desc = data.desc;
547 print.flags = data.flags;
548 print.compat = compat;
549 print.descriptions = descriptions;
550 print.precision = data.precision;
551 print.pdf = NAN;
552 print.cdf = NAN;
553
554 print(*stream);
555}
556
557void
558Text::visit(const VectorData &data)
559{
560 if (noOutput(data))
561 return;
562
477 if ((flags & nozero && vec[i] == 0.0) ||
478 (flags & nonan && isnan(vec[i])))
479 continue;
480
481 _min = i * bucket_size + min;
482 _pdf = vec[i] / total * 100.0;
483 _cdf += _pdf;
484
485
486 print.name = ValueToString(_min, 0, compat);
487 print.value = vec[i];
488 print.pdf = (flags & pdf) ? _pdf : NAN;
489 print.cdf = (flags & cdf) ? _cdf : NAN;
490 print(stream);
491 }
492
493 print.flags = flags;
494 }
495
496 if (!compat || overflow > 0.0) {
497 print.name = base + "overflows";
498 print.value = overflow;
499 if (!compat && total) {
500 print.pdf = overflow / total;
501 print.cdf += print.pdf;
502 } else {
503 print.pdf = NAN;
504 print.cdf = NAN;
505 }
506 print(stream);
507 }
508
509 print.pdf = NAN;
510 print.cdf = NAN;
511
512 if (!compat) {
513 print.name = base + "total";
514 print.value = total;
515 print(stream);
516 }
517
518 print.name = base + "max_value";
519 print.value = max_val;
520 print(stream);
521
522 if (!compat && samples != 0) {
523 print.name = base + "mean";
524 print.value = sum / samples;
525 print(stream);
526
527 print.name = base + "stdev";
528 print.value = sqrt((samples * squares - sum * sum) /
529 (samples * (samples - 1.0)));
530 print(stream);
531 }
532
533 if (compat)
534 ccprintf(stream, "%send_dist\n\n", base);
535}
536
537void
538Text::visit(const ScalarData &data)
539{
540 if (noOutput(data))
541 return;
542
543 ScalarPrint print;
544 print.value = data.result();
545 print.name = data.name;
546 print.desc = data.desc;
547 print.flags = data.flags;
548 print.compat = compat;
549 print.descriptions = descriptions;
550 print.precision = data.precision;
551 print.pdf = NAN;
552 print.cdf = NAN;
553
554 print(*stream);
555}
556
557void
558Text::visit(const VectorData &data)
559{
560 if (noOutput(data))
561 return;
562
563 int size = data.size();
563 size_type size = data.size();
564 VectorPrint print;
565
566 print.name = data.name;
567 print.desc = data.desc;
568 print.flags = data.flags;
569 print.compat = compat;
570 print.descriptions = descriptions;
571 print.precision = data.precision;
572 print.vec = data.result();
573 print.total = data.total();
574
575 if (!data.subnames.empty()) {
564 VectorPrint print;
565
566 print.name = data.name;
567 print.desc = data.desc;
568 print.flags = data.flags;
569 print.compat = compat;
570 print.descriptions = descriptions;
571 print.precision = data.precision;
572 print.vec = data.result();
573 print.total = data.total();
574
575 if (!data.subnames.empty()) {
576 for (int i = 0; i < size; ++i) {
576 for (off_type i = 0; i < size; ++i) {
577 if (!data.subnames[i].empty()) {
578 print.subnames = data.subnames;
579 print.subnames.resize(size);
577 if (!data.subnames[i].empty()) {
578 print.subnames = data.subnames;
579 print.subnames.resize(size);
580 for (int i = 0; i < size; ++i) {
580 for (off_type i = 0; i < size; ++i) {
581 if (!data.subnames[i].empty() &&
582 !data.subdescs[i].empty()) {
583 print.subdescs = data.subdescs;
584 print.subdescs.resize(size);
585 break;
586 }
587 }
588 break;
589 }
590 }
591 }
592
593 print(*stream);
594}
595
596void
597Text::visit(const Vector2dData &data)
598{
599 if (noOutput(data))
600 return;
601
602 bool havesub = false;
603 VectorPrint print;
604
605 print.subnames = data.y_subnames;
606 print.flags = data.flags;
607 print.compat = compat;
608 print.descriptions = descriptions;
609 print.precision = data.precision;
610
611 if (!data.subnames.empty()) {
581 if (!data.subnames[i].empty() &&
582 !data.subdescs[i].empty()) {
583 print.subdescs = data.subdescs;
584 print.subdescs.resize(size);
585 break;
586 }
587 }
588 break;
589 }
590 }
591 }
592
593 print(*stream);
594}
595
596void
597Text::visit(const Vector2dData &data)
598{
599 if (noOutput(data))
600 return;
601
602 bool havesub = false;
603 VectorPrint print;
604
605 print.subnames = data.y_subnames;
606 print.flags = data.flags;
607 print.compat = compat;
608 print.descriptions = descriptions;
609 print.precision = data.precision;
610
611 if (!data.subnames.empty()) {
612 for (int i = 0; i < data.x; ++i)
612 for (off_type i = 0; i < data.x; ++i)
613 if (!data.subnames[i].empty())
614 havesub = true;
615 }
616
617 VResult tot_vec(data.y);
618 Result super_total = 0.0;
613 if (!data.subnames[i].empty())
614 havesub = true;
615 }
616
617 VResult tot_vec(data.y);
618 Result super_total = 0.0;
619 for (int i = 0; i < data.x; ++i) {
619 for (off_type i = 0; i < data.x; ++i) {
620 if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
621 continue;
622
620 if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
621 continue;
622
623 int iy = i * data.y;
623 off_type iy = i * data.y;
624 VResult yvec(data.y);
625
626 Result total = 0.0;
624 VResult yvec(data.y);
625
626 Result total = 0.0;
627 for (int j = 0; j < data.y; ++j) {
627 for (off_type j = 0; j < data.y; ++j) {
628 yvec[j] = data.cvec[iy + j];
629 tot_vec[j] += yvec[j];
630 total += yvec[j];
631 super_total += yvec[j];
632 }
633
634 print.name = data.name + "_" +
635 (havesub ? data.subnames[i] : to_string(i));
636 print.desc = data.desc;
637 print.vec = yvec;
638 print.total = total;
639 print(*stream);
640 }
641
642 if ((data.flags & ::Stats::total) && (data.x > 1)) {
643 print.name = data.name;
644 print.desc = data.desc;
645 print.vec = tot_vec;
646 print.total = super_total;
647 print(*stream);
648 }
649}
650
651void
652Text::visit(const DistData &data)
653{
654 if (noOutput(data))
655 return;
656
657 DistPrint print;
658
659 print.name = data.name;
660 print.desc = data.desc;
661 print.flags = data.flags;
662 print.compat = compat;
663 print.descriptions = descriptions;
664 print.precision = data.precision;
665
666 print.min_val = data.data.min_val;
667 print.max_val = data.data.max_val;
668 print.underflow = data.data.underflow;
669 print.overflow = data.data.overflow;
670 print.vec.resize(data.data.cvec.size());
628 yvec[j] = data.cvec[iy + j];
629 tot_vec[j] += yvec[j];
630 total += yvec[j];
631 super_total += yvec[j];
632 }
633
634 print.name = data.name + "_" +
635 (havesub ? data.subnames[i] : to_string(i));
636 print.desc = data.desc;
637 print.vec = yvec;
638 print.total = total;
639 print(*stream);
640 }
641
642 if ((data.flags & ::Stats::total) && (data.x > 1)) {
643 print.name = data.name;
644 print.desc = data.desc;
645 print.vec = tot_vec;
646 print.total = super_total;
647 print(*stream);
648 }
649}
650
651void
652Text::visit(const DistData &data)
653{
654 if (noOutput(data))
655 return;
656
657 DistPrint print;
658
659 print.name = data.name;
660 print.desc = data.desc;
661 print.flags = data.flags;
662 print.compat = compat;
663 print.descriptions = descriptions;
664 print.precision = data.precision;
665
666 print.min_val = data.data.min_val;
667 print.max_val = data.data.max_val;
668 print.underflow = data.data.underflow;
669 print.overflow = data.data.overflow;
670 print.vec.resize(data.data.cvec.size());
671 for (int i = 0; i < print.vec.size(); ++i)
671 for (off_type i = 0; i < print.vec.size(); ++i)
672 print.vec[i] = (Result)data.data.cvec[i];
673 print.sum = data.data.sum;
674 print.squares = data.data.squares;
675 print.samples = data.data.samples;
676
677 print.min = data.data.min;
678 print.max = data.data.max;
679 print.bucket_size = data.data.bucket_size;
680 print.size = data.data.size;
681 print.fancy = data.data.fancy;
682
683 print(*stream);
684}
685
686void
687Text::visit(const VectorDistData &data)
688{
689 if (noOutput(data))
690 return;
691
672 print.vec[i] = (Result)data.data.cvec[i];
673 print.sum = data.data.sum;
674 print.squares = data.data.squares;
675 print.samples = data.data.samples;
676
677 print.min = data.data.min;
678 print.max = data.data.max;
679 print.bucket_size = data.data.bucket_size;
680 print.size = data.data.size;
681 print.fancy = data.data.fancy;
682
683 print(*stream);
684}
685
686void
687Text::visit(const VectorDistData &data)
688{
689 if (noOutput(data))
690 return;
691
692 for (int i = 0; i < data.size(); ++i) {
692 for (off_type i = 0; i < data.size(); ++i) {
693 DistPrint print;
694
695 print.name = data.name + "_" +
696 (data.subnames[i].empty() ? (to_string(i)) : data.subnames[i]);
697 print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
698 print.flags = data.flags;
699 print.compat = compat;
700 print.descriptions = descriptions;
701 print.precision = data.precision;
702
703 print.min_val = data.data[i].min_val;
704 print.max_val = data.data[i].max_val;
705 print.underflow = data.data[i].underflow;
706 print.overflow = data.data[i].overflow;
707 print.vec.resize(data.data[i].cvec.size());
693 DistPrint print;
694
695 print.name = data.name + "_" +
696 (data.subnames[i].empty() ? (to_string(i)) : data.subnames[i]);
697 print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
698 print.flags = data.flags;
699 print.compat = compat;
700 print.descriptions = descriptions;
701 print.precision = data.precision;
702
703 print.min_val = data.data[i].min_val;
704 print.max_val = data.data[i].max_val;
705 print.underflow = data.data[i].underflow;
706 print.overflow = data.data[i].overflow;
707 print.vec.resize(data.data[i].cvec.size());
708 for (int j = 0; j < print.vec.size(); ++j)
708 for (off_type j = 0; j < print.vec.size(); ++j)
709 print.vec[j] = (Result)data.data[i].cvec[j];
710 print.sum = data.data[i].sum;
711 print.squares = data.data[i].squares;
712 print.samples = data.data[i].samples;
713
714 print.min = data.data[i].min;
715 print.max = data.data[i].max;
716 print.bucket_size = data.data[i].bucket_size;
717 print.size = data.data[i].size;
718 print.fancy = data.data[i].fancy;
719
720 print(*stream);
721 }
722}
723
724void
725Text::visit(const FormulaData &data)
726{
727 visit((const VectorData &)data);
728}
729
730bool
731initText(const string &filename, bool desc, bool compat)
732{
733 static Text text;
734 static bool connected = false;
735
736 if (connected)
737 return false;
738
739 extern list<Output *> OutputList;
740
741 text.open(*simout.find(filename));
742 text.descriptions = desc;
743 text.compat = compat;
744 OutputList.push_back(&text);
745 connected = true;
746
747 return true;
748}
749
750/* namespace Stats */ }
709 print.vec[j] = (Result)data.data[i].cvec[j];
710 print.sum = data.data[i].sum;
711 print.squares = data.data[i].squares;
712 print.samples = data.data[i].samples;
713
714 print.min = data.data[i].min;
715 print.max = data.data[i].max;
716 print.bucket_size = data.data[i].bucket_size;
717 print.size = data.data[i].size;
718 print.fancy = data.data[i].fancy;
719
720 print(*stream);
721 }
722}
723
724void
725Text::visit(const FormulaData &data)
726{
727 visit((const VectorData &)data);
728}
729
730bool
731initText(const string &filename, bool desc, bool compat)
732{
733 static Text text;
734 static bool connected = false;
735
736 if (connected)
737 return false;
738
739 extern list<Output *> OutputList;
740
741 text.open(*simout.find(filename));
742 text.descriptions = desc;
743 text.compat = compat;
744 OutputList.push_back(&text);
745 connected = true;
746
747 return true;
748}
749
750/* namespace Stats */ }