]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Change the inner workings of the TableHandler and derived ConvergenceTable class.
authorbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 17 Oct 2011 18:26:33 +0000 (18:26 +0000)
committerbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 17 Oct 2011 18:26:33 +0000 (18:26 +0000)
git-svn-id: https://svn.dealii.org/trunk@24616 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/doc/news/changes.h
deal.II/include/deal.II/base/table_handler.h
deal.II/source/base/table_handler.cc

index 554a0b1059d199961ba96df95c7a1956d83bbc0c..f861da34a1aa2e752fc347dd625f7745a735d76c 100644 (file)
@@ -36,7 +36,9 @@ inconvenience this causes.
 <ol>
 <li> New: parallel::distributed::Triangulation::save()/load() to store
 the refinement information to disk. Also supports saving solution vectors
-using the SolutionTransfer class. (Timo Heister, 2011/10/12)
+using the SolutionTransfer class.
+<br>
+(Timo Heister, 2011/10/12)
 </ol>
 
 
@@ -46,6 +48,13 @@ using the SolutionTransfer class. (Timo Heister, 2011/10/12)
 <h3>Specific improvements</h3>
 
 <ol>
+<li> Changed: The TableHandler class has been changed significantly internally.
+It could previously store arbitrary values (though in practice, only int, unsigned int,
+double and std::string were implemented. The class is now restricted to this particular
+set of types
+<br>
+(Wolfgang Bangerth, 2011/10/17)
+
 <li> Fixed: searching in the doxygen documentation.
 <br>
 (Timo Heister, 2011/10/13)
index eb962370fab5fb75c9887134703de2b1983ee578..04f7d9afb4697a507850ec69f2f8b6c20a0487f2 100644 (file)
@@ -21,7 +21,6 @@
 #include <string>
 #include <fstream>
 
-DEAL_II_NAMESPACE_OPEN
 // we only need output streams, but older compilers did not provide
 // them in a separate include file
 #ifdef HAVE_STD_OSTREAM_HEADER
@@ -30,89 +29,53 @@ DEAL_II_NAMESPACE_OPEN
 #  include <iostream>
 #endif
 
+#include <boost/variant.hpp>
 
 
-/**
- * Abstract base class for the <tt>TableEntry</tt> class. See there.
- * This class is not to be used by the user.
- *
- * @ingroup textoutput
- * @author Ralf Hartmann, 1999
- */
-class TableEntryBase
-{
-  public:
-                                     /**
-                                      * Constructor.
-                                      */
-    TableEntryBase();
-
-                                     /**
-                                      * Virtual destructor.
-                                      */
-    virtual ~TableEntryBase();
-
-                                     /**
-                                      * Write the table entry as text.
-                                      */
-    virtual void write_text (std::ostream &) const = 0;
-
-                                     /**
-                                      * Write the table entry in tex format.
-                                      */
-    virtual void write_tex (std::ostream &) const = 0;
-};
+DEAL_II_NAMESPACE_OPEN
 
 
-/**
- * A <tt>TableEntry</tt> stores the value of a table entry.
- * The value type of this table entry is arbitrary. For
- * a <tt>TableEntry<typename value_type></tt> with a non-common value
- * type you may want to specialize the output functions in order
- * to get nicer output. This class is not to be used by the user.
- *
- * For more detail see the <tt>TableHandler</tt> class.
- *
- * @ingroup textoutput
- * @author Ralf Hartmann, 1999
- */
-template <typename value_type>
-class TableEntry : public TableEntryBase
+namespace internal
 {
-  public:
-                                     /**
-                                      * Constructor.
-                                      */
-    TableEntry (const value_type value);
-
-                                     /**
-                                      * Destructor.
-                                      */
-    virtual ~TableEntry();
-
-                                     /**
-                                      * Returns the value of this
-                                      * table entry.
-                                      */
-    value_type value () const;
-
-                                     /**
-                                      * Write the table entry as text.
-                                      */
-    virtual void write_text (std::ostream &out) const;
-
-                                     /**
-                                      * Write the table entry in tex
-                                      * format.
-                                      */
-    virtual void write_tex (std::ostream &out) const;
-
-  private:
-                                     /**
-                                      * Stored value.
-                                      */
-    const value_type val;
-};
+  /**
+   * A <tt>TableEntry</tt> stores the value of a table entry.
+   * It can either be of type int, unsigned int, double or std::string.
+   * In essence, this structure is the same as 
+   * <code>boost::variant<int,unsigned int,double,std::string></code>
+   * but we wrap this object in a structure for which we can write
+   * a function that can serialize it. This is also why the function 
+   * is not in fact of type boost::any.
+   */
+  struct TableEntry
+  {
+    /**
+     * Abbreviation for the data type stored by this object.
+     */
+    typedef boost::variant<int,unsigned int,double,std::string> value_type;
+    
+    /**
+     * Return the value stored by this object. The template type
+     * T must be one of <code>int,unsigned int,double,std::string</code>
+     * and it must match the data type of the object originally stored
+     * in this TableEntry object.
+     */
+    template <typename T>
+    T get () const;
+    
+    /**
+     * Return the numeric value of this object if data has been stored in
+     * it either as an integer, an unsigned integer, or a double.
+     *
+     * @return double
+     **/
+    double get_numeric_value () const;
+    
+    /**
+     * Stored value.
+     */
+    value_type value;
+  };
+}
 
 
 /**
@@ -177,7 +140,7 @@ class TableEntry : public TableEntryBase
  * @endcode
  *
  * @ingroup textoutput
- * @author Ralf Hartmann, 1999
+ * @author Ralf Hartmann, 1999; Wolfgang Bangerth, 2011
  */
 class TableHandler
 {
@@ -392,31 +355,23 @@ class TableHandler
                                          /**
                                           * Constructor needed by STL maps.
                                           */
-        Column();
+        Column ();
 
                                          /**
                                           * Constructor.
                                           */
-        Column(const std::string &tex_caption);
+        Column (const std::string &tex_caption);
 
-                                         /**
-                                          * Destructor.
-                                          */
-        ~Column();
 
                                          /**
                                           * List of entries within
-                                          * this column.  They may
-                                          * actually be of very
-                                          * different type, since we
-                                          * use the templated
-                                          * <tt>TableEntry<T></tt> class
-                                          * for actual values, which
-                                          * is only a wrapper for
-                                          * <tt>T</tt>, but is derived from
-                                          * <tt>TableEntryBase</tt>.
+                                          * this column. Values are
+                                         * always immediately
+                                         * converted to strings to
+                                         * provide a uniform method
+                                         * of lookup.
                                           */
-        std::vector<TableEntryBase *> entries;
+        std::vector<internal::TableEntry> entries;
 
                                          /**
                                           * The caption of the column
@@ -550,9 +505,74 @@ class TableHandler
                                       * The label of the table.
                                      */
     std::string tex_table_label;
-
 };
 
+
+// inline and template functions
+namespace internal
+{
+  template <typename T>
+  inline
+  T TableEntry::get () const
+  {
+    // we don't quite know the data type in 'value', but
+    // it must be one of the ones in the type list of the
+    // boost::variant. so if T is not in the list, or if
+    // the data stored in the TableEntry is not of type
+    // T, then we will get an exception that we can
+    // catch and produce an error message
+    try
+    {
+      return boost::get<T>(value);
+    }
+    catch (...)
+    {
+      Assert(false, ExcMessage ("This TableEntry object does not store a datum of type T"));
+      throw;
+    }
+  }
+  
+  
+  inline
+  double TableEntry::get_numeric_value () const
+  {
+    // we don't quite know the data type in 'value', but
+    // it must be one of the ones in the type list of the
+    // boost::variant. Go through this list and return
+    // the value if this happens to be a number
+    //
+    // first try with int
+    try
+    {
+      return boost::get<int>(value);
+    }
+    catch (...)
+    {}
+
+    
+    // ... then with unsigned int...
+    try
+    {
+      return boost::get<unsigned int>(value);
+    }
+    catch (...)
+    {}
+    
+    // ...and finally with double precision:
+    try
+    {
+      return boost::get<double>(value);
+    }
+    catch (...)
+    {
+      Assert (false, ExcMessage ("The number stored by this element of the "
+      "table is not a number."))
+    }
+    
+    return 0;
+  }    
+}
+
 DEAL_II_NAMESPACE_CLOSE
 
 #endif
index b2e1dd57051668234e1ad1f0d5d2744023a303ff..d9bc6c736ccf0299f976cf627e92cd624297ba43 100644 (file)
@@ -2,7 +2,7 @@
 //    $Id$
 //    Version: $Name$
 //
-//    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 by the deal.II authors
+//    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2011 by the deal.II authors
 //
 //    This file is subject to QPL and may not be  distributed
 //    without copyright and license information. Please refer
 #include <sstream>
 #include <iostream>
 #include <iomanip>
+#include "../../contrib/boost-1.46.1/include/boost/mpl/string.hpp"
 
 
 DEAL_II_NAMESPACE_OPEN
 
 
-
-TableEntryBase::TableEntryBase ()
-{}
-
-
-TableEntryBase::~TableEntryBase ()
-{}
-
 /*---------------------------------------------------------------------*/
 
-template <typename number>
-TableEntry<number>::TableEntry(const number value)
-                :
-               val(value)
-{}
-
-
-
-template <typename number>
-TableEntry<number>::~TableEntry()
-{}
-
-
-
-template <typename number>
-number TableEntry<number>::value() const
-{
-  return val;
-}
-
-
-
-template <typename number>
-void TableEntry<number>::write_tex (std::ostream &out) const
-{
-  out << val;
-}
-
-
-
-template <typename number>
-void TableEntry<number>::write_text (std::ostream &out) const
-{
-  out << val;
-}
-
-
-/*---------------------------------------------------------------------*/
 
 TableHandler::Column::Column(const std::string &tex_caption)
                 :
@@ -78,7 +33,7 @@ TableHandler::Column::Column(const std::string &tex_caption)
                tex_format("c"),
                precision(4),
                scientific(0),
-               flag(0)  
+               flag(0)
 {}
 
 
@@ -89,18 +44,11 @@ TableHandler::Column::Column()
                tex_format("c"),
                precision(4),
                scientific(0),
-               flag(0)  
+               flag(0)
 {}
 
 
 
-TableHandler::Column::~Column()
-{
-  for (unsigned int i=0; i<entries.size(); ++i)
-    delete entries[i];
-  entries.clear();
-}
-
 /*---------------------------------------------------------------------*/
 
 
@@ -108,25 +56,24 @@ TableHandler::TableHandler()
 {}
 
 
+
 template <typename number>
-void TableHandler::add_value (const std::string &key, 
+void TableHandler::add_value (const std::string &key,
                              const number value)
 {
-  if (!columns.count(key))
+  if (columns.find(key) == columns.end())
     {
       std::pair<std::string, Column> new_column(key, Column(key));
       columns.insert(new_column);
       column_order.push_back(key);
     }
-
-  TableEntry<number> *entry_ptr=new TableEntry<number>(value);
-  const std::map<std::string, Column>::iterator col_iter=columns.find(key);
-  Assert(col_iter!=columns.end(), ExcInternalError());
-  
-  col_iter->second.entries.push_back(entry_ptr);
+    
+  const internal::TableEntry entry = { value };
+  columns[key].entries.push_back (entry);
 }
 
 
+
 void TableHandler::add_column_to_supercolumn (const std::string &key,
                                              const std::string &superkey)
 {
@@ -145,12 +92,12 @@ void TableHandler::add_column_to_supercolumn (const std::string &key,
            column_order[j]=superkey;
            break;
          }
-    } 
-  else 
+    }
+  else
     {
                                       // remove key from column_order
                                       // for erase we need an iterator
-      for (std::vector<std::string>::iterator order_iter=column_order.begin(); 
+      for (std::vector<std::string>::iterator order_iter=column_order.begin();
           order_iter!=column_order.end(); ++order_iter)
        if (*order_iter==key)
          {
@@ -172,6 +119,7 @@ void TableHandler::add_column_to_supercolumn (const std::string &key,
 }
 
 
+
 void TableHandler::set_column_order (const std::vector<std::string> &new_order)
 {
   for (unsigned int j=0; j<new_order.size(); ++j)
@@ -182,23 +130,29 @@ void TableHandler::set_column_order (const std::vector<std::string> &new_order)
 }
 
 
-void TableHandler::set_tex_caption (const std::string &key, 
+void TableHandler::set_tex_caption (const std::string &key,
                                    const std::string &tex_caption)
 {
   Assert(columns.count(key), ExcColumnNotExistent(key));
   columns[key].tex_caption=tex_caption;
 }
 
+
+
 void TableHandler::set_tex_table_caption (const std::string &table_caption)
 {
   tex_table_caption=table_caption;
 }
 
+
+
 void TableHandler::set_tex_table_label (const std::string &table_label)
 {
   tex_table_label=table_label;
 }
 
+
+
 void TableHandler::set_tex_supercaption (const std::string &superkey,
                                         const std::string &tex_supercaption)
 {
@@ -208,6 +162,7 @@ void TableHandler::set_tex_supercaption (const std::string &superkey,
 }
 
 
+
 void TableHandler::set_tex_format (const std::string &key,
                                   const std::string &tex_format)
 {
@@ -218,6 +173,7 @@ void TableHandler::set_tex_format (const std::string &key,
 }
 
 
+
 void TableHandler::set_precision (const std::string &key,
                                  const unsigned int precision)
 {
@@ -236,8 +192,8 @@ void TableHandler::set_scientific (const std::string &key,
 
 void TableHandler::write_text(std::ostream &out) const
 {
-  AssertThrow (out, ExcIO());  
-  
+  AssertThrow (out, ExcIO());
+
   std::vector<std::string> sel_columns;
   get_selected_columns(sel_columns);
 
@@ -256,22 +212,23 @@ void TableHandler::write_text(std::ostream &out) const
        const std::map<std::string, Column>::const_iterator
          col_iter=columns.find(key);
        Assert(col_iter!=columns.end(), ExcInternalError());
-         
+
        const Column & column = col_iter->second;
 
                                         // write it into a dummy
                                         // stream, just to get its
                                         // size upon output
        std::ostringstream dummy_out;
-       
+
        dummy_out << std::setprecision(column.precision);
 
        if (col_iter->second.scientific)
          dummy_out.setf (std::ios::scientific, std::ios::floatfield);
        else
          dummy_out.setf (std::ios::fixed, std::ios::floatfield);
-       column.entries[i]->write_text (dummy_out);
-       
+
+       dummy_out << column.entries[i].value;
+
                                         // get size, note that we are
                                         // not interested in the
                                         // trailing \0
@@ -290,7 +247,7 @@ void TableHandler::write_text(std::ostream &out) const
   for (unsigned int j=0; j<column_order.size(); ++j)
     {
       const std::string & key = column_order[j];
-      
+
                                       // if the key of this column is
                                       // wider than the widest entry,
                                       // then adjust
@@ -312,18 +269,18 @@ void TableHandler::write_text(std::ostream &out) const
       out << ' ';
     }
   out << std::endl;
-  
+
   for (unsigned int i=0; i<nrows; ++i)
-    {    
+    {
       for (unsigned int j=0; j<n_cols; ++j)
        {
          std::string key=sel_columns[j];
          const std::map<std::string, Column>::const_iterator
            col_iter=columns.find(key);
          Assert(col_iter!=columns.end(), ExcInternalError());
-         
+
          const Column &column=col_iter->second;
-         
+
          out << std::setprecision(column.precision);
 
          if (col_iter->second.scientific)
@@ -331,7 +288,7 @@ void TableHandler::write_text(std::ostream &out) const
          else
            out.setf(std::ios::fixed, std::ios::floatfield);
          out << std::setw(column_widths[j]);
-         column.entries[i]->write_text(out);
+         out << column.entries[i].value;
          out << " ";
        }
       out << std::endl;
@@ -346,7 +303,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const
     out << "\\documentclass[10pt]{report}" << std::endl
        << "\\usepackage{float}" << std::endl << std::endl << std::endl
        << "\\begin{document}" << std::endl;
-  
+
   out << "\\begin{table}[H]" << std::endl
       << "\\begin{center}" << std::endl
       << "\\begin{tabular}{|";
@@ -359,7 +316,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const
     {
       std::string key=column_order[j];
                                       // avoid `supercolumns[key]'
-      const std::map<std::string, std::vector<std::string> >::const_iterator 
+      const std::map<std::string, std::vector<std::string> >::const_iterator
        super_iter=supercolumns.find(key);
 
       if (super_iter!=supercolumns.end())
@@ -371,7 +328,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const
              const std::map<std::string, Column>::const_iterator
                col_iter=columns.find(super_iter->second[k]);
              Assert(col_iter!=columns.end(), ExcInternalError());
-             
+
              out << col_iter->second.tex_format << "|";
            }
        }
@@ -387,20 +344,20 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const
   out << "} \\hline" << std::endl;
 
                                   // write the caption line of the table
-  
+
   for (unsigned int j=0; j<column_order.size(); ++j)
     {
       std::string key=column_order[j];
-      const std::map<std::string, std::vector<std::string> >::const_iterator 
+      const std::map<std::string, std::vector<std::string> >::const_iterator
        super_iter=supercolumns.find(key);
 
       if (super_iter!=supercolumns.end())
        {
          const unsigned int n_subcolumns=super_iter->second.size();
                                           // avoid use of `tex_supercaptions[key]'
-         std::map<std::string,std::string>::const_iterator 
+         std::map<std::string,std::string>::const_iterator
            tex_super_cap_iter=tex_supercaptions.find(key);
-         out << std::endl << "\\multicolumn{" << n_subcolumns << "}{|c|}{" 
+         out << std::endl << "\\multicolumn{" << n_subcolumns << "}{|c|}{"
              << tex_super_cap_iter->second << "}";
        }
       else
@@ -421,7 +378,7 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const
   for (unsigned int i=0; i<nrows; ++i)
     {
       const unsigned int n_cols=sel_columns.size();
-      
+
       for (unsigned int j=0; j<n_cols; ++j)
        {
          std::string key=sel_columns[j];
@@ -429,18 +386,18 @@ void TableHandler::write_tex (std::ostream &out, const bool with_header) const
          const std::map<std::string, Column>::const_iterator
            col_iter=columns.find(key);
          Assert(col_iter!=columns.end(), ExcInternalError());
-         
+
          const Column &column=col_iter->second;
-         
+
          out << std::setprecision(column.precision);
 
          if (col_iter->second.scientific)
            out.setf(std::ios::scientific, std::ios::floatfield);
          else
            out.setf(std::ios::fixed, std::ios::floatfield);
-         
-         column.entries[i]->write_tex(out);
-         
+
+         out << column.entries[i].value;
+
          if (j<n_cols-1)
            out << " & ";
        }
@@ -466,9 +423,9 @@ unsigned int TableHandler::n_rows() const
   std::string first_name=col_iter->first;
 
   for (++col_iter; col_iter!=columns.end(); ++col_iter)
-    Assert(col_iter->second.entries.size()==n, 
-          ExcWrongNumberOfDataEntries(col_iter->first, 
-                                      col_iter->second.entries.size(), 
+    Assert(col_iter->second.entries.size()==n,
+          ExcWrongNumberOfDataEntries(col_iter->first,
+                                      col_iter->second.entries.size(),
                                       first_name, n));
 
   return n;
@@ -478,11 +435,11 @@ unsigned int TableHandler::n_rows() const
 void TableHandler::get_selected_columns(std::vector<std::string> &sel_columns) const
 {
   sel_columns.clear();
-  
+
   for (unsigned int j=0; j<column_order.size(); ++j)
     {
       std::string key=column_order[j];
-      const std::map<std::string, std::vector<std::string> >::const_iterator 
+      const std::map<std::string, std::vector<std::string> >::const_iterator
        super_iter=supercolumns.find(key);
 
       if (super_iter!=supercolumns.end())
@@ -507,13 +464,6 @@ void TableHandler::get_selected_columns(std::vector<std::string> &sel_columns) c
 
 
 // explicit instantiations
-template class TableEntry<double>;
-template class TableEntry<float>;
-template class TableEntry<int>;
-template class TableEntry<unsigned int>;
-template class TableEntry<std::string>;
-
-
 template
 void TableHandler::add_value<double> (const std::string &,
                                      const double);

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.