Reference documentation for deal.II version GIT 2c37b3e359 2022-05-26 00:10:02+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
table_handler.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2022 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
17 
18 #include <boost/io/ios_state.hpp>
19 
20 #include <algorithm>
21 #include <iomanip>
22 #include <iostream>
23 #include <sstream>
24 
25 
27 
28 
29 /*---------------------------------------------------------------------*/
30 
31 // inline and template functions
32 namespace internal
33 {
34  double
36  {
37  // we don't quite know the data type in 'value', but
38  // it must be one of the ones in the type list of the
39  // std_cxx17::variant. Go through this list and return
40  // the value if this happens to be a number
41  //
42  // first try with int
43  try
44  {
45  return std_cxx17::get<int>(value);
46  }
47  catch (...)
48  {}
49 
50 
51  // ... then with unsigned int...
52  try
53  {
54  return std_cxx17::get<unsigned int>(value);
55  }
56  catch (...)
57  {}
58 
59  // ... then with std::uint64_t...
60  try
61  {
62  return std_cxx17::get<std::uint64_t>(value);
63  }
64  catch (...)
65  {}
66 
67  // ...and finally with double precision:
68  try
69  {
70  return std_cxx17::get<double>(value);
71  }
72  catch (...)
73  {
74  Assert(false,
75  ExcMessage("The number stored by this element of the "
76  "table is not a number."))
77  }
78 
79  return 0;
80  }
81 
82  void
83  TableEntry::cache_string(bool scientific, unsigned int precision) const
84  {
85  std::ostringstream ss;
86 
87  ss << std::setprecision(precision);
88 
89  if (scientific)
90  ss.setf(std::ios::scientific, std::ios::floatfield);
91  else
92  ss.setf(std::ios::fixed, std::ios::floatfield);
93 
94 #ifdef DEAL_II_HAVE_CXX17
95  std::visit([&ss](auto &v) { ss << v; }, value);
96 #else
97  ss << value;
98 #endif
99 
100  cached_value = ss.str();
101  if (cached_value.size() == 0)
102  cached_value = "\"\"";
103  }
104 
105  const std::string &
107  {
108  return cached_value;
109  }
110 
111 
112 #ifndef DEAL_II_HAVE_CXX17
113  namespace Local
114  {
115  // see which type we can cast to, then use this type to create
116  // a default constructed object
117  struct SetValueToDefault : public boost::static_visitor<>
118  {
119  template <typename T>
120  void
121  operator()(T &operand) const
122  {
123  operand = T();
124  }
125  };
126  } // namespace Local
127 #endif
128 
129  TableEntry
131  {
132  TableEntry new_entry = *this;
133 #ifndef DEAL_II_HAVE_CXX17
134  boost::apply_visitor(Local::SetValueToDefault(), new_entry.value);
135 #else
136  // Let std::visit figure out which data type is actually stored,
137  // and then set the object so stored to a default-constructed
138  // one.
139  std::visit([](
140  auto &arg) { arg = std::remove_reference_t<decltype(arg)>(); },
141  new_entry.value);
142 #endif
143 
144  return new_entry;
145  }
146 
147 
148 } // namespace internal
149 
150 /* ------------------------------------------------ */
151 
152 TableHandler::Column::Column(const std::string &tex_caption)
153  : tex_caption(tex_caption)
154  , tex_format("c")
155  , precision(4)
156  , scientific(false)
157  , flag(0)
158  , max_length(0)
159 {}
160 
161 
162 
164  : tex_caption()
165  , tex_format("c")
166  , precision(4)
167  , scientific(false)
168  , flag(0)
169  , max_length(0)
170 {}
171 
172 
173 
174 void
176 {
177  // we should never have a column that is completely
178  // empty and that needs to be padded
179  Assert(entries.size() > 0, ExcInternalError());
180 
181  // add as many elements as necessary
182  while (entries.size() < size)
183  {
184  entries.push_back(entries.back().get_default_constructed_copy());
185  internal::TableEntry &entry = entries.back();
186  entry.cache_string(scientific, precision);
187  max_length =
188  std::max(max_length,
189  static_cast<unsigned int>(entry.get_cached_string().size()));
190  }
191 }
192 
193 
194 void
196 {
197  max_length = 0;
198 
199  for (const auto &entry : entries)
200  {
201  entry.cache_string(this->scientific, this->precision);
202  max_length =
203  std::max(max_length,
204  static_cast<unsigned int>(entry.get_cached_string().size()));
205  }
206 }
207 
208 
209 /*---------------------------------------------------------------------*/
210 
211 
213  : auto_fill_mode(false)
214 {}
215 
216 
217 
218 void
219 TableHandler::declare_column(const std::string &key)
220 {
221  // see if the column already exists; insert it if not
222  Assert(columns.find(key) == columns.end(),
223  ExcMessage("You are trying to declare a column with key <" + key +
224  "> but such a column already exists."));
225 
226  columns.insert(std::make_pair(key, Column(key)));
227  column_order.push_back(key);
228 }
229 
230 
231 
232 void
234 {
235  // figure out the longest current column
236  unsigned int max_col_length = 0;
237  for (const auto &column : columns)
238  max_col_length =
239  std::max(max_col_length,
240  static_cast<unsigned int>(column.second.entries.size()));
241 
242 
243  // then pad all columns to that length with empty strings
244  for (auto &column : columns)
245  while (column.second.entries.size() < max_col_length)
246  {
247  column.second.entries.emplace_back("");
248  internal::TableEntry &entry = column.second.entries.back();
249  entry.cache_string(column.second.scientific, column.second.precision);
250  column.second.max_length =
251  std::max(column.second.max_length,
252  static_cast<unsigned int>(entry.get_cached_string().size()));
253  }
254 }
255 
256 
257 
258 void
260 {
261  auto_fill_mode = state;
262 }
263 
264 
265 void
267  const std::string &superkey)
268 {
269  Assert(columns.count(key), ExcColumnNotExistent(key));
270 
271  if (supercolumns.count(superkey) == 0u)
272  {
273  std::pair<std::string, std::vector<std::string>> new_column(
274  superkey, std::vector<std::string>());
275  supercolumns.insert(new_column);
276  // replace key in column_order
277  // by superkey
278  for (auto &column : column_order)
279  if (column == key)
280  {
281  column = superkey;
282  break;
283  }
284  }
285  else
286  {
287  // remove key from column_order
288  const auto order_iter =
289  std::find(column_order.begin(), column_order.end(), key);
290  if (order_iter != column_order.end())
291  column_order.erase(order_iter);
292  }
293 
294  if (supercolumns.count(superkey) != 0u)
295  {
296  supercolumns[superkey].push_back(key);
297  // By default set the
298  // tex_supercaption to superkey
299  std::pair<std::string, std::string> new_tex_supercaption(superkey,
300  superkey);
301  tex_supercaptions.insert(new_tex_supercaption);
302  }
303  else
304  Assert(false, ExcInternalError());
305 }
306 
307 
308 
309 void
310 TableHandler::set_column_order(const std::vector<std::string> &new_order)
311 {
312  for (const auto &new_column : new_order)
313  {
314  (void)new_column;
315  Assert(supercolumns.count(new_column) || columns.count(new_column),
317  }
318 
319  column_order = new_order;
320 }
321 
322 
323 void
324 TableHandler::set_tex_caption(const std::string &key,
325  const std::string &tex_caption)
326 {
327  Assert(columns.count(key), ExcColumnNotExistent(key));
328  columns[key].tex_caption = tex_caption;
329 }
330 
331 
332 
333 void
334 TableHandler::set_tex_table_caption(const std::string &table_caption)
335 {
336  tex_table_caption = table_caption;
337 }
338 
339 
340 
341 void
342 TableHandler::set_tex_table_label(const std::string &table_label)
343 {
344  tex_table_label = table_label;
345 }
346 
347 
348 
349 void
350 TableHandler::set_tex_supercaption(const std::string &superkey,
351  const std::string &tex_supercaption)
352 {
353  Assert(supercolumns.count(superkey), ExcSuperColumnNotExistent(superkey));
354  Assert(tex_supercaptions.count(superkey), ExcInternalError());
355  tex_supercaptions[superkey] = tex_supercaption;
356 }
357 
358 
359 
360 void
361 TableHandler::set_tex_format(const std::string &key,
362  const std::string &tex_format)
363 {
364  Assert(columns.count(key), ExcColumnNotExistent(key));
365  Assert(tex_format == "l" || tex_format == "c" || tex_format == "r",
366  ExcUndefinedTexFormat(tex_format));
367  columns[key].tex_format = tex_format;
368 }
369 
370 
371 
372 void
373 TableHandler::set_precision(const std::string &key,
374  const unsigned int precision)
375 {
376  Assert(columns.count(key), ExcColumnNotExistent(key));
377  if (columns[key].precision != precision)
378  {
379  columns[key].precision = precision;
380  columns[key].invalidate_cache();
381  }
382 }
383 
384 
385 void
386 TableHandler::set_scientific(const std::string &key, const bool scientific)
387 {
388  Assert(columns.count(key), ExcColumnNotExistent(key));
389  if (columns[key].scientific != scientific)
390  {
391  columns[key].scientific = scientific;
392  columns[key].invalidate_cache();
393  }
394 }
395 
396 
397 void
398 TableHandler::write_text(std::ostream &out, const TextOutputFormat format) const
399 {
400  AssertThrow(out.fail() == false, ExcIO());
401  boost::io::ios_flags_saver restore_flags(out);
402 
403  // first pad the table from below if necessary
404  if (auto_fill_mode == true)
405  {
406  unsigned int max_rows = 0;
407  for (std::map<std::string, Column>::const_iterator p = columns.begin();
408  p != columns.end();
409  ++p)
410  max_rows = std::max<unsigned int>(max_rows, p->second.entries.size());
411 
412  for (auto &column : columns)
413  column.second.pad_column_below(max_rows);
414  }
415 
416  std::vector<std::string> sel_columns;
417  get_selected_columns(sel_columns);
418 
419  const unsigned int nrows = n_rows();
420  const unsigned int n_cols = sel_columns.size();
421 
422  // cache the columns and compute the widths of each column for alignment
423  std::vector<const Column *> cols;
424  std::vector<unsigned int> column_widths(n_cols, 0);
425  for (unsigned int j = 0; j < n_cols; ++j)
426  {
427  std::string key = sel_columns[j];
428  const std::map<std::string, Column>::const_iterator col_iter =
429  columns.find(key);
430  Assert(col_iter != columns.end(), ExcInternalError());
431  cols.push_back(&(col_iter->second));
432 
433  column_widths[j] = col_iter->second.max_length;
434  }
435 
436  switch (format)
437  {
438  case org_mode_table:
439  {
440  // write the captions
441  out << "| " << std::left;
442  for (unsigned int j = 0; j < n_cols; ++j)
443  {
444  const std::string &key = sel_columns[j];
445  column_widths[j] =
446  std::max(column_widths[j],
447  static_cast<unsigned int>(key.size()));
448  out << std::setw(column_widths[j]);
449  out << key << " | ";
450  }
451  out << '\n';
452 
453  // write the body
454  for (unsigned int i = 0; i < nrows; ++i)
455  {
456  out << "| ";
457  for (unsigned int j = 0; j < n_cols; ++j)
458  {
459  const Column &column = *(cols[j]);
460 
461  out << std::setw(column_widths[j]);
462  out << column.entries[i].get_cached_string();
463  out << " | ";
464  }
465  out << '\n';
466  }
467 
468  out << std::flush;
469  return;
470  }
471 
473  {
474  // write the captions
475  for (unsigned int j = 0; j < n_cols; ++j)
476  {
477  const std::string &key = sel_columns[j];
478  out << "# " << j + 1 << ": " << key << '\n';
479  }
480 
481  // write the body
482  for (unsigned int i = 0; i < nrows; ++i)
483  {
484  for (unsigned int j = 0; j < n_cols; ++j)
485  {
486  const Column &column = *(cols[j]);
487 
488  out << column.entries[i].get_cached_string();
489  out << ' ';
490  }
491  out << '\n';
492  }
493 
494  out << std::flush;
495  return;
496  }
497 
499  {
500  // writing the captions for table_with_separate_column_description
501  // means that we ignore supercolumns and output the column
502  // header for each column. enumerate columns starting with 1
503  for (unsigned int j = 0; j < n_cols; ++j)
504  {
505  std::string key = sel_columns[j];
506  out << "# " << j + 1 << ": " << key << '\n';
507  }
508  break;
509  }
510 
511  case table_with_headers:
512  {
513  // This format output supercolumn headers and aligns them centered
514  // over all the columns that belong to it.
515  for (const auto &key : column_order)
516  {
517  unsigned int width = 0;
518  {
519  // compute the width of this column or supercolumn
520  const std::map<std::string,
521  std::vector<std::string>>::const_iterator
522  super_iter = supercolumns.find(key);
523  if (super_iter != supercolumns.end())
524  {
525  const unsigned int n_subcolumns = super_iter->second.size();
526  for (unsigned int k = 0; k < n_subcolumns; ++k)
527  {
528  const std::map<std::string, Column>::const_iterator
529  col_iter = columns.find(super_iter->second[k]);
530  Assert(col_iter != columns.end(), ExcInternalError());
531 
532  width += col_iter->second.max_length;
533  }
534  width += n_subcolumns - 1; // separators between subcolumns
535  }
536  else
537  {
538  const std::map<std::string, Column>::const_iterator
539  col_iter = columns.find(key);
540 
541  width = col_iter->second.max_length;
542  }
543  }
544 
545  // header is longer than the column(s) under it
546  if (width < key.size())
547  {
548  // make the column or the last column in this
549  // supercolumn wide enough
550  std::string colname;
551 
552  const std::map<std::string,
553  std::vector<std::string>>::const_iterator
554  super_iter = supercolumns.find(key);
555  if (super_iter != supercolumns.end())
556  colname = super_iter->second.back();
557  else
558  colname = key;
559 
560  // find column and change output width
561  for (unsigned int i = 0; i < n_cols; ++i)
562  {
563  if (sel_columns[i] == colname)
564  {
565  column_widths[i] += key.size() - width;
566  break;
567  }
568  }
569 
570  width = key.size();
571  }
572 
573  // now write key. try to center it somehow
574  const unsigned int front_padding = (width - key.size()) / 2,
575  rear_padding =
576  (width - key.size()) - front_padding;
577  for (unsigned int i = 0; i < front_padding; ++i)
578  out << ' ';
579  out << key;
580  for (unsigned int i = 0; i < rear_padding; ++i)
581  out << ' ';
582 
583  out << ' ';
584  }
585  out << '\n';
586  break;
587  }
588 
589  default:
590  Assert(false, ExcInternalError());
591  }
592 
593 
594  // finally output the data itself for
595  // table_with_headers or table_with_separate_column_description:
596  for (unsigned int i = 0; i < nrows; ++i)
597  {
598  for (unsigned int j = 0; j < n_cols; ++j)
599  {
600  const Column &column = *(cols[j]);
601  out << std::setw(column_widths[j]);
602  out << column.entries[i].get_cached_string();
603 
604  // pad after this column
605  out << ' ';
606  }
607  out << '\n';
608  }
609  out << std::flush;
610 }
611 
612 
613 void
614 TableHandler::write_tex(std::ostream &out, const bool with_header) const
615 {
616  // TODO[TH]: update code similar to
617  // write_text() to use the cache
618  AssertThrow(out.fail() == false, ExcIO());
619  if (with_header)
620  out << "\\documentclass[10pt]{report}" << '\n'
621  << "\\usepackage{float}" << '\n'
622  << '\n'
623  << '\n'
624  << "\\begin{document}" << '\n';
625 
626  out << "\\begin{table}[H]" << '\n'
627  << "\\begin{center}" << '\n'
628  << "\\begin{tabular}{|";
629 
630  // first pad the table from below if necessary
631  if (auto_fill_mode == true)
632  {
633  unsigned int max_rows = 0;
634  for (std::map<std::string, Column>::const_iterator p = columns.begin();
635  p != columns.end();
636  ++p)
637  max_rows = std::max<unsigned int>(max_rows, p->second.entries.size());
638 
639  for (auto &column : columns)
640  column.second.pad_column_below(max_rows);
641  }
642 
643  std::vector<std::string> sel_columns;
644  get_selected_columns(sel_columns);
645 
646  // write the column formats
647  for (const auto &key : column_order)
648  {
649  // avoid `supercolumns[key]'
650  const std::map<std::string, std::vector<std::string>>::const_iterator
651  super_iter = supercolumns.find(key);
652 
653  if (super_iter != supercolumns.end())
654  {
655  const unsigned int n_subcolumns = super_iter->second.size();
656  for (unsigned int k = 0; k < n_subcolumns; ++k)
657  {
658  // avoid `columns[supercolumns[key]]'
659  const std::map<std::string, Column>::const_iterator col_iter =
660  columns.find(super_iter->second[k]);
661  Assert(col_iter != columns.end(), ExcInternalError());
662 
663  out << col_iter->second.tex_format << "|";
664  }
665  }
666  else
667  {
668  // avoid `columns[key]';
669  const std::map<std::string, Column>::const_iterator col_iter =
670  columns.find(key);
671  Assert(col_iter != columns.end(), ExcInternalError());
672  out << col_iter->second.tex_format << "|";
673  }
674  }
675  out << "} \\hline" << '\n';
676 
677  // write the caption line of the table
678 
679  for (unsigned int j = 0; j < column_order.size(); ++j)
680  {
681  std::string key = column_order[j];
682  const std::map<std::string, std::vector<std::string>>::const_iterator
683  super_iter = supercolumns.find(key);
684 
685  if (super_iter != supercolumns.end())
686  {
687  const unsigned int n_subcolumns = super_iter->second.size();
688  // avoid use of `tex_supercaptions[key]'
689  std::map<std::string, std::string>::const_iterator
690  tex_super_cap_iter = tex_supercaptions.find(key);
691  out << '\n'
692  << "\\multicolumn{" << n_subcolumns << "}{|c|}{"
693  << tex_super_cap_iter->second << "}";
694  }
695  else
696  {
697  // col_iter->second=columns[col];
698  const std::map<std::string, Column>::const_iterator col_iter =
699  columns.find(key);
700  Assert(col_iter != columns.end(), ExcInternalError());
701  out << col_iter->second.tex_caption;
702  }
703  if (j < column_order.size() - 1)
704  out << " & ";
705  }
706  out << "\\\\ \\hline" << '\n';
707 
708  // write the n rows
709  const unsigned int nrows = n_rows();
710  for (unsigned int i = 0; i < nrows; ++i)
711  {
712  const unsigned int n_cols = sel_columns.size();
713 
714  for (unsigned int j = 0; j < n_cols; ++j)
715  {
716  std::string key = sel_columns[j];
717  // avoid `column[key]'
718  const std::map<std::string, Column>::const_iterator col_iter =
719  columns.find(key);
720  Assert(col_iter != columns.end(), ExcInternalError());
721 
722  const Column &column = col_iter->second;
723 
724  out << std::setprecision(column.precision);
725 
726  if (col_iter->second.scientific)
727  out.setf(std::ios::scientific, std::ios::floatfield);
728  else
729  out.setf(std::ios::fixed, std::ios::floatfield);
730 
731 #ifdef DEAL_II_HAVE_CXX17
732  std::visit([&out](auto &v) { out << v; }, column.entries[i].value);
733 #else
734  out << column.entries[i].value;
735 #endif
736 
737  if (j < n_cols - 1)
738  out << " & ";
739  }
740  out << "\\\\ \\hline" << '\n';
741  }
742 
743  out << "\\end{tabular}" << '\n' << "\\end{center}" << '\n';
744  if (!tex_table_caption.empty())
745  out << "\\caption{" << tex_table_caption << "}" << '\n';
746  if (!tex_table_label.empty())
747  out << "\\label{" << tex_table_label << "}" << '\n';
748  out << "\\end{table}" << '\n';
749  if (with_header)
750  out << "\\end{document}" << '\n';
751 
752  // Now flush all of the data we've put into the stream to make it
753  // sure it really gets written.
754  out << std::flush;
755 }
756 
757 
758 
759 void
761 {
762  columns.clear();
763  supercolumns.clear();
764  column_order.clear();
765  tex_supercaptions.clear();
766 
767  tex_table_label.clear();
768  tex_table_caption.clear();
769 }
770 
771 
772 unsigned int
774 {
775  if (columns.size() == 0)
776  return 0;
777 
778  std::map<std::string, Column>::const_iterator col_iter = columns.begin();
779  unsigned int n = col_iter->second.entries.size();
780 
781 #ifdef DEBUG
782  std::string first_name = col_iter->first;
783  for (++col_iter; col_iter != columns.end(); ++col_iter)
784  Assert(col_iter->second.entries.size() == n,
786  col_iter->first, col_iter->second.entries.size(), first_name, n));
787 #endif
788 
789  return n;
790 }
791 
792 
793 void
794 TableHandler::get_selected_columns(std::vector<std::string> &sel_columns) const
795 {
796  sel_columns.clear();
797 
798  for (const auto &key : column_order)
799  {
800  const std::map<std::string, std::vector<std::string>>::const_iterator
801  super_iter = supercolumns.find(key);
802 
803  if (super_iter != supercolumns.end())
804  {
805  // i.e. key is a supercolumn key
806  const unsigned int n_subcolumns = super_iter->second.size();
807  for (unsigned int k = 0; k < n_subcolumns; ++k)
808  {
809  const std::string subkey = super_iter->second[k];
810  Assert(columns.count(subkey), ExcInternalError());
811  sel_columns.push_back(subkey);
812  }
813  }
814  else
815  {
816  Assert(columns.count(key), ExcInternalError());
817  // i.e. key is a column key
818  sel_columns.push_back(key);
819  }
820  }
821 }
822 
823 
824 void
826 {
827  // Figure out what is the correct (max) length of the columns
828  // so that we "shave" one off.
830  for (const auto &column : columns)
831  n = std::max(n, column.second.entries.size());
832 
833  // shave the top most element
834  if (n != 0)
835  for (auto &column : columns)
836  if (column.second.entries.size() == n)
837  column.second.entries.pop_back();
838 }
839 
840 
void set_tex_format(const std::string &key, const std::string &format="c")
void start_new_row()
void set_tex_table_caption(const std::string &table_caption)
void set_tex_supercaption(const std::string &superkey, const std::string &tex_supercaption)
void declare_column(const std::string &key)
void write_text(std::ostream &out, const TextOutputFormat format=table_with_headers) const
void set_auto_fill_mode(const bool state)
void write_tex(std::ostream &file, const bool with_header=true) const
void add_column_to_supercolumn(const std::string &key, const std::string &superkey)
void set_column_order(const std::vector< std::string > &new_order)
void set_tex_caption(const std::string &key, const std::string &tex_caption)
void clear_current_row()
void set_scientific(const std::string &key, const bool scientific)
void set_tex_table_label(const std::string &table_label)
void set_precision(const std::string &key, const unsigned int precision)
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:416
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:417
static ::ExceptionBase & ExcColumnNotExistent(std::string arg1)
static ::ExceptionBase & ExcUndefinedTexFormat(std::string arg1)
static ::ExceptionBase & ExcInternalError()
void pad_column_below(const unsigned int length)
static ::ExceptionBase & ExcColumnOrSuperColumnNotExistent(std::string arg1)
static ::ExceptionBase & ExcSuperColumnNotExistent(std::string arg1)
unsigned int n_rows() const
void get_selected_columns(std::vector< std::string > &sel_columns) const
static ::ExceptionBase & ExcWrongNumberOfDataEntries(std::string arg1, int arg2, std::string arg3, int arg4)
#define Assert(cond, exc)
Definition: exceptions.h:1473
std::map< std::string, std::vector< std::string > > supercolumns
@ simple_table_with_separate_column_description
@ table_with_separate_column_description
std::map< std::string, std::string > tex_supercaptions
std::string tex_table_label
std::string tex_table_caption
static ::ExceptionBase & ExcIO()
unsigned int precision
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< std::string > column_order
std::vector< internal::TableEntry > entries
#define AssertThrow(cond, exc)
Definition: exceptions.h:1583
std::map< std::string, Column > columns
static const char T
types::global_dof_index size_type
Definition: cuda_kernels.h:45
void operator()(T &operand) const
TableEntry get_default_constructed_copy() const
std::string cached_value
const std::string & get_cached_string() const
double get_numeric_value() const
void cache_string(bool scientific, unsigned int precision) const