6 #ifndef CHEBYSHEV_OUTPUT_H
7 #define CHEBYSHEV_OUTPUT_H
15 #include "../prec/prec_structures.h"
16 #include "../benchmark/benchmark_structures.h"
17 #include "../err/err_structures.h"
53 using OutputFormat_t = std::function<
55 const std::vector<std::vector<std::string>>&,
56 const std::vector<std::string>&,
123 const std::vector<std::vector<std::string>>& table,
124 const std::vector<std::string>& fields,
130 std::stringstream result;
132 for (
size_t i = 0; i < table.size(); ++i) {
134 if(table[i].size() != fields.size()) {
136 "Number of columns and fields argument must have "
137 "the same size in output::format::barebone");
140 for (
size_t j = 0; j < table[i].size(); ++j) {
142 auto it = settings.fieldOptions.find(fields[j]);
144 if(it != settings.fieldOptions.end() && i)
145 result << std::setw(it->second.columnWidth)
146 << std::left << it->second.fieldInterpreter(table[i][j]);
147 else if(it != settings.fieldOptions.end())
148 result << std::setw(it->second.columnWidth)
149 << std::left << table[i][j];
151 result << std::setw(settings.defaultColumnWidth)
152 << std::left << table[i][j];
171 const std::vector<std::vector<std::string>>& table,
172 const std::vector<std::string>& fields,
178 std::stringstream result;
179 std::stringstream header_str;
183 for (
size_t i = 0; i < table[0].size(); ++i) {
185 auto it = settings.fieldOptions.find(fields[i]);
187 if(it != settings.fieldOptions.end())
188 header_str << std::setw(it->second.columnWidth) << table[0][i] <<
" | ";
190 header_str << std::setw(settings.defaultColumnWidth) << table[0][i] <<
" | ";
195 for (
size_t i = 4; i < header.size(); ++i)
197 decoration +=
"+ \n";
199 for (
size_t i = 1; i < table.size(); ++i) {
201 if(table[i].size() != fields.size()) {
203 "Number of columns and <fields> argument must have "
204 "the same size in output::format::simple");
209 for (
size_t j = 0; j < table[i].size(); ++j) {
211 auto it = settings.fieldOptions.find(fields[j]);
213 if(it != settings.fieldOptions.end())
214 result << std::setw(it->second.columnWidth)
215 << it->second.fieldInterpreter(table[i][j]) <<
" | ";
217 result << std::setw(settings.defaultColumnWidth)
218 << table[i][j] <<
" | ";
238 return [adaptiveWidth](
239 const std::vector<std::vector<std::string>>& table,
240 const std::vector<std::string>& fields,
248 size_t eff_length = 0;
249 std::stringstream header_str;
255 auto proc_table = table;
258 for (
size_t i = 0; i < proc_table[0].size(); ++i) {
260 auto it = settings.fieldOptions.find(fields[i]);
262 if (it == settings.fieldOptions.end())
265 for (
size_t j = 1; j < proc_table.size(); ++j)
266 proc_table[j][i] = it->second.fieldInterpreter(table[j][i]);
269 std::vector<size_t> computedWidth;
274 computedWidth.resize(proc_table[0].size());
276 for (
size_t i = 0; i < proc_table[0].size(); ++i) {
278 computedWidth[i] = settings.defaultColumnWidth;
280 for (
size_t j = 0; j < proc_table.size(); ++j)
281 if (proc_table[j][i].size() > computedWidth[i])
282 computedWidth[i] = proc_table[j][i].size();
287 for (
size_t i = 0; i < table[0].size(); ++i) {
289 auto it = settings.fieldOptions.find(fields[i]);
291 unsigned int width = 0;
293 if(it != settings.fieldOptions.end() && !adaptiveWidth)
294 width = it->second.columnWidth;
295 else if (adaptiveWidth)
296 width = computedWidth[i];
298 width = settings.defaultColumnWidth;
300 header_str << std::setw(width) << table[0][i] <<
" │ ";
301 eff_length += width + 3;
307 for (
size_t i = 4; i < eff_length; ++i)
311 header += header_str.str() +
"\n";
315 for (
size_t i = 4; i < eff_length; ++i)
319 std::stringstream result;
321 for (
size_t i = 1; i < proc_table.size(); ++i) {
323 if(proc_table[i].size() != fields.size()) {
325 "Number of columns and <fields> argument must have "
326 "the same size in output::format::fancy");
331 for (
size_t j = 0; j < proc_table[i].size(); ++j) {
333 auto it = settings.fieldOptions.find(fields[j]);
335 if(it != settings.fieldOptions.end() && !adaptiveWidth)
336 result << std::setw(it->second.columnWidth)
337 << proc_table[i][j] <<
" │ ";
338 else if (adaptiveWidth) {
339 result << std::setw(computedWidth[j])
340 << proc_table[i][j] <<
" │ ";
342 result << std::setw(settings.defaultColumnWidth)
343 << proc_table[i][j] <<
" │ ";
350 for (
size_t i = 4; i < eff_length; ++i) {
355 return header + result.str() + underline;
368 const std::vector<std::vector<std::string>>& table,
369 const std::vector<std::string>& fields,
374 for (
size_t i = 0; i < table.size(); ++i) {
376 if(table[i].size() != fields.size()) {
377 throw std::runtime_error(
378 "Number of columns and <fields> argument must have "
379 "the same size in output::format::csv");
383 for (
size_t j = 0; j < table[i].size(); ++j) {
385 auto it = settings.fieldOptions.find(fields[j]);
387 if(it != settings.fieldOptions.end() && i)
388 s <<
"\"" << it->second.fieldInterpreter(table[i][j]) <<
"\"";
390 s <<
"\"" << table[i][j] <<
"\"";
392 if(j != table[i].size() - 1)
409 const std::vector<std::vector<std::string>>& table,
410 const std::vector<std::string>& fields,
416 std::stringstream result;
417 std::stringstream header_str;
421 for (
size_t i = 0; i < table[0].size(); ++i) {
423 auto it = settings.fieldOptions.find(fields[i]);
425 if(it != settings.fieldOptions.end())
426 header_str << std::setw(it->second.columnWidth)
427 << std::left << table[0][i];
429 header_str << std::setw(settings.defaultColumnWidth)
430 << std::left << table[0][i];
437 for (
size_t i = 1; i < header.size() - 1; ++i)
438 decoration += (header[i] ==
'|') ?
"|" :
"-";
441 for (
size_t i = 1; i < table.size(); ++i) {
443 if(table[i].size() != fields.size()) {
445 "Number of columns and <fields> argument must have "
446 "the same size in output::format::markdown");
451 for (
size_t j = 0; j < table[i].size(); ++j) {
453 auto it = settings.fieldOptions.find(fields[j]);
455 if(it != settings.fieldOptions.end())
456 result << std::setw(it->second.columnWidth)
457 << std::left << it->second.fieldInterpreter(table[i][j]);
459 result << std::setw(settings.defaultColumnWidth)
460 << std::left << table[i][j];
468 return header +
"\n" + decoration + result.str();
478 const std::vector<std::vector<std::string>>& table,
479 const std::vector<std::string>& fields,
485 std::stringstream result;
486 result <<
"\\begin{tabular}{";
491 for (
unsigned int i = 0; i < fields.size(); ++i)
494 result <<
"}\n\\hline\n";
496 for (
size_t i = 0; i < table[0].size(); ++i) {
498 result << table[0][i];
500 if(i != table[0].size() - 1)
503 result <<
" \\\\\n\\hline\n";
505 for (
size_t i = 1; i < table.size(); ++i) {
507 if(table[i].size() != fields.size()) {
509 "Number of columns and <fields> argument must have "
510 "the same size in output::format::latex");
513 for (
size_t j = 0; j < table[i].size(); ++j) {
515 auto it = settings.fieldOptions.find(fields[j]);
517 if(it != settings.fieldOptions.end())
518 result << it->second.fieldInterpreter(table[i][j]);
520 result << table[i][j];
522 if(j != table[i].size() - 1)
529 result <<
"\\hline\n\\end{tabular}\n";
542 if (settings.wasSetup)
546 settings.fieldNames[
"name"] =
"Function";
547 settings.fieldNames[
"maxErr"] =
"Max Err.";
548 settings.fieldNames[
"meanErr"] =
"Mean Err.";
549 settings.fieldNames[
"rmsErr"] =
"RMS Err.";
550 settings.fieldNames[
"relErr"] =
"Rel. Err.";
551 settings.fieldNames[
"absErr"] =
"Abs. Err.";
552 settings.fieldNames[
"tolerance"] =
"Tolerance";
553 settings.fieldNames[
"failed"] =
"Result";
554 settings.fieldNames[
"iterations"] =
"Iterations";
557 settings.fieldNames[
"difference"] =
"Difference";
558 settings.fieldNames[
"evaluated"] =
"Evaluated";
559 settings.fieldNames[
"expected"] =
"Expected";
562 settings.fieldNames[
"totalRuntime"] =
"Tot. Time (ms)";
563 settings.fieldNames[
"averageRuntime"] =
"Avg. Time (ms)";
564 settings.fieldNames[
"stdevRuntime"] =
"Stdev. Time (ms)";
565 settings.fieldNames[
"runsPerSecond"] =
"Runs per Sec.";
566 settings.fieldNames[
"runs"] =
"Runs";
569 settings.fieldNames[
"correctType"] =
"Correct Type";
570 settings.fieldNames[
"description"] =
"Description";
571 settings.fieldNames[
"expectedFlags"] =
"Exp. Flags";
572 settings.fieldNames[
"thrown"] =
"Has Thrown";
575 settings.fieldOptions[
"name"].columnWidth = 20;
576 settings.fieldOptions[
"averageRuntime"].columnWidth = 14;
577 settings.fieldOptions[
"stdevRuntime"].columnWidth = 16;
578 settings.fieldOptions[
"runsPerSecond"].columnWidth = 14;
579 settings.fieldOptions[
"description"].columnWidth = 20;
582 settings.fieldOptions[
"failed"].fieldInterpreter = [](
const std::string& s) {
583 if(s ==
"0")
return "PASS";
584 else if(s ==
"1")
return "FAIL";
585 else return "UNKNOWN";
592 settings.wasSetup =
true;
601 for (
auto& file_pair : settings.openFiles)
602 if(file_pair.second.is_open())
603 file_pair.second.close();
615 std::stringstream value;
617 if(fieldName ==
"name") {
619 }
else if(fieldName ==
"maxErr") {
620 value << std::scientific
621 << std::setprecision(settings.outputPrecision)
623 }
else if(fieldName ==
"meanErr") {
624 value << std::scientific
625 << std::setprecision(settings.outputPrecision)
627 }
else if(fieldName ==
"rmsErr") {
628 value << std::scientific
629 << std::setprecision(settings.outputPrecision)
631 }
else if(fieldName ==
"relErr") {
632 value << std::scientific
633 << std::setprecision(settings.outputPrecision)
635 }
else if(fieldName ==
"absErr") {
636 value << std::scientific
637 << std::setprecision(settings.outputPrecision)
639 }
else if(fieldName ==
"tolerance") {
640 value << std::scientific
641 << std::setprecision(settings.outputPrecision)
643 }
else if(fieldName ==
"failed") {
665 std::stringstream value;
667 if(fieldName ==
"name") {
669 }
else if(fieldName ==
"evaluated") {
671 }
else if(fieldName ==
"expected") {
673 }
else if(fieldName ==
"difference") {
674 value << std::scientific
675 << std::setprecision(settings.outputPrecision)
677 }
else if(fieldName ==
"tolerance") {
678 value << std::scientific
679 << std::setprecision(settings.outputPrecision)
681 }
else if(fieldName ==
"failed") {
700 std::stringstream value;
702 if(fieldName ==
"name") {
704 }
else if(fieldName ==
"runs") {
706 }
else if(fieldName ==
"iterations") {
708 }
else if(fieldName ==
"totalRuntime") {
709 value << std::scientific
710 << std::setprecision(settings.outputPrecision)
712 }
else if(fieldName ==
"averageRuntime") {
713 value << std::scientific
714 << std::setprecision(settings.outputPrecision)
716 }
else if(fieldName ==
"stdevRuntime") {
717 value << std::scientific
718 << std::setprecision(settings.outputPrecision)
720 }
else if(fieldName ==
"runsPerSecond") {
725 }
else if(fieldName ==
"failed") {
747 std::stringstream value;
749 if(fieldName ==
"name") {
751 }
else if(fieldName ==
"evaluated") {
753 }
else if(fieldName ==
"description") {
755 }
else if(fieldName ==
"failed") {
773 std::stringstream value;
775 if(fieldName ==
"name") {
777 }
else if(fieldName ==
"evaluated") {
779 }
else if(fieldName ==
"expectedFlags") {
781 int res_flag = 0xFFFFFFFF;
787 }
else if(fieldName ==
"failed") {
805 std::stringstream value;
807 if(fieldName ==
"name") {
809 }
else if(fieldName ==
"thrown") {
811 }
else if(fieldName ==
"correctType") {
813 }
else if(fieldName ==
"failed") {
832 template<
typename ResultType>
834 const std::map<
std::string, std::vector<ResultType>>& results,
835 const std::vector<std::string>& fields) {
837 std::vector<std::vector<std::string>> table;
840 std::vector<std::string> header (fields.size());
841 for (
size_t i = 0; i < fields.size(); ++i) {
843 const auto it = settings.fieldNames.find(fields[i]);
846 if(it != settings.fieldNames.end())
847 header[i] = it->second;
849 header[i] = fields[i];
851 table.emplace_back(header);
854 for (
const auto& p : results) {
855 for (
const auto& result : p.second) {
861 std::vector<std::string> row (fields.size());
863 for (
size_t i = 0; i < fields.size(); ++i)
866 table.emplace_back(row);
882 const auto file_pair = settings.openFiles.find(filename);
885 if (file_pair == settings.openFiles.end() || !file_pair->second.is_open()) {
887 settings.openFiles[filename].open(filename);
889 if (!settings.openFiles[filename].is_open()) {
890 settings.openFiles.erase(filename);
906 template<
typename ResultType>
908 const std::map<
std::string, std::vector<ResultType>>& results,
909 const std::vector<std::string>& fields,
910 const std::vector<std::string>& filenames) {
917 std::vector<std::vector<std::string>> table =
generate_table(results, fields);
921 std::cout <<
"\n" << settings.outputFormat(table, fields, settings) <<
"\n";
924 for (
const auto& filename : filenames) {
927 std::cout <<
"Unable to write to output file: " << filename << std::endl;
931 auto& file = settings.openFiles[filename];
934 const auto it = settings.fileOutputFormat.find(filename);
936 if(it != settings.fileOutputFormat.end())
937 file << it->second(table, fields, settings);
939 file << settings.defaultFileOutputFormat(table, fields, settings);
941 std::cout <<
"Results have been saved in: " << filename << std::endl;
945 for (
const auto& filename : settings.
outputFiles) {
948 std::cout <<
"Unable to write to output file: " << filename << std::endl;
952 auto& file = settings.openFiles[filename];
955 const auto it = settings.fileOutputFormat.find(filename);
957 if(it != settings.fileOutputFormat.end())
958 file << it->second(table, fields, settings);
960 file << settings.defaultFileOutputFormat(table, fields, settings);
962 std::cout <<
"Results have been saved in: " << filename << std::endl;
#define CHEBYSHEV_OUTPUT_WIDTH
Default width of output columns.
Definition: common.h:32
void print_results(const std::map< std::string, std::vector< ResultType >> &results, const std::vector< std::string > &fields, const std::vector< std::string > &filenames)
Print the test results to standard output and output files with their given formats,...
Definition: output.h:907
std::string resolve_field(const std::string &fieldName, prec::estimate_result r)
Resolve the field of an estimate result by name, returning the value as a string.
Definition: output.h:612
output_settings::OutputFormat_t OutputFormat
A function which converts the table entries of a row to a string to print (e.g.
Definition: output.h:100
void setup()
Setup printing to the output stream with default options.
Definition: output.h:539
void terminate()
Terminate the output module by closing all output files and resetting its settings.
Definition: output.h:598
bool open_file(std::string filename)
Try to open a new output file, returning whether it was correctly opened.
Definition: output.h:880
auto generate_table(const std::map< std::string, std::vector< ResultType >> &results, const std::vector< std::string > &fields)
Generate a table of results as a string matrix to pass to a specific formatter of OutputFormat type.
Definition: output.h:833
std::string string(size_t length)
Generate a random string made of human-readable ASCII characters.
Definition: random.h:102
General namespace of the framework.
Definition: benchmark_structures.h:16
Structure holding the results of a benchmark.
Definition: benchmark_structures.h:23
long double averageRuntime
Estimated average runtime.
Definition: benchmark_structures.h:38
bool failed
Whether the benchmark failed because an exception was thrown.
Definition: benchmark_structures.h:48
unsigned int runs
Number of runs.
Definition: benchmark_structures.h:29
unsigned int iterations
Number of iterations.
Definition: benchmark_structures.h:32
long double runsPerSecond
Number of runs per second.
Definition: benchmark_structures.h:44
long double totalRuntime
Total runtime over all runs and iterations.
Definition: benchmark_structures.h:35
std::string name
Identifying name of the function or test case.
Definition: benchmark_structures.h:26
std::map< std::string, long double > additionalFields
Additional fields in floating point representation.
Definition: benchmark_structures.h:54
long double stdevRuntime
Sample standard deviation of the runtime.
Definition: benchmark_structures.h:41
std::vector< std::string > outputFiles
The files to write all benchmark results to.
Definition: benchmark.h:50
bool quiet
Whether to print benchmark results to standard output.
Definition: benchmark.h:35
Result of assertion checking of a function.
Definition: err_structures.h:21
std::string name
Identifying name of the function or test case.
Definition: err_structures.h:24
bool evaluated
Evaluated boolean value.
Definition: err_structures.h:27
bool failed
Whether the test failed.
Definition: err_structures.h:33
std::string description
Description of the assertion.
Definition: err_structures.h:30
Result of errno checking of a function.
Definition: err_structures.h:42
int evaluated
Evaluated errno value.
Definition: err_structures.h:48
std::string name
Identifying name of the function or test case.
Definition: err_structures.h:45
std::vector< int > expectedFlags
Expected errno flags.
Definition: err_structures.h:51
bool failed
Whether the test failed.
Definition: err_structures.h:54
Result of exception checking of a function.
Definition: err_structures.h:63
bool thrown
Whether the function has thrown.
Definition: err_structures.h:69
std::string name
Identifying name of the function or test case.
Definition: err_structures.h:66
bool correctType
Whether the type of the thrown exception was correct.
Definition: err_structures.h:73
bool failed
Whether the test failed.
Definition: err_structures.h:76
Custom options for printing a certain field.
Definition: output.h:27
unsigned int columnWidth
Width for the column associated with the field.
Definition: output.h:32
FieldInterpreter fieldInterpreter
A function which gets as input the value of a field as a string and returns a new string (e....
Definition: output.h:36
std::map< std::string, long double > additionalFields
Additional custom options.
Definition: output.h:39
Global settings of printing results to standard output.
Definition: output.h:51
bool quiet
Whether to output to standard output.
Definition: output.h:89
std::map< std::string, OutputFormat_t > fileOutputFormat
The output format to use for a specific file, by filename.
Definition: output.h:86
std::vector< std::string > outputFiles
A list of output files.
Definition: output.h:67
OutputFormat_t defaultFileOutputFormat
The default output format to use for files, when no format has been set for a file.
Definition: output.h:83
std::map< std::string, field_options > fieldOptions
Options for the different fields.
Definition: output.h:64
OutputFormat_t outputFormat
The output format to use to print to standard output.
Definition: output.h:79
unsigned int defaultColumnWidth
Default width for a field.
Definition: output.h:73
std::map< std::string, std::string > fieldNames
Map of field name to output string (e.g.
Definition: output.h:61
std::map< std::string, std::ofstream > openFiles
A map of open output files, by filename.
Definition: output.h:70
unsigned int outputPrecision
The number of digits to show in scientific notation.
Definition: output.h:76
bool wasSetup
Whether the output module was setup.
Definition: output.h:92
A structure holding the result of an evaluation.
Definition: prec_structures.h:163
long double tolerance
Tolerance on the absolute difference.
Definition: prec_structures.h:182
bool failed
Whether the test failed.
Definition: prec_structures.h:185
std::string name
Identifying name of the function or test case.
Definition: prec_structures.h:166
long double difference
Evaluated difference between expected and evaluated values.
Definition: prec_structures.h:175
std::map< std::string, long double > additionalFields
Additional fields by name, as a floating point value.
Definition: prec_structures.h:179
long double evaluated
Evaluated value.
Definition: prec_structures.h:169
long double expected
Expected value.
Definition: prec_structures.h:172
A structure holding the result of precision estimation.
Definition: prec_structures.h:25
std::string name
Identifying name of the function or test case.
Definition: prec_structures.h:28
std::map< std::string, long double > additionalFields
Additional fields by name, as a floating point value.
Definition: prec_structures.h:52
long double meanErr
Estimated mean error on interval.
Definition: prec_structures.h:40
long double relErr
Estimated relative error on interval.
Definition: prec_structures.h:46
long double maxErr
Estimated maximum absolute error on interval.
Definition: prec_structures.h:37
bool failed
Whether the test failed.
Definition: prec_structures.h:55
long double rmsErr
Estimated RMS error on interval.
Definition: prec_structures.h:43
long double absErr
Estimated absolute error on interval.
Definition: prec_structures.h:49
long double tolerance
Tolerance on the max absolute error.
Definition: prec_structures.h:34