Object-oriented Scientific Computing Library: Version 0.910
table.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_TABLE_H
00024 #define O2SCL_TABLE_H
00025 
00026 #include <iostream>
00027 #include <fstream>
00028 #include <string>
00029 #include <cmath>
00030 #include <sstream>
00031 #include <o2scl/misc.h>
00032 #include <o2scl/err_hnd.h>
00033 #include <o2scl/multi_funct.h>
00034 #include <o2scl/search_vec.h>
00035 #include <o2scl/ovector_tlate.h>
00036 #include <o2scl/smart_interp.h>
00037 #if O2SCL_HDF_SVAR
00038 #include <o2scl/hdf_file.h>
00039 #endif
00040 
00041 #ifndef DOXYGENP
00042 namespace o2scl {
00043 #endif
00044 
00045   /** \brief Data \table class
00046       
00047       \b Summary \n 
00048 
00049       A class to contain and manipulate several equally-sized columns
00050       of data. The purpose of this class is to provide a structure
00051       which allows one to refer to the columns using a name
00052       represented by a string. Thus for a table object named \c t with
00053       3 columns (named "colx", "coly" and "colz") and three rows, one
00054       could do the following:
00055       \include table_doc1.cpp
00056       Note that the rows are numbered starting with 0 instead of 
00057       starting with 1.
00058       To output all the rows of entire column, one can use
00059       \include table_doc2.cpp
00060       To output all the columns of an entire row (in the following
00061       example it is the second row), labeled by their column name, one
00062       can use:
00063       \include table_doc3.cpp
00064 
00065       Methods are provided for interpolating columns, sorting 
00066       columns, finding data points, and several other manipulations
00067       of the data. 
00068 
00069       \b Column \b size \n 
00070 
00071       The columns grow automatically (similar to the STL <vector>)
00072       in reponse to an attempt to call set() for a row that does not
00073       presently exist or in a call to line_of_data() when the table is
00074       already full. However, this forces memory rearrangments that are
00075       expensive, O(R*C). If the user has a good estimate of the number
00076       of rows beforehand, it is best to either specify this in the
00077       constructor, or in an explicit call to inc_maxlines().
00078 
00079       <B> Lookup, differentiation, integration, and 
00080       interpolation </b> \n
00081 
00082       Lookup, differentiation, integration, and interpolation are
00083       automatically implemented using splines from the class \ref
00084       smart_interp_vec. A caching mechanism is implemented so that
00085       successive interpolations, derivative evaluations or
00086       integrations over the same two columns are fast.
00087 
00088       <B> Sorting </b>\n
00089 
00090       The columns are automatically sorted by name for speed, the
00091       results can be accessed by table::get_sorted_name(i). Individual
00092       columns can be sorted (\ref sort_column() ), or the entire table
00093       can be sorted by one column (\ref sort_table() ).
00094 
00095       <B> Data representation </b> \n
00096 
00097       Each individual column is just an ovector_base object.
00098       The columns can be referred to in one of two ways:
00099       - A numerical index from 0 to C-1 (where C is the number of
00100       columns). For example, data can be accessed through \ref
00101       table::get() and \ref table::set(size_t c, size_t r,
00102       double val), or the overloaded [] operator, <tt>table[c][r]</tt>. 
00103       - A name of the column which is a string with no whitespace.
00104       For example, data can be accessed with table::get(string cname,
00105       int r) and table::set(string cname, int r, double val).
00106       
00107       The columns are organized in a both a <map> and a <vector>
00108       structure so that finding a column by its index, using either of
00109       \code
00110       std::string table::get_column_name(size_t index);
00111       ovector_base &table::get_column(int index);
00112       \endcode
00113       takes only constant time, and finding a column by its name
00114       using either of
00115       \code
00116       int lookup_column(std::string name, int &ix) const;
00117       const ovector_base &get_column(std::string col) const;      
00118       \endcode
00119       is O(log(C)). Insertion of a column ( \ref new_column() ) is
00120       O(log(C)), but deletion ( \ref delete_column() ) is O(C). Adding
00121       a row of data can be either O(1) or O(C), but row insertion and
00122       deletion is slow, since the all of the rows must be shifted
00123       accordingly.
00124       
00125       Because of the structure, this class is not suitable for the
00126       matrix manipulation. The classes \ref omatrix and \ref umatrix
00127       are better used for that purpose.
00128 
00129       <B> Thread-safety </b> \n
00130 
00131       Generally, the member functions are thread-safe in the sense
00132       that one would expect: it is always permitted to have many
00133       threads accessing many distinct tables, but care must be taken
00134       if many threads are accessing only one table. Simple get() and
00135       set() functions are thread-safe (unless a set() function forces
00136       memory rearrangement), while insertion and deletion operations
00137       are not. Only the <tt>const</tt> version of the interpolation
00138       routines are thread-safe.
00139 
00140       \b I/O \b and \b command-line \b manipulation \n
00141 
00142       When data from an object of type \ref table is output to a file
00143       through a <tt>hdf_output()</tt> function (see \ref hdf_io.h), 
00144       the table can be
00145       manipulated on the command-line through the \c acol utility.
00146 
00147       There is an example for the usage of this class given
00148       in <tt>examples/ex_table.cpp</tt>.
00149 
00150       \todo Document or fix the fact that the table 
00151       copy constructors do not copy the interpolation objects.
00152       Maybe def_interp_mgr objects can have their own
00153       copy constructors?
00154       
00155       \future 
00156       - Rewrite the \ref table::create_array() and \ref
00157       table::insert_data() functions for generic vector type
00158       - Return the empty column in the operator[] functions
00159       as is done for the get_column() functions.
00160       - A "delete rows" method to delete a range of several rows
00161       - The present structure, \c
00162       std::map<std::string,col,string_comp> atree and \c
00163       std::vector<aiter> alist; could be replaced with \c
00164       std::vector<col> list and \c std::map<std::string,int> tree
00165       where the map just stores the index of the the column in the
00166       list.
00167 
00168       \comment
00169 
00170       10/16/07: This issue may be unimportant, as it might be better
00171       to just move to a template based approach with a user-specified
00172       vector type. The interpolation is now flexible enough to handle
00173       different types. Might check to ensure sorting works with other
00174       types.
00175 
00176       10/9/08: Actually, the native vector types are very useful here,
00177       and I'm thinking now that the vector types should not be
00178       templated. If there is a user-owned column, then no lines should
00179       ever be added beyond the length of the user-owned column. For
00180       adding user-owned columns into a table which already contains
00181       data, it should fail if the user-owned column is smaller than
00182       nlines and succeed otherwise. If after adding a user-owned
00183       column maxlines is greater than the user-owned column size, then
00184       maxlines should be decreases accordingly.
00185 
00186       1/30/08: User-owned columns have been removed for now,
00187       which avoids a lot of complications.
00188 
00189       \endcomment
00190   */
00191   class table {
00192   public:
00193   
00194     /** \brief Create a new table with space for nlines<=cmaxlines.
00195      */
00196     table(int cmaxlines=0);
00197 
00198     virtual ~table();
00199 
00200     /// Copy constructor
00201     table(const table &t);
00202 
00203     /// Copy constructor
00204     table &operator=(const table &t);
00205 
00206     // --------------------------------------------------------
00207     /** \name Basic get and set methods */
00208     //@{
00209     /** \brief Set row \c row of column named \c col to value \c val - 
00210         O(log(C)).
00211 
00212         This function adds the column \c col if it does not already
00213         exist and adds rows using inc_maxlines() and set_nlines() to
00214         create at least \c (row+1) rows if they do not already exist.
00215     */
00216     int set(std::string col, size_t row, double val);
00217 
00218     /** \brief Set row \c row of column number \c icol to value \c val
00219         - O(1).
00220      */
00221     int set(size_t icol, size_t row, double val);
00222   
00223     /** \brief Get value from row \c row of column named \c col -
00224         O(log(C)).
00225      */
00226     double get(std::string col, size_t row) const;
00227 
00228     /** \brief Get value from row \c row of column number \c icol -
00229         O(1).
00230      */
00231     double get(size_t icol, size_t row) const;
00232 
00233     /** \brief Return the number of columns
00234      */
00235     size_t get_ncolumns() const {return atree.size();};
00236     
00237     /** \brief Return the number of lines
00238      */
00239     size_t get_nlines() const {return nlines;};
00240 
00241     /** \brief Set the number of lines
00242         
00243         This function is stingy about increasing the table memory
00244         space and will only increase it enough to fit \c il lines.
00245         Using it in succession to slowly increase the number of lines
00246         in the table is likely to be inefficient compared to \ref
00247         set_nlines_auto() in this case.
00248      */
00249     int set_nlines(size_t il);
00250 
00251     /** \brief Set the number of lines, increasing the size more 
00252         agressively
00253 
00254         This function is like set_nlines(), but doubles the maximum
00255         column size if an increase in the maximum size is required
00256         instead of simply making enough room for the current number of
00257         lines. This function is used internally by \ref set() to
00258         ensure that the cost of setting lines in sequence is linear
00259         and not quadratic.
00260     */
00261     int set_nlines_auto(size_t il);
00262 
00263     /** \brief Return the maximum number of lines
00264      */
00265     int get_maxlines() {return maxlines;};
00266 
00267     /** \brief Returns a reference to the column named \c col -
00268         O(log(C))
00269      */
00270     ovector_base &get_column(std::string col);
00271     
00272     /** \brief Returns a reference to the column named \c col -
00273         O(log(C))
00274      */
00275     const ovector_base &get_column(std::string col) const;
00276 
00277     /** \brief Returns the column of index \c icol - O(1) (const
00278         version)
00279 
00280         This does not do any sort of bounds checking and is quite
00281         fast.
00282 
00283         Note that several of the methods require reallocation of
00284         memory and refereces previously returned by this function will
00285         be incorrect.
00286 
00287         Unlike set(), this function will not automatically result in
00288         an increase in the size of the table if the user attempts to
00289         set an element beyond the current column range.
00290     */
00291     const ovector_base &operator[] (size_t icol) const {
00292       return (*alist[icol]->second.dat);
00293     }
00294 
00295     /** \brief Returns the column of index \c icol - O(1).
00296 
00297         This does not do any sort of bounds checking and is 
00298         quite fast. 
00299 
00300         Note that several of the methods require reallocation of
00301         memory and refereces previously returned by this function will
00302         be incorrect.
00303 
00304         Unlike set(), this function will not automatically result
00305         in an increase in the size of the table if the user
00306         attempts to set an element beyond the current column range.
00307     */
00308     ovector_base &operator[] (size_t icol) {
00309       return (*alist[icol]->second.dat);
00310     }
00311 
00312     /** \brief Returns the column named \c scol - O(log(C)) (const version)
00313 
00314         No error checking is performed.
00315 
00316         Note that several of the methods require reallocation of
00317         memory and refereces previously returned by this function will
00318         be incorrect.
00319 
00320         Unlike set(), this function will not automatically result in
00321         an increase in the size of the table if the user attempts to
00322         set an element beyond the current column range.
00323     */
00324     const ovector_base &operator[](std::string scol) const {
00325       aciter it=atree.find(scol);
00326       return *(it->second.dat);
00327     }
00328 
00329     /** \brief Returns the column named \c scol - O(log(C))
00330 
00331         No error checking is performed.
00332 
00333         Note that several of the methods require reallocation of
00334         memory and refereces previously returned by this function will
00335         be incorrect.
00336 
00337         Unlike set(), this function will not automatically result in
00338         an increase in the size of the table if the user attempts to
00339         set an element beyond the current column range.
00340     */
00341     ovector_base &operator[](std::string scol) {
00342       aiter it=atree.find(scol);
00343       return *(it->second.dat);
00344     }
00345 
00346     /** \brief Returns a copy of the row with value \c val in column
00347         \c col - O(R*C)
00348 
00349         This function searches the entire table for the row which has
00350         the entry in column \c col which is closest to the value \c
00351         val, and copies that row to the vector \c row.
00352 
00353         If the \ref ovector object \c row previously contains any
00354         data, it will be lost.
00355     */
00356     int get_row(std::string col, double val, ovector &row) const;
00357     
00358     /** \brief Returns a copy of row number \c irow - O(C)
00359         
00360         This function returns a copy of row with index \c irow,
00361         where \c irow ranges from 0 to <tt>get_nlines()-1</tt>,
00362         inclusive.
00363 
00364         If the \ref ovector object \c row previously contains any
00365         data, it will be lost.
00366      */
00367     int get_row(size_t irow, ovector &row) const;
00368     //@}
00369 
00370     // --------------------------------------------------------
00371     /** \name Histogram-like functions
00372      */
00373     //@{
00374     /** \brief Update a histogram entry
00375 
00376         Assuming that the histogram bins are given in column named \c
00377         ix_col, this updates the histogram found in column \c scol at
00378         index location \c ix by incrementing it by an amount given in
00379         \c inc.
00380     */
00381     int hist_update(std::string ix_col, std::string scol,
00382                     double ix, double inc=1.0);
00383 
00384     /** \brief Get a histogram entry
00385 
00386         Assuming that the histogram bins are given in column named \c
00387         ix_col, this returns the histogram entry found in column \c
00388         scol at index location \c ix .
00389     */
00390     double hist_get(std::string ix_col, std::string scol,
00391                     double ix);
00392 
00393     /** \brief Set a histogram entry
00394 
00395         Assuming that the histogram bins are given in column named \c
00396         ix_col, this sets the histogram entry found in column \c scol
00397         at index location \c ix to the value given in \c value .
00398     */
00399     int hist_set(std::string ix_col, std::string scol,
00400                  double ix, double value);
00401     //@}
00402   
00403     // --------------------------------------------------------
00404     /** \name Column manipulation */
00405     //@{
00406 
00407     /** \brief Returns the name of column \c col - O(1).
00408      */
00409     std::string get_column_name(size_t col) const;
00410 
00411     /** \brief Returns the name of column \c col in sorted order -
00412         O(1).
00413      */
00414     std::string get_sorted_name(size_t col);
00415 
00416     /** \brief Add a new column owned by the \table - O(log(C)).
00417 
00418         \note This function does not set all the column entries to
00419         zero in the case that a new column is added to a table which
00420         already contains data.
00421      */
00422     int new_column(std::string name);
00423 
00424     /** \brief Add a new column by copying data from another vector
00425 
00426         This function copies \c sz elements of vector \c v into the
00427         table in a new column named \c name. If \c sz is larger than
00428         the current number of lines (as given, e.g. in \ref
00429         get_nlines() ), then only the first part of the vector \c v is
00430         copied, up to the current number of lines.
00431 
00432         This function calls the error handler if \c sz is zero.
00433      */
00434     template<class vec_t> int new_column(std::string name, 
00435                                          size_t sz, vec_t &v) {
00436 
00437       if (sz==0) {
00438         O2SCL_ERR2_RET("Sent column of zero size in ",
00439                        "table::new_column(string,size_t,vec_t)",
00440                        gsl_einval);
00441       }
00442 
00443       // Create the space
00444       int ret=new_column(name);
00445       if (ret!=0) return ret;
00446 
00447       // Copy the data over
00448       size_t mxl=sz;
00449       if (sz>get_nlines()) mxl=get_nlines();
00450       for(size_t i=0;i<mxl;i++) {
00451         set(name,i,v[i]);
00452       }
00453         
00454       return 0;
00455     }
00456 
00457 
00458 #ifdef O2SCL_NEVER_DEFINED
00459 
00460     /** \brief Add a new column owned by the user - O(log(C)).
00461         
00462         This function does not modify the number of lines of data in 
00463         the table. 
00464 
00465         \todo We've got to figure out what to do if ldat is too small.
00466         If it's smaller than nlines, obviously we should just 
00467         fail, but what if it's size is between nlines and maxlines?
00468     */
00469     int new_column(std::string name, ovector_view *ldat);
00470 
00471 #endif
00472 
00473     /** \brief Return true if \c scol is a column in the current \table
00474 
00475         This function does not call the error handler if the column is
00476         not found, but just silently returns false.
00477      */
00478     bool is_column(std::string scol);
00479 
00480     /** \brief Find the index for column named \c name - O(log(C)).
00481 
00482         If the column is not present, this does not call the error
00483         handler, but quietly sets \c ix to zero and returns \ref
00484         gsl_enotfound.
00485      */
00486     int lookup_column(std::string name, int &ix) const;
00487 
00488 #ifdef O2SCL_NEVER_DEFINED
00489 
00490     /** \brief Rename column named \c olds to \c news - O(C). 
00491 
00492         This is slow since we have to delete the column and re-insert
00493         it. This process in turn mangles all of the iterators in the
00494         list.
00495     */
00496     int rename_column(std::string olds, std::string news);
00497 
00498 #endif
00499 
00500     /** \brief Make a new column named \c dest equal to \c src - O(log(C)*R).
00501      */
00502     int copy_column(std::string src, std::string dest);
00503 
00504     /// Create (using \c new) a generic array from column \c col
00505     double *create_array(std::string col) const;
00506 
00507     /** \brief Initialize all values of column named \c scol to \c val - 
00508         O(log(C)*R). 
00509 
00510         Note that this does not initialize elements beyond nlines so
00511         that if the number of rows is increased afterwards, the new
00512         rows will have uninitialized values.
00513     */
00514     int init_column(std::string scol, double val);
00515 
00516 #ifdef O2SCL_NEVER_DEFINED
00517     /** \brief Modify ownership - O(log(C)). 
00518         
00519         \warning columns allocated using malloc() should never be
00520         owned by the table object since it uses delete instead of
00521         free().
00522     */
00523     int ch_owner(std::string name, bool ow);
00524 #endif
00525 
00526     /** \brief Get a gsl_vector from column \c name - O(log(C)). 
00527     */
00528     const gsl_vector *get_gsl_vector(std::string name) const;
00529   
00530     /** \brief Insert a column from a separate table, interpolating
00531         it into a new column
00532         
00533         Given a pair of columns ( \c src_index, \c src_col ) in a
00534         separate table (\c source), this creates a new column in the
00535         present table named \c src_col which interpolates \c loc_index
00536         into \c src_index.  The interpolation objects from the \c
00537         source table will be used. If there is already a column in the
00538         present table named \c src_col, then this will fail.
00539 
00540         If there is an error in the interpolation for any particular
00541         row, then the value of \c src_col in that row will be set to
00542         zero.
00543     */
00544     int add_col_from_table(std::string loc_index, table &source,
00545                            std::string src_index, std::string src_col,
00546                            std::string dest_col="");
00547     //@}
00548   
00549     // --------------------------------------------------------
00550     /** \name Row maninpulation and data input */
00551     //@{
00552 
00553     /** \brief Insert a row before row \c n 
00554 
00555         Acceptable values for \c n are between 0 and
00556         <tt>get_nlines()</tt> inclusive, with the maximum value
00557         denoting the addition of a row after the last row presently in
00558         the table.
00559      */
00560     int new_row(size_t n);
00561 
00562     /** \brief Copy the data in row \c src  to row \c dest 
00563      */
00564     int copy_row(size_t src, size_t dest);
00565 
00566     /** \brief Insert a row of data before row \c n 
00567      */
00568     int insert_data(size_t n, size_t nv, double *v);
00569 
00570     /** \brief Insert a row of data before row \c n 
00571      */
00572     int insert_data(size_t n, size_t nv, double **v);
00573 
00574     /** \brief Read a new set of names from \c newheads
00575 
00576         This function reads a set of white-space delimited column
00577         names from the string \c newheads, and creates a new column
00578         for each name which is specified.
00579         
00580         For example
00581         \code
00582         table t;
00583         t.line_of_names("position velocity acceleration");
00584         \endcode
00585         will create three new columns with the names ""position",
00586         "velocity", and "acceleration".
00587     */
00588     int line_of_names(std::string newheads);
00589 
00590     /** \brief Read a line of data from an array
00591      */
00592     template<class vec_t> int line_of_data(size_t nv, const vec_t &v) {
00593       if (maxlines==0) inc_maxlines(5);
00594       if (nlines>=maxlines) inc_maxlines(maxlines);
00595       
00596       if (intp_set) {
00597         intp_set=false;
00598         delete si;
00599       }
00600       
00601       if (nlines<maxlines && nv<=(atree.size())) {
00602         
00603         for(size_t i=0;i<nv;i++) {
00604           (*this)[i][nlines]=v[i];
00605         }
00606         nlines++;
00607         
00608         return 0;
00609       }
00610       
00611       O2SCL_ERR("Not enough lines or columns in line_of_data().",gsl_einval);
00612       return gsl_einval;
00613     }
00614     //@}
00615 
00616     // --------------------------------------------------------
00617     /** \name Lookup and search methods */
00618     //@{
00619 
00620     /** \brief Look for a value in an ordered column
00621 
00622         O(log(C)*log(R))
00623 
00624         This uses the function search_vec::ordered_lookup(), which
00625         offers caching and assumes the vector is monotonic. If you
00626         don't have monotonic data, you can still use the
00627         table::lookup() function, which is more general.
00628      */
00629     size_t ordered_lookup(std::string col, double val);
00630 
00631     /// Exhaustively search column \c col for the value \c val - O(log(C)*R).
00632     size_t lookup(std::string col, double val) const;
00633 
00634     /// Search column \c col for the value \c val and return value in \c col2
00635     double lookup_val(std::string col, double val, std::string col2) const;
00636 
00637     /// Exhaustively search column \c col for the value \c val - O(log(C)*R).
00638     size_t lookup(int col, double val) const;
00639 
00640     /** \brief Exhaustively search column \c col for many occurences 
00641         of \c val - O(log(C)*R).
00642     */
00643     size_t mlookup(std::string col, double val, std::vector<double> &results,
00644                    double threshold=0.0) const;
00645     //@}
00646 
00647     // --------------------------------------------------------
00648     /** \name Interpolation, differentiation, and integration, max,
00649         and min */
00650     //@{
00651 
00652     /// Set the base interpolation objects
00653     int set_interp(base_interp_mgr<ovector_const_view> &bi1,
00654                    base_interp_mgr<ovector_const_subvector> &bi2) {
00655       bim1=&bi1;
00656       bim2=&bi2;
00657       intp_set=false;
00658       return 0;
00659     }
00660 
00661     /** \brief Interpolate \c x0 from \c sx into \c sy
00662 
00663         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if the
00664         relevant columns are not well ordered.
00665     */
00666     double interp(std::string sx, double x0, std::string sy);
00667 
00668     /** \brief Interpolate \c x0 from \c sx into \c sy
00669 
00670         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if the
00671         relevant columns are not well ordered.
00672     */
00673     double interp_const(std::string sx, double x0, std::string sy) const;
00674     
00675     /** \brief Interpolate \c x0 from \c ix into \c iy
00676 
00677         O(log(R)) but can be as bad as O(R) if the relevant columns
00678         are not well ordered.
00679      */
00680     double interp(size_t ix, double x0, size_t iy);
00681 
00682     /** \brief Interpolate \c x0 from \c ix into \c iy
00683 
00684         O(log(R)) but can be as bad as O(R) if the relevant columns
00685         are not well ordered.
00686      */
00687     double interp_const(size_t ix, double x0, size_t iy) const;
00688 
00689     /** \brief Make a new column \c yp which is the derivative y'(x) - 
00690         O(log(C)*R).
00691      */
00692     int deriv(std::string x, std::string y, std::string yp);
00693 
00694     /** \brief The first derivative of the function sy(sx) at sx=x0.
00695 
00696         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if 
00697         the relevant columns are not well ordered.
00698     */
00699     double deriv(std::string sx, double x0, std::string sy);
00700 
00701     /** \brief The first derivative of the function sy(sx) at sx=x0.
00702 
00703         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if 
00704         the relevant columns are not well ordered.
00705     */
00706     double deriv_const(std::string sx, double x0, std::string sy) const;
00707 
00708     /** \brief The first derivative of the function iy(ix) at ix=x0.
00709       
00710         O(log(R)) but can be as bad as O(R) if the relevant columns
00711         are not well ordered.
00712     */
00713     double deriv(size_t ix, double x0, size_t iy);
00714 
00715     /** \brief The first derivative of the function iy(ix) at ix=x0.
00716       
00717         O(log(R)) but can be as bad as O(R) if 
00718         the relevant columns are not well ordered.
00719     */
00720     double deriv_const(size_t ix, double x0, size_t iy) const;
00721 
00722     /** \brief Make a new column \c yp which is 
00723         \f$ y^{\prime \prime}(x) \f$ - O(log(C)*R).
00724      */
00725     int deriv2(std::string x, std::string y, std::string yp);
00726 
00727     /** \brief The second derivative of the function sy(sx) at sx=x0.
00728 
00729         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if 
00730         the relevant columns are not well ordered.
00731     */
00732     double deriv2(std::string sx, double x0, std::string sy);
00733 
00734     /** \brief The second derivative of the function sy(sx) at sx=x0.
00735 
00736         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if 
00737         the relevant columns are not well ordered.
00738     */
00739     double deriv2_const(std::string sx, double x0, std::string sy) const;
00740 
00741     /** \brief The second derivative of the function iy(ix) at ix=x0.
00742 
00743         O(log(R)) but can be as bad as O(R) if 
00744         the relevant columns are not well ordered.
00745     */
00746     double deriv2(size_t ix, double x0, size_t iy);
00747 
00748     /** \brief The second derivative of the function iy(ix) at ix=x0.
00749 
00750         O(log(R)) but can be as bad as O(R) if 
00751         the relevant columns are not well ordered.
00752     */
00753     double deriv2_const(size_t ix, double x0, size_t iy) const;
00754 
00755     /** \brief The integral of the function sy(sx) from sx=x1 to sx=x2.
00756         
00757         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if 
00758         the relevant columns are not well ordered.
00759     */
00760     double integ(std::string sx, double x1, double x2, std::string sy);
00761   
00762     /** \brief The integral of the function sy(sx) from sx=x1 to sx=x2.
00763         
00764         O(log(C)*log(R)) but can be as bad as O(log(C)*R) if 
00765         the relevant columns are not well ordered.
00766     */
00767     double integ_const(std::string sx, double x1, double x2, 
00768                        std::string sy) const;
00769   
00770     /** \brief The integral of the function iy(ix) from ix=x1 to ix=x2.
00771 
00772         O(log(R)) but can be as bad as O(R) if 
00773         the relevant columns are not well ordered.
00774     */
00775     double integ(size_t ix, double x1, double x2, size_t iy);
00776 
00777     /** \brief The integral of the function iy(ix) from ix=x1 to ix=x2.
00778 
00779         O(log(R)) but can be as bad as O(R) if 
00780         the relevant columns are not well ordered.
00781     */
00782     double integ_const(size_t ix, double x1, double x2, size_t iy) const;
00783 
00784     /** \brief The integral of the function iy(ix) 
00785 
00786         O(log(R)) but can be as bad as O(R) if the relevant columns
00787         are not well ordered.
00788     */
00789     int integ(std::string x, std::string y, std::string ynew);
00790 
00791     /** \brief Return column maximum. Makes no assumptions about 
00792         ordering - O(R).
00793      */
00794     double max(std::string col) const;
00795 
00796     /** \brief Return column minimum. Makes no assumptions about 
00797         ordering - O(R).
00798      */
00799     double min(std::string col) const;
00800     //@}
00801 
00802     // --------------------------------------------------------
00803     /** \name Subtable method */
00804     //@{
00805 
00806     /** \brief Make a subtable
00807 
00808         Uses the columns specified in \c list from the row \c top
00809         to the row of index \c bottom to generate a new table
00810         which is a copy of part of the original.
00811     */
00812     table *subtable(std::string list, size_t top, size_t bottom) const;
00813     //@}
00814   
00815     // --------------------------------------------------------
00816     /** \name Add space */
00817     //@{
00818 
00819     /** \brief Manually increase the maximum number of lines
00820      */
00821     int inc_maxlines(size_t llines);
00822     //@}
00823 
00824     // --------------------------------------------------------
00825     /** \name Delete methods */
00826     //@{
00827 
00828     /** \brief Delete column named \c scol - O(C). 
00829     
00830         This is slow because the iterators in \ref alist are mangled
00831         and we have to call \ref reset_list() to get them back.
00832     */
00833     virtual int delete_column(std::string scol);
00834 
00835     /** \brief Delete the row with the entry closest to
00836         the value \c val in column \c scol - O(R*C)
00837      */
00838     int delete_row(std::string scol, double val);
00839 
00840     /** \brief Delete the row of index \c irow - O(R*C)
00841      */
00842     int delete_row(size_t irow);
00843     //@}
00844 
00845     // --------------------------------------------------------
00846     /** \name Clear methods */
00847     //@{
00848 
00849     /** \brief Zero the data entries but keep the column names 
00850         and nlines fixed
00851     */
00852     void zero_table();
00853 
00854     /** \brief Clear everything
00855      */
00856     void clear_all();
00857 
00858     /** \brief Clear the table and the column names (but leave constants)
00859      */
00860     void clear_table();
00861 
00862     /** \brief Remove all of the data by setting the number
00863         of lines to zero
00864 
00865         This leaves the column names intact and does not remove
00866         the constants.
00867      */
00868     void clear_data() {
00869       nlines=0;   
00870       if (intp_set==true) {
00871         delete si; 
00872         intp_set=false;
00873       }
00874       return;
00875     };
00876 
00877     /// CLear all constants
00878     void clear_constants() {
00879       constants.clear();
00880     }
00881     //@}
00882 
00883     // --------------------------------------------------------
00884     /** \name Sorting methods */
00885     //@{
00886 
00887     /** \brief Sort the entire table by the column \c scol
00888 
00889         \note This function works by allocating space for an entirely
00890         new chunk of memory for the data in the table.
00891 
00892         \todo Use vector_sort() rather than qsort().
00893      */
00894     int sort_table(std::string scol);
00895 
00896     /** \brief Individually sort the column \c scol
00897 
00898         \todo Use vector_sort() rather than qsort().
00899      */
00900     int sort_column(std::string scol);
00901     //@}
00902 
00903     // --------------------------------------------------------
00904     /** \name Summary method */
00905     //@{
00906     /** \brief Output a summary of the information stored
00907 
00908         Outputs the number of constants, the number of columns,
00909         a list of the column names, and the number of lines of
00910         data.
00911     */
00912     virtual int summary(std::ostream *out, int ncol=79) const;
00913     //@}
00914 
00915     /// \name Constant manipulation
00916     //@{
00917     /// Add a constant, or if the constant already exists, change its value
00918     virtual int add_constant(std::string name, double val);
00919 
00920     /// Add a constant
00921     virtual int set_constant(std::string name, double val,
00922                              bool err_on_notfound=true);
00923 
00924     /// Get a constant
00925     virtual double get_constant(std::string name) const {
00926       return constants.find(name)->second;
00927     }
00928 
00929     /// Get the number of constants
00930     virtual size_t get_nconsts() const {
00931       return constants.size();
00932     }
00933 
00934     /// Get a constant by index
00935     virtual int get_constant(size_t ix, std::string &name, double &val) const;
00936 
00937     /// Remove a constant
00938     virtual int remove_constant(std::string name) {
00939       constants.erase(name);
00940       return 0;
00941     }
00942     //@}
00943     
00944     /// \name Miscellaneous methods
00945     //@{
00946     /// Clear the current table and read from a generic data file
00947     int read_generic(std::istream &fin, int verbose=0);
00948 
00949     /** \brief Return 0 if the tree and list are properly synchronized
00950      */
00951     int check_synchro() const;
00952 
00953     /** \brief Get ownership - O(log(C)). 
00954      */
00955     bool get_owner(std::string name) const;
00956 
00957     //@}
00958 
00959     /// Default interpolation manager
00960     def_interp_mgr<ovector_const_view,cspline_interp> dim1;
00961 
00962     /// Default interpolation manager
00963     def_interp_mgr<ovector_const_subvector,cspline_interp> dim2;
00964 
00965     /// Return the type, \c "table".
00966     virtual const char *type() { return "table"; }
00967 
00968     /// True if the interpolation type has been set
00969     bool intp_set;
00970 
00971   protected:
00972 
00973 #ifndef DOXYGEN_INTERNAL
00974     
00975     /** \brief The list of constants 
00976      */
00977     std::map<std::string,double> constants;
00978 
00979     /** \brief Set the elements of alist with the appropriate 
00980         iterators from atree - O(C).
00981 
00982         Generally, the end-user shouldn't need this method. It is 
00983         only used in delete_column() to rearrange the list when
00984         a column is deleted from the tree.
00985     */
00986     int reset_list();
00987 
00988     /** \brief Ensure a variable name does not match a function or contain 
00989         non-alphanumeric characters
00990     */
00991     int make_fp_varname(std::string &s);
00992 
00993     /// Make sure a name is unique
00994     int make_unique_name(std::string &col, std::vector<std::string> &cnames);
00995 
00996     /** \brief Column structure for \ref table [protected]
00997 
00998         This struct is used internally by \ref table to organize the
00999         columns and need not be instantiated by the casual end-user.
01000      */
01001     typedef struct col_s {
01002       /// Pointer to column
01003       ovector_base *dat;
01004       /// Owner of column
01005       bool owner;
01006       /// Column index
01007       int index;
01008     } col;
01009     
01010     /// \name Iterator types
01011     //@{
01012     typedef std::map<std::string,col,string_comp>::iterator aiter;
01013     typedef std::map<std::string,col,string_comp>::const_iterator aciter;
01014     typedef std::vector<aiter>::iterator aviter;
01015     //@}
01016   
01017     /// \name Actual data
01018     //@{
01019     /// The size of allocated memory
01020     size_t maxlines;
01021     /// The size of presently used memory
01022     size_t nlines;
01023     /// The tree of columns
01024     std::map<std::string,col,string_comp> atree;
01025     /// The list of tree iterators
01026     std::vector<aiter> alist;
01027     //@}
01028   
01029     /// \name Column manipulation methods
01030     //@{
01031     /// Return the iterator for a column
01032     aiter get_iterator(std::string lname);
01033     /// Return the column structure for a column
01034     col *get_col_struct(std::string lname);
01035     /// Return the beginning of the column tree
01036     aiter begin() {return atree.begin();};
01037     /// Return the end of the column tree
01038     aiter end() {return atree.end();};
01039     //@}
01040 
01041     /// An empty vector for get_column()
01042     ovector empty_col;
01043 
01044     /// The sorting function
01045     static int sortd_comp(const void *a, const void *b);
01046 
01047     /** \brief A structure for sorting in \ref table [protected]
01048         
01049         This struct is used internally by \ref table to perform
01050         sorting and need not be instantiated by the casual end-user.
01051     */
01052     typedef struct sortd_s {
01053       /// Value to sort
01054       double val;
01055       /// Sorted index
01056       int indx;
01057     } sortd;
01058   
01059     /// \name Interpolation
01060     //@{
01061     /// The interpolation object
01062     sm_interp_vec *si;
01063 
01064     /// A pointer to the interpolation manager
01065     base_interp_mgr<ovector_const_view> *bim1;
01066     /// A pointer to the subvector interpolation manager
01067     base_interp_mgr<ovector_const_subvector> *bim2;
01068 
01069     /// The last x-column interpolated
01070     std::string intp_colx;
01071 
01072     /// The last y-column interpolated
01073     std::string intp_coly;
01074 
01075     //@}
01076 
01077 #endif
01078 
01079   };
01080 
01081 #ifndef DOXYGENP
01082 }
01083 #endif
01084 
01085 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.