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] <<
" | ";
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;
254 for (
size_t i = 0; i < table[0].size(); ++i) {
256 auto it = settings.fieldOptions.find(fields[i]);
258 if(it != settings.fieldOptions.end()) {
259 header_str << std::setw(it->second.columnWidth)
260 << table[0][i] <<
" │ ";
261 eff_length += it->second.columnWidth;
263 header_str << std::setw(settings.defaultColumnWidth)
264 << table[0][i] <<
" │ ";
265 eff_length += settings.defaultColumnWidth;
274 for (
size_t i = 4; i < eff_length; ++i)
278 header += header_str.str() +
"\n";
282 for (
size_t i = 4; i < eff_length; ++i)
286 std::stringstream result;
288 for (
size_t i = 1; i < table.size(); ++i) {
290 if(table[i].size() != fields.size()) {
292 "Number of columns and <fields> argument must have "
293 "the same size in output::format::fancy");
298 for (
size_t j = 0; j < table[i].size(); ++j) {
300 auto it = settings.fieldOptions.find(fields[j]);
302 if(it != settings.fieldOptions.end())
303 result << std::setw(it->second.columnWidth)
304 << it->second.fieldInterpreter(table[i][j]) <<
" │ ";
306 result << std::setw(settings.defaultColumnWidth)
307 << table[i][j] <<
" │ ";
314 for (
size_t i = 4; i < eff_length; ++i) {
319 return header + result.str() + underline;
332 const std::vector<std::vector<std::string>>& table,
333 const std::vector<std::string>& fields,
338 for (
size_t i = 0; i < table.size(); ++i) {
340 if(table[i].size() != fields.size()) {
341 throw std::runtime_error(
342 "Number of columns and <fields> argument must have "
343 "the same size in output::format::csv");
347 for (
size_t j = 0; j < table[i].size(); ++j) {
349 auto it = settings.fieldOptions.find(fields[j]);
351 if(it != settings.fieldOptions.end() && i)
352 s <<
"\"" << it->second.fieldInterpreter(table[i][j]) <<
"\"";
354 s <<
"\"" << table[i][j] <<
"\"";
356 if(j != table[i].size() - 1)
373 const std::vector<std::vector<std::string>>& table,
374 const std::vector<std::string>& fields,
380 std::stringstream result;
381 std::stringstream header_str;
385 for (
size_t i = 0; i < table[0].size(); ++i) {
387 auto it = settings.fieldOptions.find(fields[i]);
389 if(it != settings.fieldOptions.end())
390 header_str << std::setw(it->second.columnWidth)
391 << std::left << table[0][i];
393 header_str << std::setw(settings.defaultColumnWidth)
394 << std::left << table[0][i];
401 for (
size_t i = 1; i < header.size() - 1; ++i)
402 decoration += (header[i] ==
'|') ?
"|" :
"-";
405 for (
size_t i = 1; i < table.size(); ++i) {
407 if(table[i].size() != fields.size()) {
409 "Number of columns and <fields> argument must have "
410 "the same size in output::format::markdown");
415 for (
size_t j = 0; j < table[i].size(); ++j) {
417 auto it = settings.fieldOptions.find(fields[j]);
419 if(it != settings.fieldOptions.end())
420 result << std::setw(it->second.columnWidth)
421 << std::left << it->second.fieldInterpreter(table[i][j]);
423 result << std::setw(settings.defaultColumnWidth)
424 << std::left << table[i][j];
432 return header +
"\n" + decoration + result.str();
442 const std::vector<std::vector<std::string>>& table,
443 const std::vector<std::string>& fields,
449 std::stringstream result;
450 result <<
"\\begin{tabular}{";
455 for (
unsigned int i = 0; i < fields.size(); ++i)
458 result <<
"}\n\\hline\n";
460 for (
size_t i = 0; i < table[0].size(); ++i) {
462 result << table[0][i];
464 if(i != table[0].size() - 1)
467 result <<
" \\\\\n\\hline\n";
469 for (
size_t i = 1; i < table.size(); ++i) {
471 if(table[i].size() != fields.size()) {
473 "Number of columns and <fields> argument must have "
474 "the same size in output::format::latex");
477 for (
size_t j = 0; j < table[i].size(); ++j) {
479 auto it = settings.fieldOptions.find(fields[j]);
481 if(it != settings.fieldOptions.end())
482 result << it->second.fieldInterpreter(table[i][j]);
484 result << table[i][j];
486 if(j != table[i].size() - 1)
493 result <<
"\\hline\n\\end{tabular}\n";
506 if (settings.wasSetup)
510 settings.fieldNames[
"name"] =
"Function";
511 settings.fieldNames[
"maxErr"] =
"Max Err.";
512 settings.fieldNames[
"meanErr"] =
"Mean Err.";
513 settings.fieldNames[
"rmsErr"] =
"RMS Err.";
514 settings.fieldNames[
"relErr"] =
"Rel. Err.";
515 settings.fieldNames[
"absErr"] =
"Abs. Err.";
516 settings.fieldNames[
"tolerance"] =
"Tolerance";
517 settings.fieldNames[
"failed"] =
"Result";
518 settings.fieldNames[
"iterations"] =
"Iterations";
521 settings.fieldNames[
"difference"] =
"Difference";
522 settings.fieldNames[
"evaluated"] =
"Evaluated";
523 settings.fieldNames[
"expected"] =
"Expected";
526 settings.fieldNames[
"totalRuntime"] =
"Tot. Time (ms)";
527 settings.fieldNames[
"averageRuntime"] =
"Avg. Time (ms)";
528 settings.fieldNames[
"stdevRuntime"] =
"Stdev. Time (ms)";
529 settings.fieldNames[
"runsPerSecond"] =
"Runs per Sec.";
530 settings.fieldNames[
"runs"] =
"Runs";
533 settings.fieldNames[
"correctType"] =
"Correct Type";
534 settings.fieldNames[
"description"] =
"Description";
535 settings.fieldNames[
"expectedFlags"] =
"Exp. Flags";
536 settings.fieldNames[
"thrown"] =
"Has Thrown";
539 settings.fieldOptions[
"name"].columnWidth = 20;
540 settings.fieldOptions[
"averageRuntime"].columnWidth = 14;
541 settings.fieldOptions[
"stdevRuntime"].columnWidth = 16;
542 settings.fieldOptions[
"runsPerSecond"].columnWidth = 14;
543 settings.fieldOptions[
"description"].columnWidth = 20;
546 settings.fieldOptions[
"failed"].fieldInterpreter = [](
const std::string& s) {
547 if(s ==
"0")
return "PASS";
548 else if(s ==
"1")
return "FAIL";
549 else return "UNKNOWN";
556 settings.wasSetup =
true;
565 for (
auto& file_pair : settings.openFiles)
566 if(file_pair.second.is_open())
567 file_pair.second.close();
579 std::stringstream value;
581 if(fieldName ==
"name") {
583 }
else if(fieldName ==
"maxErr") {
584 value << std::scientific
585 << std::setprecision(settings.outputPrecision)
587 }
else if(fieldName ==
"meanErr") {
588 value << std::scientific
589 << std::setprecision(settings.outputPrecision)
591 }
else if(fieldName ==
"rmsErr") {
592 value << std::scientific
593 << std::setprecision(settings.outputPrecision)
595 }
else if(fieldName ==
"relErr") {
596 value << std::scientific
597 << std::setprecision(settings.outputPrecision)
599 }
else if(fieldName ==
"absErr") {
600 value << std::scientific
601 << std::setprecision(settings.outputPrecision)
603 }
else if(fieldName ==
"tolerance") {
604 value << std::scientific
605 << std::setprecision(settings.outputPrecision)
607 }
else if(fieldName ==
"failed") {
629 std::stringstream value;
631 if(fieldName ==
"name") {
633 }
else if(fieldName ==
"evaluated") {
635 }
else if(fieldName ==
"expected") {
637 }
else if(fieldName ==
"difference") {
638 value << std::scientific
639 << std::setprecision(settings.outputPrecision)
641 }
else if(fieldName ==
"tolerance") {
642 value << std::scientific
643 << std::setprecision(settings.outputPrecision)
645 }
else if(fieldName ==
"failed") {
664 std::stringstream value;
666 if(fieldName ==
"name") {
668 }
else if(fieldName ==
"runs") {
670 }
else if(fieldName ==
"iterations") {
672 }
else if(fieldName ==
"totalRuntime") {
673 value << std::scientific
674 << std::setprecision(settings.outputPrecision)
676 }
else if(fieldName ==
"averageRuntime") {
677 value << std::scientific
678 << std::setprecision(settings.outputPrecision)
680 }
else if(fieldName ==
"stdevRuntime") {
681 value << std::scientific
682 << std::setprecision(settings.outputPrecision)
684 }
else if(fieldName ==
"runsPerSecond") {
689 }
else if(fieldName ==
"failed") {
711 std::stringstream value;
713 if(fieldName ==
"name") {
715 }
else if(fieldName ==
"evaluated") {
717 }
else if(fieldName ==
"description") {
719 }
else if(fieldName ==
"failed") {
737 std::stringstream value;
739 if(fieldName ==
"name") {
741 }
else if(fieldName ==
"evaluated") {
743 }
else if(fieldName ==
"expectedFlags") {
745 int res_flag = 0xFFFFFFFF;
751 }
else if(fieldName ==
"failed") {
769 std::stringstream value;
771 if(fieldName ==
"name") {
773 }
else if(fieldName ==
"thrown") {
775 }
else if(fieldName ==
"correctType") {
777 }
else if(fieldName ==
"failed") {
796 template<
typename ResultType>
798 const std::map<
std::string, std::vector<ResultType>>& results,
799 const std::vector<std::string>& fields) {
801 std::vector<std::vector<std::string>> table;
804 std::vector<std::string> header (fields.size());
805 for (
size_t i = 0; i < fields.size(); ++i) {
807 const auto it = settings.fieldNames.find(fields[i]);
810 if(it != settings.fieldNames.end())
811 header[i] = it->second;
813 header[i] = fields[i];
815 table.emplace_back(header);
818 for (
const auto& p : results) {
819 for (
const auto& result : p.second) {
825 std::vector<std::string> row (fields.size());
827 for (
size_t i = 0; i < fields.size(); ++i)
830 table.emplace_back(row);
846 const auto file_pair = settings.openFiles.find(filename);
849 if (file_pair == settings.openFiles.end() || !file_pair->second.is_open()) {
851 settings.openFiles[filename].open(filename);
853 if (!settings.openFiles[filename].is_open()) {
854 settings.openFiles.erase(filename);
870 template<
typename ResultType>
872 const std::map<
std::string, std::vector<ResultType>>& results,
873 const std::vector<std::string>& fields,
874 const std::vector<std::string>& filenames) {
881 std::vector<std::vector<std::string>> table =
generate_table(results, fields);
885 std::cout <<
"\n" << settings.outputFormat(table, fields, settings) <<
"\n";
888 for (
const auto& filename : filenames) {
891 std::cout <<
"Unable to write to output file: " << filename << std::endl;
895 auto& file = settings.openFiles[filename];
898 const auto it = settings.fileOutputFormat.find(filename);
900 if(it != settings.fileOutputFormat.end())
901 file << it->second(table, fields, settings);
903 file << settings.defaultFileOutputFormat(table, fields, settings);
905 std::cout <<
"Results have been saved in: " << filename << std::endl;
909 for (
const auto& filename : settings.
outputFiles) {
912 std::cout <<
"Unable to write to output file: " << filename << std::endl;
916 auto& file = settings.openFiles[filename];
919 const auto it = settings.fileOutputFormat.find(filename);
921 if(it != settings.fileOutputFormat.end())
922 file << it->second(table, fields, settings);
924 file << settings.defaultFileOutputFormat(table, fields, settings);
926 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:871
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:576
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:503
void terminate()
Terminate the output module by closing all output files and resetting its settings.
Definition: output.h:562
bool open_file(std::string filename)
Try to open a new output file, returning whether it was correctly opened.
Definition: output.h:844
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:797
std::string string(size_t length)
Generate a random string made of human-readable ASCII characters.
Definition: random.h:84
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