Chebyshev
Unit testing for scientific software
output.h
Go to the documentation of this file.
1 
5 
6 #ifndef CHEBYSHEV_OUTPUT_H
7 #define CHEBYSHEV_OUTPUT_H
8 
9 #include <vector>
10 #include <string>
11 #include <map>
12 #include <sstream>
13 #include <iomanip>
14 
15 #include "../prec/prec_structures.h"
16 #include "../benchmark/benchmark_structures.h"
17 #include "../err/err_structures.h"
18 
19 
20 namespace chebyshev {
21 
23  namespace output {
24 
27  struct field_options {
28 
29  using FieldInterpreter = std::function<std::string(const std::string&)>;
30 
33 
36  FieldInterpreter fieldInterpreter = [](const std::string& s) { return s; };
37 
39  std::map<std::string, long double> additionalFields {};
40 
41  // Default constructor
42  field_options() {}
43 
44  // Construct field options from the custom column width.
45  field_options(unsigned int columnWidth) : columnWidth(columnWidth) {}
46  };
47 
48 
51  struct output_settings {
52 
53  using OutputFormat_t = std::function<
55  const std::vector<std::vector<std::string>>&,
56  const std::vector<std::string>&,
57  const output_settings&)>;
58 
61  std::map<std::string, std::string> fieldNames {};
62 
64  std::map<std::string, field_options> fieldOptions {};
65 
67  std::vector<std::string> outputFiles {};
68 
70  std::map<std::string, std::ofstream> openFiles {};
71 
74 
76  unsigned int outputPrecision = 1;
77 
79  OutputFormat_t outputFormat {};
80 
83  OutputFormat_t defaultFileOutputFormat {};
84 
86  std::map<std::string, OutputFormat_t> fileOutputFormat {};
87 
89  bool quiet = false;
90 
92  bool wasSetup = false;
93 
94  } settings;
95 
96 
100  using OutputFormat = output_settings::OutputFormat_t;
101 
102 
115  namespace format {
116 
117 
121 
122  return [](
123  const std::vector<std::vector<std::string>>& table,
124  const std::vector<std::string>& fields,
125  const output_settings& settings) -> std::string {
126 
127  if(!table.size())
128  return "";
129 
130  std::stringstream result;
131 
132  for (size_t i = 0; i < table.size(); ++i) {
133 
134  if(table[i].size() != fields.size()) {
135  std::runtime_error(
136  "Number of columns and fields argument must have "
137  "the same size in output::format::barebone");
138  }
139 
140  for (size_t j = 0; j < table[i].size(); ++j) {
141 
142  auto it = settings.fieldOptions.find(fields[j]);
143 
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];
150  else
151  result << std::setw(settings.defaultColumnWidth)
152  << std::left << table[i][j];
153  }
154 
155  result << "\n";
156  }
157 
158  return result.str();
159  };
160  }
161 
162 
168  inline OutputFormat simple() {
169 
170  return [](
171  const std::vector<std::vector<std::string>>& table,
172  const std::vector<std::string>& fields,
173  const output_settings& settings) -> std::string {
174 
175  if(!table.size())
176  return "";
177 
178  std::stringstream result;
179  std::stringstream header_str;
180 
181  header_str << " | ";
182 
183  for (size_t i = 0; i < table[0].size(); ++i) {
184 
185  auto it = settings.fieldOptions.find(fields[i]);
186 
187  if(it != settings.fieldOptions.end())
188  header_str << std::setw(it->second.columnWidth) << table[0][i] << " | ";
189  else
190  header_str << std::setw(settings.defaultColumnWidth) << table[0][i] << " | ";
191  }
192 
193  std::string header = header_str.str();
194  std::string decoration = " +";
195  for (size_t i = 4; i < header.size(); ++i)
196  decoration += "-";
197  decoration += "+ \n";
198 
199  for (size_t i = 1; i < table.size(); ++i) {
200 
201  if(table[i].size() != fields.size()) {
202  std::runtime_error(
203  "Number of columns and <fields> argument must have "
204  "the same size in output::format::simple");
205  }
206 
207  result << " | ";
208 
209  for (size_t j = 0; j < table[i].size(); ++j) {
210 
211  auto it = settings.fieldOptions.find(fields[j]);
212 
213  if(it != settings.fieldOptions.end())
214  result << std::setw(it->second.columnWidth)
215  << it->second.fieldInterpreter(table[i][j]) << " | ";
216  else
217  result << std::setw(settings.defaultColumnWidth)
218  << table[i][j] << " | ";
219  }
220 
221  result << "\n";
222  }
223 
224  return decoration
225  + header + "\n"
226  + decoration
227  + result.str()
228  + decoration;
229  };
230  }
231 
232 
236  inline OutputFormat fancy(bool adaptiveWidth = true) {
237 
238  return [adaptiveWidth](
239  const std::vector<std::vector<std::string>>& table,
240  const std::vector<std::string>& fields,
241  const output_settings& settings) -> std::string {
242 
243  if(!table.size())
244  return "";
245 
246  // Effective length of the string
247  // (needed because Unicode is used)
248  size_t eff_length = 0;
249  std::stringstream header_str;
250 
251  header_str << " │ ";
252  eff_length += 3;
253 
254  // Processed table
255  auto proc_table = table;
256 
257  // Field value interpretation step
258  for (size_t i = 0; i < proc_table[0].size(); ++i) {
259 
260  auto it = settings.fieldOptions.find(fields[i]);
261 
262  if (it == settings.fieldOptions.end())
263  continue;
264 
265  for (size_t j = 1; j < proc_table.size(); ++j)
266  proc_table[j][i] = it->second.fieldInterpreter(table[j][i]);
267  }
268 
269  std::vector<size_t> computedWidth;
270 
271  // Compute the ideal column width
272  if (adaptiveWidth) {
273 
274  computedWidth.resize(proc_table[0].size());
275 
276  for (size_t i = 0; i < proc_table[0].size(); ++i) {
277 
278  computedWidth[i] = settings.defaultColumnWidth;
279 
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();
283  }
284  }
285 
286  // Print table header
287  for (size_t i = 0; i < table[0].size(); ++i) {
288 
289  auto it = settings.fieldOptions.find(fields[i]);
290 
291  unsigned int width = 0;
292 
293  if(it != settings.fieldOptions.end() && !adaptiveWidth)
294  width = it->second.columnWidth;
295  else if (adaptiveWidth)
296  width = computedWidth[i];
297  else
298  width = settings.defaultColumnWidth;
299 
300  header_str << std::setw(width) << table[0][i] << " │ ";
301  eff_length += width + 3;
302  }
303 
304  std::string header = " ┌";
305 
306  // Upper outline
307  for (size_t i = 4; i < eff_length; ++i)
308  header += "─";
309  header += "┐ \n";
310 
311  header += header_str.str() + "\n";
312 
313  // Lower outline
314  header += " ├";
315  for (size_t i = 4; i < eff_length; ++i)
316  header += "─";
317  header += "┤ \n";
318 
319  std::stringstream result;
320 
321  for (size_t i = 1; i < proc_table.size(); ++i) {
322 
323  if(proc_table[i].size() != fields.size()) {
324  std::runtime_error(
325  "Number of columns and <fields> argument must have "
326  "the same size in output::format::fancy");
327  }
328 
329  result << " │ ";
330 
331  for (size_t j = 0; j < proc_table[i].size(); ++j) {
332 
333  auto it = settings.fieldOptions.find(fields[j]);
334 
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] << " │ ";
341  } else
342  result << std::setw(settings.defaultColumnWidth)
343  << proc_table[i][j] << " │ ";
344  }
345 
346  result << "\n";
347  }
348 
349  std::string underline = " └";
350  for (size_t i = 4; i < eff_length; ++i) {
351  underline += "─";
352  }
353  underline += "┘ \n";
354 
355  return header + result.str() + underline;
356  };
357  }
358 
359 
365  inline OutputFormat csv(const std::string& separator = ",") {
366 
367  return [separator](
368  const std::vector<std::vector<std::string>>& table,
369  const std::vector<std::string>& fields,
370  const output_settings& settings) -> std::string {
371 
372  std::stringstream s;
373 
374  for (size_t i = 0; i < table.size(); ++i) {
375 
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");
380  }
381 
382 
383  for (size_t j = 0; j < table[i].size(); ++j) {
384 
385  auto it = settings.fieldOptions.find(fields[j]);
386 
387  if(it != settings.fieldOptions.end() && i)
388  s << "\"" << it->second.fieldInterpreter(table[i][j]) << "\"";
389  else
390  s << "\"" << table[i][j] << "\"";
391 
392  if(j != table[i].size() - 1)
393  s << separator;
394  }
395 
396  s << "\n";
397  }
398 
399  return s.str();
400  };
401  }
402 
403 
407 
408  return [](
409  const std::vector<std::vector<std::string>>& table,
410  const std::vector<std::string>& fields,
411  const output_settings& settings) -> std::string {
412 
413  if(!table.size())
414  return "";
415 
416  std::stringstream result;
417  std::stringstream header_str;
418 
419  header_str << "|";
420 
421  for (size_t i = 0; i < table[0].size(); ++i) {
422 
423  auto it = settings.fieldOptions.find(fields[i]);
424 
425  if(it != settings.fieldOptions.end())
426  header_str << std::setw(it->second.columnWidth)
427  << std::left << table[0][i];
428  else
429  header_str << std::setw(settings.defaultColumnWidth)
430  << std::left << table[0][i];
431 
432  header_str << "|";
433  }
434 
435  std::string header = header_str.str();
436  std::string decoration = "|";
437  for (size_t i = 1; i < header.size() - 1; ++i)
438  decoration += (header[i] == '|') ? "|" : "-";
439  decoration += "|\n";
440 
441  for (size_t i = 1; i < table.size(); ++i) {
442 
443  if(table[i].size() != fields.size()) {
444  std::runtime_error(
445  "Number of columns and <fields> argument must have "
446  "the same size in output::format::markdown");
447  }
448 
449  result << "|";
450 
451  for (size_t j = 0; j < table[i].size(); ++j) {
452 
453  auto it = settings.fieldOptions.find(fields[j]);
454 
455  if(it != settings.fieldOptions.end())
456  result << std::setw(it->second.columnWidth)
457  << std::left << it->second.fieldInterpreter(table[i][j]);
458  else
459  result << std::setw(settings.defaultColumnWidth)
460  << std::left << table[i][j];
461 
462  result << "|";
463  }
464 
465  result << "\n";
466  }
467 
468  return header + "\n" + decoration + result.str();
469  };
470  }
471 
472 
475  inline OutputFormat latex() {
476 
477  return [=](
478  const std::vector<std::vector<std::string>>& table,
479  const std::vector<std::string>& fields,
480  const output_settings& settings) -> std::string {
481 
482  if(!table.size())
483  return "";
484 
485  std::stringstream result;
486  result << "\\begin{tabular}{";
487 
488  if(fields.size())
489  result << "|";
490 
491  for (unsigned int i = 0; i < fields.size(); ++i)
492  result << "c|";
493 
494  result << "}\n\\hline\n";
495 
496  for (size_t i = 0; i < table[0].size(); ++i) {
497 
498  result << table[0][i];
499 
500  if(i != table[0].size() - 1)
501  result << " & ";
502  }
503  result << " \\\\\n\\hline\n";
504 
505  for (size_t i = 1; i < table.size(); ++i) {
506 
507  if(table[i].size() != fields.size()) {
508  std::runtime_error(
509  "Number of columns and <fields> argument must have "
510  "the same size in output::format::latex");
511  }
512 
513  for (size_t j = 0; j < table[i].size(); ++j) {
514 
515  auto it = settings.fieldOptions.find(fields[j]);
516 
517  if(it != settings.fieldOptions.end())
518  result << it->second.fieldInterpreter(table[i][j]);
519  else
520  result << table[i][j];
521 
522  if(j != table[i].size() - 1)
523  result << " & ";
524  }
525 
526  result << " \\\\\n";
527  }
528 
529  result << "\\hline\n\\end{tabular}\n";
530 
531  return result.str();
532  };
533  }
534 
535  }
536 
537 
539  inline void setup() {
540 
541  // Skip subsequent setup calls
542  if (settings.wasSetup)
543  return;
544 
545  // Estimate fields
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";
555 
556  // Equation fields
557  settings.fieldNames["difference"] = "Difference";
558  settings.fieldNames["evaluated"] = "Evaluated";
559  settings.fieldNames["expected"] = "Expected";
560 
561  // Benchmark fields
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";
567 
568  // Error checking
569  settings.fieldNames["correctType"] = "Correct Type";
570  settings.fieldNames["description"] = "Description";
571  settings.fieldNames["expectedFlags"] = "Exp. Flags";
572  settings.fieldNames["thrown"] = "Has Thrown";
573 
574  // Set wider column width for some fields
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;
580 
581  // Set a special field interpreter for the "failed" field
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";
586  };
587 
588  // Set the default output formats
589  settings.outputFormat = format::fancy();
590  settings.defaultFileOutputFormat = format::csv();
591 
592  settings.wasSetup = true;
593  }
594 
595 
598  inline void terminate() {
599 
600  // Close all open files
601  for (auto& file_pair : settings.openFiles)
602  if(file_pair.second.is_open())
603  file_pair.second.close();
604  }
605 
606 
613  const std::string& fieldName, prec::estimate_result r) {
614 
615  std::stringstream value;
616 
617  if(fieldName == "name") {
618  value << r.name;
619  } else if(fieldName == "maxErr") {
620  value << std::scientific
621  << std::setprecision(settings.outputPrecision)
622  << r.maxErr;
623  } else if(fieldName == "meanErr") {
624  value << std::scientific
625  << std::setprecision(settings.outputPrecision)
626  << r.meanErr;
627  } else if(fieldName == "rmsErr") {
628  value << std::scientific
629  << std::setprecision(settings.outputPrecision)
630  << r.rmsErr;
631  } else if(fieldName == "relErr") {
632  value << std::scientific
633  << std::setprecision(settings.outputPrecision)
634  << r.relErr;
635  } else if(fieldName == "absErr") {
636  value << std::scientific
637  << std::setprecision(settings.outputPrecision)
638  << r.absErr;
639  } else if(fieldName == "tolerance") {
640  value << std::scientific
641  << std::setprecision(settings.outputPrecision)
642  << r.tolerance;
643  } else if(fieldName == "failed") {
644  value << r.failed;
645  } else {
646 
647  if(r.additionalFields.find(fieldName) == r.additionalFields.end())
648  return "";
649 
650  value << r.additionalFields[fieldName];
651  }
652 
653  return value.str();
654  }
655 
656 
663  const std::string& fieldName, prec::equation_result r) {
664 
665  std::stringstream value;
666 
667  if(fieldName == "name") {
668  value << r.name;
669  } else if(fieldName == "evaluated") {
670  value << r.evaluated;
671  } else if(fieldName == "expected") {
672  value << r.expected;
673  } else if(fieldName == "difference") {
674  value << std::scientific
675  << std::setprecision(settings.outputPrecision)
676  << r.difference;
677  } else if(fieldName == "tolerance") {
678  value << std::scientific
679  << std::setprecision(settings.outputPrecision)
680  << r.tolerance;
681  } else if(fieldName == "failed") {
682  value << r.failed;
683  } else {
684 
685  if(r.additionalFields.find(fieldName) == r.additionalFields.end())
686  return "";
687 
688  value << r.additionalFields[fieldName];
689  }
690 
691  return value.str();
692  }
693 
694 
698  const std::string& fieldName, benchmark::benchmark_result r) {
699 
700  std::stringstream value;
701 
702  if(fieldName == "name") {
703  value << r.name;
704  } else if(fieldName == "runs") {
705  value << r.runs;
706  } else if(fieldName == "iterations") {
707  value << r.iterations;
708  } else if(fieldName == "totalRuntime") {
709  value << std::scientific
710  << std::setprecision(settings.outputPrecision)
711  << r.totalRuntime;
712  } else if(fieldName == "averageRuntime") {
713  value << std::scientific
714  << std::setprecision(settings.outputPrecision)
715  << r.averageRuntime;
716  } else if(fieldName == "stdevRuntime") {
717  value << std::scientific
718  << std::setprecision(settings.outputPrecision)
719  << r.stdevRuntime;
720  } else if(fieldName == "runsPerSecond") {
721  if(r.runsPerSecond > 1000)
722  value << uint64_t(r.runsPerSecond);
723  else
724  value << r.runsPerSecond;
725  } else if(fieldName == "failed") {
726  value << r.failed;
727  } else {
728 
729  if(r.additionalFields.find(fieldName) == r.additionalFields.end())
730  return "";
731 
732  value << r.additionalFields[fieldName];
733  }
734 
735  return value.str();
736  }
737 
738 
745  const std::string& fieldName, err::assert_result r) {
746 
747  std::stringstream value;
748 
749  if(fieldName == "name") {
750  value << r.name;
751  } else if(fieldName == "evaluated") {
752  value << r.evaluated;
753  } else if(fieldName == "description") {
754  value << r.description;
755  } else if(fieldName == "failed") {
756  value << r.failed;
757  } else {
758  return "";
759  }
760 
761  return value.str();
762  }
763 
764 
771  const std::string& fieldName, err::errno_result r) {
772 
773  std::stringstream value;
774 
775  if(fieldName == "name") {
776  value << r.name;
777  } else if(fieldName == "evaluated") {
778  value << r.evaluated;
779  } else if(fieldName == "expectedFlags") {
780 
781  int res_flag = 0xFFFFFFFF;
782  for (int flag : r.expectedFlags)
783  res_flag &= flag;
784 
785  value << res_flag;
786 
787  } else if(fieldName == "failed") {
788  value << r.failed;
789  } else {
790  return "";
791  }
792 
793  return value.str();
794  }
795 
796 
803  const std::string& fieldName, err::exception_result r) {
804 
805  std::stringstream value;
806 
807  if(fieldName == "name") {
808  value << r.name;
809  } else if(fieldName == "thrown") {
810  value << r.thrown;
811  } else if(fieldName == "correctType") {
812  value << r.correctType;
813  } else if(fieldName == "failed") {
814  value << r.failed;
815  } else {
816  return "";
817  }
818 
819  return value.str();
820  }
821 
822 
832  template<typename ResultType>
833  inline auto generate_table(
834  const std::map<std::string, std::vector<ResultType>>& results,
835  const std::vector<std::string>& fields) {
836 
837  std::vector<std::vector<std::string>> table;
838 
839  // Construct header
840  std::vector<std::string> header (fields.size());
841  for (size_t i = 0; i < fields.size(); ++i) {
842 
843  const auto it = settings.fieldNames.find(fields[i]);
844 
845  // Associate string to field name
846  if(it != settings.fieldNames.end())
847  header[i] = it->second;
848  else
849  header[i] = fields[i];
850  }
851  table.emplace_back(header);
852 
853  // Construct rows
854  for (const auto& p : results) {
855  for (const auto& result : p.second) {
856 
857  // Skip results marked as quiet
858  if (result.quiet)
859  continue;
860 
861  std::vector<std::string> row (fields.size());
862 
863  for (size_t i = 0; i < fields.size(); ++i)
864  row[i] = resolve_field(fields[i], result);
865 
866  table.emplace_back(row);
867  }
868  }
869 
870  return table;
871  }
872 
873 
880  inline bool open_file(std::string filename) {
881 
882  const auto file_pair = settings.openFiles.find(filename);
883 
884  // If the file is not already open, try to open it and write to it
885  if (file_pair == settings.openFiles.end() || !file_pair->second.is_open()) {
886 
887  settings.openFiles[filename].open(filename);
888 
889  if (!settings.openFiles[filename].is_open()) {
890  settings.openFiles.erase(filename);
891  return false;
892  }
893  }
894 
895  return true;
896  }
897 
898 
906  template<typename ResultType>
907  inline void print_results(
908  const std::map<std::string, std::vector<ResultType>>& results,
909  const std::vector<std::string>& fields,
910  const std::vector<std::string>& filenames) {
911 
912  // Skip output on no test case results
913  if(results.empty())
914  return;
915 
916  // Table data as a string matrix
917  std::vector<std::vector<std::string>> table = generate_table(results, fields);
918 
919  // Write to standard output
920  if(!settings.quiet)
921  std::cout << "\n" << settings.outputFormat(table, fields, settings) << "\n";
922 
923  // Write to the module specific output files
924  for (const auto& filename : filenames) {
925 
926  if (!open_file(filename)) {
927  std::cout << "Unable to write to output file: " << filename << std::endl;
928  continue;
929  }
930 
931  auto& file = settings.openFiles[filename];
932 
933  // Apply formatting according to set options
934  const auto it = settings.fileOutputFormat.find(filename);
935 
936  if(it != settings.fileOutputFormat.end())
937  file << it->second(table, fields, settings);
938  else
939  file << settings.defaultFileOutputFormat(table, fields, settings);
940 
941  std::cout << "Results have been saved in: " << filename << std::endl;
942  }
943 
944  // Write to the generic output files
945  for (const auto& filename : settings.outputFiles) {
946 
947  if (!open_file(filename)) {
948  std::cout << "Unable to write to output file: " << filename << std::endl;
949  continue;
950  }
951 
952  auto& file = settings.openFiles[filename];
953 
954  // Apply formatting according to set options
955  const auto it = settings.fileOutputFormat.find(filename);
956 
957  if(it != settings.fileOutputFormat.end())
958  file << it->second(table, fields, settings);
959  else
960  file << settings.defaultFileOutputFormat(table, fields, settings);
961 
962  std::cout << "Results have been saved in: " << filename << std::endl;
963  }
964  }
965  }
966 }
967 
968 #endif
#define CHEBYSHEV_OUTPUT_WIDTH
Default width of output columns.
Definition: common.h:32
OutputFormat markdown()
Format the table as Markdown.
Definition: output.h:406
OutputFormat barebone()
Bare bone output format which just prints the result table as is, without any formatting beyond adjus...
Definition: output.h:120
OutputFormat fancy(bool adaptiveWidth=true)
Fancy output format which uses Unicode characters to print a continuous outline around the table.
Definition: output.h:236
OutputFormat latex()
Format the table as a LaTeX table in the tabular environment.
Definition: output.h:475
OutputFormat simple()
Simple output format which prints the fields separated by the separator string and padding,...
Definition: output.h:168
OutputFormat csv(const std::string &separator=",")
Format function for CSV format files.
Definition: output.h:365
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