table.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2017, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 #ifndef O2SCL_TABLE_H
24 #define O2SCL_TABLE_H
25 
26 /** \file table.h
27  \brief File defining \ref o2scl::table
28 */
29 
30 #include <iostream>
31 #include <fstream>
32 #include <string>
33 #include <cmath>
34 #include <sstream>
35 #include <map>
36 
37 #include <boost/numeric/ublas/vector.hpp>
38 #include <boost/numeric/ublas/matrix.hpp>
39 
40 #include <o2scl/misc.h>
41 #include <o2scl/interp.h>
42 
43 #include <o2scl/shunting_yard.h>
44 
45 #ifndef DOXYGEN_NO_O2NS
46 
47 // Forward definition of the table class for HDF I/O
48 namespace o2scl {
49  template<class vec_t> class table;
50 }
51 
52 // Forward definition of HDF I/O to extend friendship in table
53 namespace o2scl_hdf {
54  class hdf_file;
55  template<class vec_t>
56  void hdf_input(hdf_file &hf, o2scl::table<vec_t> &t, std::string name);
57  void hdf_output(hdf_file &hf,
58  o2scl::table<std::vector<double> > &t,
59  std::string name);
60  template<class vec_t>
62  void hdf_output_data(hdf_file &hf,
63  o2scl::table<std::vector<double> > &t);
64 }
65 
66 #endif
67 
68 #ifndef DOXYGEN_NO_O2NS
69 namespace o2scl {
70 #endif
71 
72  /** \brief Data \table class
73 
74  \b Summary \n
75 
76  A class to contain and manipulate several equally-sized columns
77  of data. The purpose of this class is to provide a structure
78  which allows one to refer to the columns using a name
79  represented by a string. Thus for a table object named \c t with
80  3 columns (named "colx", "coly" and "colz") and three rows, one
81  could do the following:
82  \include table_doc1.cpp
83  Note that the rows are numbered starting with 0 instead of
84  starting with 1.
85  To output all the rows of entire column, one can use
86  \include table_doc2.cpp
87  To output all the columns of an entire row (in the following
88  example it is the second row), labeled by their column name, one
89  can use:
90  \include table_doc3.cpp
91 
92  Methods are provided for interpolating columns, sorting
93  columns, finding data points, and several other manipulations
94  of the data.
95 
96  \b Column \b size \n
97 
98  The columns grow automatically (similar to the STL <vector>)
99  in reponse to an attempt to call set() for a row that does not
100  presently exist or in a call to line_of_data() when the table is
101  already full. However, this forces memory rearrangments that are
102  expensive, O(R*C). If the user has a good estimate of the number
103  of rows beforehand, it is best to either specify this in the
104  constructor, or in an explicit call to inc_maxlines().
105 
106  <B> Lookup, differentiation, integration, and
107  interpolation </b> \n
108 
109  Lookup, differentiation, integration, and interpolation are
110  automatically implemented using splines from the class \ref
111  interp_vec. A caching mechanism is implemented so that
112  successive interpolations, derivative evaluations or
113  integrations over the same two columns are fast.
114 
115  <B> Sorting </b>\n
116 
117  The columns are automatically sorted by name for speed, the
118  results can be accessed from \ref get_sorted_name(). Individual
119  columns can be sorted (\ref sort_column() ), or the entire table
120  can be sorted by one column (\ref sort_table() ).
121 
122  <B> Data representation </b> \n
123 
124  Each individual column is just a vector object.
125  The columns can be referred to in one of two ways:
126  - A numerical index from 0 to C-1 (where C is the number of
127  columns). For example, data can be accessed through \ref
128  table::get() and \ref table::set(size_t c, size_t r,
129  double val), or the overloaded [] operator, <tt>table[c][r]</tt>.
130  - A name of the column which is a string.
131  For example, data can be accessed with table::get(string cname,
132  int r) and table::set(string cname, int r, double val).
133 
134  The columns are organized in a both a <map> and a <vector>
135  structure so that finding a column by its index, using either of
136  \code
137  std::string table::get_column_name(size_t index);
138  ubvector &table::operator[](size_t index);
139  \endcode
140  takes only constant time, and finding a column by its name
141  using either of
142  \code
143  size_t lookup_column(std::string name) const;
144  const ubvector &get_column(std::string col) const;
145  \endcode
146  is O(log(C)). Insertion of a column ( \ref new_column() ) is
147  O(log(C)), but deletion ( \ref delete_column() ) is O(C). Adding
148  a row of data can be either O(1) or O(C), but row insertion and
149  deletion is slow, since the all of the rows must be shifted
150  accordingly.
151 
152  Because of the structure, this class is not suitable for the
153  matrix manipulation.
154 
155  <b>Vector types</b> \n
156 
157  The type <tt>vec_t</tt> can be any vector type with
158  <tt>operator[]</tt>, <tt>size()</tt> and <tt>resize()</tt>
159  methods. HDF5 I/O with vector types other than
160  <tt>std::vector<double> </tt> requires a copy. See the
161  the discussion in the sections \ref tensor_subsect
162  and \ref vec_io_cont_subsect of the user's guide for
163  more details.
164 
165  <b>Thread-safety</b> \n
166 
167  Generally, the member functions are only thread-safe
168  if they are <tt>const</tt> .
169 
170  \b I/O \b and \b command-line \b manipulation \n
171 
172  When data from an object of type \ref table is output to a file
173  through the <tt>hdf_output() function</tt> in \ref o2scl_hdf,
174  the table can be manipulated on the command-line through the \c
175  acol utility (see \ref acol_section).
176 
177  There is an example for the usage of this class given
178  in <tt>examples/ex_table.cpp</tt>.
179 
180  \future
181  - Create a sort_column_names() or a function to
182  arbitrarily rearrange the columns
183  - The present structure, \c
184  std::map<std::string,col,string_comp> atree and \c
185  std::vector<aiter> alist; could be replaced with \c
186  std::vector<col> list and \c std::map<std::string,int> tree
187  where the map just stores the index of the the column in the
188  list.
189  - Rewrite check_synchro into a full is_valid()-like
190  sanity check
191  */
192  template<class vec_t=std::vector<double> > class table {
193 
194  public:
195 
196  /// \name Constructors, destructors
197  //@{
198  /** \brief Create a new table with space for nlines<=cmaxlines.
199  */
200  table(size_t cmaxlines=0) {
201  nlines=0;
202  intp_set=false;
203  maxlines=cmaxlines;
204  itype=itp_cspline;
205  }
206 
207  virtual ~table() {
208  if (intp_set==true) {
209  delete si;
210  }
211  }
212 
213  /// Copy constructor
214  table(const table &t) {
215 
216  // Copy constants
217  size_t nc=t.get_nconsts();
218  for(size_t i=0;i<nc;i++) {
219  std::string name;
220  double val;
221  t.get_constant(i,name,val);
222  constants.insert(make_pair(name,val));
223  }
224 
225  // Copy interpolation type
226  itype=t.itype;
227 
228  // Copy the columns and data
229  nlines=t.get_nlines();
230  maxlines=nlines;
231 
232  for(size_t i=0;i<t.get_ncolumns();i++) {
233 
234  // Column name
235  std::string cname=t.get_column_name(i);
236 
237  // Insert column into tree
238  col s;
239  s.dat.resize(nlines);
240  s.index=atree.size();
241  atree.insert(make_pair(cname,s));
242 
243  // Insert in iterator index
244  aiter it=atree.find(cname);
245  alist.push_back(it);
246 
247  // Fill the data
248  for(size_t j=0;j<t.get_nlines();j++) {
249  it->second.dat[j]=t.get(cname,j);
250  }
251 
252  }
253 
254  intp_set=false;
255 
256  return;
257  }
258 
259  /// Copy constructor
260  table &operator=(const table &t) {
261 
262  if (this!=&t) {
263 
264  clear_table();
265  constants.clear();
266 
267  // Copy constants
268  size_t nc=t.get_nconsts();
269  for(size_t i=0;i<nc;i++) {
270  std::string name;
271  double val;
272  t.get_constant(i,name,val);
273  constants.insert(make_pair(name,val));
274  }
275 
276  // Copy the columns and data
277  nlines=t.get_nlines();
278  maxlines=nlines;
279 
280  // Copy interpolation type
281  itype=t.itype;
282 
283  for(size_t i=0;i<t.get_ncolumns();i++) {
284 
285  // Column name
286  std::string cname=t.get_column_name(i);
287 
288  // Insert column into tree
289  col s;
290  s.dat.resize(nlines);
291  s.index=atree.size();
292  atree.insert(make_pair(cname,s));
293 
294  // Insert in iterator index
295  aiter it=atree.find(cname);
296  alist.push_back(it);
297 
298  // Fill the data
299  for(size_t j=0;j<t.get_nlines();j++) {
300  it->second.dat[j]=t.get(cname,j);
301  }
302 
303  }
304 
305  if (intp_set) {
306  intp_set=false;
307  delete si;
308  }
309 
310  }
311 
312  return *this;
313  }
314  //@}
315 
316  // --------------------------------------------------------
317  /** \name Basic get and set methods */
318  //@{
319  /** \brief Set row \c row of column named \c col to value \c val .
320  \f$ {\cal O}(\log(C)) \f$
321 
322  This function adds the column \c col if it does not already
323  exist and adds rows using inc_maxlines() and set_nlines() to
324  create at least <tt>row+1</tt> rows if they do not already
325  exist.
326  */
327  void set(std::string scol, size_t row, double val) {
328  if (!std::isfinite(val)) {
329  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
330  "' not finite for column '"+
331  scol+"' in table::set(string,size_t,double)").c_str(),
332  exc_einval);
333  return;
334  }
335 
336  if (maxlines==0) inc_maxlines(row+1);
337  while(row>maxlines-1) inc_maxlines(maxlines);
338  if (row>=nlines) set_nlines_auto(row+1);
339 
340  if ((intp_colx==scol || intp_coly==scol) && intp_set==true) {
341  delete si;
342  intp_set=false;
343  }
344 
345  aiter it=atree.find(scol);
346  if (it==atree.end()) {
347  new_column(scol);
348  it=atree.find(scol);
349  }
350  if (it==atree.end()) {
351  O2SCL_ERR((((std::string)"Refused to add column '")+scol+
352  "' in table::set(string,size_t,double).").c_str(),
353  exc_enotfound);
354  return;
355  }
356 
357  it->second.dat[row]=val;
358  return;
359  }
360 
361  /** \brief Set row \c row of column number \c icol to value \c val .
362  \f$ {\cal O}(1) \f$
363  */
364  void set(size_t icol, size_t row, double val) {
365  if (!std::isfinite(val)) {
366  if (icol>=get_ncolumns()) {
367  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
368  "' not finite and index "+szttos(icol)+
369  " too large in table::set(size_t,size_t,double)").c_str(),
370  exc_einval);
371  }
372  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
373  "' not finite for column '"+get_column_name(icol)+
374  "' in table::set(size_t,size_t,double)").c_str(),
375  exc_einval);
376  }
377  if (icol>=atree.size()) {
378  std::string err=((std::string)"Column out of range, ")+szttos(icol)+
379  ">="+szttos(atree.size())+", in table::set(size_t,size_t,double).";
380  O2SCL_ERR(err.c_str(),exc_einval);
381  }
382 
383  while(row>maxlines-1) inc_maxlines(maxlines);
384  if (row>=nlines) set_nlines_auto(row+1);
385 
386  std::string scol=get_column_name(icol);
387  if ((intp_colx==scol || intp_coly==scol) && intp_set==true) {
388  delete si;
389  intp_set=false;
390  }
391 
392  alist[icol]->second.dat[row]=val;
393  return;
394  }
395 
396  /** \brief Set an entire row of data
397 
398  The type <tt>size_vec_t</tt> must be a type which has a
399  <tt>size()</tt> method.
400  */
401  template<class size_vec_t> void set_row(size_t row, size_vec_t &v) {
402  if (row>=get_nlines()) {
403  O2SCL_ERR("Row not found in table::set_line().",o2scl::exc_einval);
404  }
405  for(size_t i=0;i<get_ncolumns() && i<v.size();i++) {
406  alist[i]->second.dat[row]=v[i];
407  }
408  return;
409  }
410 
411  /** \brief Get value from row \c row of column named \c col.
412  \f$ {\cal O}(\log(C)) \f$
413  */
414  double get(std::string scol, size_t row) const {
415  double tmp;
416  aciter it=atree.find(scol);
417  if (it==atree.end()) {
418  O2SCL_ERR((((std::string)"Column '")+scol+
419  "' not found in table::get().").c_str(),
420  exc_enotfound);
421  tmp=0.0;
422  } else {
423  tmp=it->second.dat[row];
424  }
425  return tmp;
426  }
427 
428  /** \brief Get value from row \c row of column number \c icol.
429  \f$ {\cal O}(1) \f$
430  */
431  double get(size_t icol, size_t row) const {
432  if (icol>=atree.size()) {
433  std::string err=((std::string)"Column out of range, ")+
434  itos(icol)+">="+itos(atree.size())+", in table::get(size_t,size_t).";
435  O2SCL_ERR(err.c_str(),exc_einval);
436  return 0.0;
437  }
438  if (row>=nlines) {
439  std::string err=((std::string)"Column out of range, ")+
440  itos(row)+">="+itos(nlines)+", in table::get(size_t,size_t).";
441  O2SCL_ERR(err.c_str(),exc_einval);
442  return 0.0;
443  }
444  return alist[icol]->second.dat[row];
445  }
446 
447  /** \brief Return the number of columns
448  */
449  size_t get_ncolumns() const {return atree.size();};
450  //@}
451 
452  // --------------------------------------------------------
453  /** \name Manipulate current and maximum number of rows */
454  //@{
455  /** \brief Return the number of lines
456  */
457  size_t get_nlines() const {return nlines;};
458 
459  /** \brief Set the number of lines
460 
461  This function is stingy about increasing the table memory
462  space and will only increase it enough to fit \c il lines.
463  Using it in succession to slowly increase the number of lines
464  in the table is likely to be inefficient compared to \ref
465  set_nlines_auto() in this case.
466  */
467  void set_nlines(size_t il) {
468 
469  // Try to increase the number of lines
470  if (il>maxlines) {
471  inc_maxlines(il-maxlines);
472  }
473 
474  // Now that maxlines is large enough, set the number of lines
475  nlines=il;
476 
477  // Reset the interpolation object for future interpolations
478  if (intp_set) {
479  intp_set=false;
480  delete si;
481  }
482 
483  return;
484  }
485 
486  /** \brief Return the maximum number of lines before a reallocation
487  is required
488  */
489  size_t get_maxlines() {return maxlines; };
490 
491  /** \brief Returns a copy of the row with value \c val in column
492  \c col. \f$ {\cal O}(R C) \f$
493 
494  This function searches the entire table for the row which has
495  the entry in column \c col which is closest to the value \c
496  val, and copies that row to the vector \c row.
497 
498  If the object \c row previously contains any data, it will be
499  lost.
500 
501  The type <tt>resize_vec_t</tt> must be a type which has
502  <tt>size()</tt> and <tt>resize()</tt> methods.
503  */
504  template<class resize_vec_t>
505  void get_row(std::string scol, double val, resize_vec_t &row) const {
506 
507  int irow=lookup(scol,val);
508  if (irow==exc_enotfound) {
509  O2SCL_ERR((((std::string)"Column '")+scol+
510  "' not found in table::get_row() const.").c_str(),
511  exc_enotfound);
512  return;
513  }
514  get_row(irow,row);
515  return;
516  }
517 
518  /** \brief Returns a copy of row number \c irow. \f$ {\cal O}(C) \f$
519 
520  This function returns a copy of row with index \c irow,
521  where \c irow ranges from 0 to <tt>get_nlines()-1</tt>,
522  inclusive.
523 
524  If the object \c row previously contains any data, it will be
525  lost.
526 
527  The type <tt>resize_vec_t</tt> must be a type which has
528  <tt>size()</tt> and <tt>resize()</tt> methods.
529  */
530  template<class resize_vec_t>
531  void get_row(size_t irow, resize_vec_t &row) const {
532 
533  if (irow+1>nlines) {
534  O2SCL_ERR((((std::string)"Row '")+ itos(irow)+
535  "' not found in table::get_row().").c_str(),
536  exc_enotfound);
537  return;
538  }
539 
540  int i;
541  aciter it;
542  row.allocate(atree.size());
543  for(i=0,it=atree.begin();it!=atree.end();it++,i++) {
544  row[i]=(it->second.dat)[irow];
545  }
546  return;
547  }
548 
549  /** \brief Set the number of lines, increasing the size more
550  agressively
551 
552  This function is like set_nlines(), but doubles the maximum
553  column size if an increase in the maximum size is required
554  instead of simply making enough room for the current number of
555  lines. This function is used internally by \ref set() to
556  ensure that the cost of setting lines in sequence is linear
557  and not quadratic.
558  */
559  void set_nlines_auto(size_t il) {
560 
561  // Try to increase the number of lines
562  if (il>maxlines) {
563  size_t inc=il-maxlines;
564  if (inc<maxlines) inc=maxlines;
565  inc_maxlines(inc);
566  }
567 
568  // Now that maxlines is large enough, set the number of lines
569  nlines=il;
570 
571  // Reset the interpolation object for future interpolations
572  if (intp_set) {
573  intp_set=false;
574  delete si;
575  }
576 
577  return;
578  }
579 
580  /** \brief Manually increase the maximum number of lines
581  */
582  void inc_maxlines(size_t llines) {
583 
584  vec_t temp_col;
585 
586  // For the moment, we assume resizes are destructive, so
587  // we have to copy the data to a temporary and then
588  // copy it back
589  for(aiter it=atree.begin();it!=atree.end();it++) {
590 
591  // Copy data to temporary array
592  temp_col.resize(maxlines+llines);
593  for(size_t j=0;j<maxlines;j++) {
594  temp_col[j]=it->second.dat[j];
595  }
596 
597  // Resize
598  it->second.dat.resize(maxlines+llines);
599 
600  // Copy data back to resized array
601  for(size_t j=0;j<maxlines;j++) {
602  it->second.dat[j]=temp_col[j];
603  }
604 
605  }
606 
607  maxlines+=llines;
608 
609  return;
610  }
611  //@}
612 
613  // --------------------------------------------------------
614  /** \name Column manipulation */
615  //@{
616  /** \brief Returns a reference to the column named \c col.
617  \f$ {\cal O}(\log(C)) \f$
618  */
619  const vec_t &get_column(std::string scol) const {
620  aciter it=atree.find(scol);
621  if (it==atree.end()) {
622  O2SCL_ERR((((std::string)"Column '")+scol+
623  "' not found in table::get_column() const.").c_str(),
624  exc_enotfound);
625  return empty_col;
626  }
627  return it->second.dat;
628  }
629 
630  /** \brief Returns the column of index \c icol (const
631  version). \f$ {\cal O}(1) \f$
632 
633  Note that several of the methods require reallocation of
634  memory and refereces previously returned by this function will
635  be incorrect.
636 
637  Unlike set(), this function will not automatically result in
638  an increase in the size of the table if the user attempts to
639  set an element beyond the current column range.
640 
641  This function will throw an exception if \c icol is out
642  of range unless <tt>O2SCL_NO_RANGE_CHECK</tt> is defined.
643  */
644  const vec_t &operator[] (size_t icol) const {
645 #if !O2SCL_NO_RANGE_CHECK
646  if (icol>=atree.size()) {
647  O2SCL_ERR((((std::string)"Array index ")+szttos(icol)+
648  " out of bounds"+
649  " in table::operator[size_t] const. Size: "+
650  szttos(atree.size())+
651  " (index should be less than size).").c_str(),exc_eindex);
652  return empty_col;
653  }
654 #endif
655  return (alist[icol]->second.dat);
656  }
657 
658  /** \brief Returns the column named \c scol (const version).
659  \f$ {\cal O}(\log(C)) \f$
660 
661  Note that several of the methods require reallocation of
662  memory and refereces previously returned by this function will
663  be incorrect.
664 
665  Unlike set(), this function will not automatically result in
666  an increase in the size of the table if the user attempts to
667  set an element beyond the current column range.
668 
669  This function will throw an exception if \c icol is out
670  of range unless <tt>O2SCL_NO_RANGE_CHECK</tt> is defined.
671  */
672  const vec_t &operator[](std::string scol) const {
673  aciter it=atree.find(scol);
674 #if !O2SCL_NO_RANGE_CHECK
675  if (it==atree.end()) {
676  O2SCL_ERR((((std::string)"Column '")+scol+"' not found in table::"+
677  "operator[string] const.").c_str(),exc_enotfound);
678  return empty_col;
679  }
680 #endif
681  return (it->second.dat);
682  }
683 
684  /** \brief Add a new column owned by the \table \f$ {\cal O}(\log(C)) \f$
685 
686  \note This function does not set all the column entries to
687  zero in the case that a new column is added to a table which
688  already contains data.
689  */
690  void new_column(std::string head) {
691  if (head.length()==0) {
692  O2SCL_ERR2("Cannot add column with empty name in ",
693  "table::new_column().",exc_einval);
694  }
695  if (is_column(head)==true) {
696  O2SCL_ERR((((std::string)"Column '")+head+
697  "' already present in table::new_column().").c_str(),
698  exc_einval);
699  }
700  for(int i=0;i<((int)head.size());i++) {
701  if (head[i]==' ' || head[i]=='\t' || head[i]=='\n' || head[i]=='\r'
702  || head[i]=='\v' || head[i]=='\f') {
703  O2SCL_ERR((((std::string)"Invalid column name '")+head+
704  "' in table::new_column().").c_str(),
705  exc_einval);
706  }
707  }
708  col s;
709  s.dat.resize(maxlines);
710  s.index=((int)atree.size());
711  atree.insert(make_pair(head,s));
712  aiter it=atree.find(head);
713  alist.push_back(it);
714  return;
715  }
716 
717  /** \brief Add a new column by copying data from another vector
718 
719  This function copies \c sz elements of vector \c v into the
720  table in a new column named \c name. If \c sz is larger than
721  the current number of lines (as given, e.g. in \ref
722  get_nlines() ), then only the first part of the vector \c v is
723  copied, up to the current number of lines.
724 
725  This function calls the error handler if \c sz is zero.
726 
727  The type <tt>vec2_t</tt> can be any type with an
728  <tt>operator[]</tt> method.
729  */
730  template<class vec2_t> int new_column(std::string name,
731  size_t sz, vec2_t &v) {
732 
733  if (sz==0) {
734  O2SCL_ERR2("Sent column of zero size in ",
735  "table::new_column(string,size_t,vec2_t)",
736  exc_einval);
737  }
738 
739  // Create the space
740  int ret=new_column(name);
741  if (ret!=0) return ret;
742 
743  // Copy the data over
744  size_t mxl=sz;
745  if (sz>get_nlines()) mxl=get_nlines();
746  for(size_t i=0;i<mxl;i++) {
747  set(name,i,v[i]);
748  }
749 
750  return 0;
751  }
752 
753  /** \brief Returns the name of column \c col \f$ {\cal O}(1) \f$
754 
755  This will throw if \c icol is larger than or equal to
756  the number of columns.
757  */
758  std::string get_column_name(size_t icol) const {
759  if (icol+1>atree.size()) {
760  O2SCL_ERR((((std::string)"Index '")+o2scl::itos(icol)+
761  " larger than number of "+
762  "columns in table::get_column_name().").c_str(),
763  exc_enotfound);
764  }
765  return alist[icol]->first;
766  }
767 
768  /** \brief Swap the data in column \c scol with that in vector \c v
769 
770  This requires that the column \c v must have the correct size,
771  that returned by \ref get_maxlines().
772 
773  This function is useful, in part, because if objects of type
774  <tt>vec_t</tt> have <tt>std::move</tt> defined, then the swap
775  doesn't require a full copy.
776  */
777  virtual void swap_column_data(std::string scol, vec_t &v) {
778  aiter its=atree.find(scol);
779  if (its==atree.end()) {
780  O2SCL_ERR((((std::string)"Column '")+scol+
781  " not found in table::swap_column_data().").c_str(),
782  exc_enotfound);
783  return;
784  }
785  if (v.size()!=its->second.dat.size()) {
786  O2SCL_ERR2("Vector sizes not commensurate in ",
787  "table::swap_column_data().",exc_einval);
788  }
789  std::swap(its->second.dat,v);
790  return;
791  }
792 
793  /** \brief Rename column named \c src to \c dest
794  \f$ {\cal O}(C) \f$
795  */
796  virtual void rename_column(std::string src, std::string dest) {
797  aiter its=atree.find(src);
798  if (its==atree.end()) {
799  O2SCL_ERR((((std::string)"Column '")+src+
800  " not found in table::rename_column().").c_str(),
801  exc_enotfound);
802  return;
803  }
804  new_column(dest);
805  aiter itd=atree.find(dest);
806  std::swap(its->second.dat,itd->second.dat);
807  delete_column(src);
808  return;
809  }
810 
811  /** \brief Delete column named \c scol \f$ {\cal O}(C) \f$
812 
813  This is slow because the iterators in \ref alist are mangled
814  and we have to call \ref reset_list() to get them back.
815  */
816  virtual void delete_column(std::string scol) {
817 
818  // Find the tree iterator for the element we want to erase
819  aiter it=atree.find(scol);
820  if (it==atree.end()) {
821  O2SCL_ERR((((std::string)"Column '")+scol+
822  " not found in table::delete_column().").c_str(),
823  exc_enotfound);
824  return;
825  }
826 
827  // Find the corresponding list iterator
828  aviter vit=alist.begin();
829  vit+=it->second.index;
830 
831  // Find the last element in the list and it's corresponding table
832  // entry. Change it's index to the index of the column to be
833  // deleted.
834  alist[alist.size()-1]->second.index=it->second.index;
835 
836  // Erase the elements from the list and the tree
837  atree.erase(it);
838  alist.erase(vit);
839 
840  // Reset the list to reflect the proper iterators
841  reset_list();
842 
843  if ((intp_colx==scol || intp_coly==scol) && intp_set==true) {
844  delete si;
845  intp_set=false;
846  }
847 
848  return;
849  }
850 
851  /** \brief Returns the name of column \c col in sorted order.
852  \f$ {\cal O}(1) \f$
853  */
854  std::string get_sorted_name(size_t icol) const {
855  if (icol+1>atree.size()) {
856  return "";
857  }
858  aciter it=atree.begin();
859  for(size_t i=0;i<icol;i++) it++;
860  return it->first;
861  }
862 
863  /** \brief Initialize all values of column named \c scol to \c val
864  \f$ {\cal O}(R \log(C)) \f$
865 
866  Note that this does not initialize elements beyond nlines so
867  that if the number of rows is increased afterwards, the new
868  rows will have uninitialized values.
869  */
870  void init_column(std::string scol, double val) {
871  if (!std::isfinite(val)) {
872  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
873  "' not finite for column '"+
874  scol+"' in table::init_column()").c_str(),exc_einval);
875  return;
876  }
877  aiter it=atree.find(scol);
878  if (it==atree.end()) {
879  O2SCL_ERR((((std::string)"Column '")+scol+
880  "' not found in table::init_column()").c_str(),
881  exc_enotfound);
882  return;
883  }
884  for(size_t i=0;i<nlines;i++) {
885  it->second.dat[i]=val;
886  }
887  if (intp_set && (scol==intp_colx || scol==intp_coly)) {
888  intp_set=false;
889  delete si;
890  }
891  return;
892  }
893 
894  /** \brief Return true if \c scol is a column in the current \table
895 
896  This function does not call the error handler if the column is
897  not found, but just silently returns false.
898  */
899  bool is_column(std::string scol) const {
900  aciter it=atree.find(scol);
901  if (it==atree.end()) return false;
902  return true;
903  }
904 
905  /** \brief Find the index for column named \c name
906  \f$ {\cal O}(\log(C)) \f$
907 
908  If the column is not present, this function calls the error
909  handler.
910  */
911  size_t lookup_column(std::string lname) const {
912  aciter it=atree.find(lname);
913  if (it==atree.end()) {
914  O2SCL_ERR("Column not found in table::lookup_column().",
915  exc_enotfound);
916  }
917  return it->second.index;
918  }
919 
920  /** \brief Copy data from column named \c src to column
921  named \c dest, creating a new column if necessary
922  \f$ {\cal O}(R \log(C)) \f$
923  */
924  virtual void copy_column(std::string src, std::string dest) {
925  if (!is_column(dest)) new_column(dest);
926  aiter its=atree.find(src);
927  if (its==atree.end()) {
928  O2SCL_ERR((((std::string)"Column '")+src+
929  " not found in table::copy_column().").c_str(),
930  exc_enotfound);
931  return;
932  }
933  aiter itd=atree.find(dest);
934  if (itd==atree.end()) {
935  O2SCL_ERR((((std::string)"Destination column '")+dest+
936  " not found in table::copy_column().").c_str(),
937  exc_esanity);
938  return;
939  }
940  for(size_t i=0;i<nlines;i++) {
941  itd->second.dat[i]=its->second.dat[i];
942  }
943  return;
944  }
945 
946  /** \brief Copy a column to a generic vector object
947 
948  \note It is assumed that the vector type is one that can be
949  resized with <tt>resize()</tt>.
950  */
951  template<class resize_vec_t>
952  void column_to_vector(std::string scol, resize_vec_t &v) const {
953  v.resize(nlines);
954  for(size_t i=0;i<nlines;i++) {
955  v[i]=this->get(scol,i);
956  }
957  return;
958  }
959 
960  /** \brief Copy to a column from a generic vector object
961 
962  The type <tt>vec2_t</tt> can be any type with an
963  <tt>operator[]</tt> method.
964  */
965  template<class vec2_t>
966  void copy_to_column(vec2_t &v, std::string scol) {
967  for(size_t i=0;i<nlines;i++) {
968  this->set(scol,i,v[i]);
969  }
970  return;
971  }
972 
973  /** \brief Insert a column from a separate table, interpolating
974  it into a new column
975 
976  Given a pair of columns ( \c src_index, \c src_col ) in a
977  separate table (\c source), this creates a new column in the
978  present table named \c src_col which interpolates \c loc_index
979  into \c src_index. The interpolation objects from the \c
980  source table will be used. If there is already a column in the
981  present table named \c src_col, then this will fail.
982  */
983  template<class vec2_t>
985  std::string src_index, std::string src_col,
986  std::string dest_index, std::string dest_col="") {
987 
988  if (dest_col=="") dest_col=src_col;
989 
990  // Add the new column
991  if (!is_column(dest_col)) new_column(dest_col);
992 
993  // Fill the new column
994  for(size_t i=0;i<nlines;i++) {
995  set(dest_col,i,source.interp(src_index,get(dest_index,i),src_col));
996  }
997 
998  return;
999  }
1000  //@}
1001 
1002  /** \brief Insert columns from a source table into the new
1003  table by interpolation (or extrapolation)
1004  */
1005  template<class vec2_t>
1006  void insert_table(table<vec2_t> &source, std::string src_index,
1007  bool allow_extrap=true, std::string dest_index="") {
1008 
1009  if (dest_index=="") dest_index=src_index;
1010 
1011  // Find limits to avoid extrapolation if necessary
1012  double min=source.min(src_index);
1013  double max=source.max(src_index);
1014  if (allow_extrap==false) {
1015  if (!std::isfinite(min) || !std::isfinite(max)) {
1016  O2SCL_ERR2("Minimum or maximum of source index not finite ",
1017  "in table::insert_table().",exc_einval);
1018  }
1019  }
1020 
1021  // Create list of columns to interpolate
1022  std::vector<std::string> col_list;
1023  for(size_t i=0;i<source.get_ncolumns();i++) {
1024  std::string col=source.get_column_name(i);
1025  if (col!=src_index && col!=dest_index && is_column(col)==false) {
1026  col_list.push_back(col);
1027  }
1028  }
1029 
1030  // Create new columns and perform interpolation
1031  for(size_t i=0;i<col_list.size();i++) {
1032  new_column(col_list[i]);
1033  for(size_t j=0;j<get_nlines();j++) {
1034  double val=get(dest_index,j);
1035  if (allow_extrap || (val>=min && val<=max)) {
1036  set(col_list[i],j,source.interp(src_index,val,col_list[i]));
1037  }
1038  }
1039  }
1040 
1041  return;
1042  }
1043 
1044  // --------------------------------------------------------
1045  /** \name Row maninpulation and data input */
1046  //@{
1047 
1048  /** \brief Insert a row before row \c n
1049 
1050  Acceptable values for \c n are between 0 and
1051  <tt>get_nlines()</tt> inclusive, with the maximum value
1052  denoting the addition of a row after the last row presently in
1053  the table.
1054  */
1055  void new_row(size_t n) {
1056  if (nlines>=maxlines) inc_maxlines(maxlines);
1057 
1058  nlines++;
1059  for(int i=((int)nlines)-2;i>=((int)n);i--) {
1060  copy_row(i,i+1);
1061  }
1062 
1063  if (intp_set) {
1064  intp_set=false;
1065  delete si;
1066  }
1067 
1068  return;
1069  }
1070 
1071  /** \brief Copy the data in row \c src to row \c dest
1072  */
1073  void copy_row(size_t src, size_t dest) {
1074  for(int i=0;i<((int)atree.size());i++) {
1075  set(i,dest,get(i,src));
1076  }
1077  if (intp_set) {
1078  intp_set=false;
1079  delete si;
1080  }
1081  return;
1082  }
1083 
1084  /** \brief Delete the row with the entry closest to
1085  the value \c val in column \c scol \f$ {\cal O}(R C) \f$
1086  */
1087  void delete_row(std::string scol, double val) {
1088  // If lookup() fails, it will throw an exception,
1089  // so there's no need to double-check it here
1090  size_t irow=lookup(scol,val);
1091  delete_row(irow);
1092  return;
1093  }
1094 
1095  /** \brief Delete the row of index \c irow \f$ {\cal O}(R C) \f$
1096  */
1097  void delete_row(size_t irow) {
1098  for(aiter it=atree.begin();it!=atree.end();it++) {
1099  // Can't do size_t because we have to compare to nlines-1
1100  for(int i=((int)irow);i<((int)nlines)-1;i++) {
1101  it->second.dat[i]=it->second.dat[i+1];
1102  }
1103  }
1104  nlines--;
1105  if (intp_set==true) {
1106  delete si;
1107  intp_set=false;
1108  }
1109  return;
1110  }
1111 
1112  /** \brief Delete all rows where \c func evaluates to a number greater
1113  than 0.5 \f$ {\cal O}(R C) \f$
1114 
1115  If no rows match the delete condition, this function silently
1116  performs no changes to the table.
1117  */
1118  void delete_rows(std::string func) {
1119  size_t new_nlines=0;
1120  for(size_t i=0;i<nlines;i++) {
1121  double val=row_function(func,i);
1122  if (val<0.5) {
1123  // If val<0.5, then the function was evaluated to false and
1124  // we want to keep the row, but if i==new_nlines, then
1125  // we don't need to copy because the row is already in
1126  // the correct place.
1127  if (i!=new_nlines) {
1128  for(aiter it=atree.begin();it!=atree.end();it++) {
1129  it->second.dat[new_nlines]=it->second.dat[i];
1130  }
1131  }
1132  new_nlines++;
1133  }
1134  }
1135  nlines=new_nlines;
1136  if (intp_set==true) {
1137  delete si;
1138  intp_set=false;
1139  }
1140  return;
1141  }
1142 
1143  /** \brief Copy all rows matching a particular condition to
1144  a new table
1145 
1146  This function begins by ensuring that all columns in the current
1147  table are present in \c dest, creating new columns in \c dest if
1148  necessary. It then copies all rows where \c func evaluates to a
1149  number greater than 0.5 to table \c dest by adding rows at
1150  the end of the table.
1151  */
1152  template<class vec2_t>
1153  void copy_rows(std::string func, table<vec2_t> &dest) {
1154 
1155  // Set up columns
1156  for(size_t i=0;i<get_ncolumns();i++) {
1157  std::string cname=get_column_name(i);
1158  if (dest.is_column(cname)==false) {
1159  dest.new_column(cname);
1160  }
1161  }
1162 
1163  size_t new_lines=dest.get_nlines();
1164  for(size_t i=0;i<nlines;i++) {
1165  double val=row_function(func,i);
1166  if (val>0.5) {
1167  dest.set_nlines_auto(new_lines+1);
1168  for(size_t j=0;j<get_ncolumns();j++) {
1169  std::string cname=get_column_name(j);
1170  dest.set(cname,new_lines);
1171  }
1172  new_lines++;
1173  }
1174  }
1175 
1176  return;
1177  }
1178 
1179  /** \brief Delete all rows between \c row_start and \c row_end
1180  \f$ {\cal O}(R C) \f$
1181 
1182  If <tt>row_start</tt> is less or equal to <tt>row_end</tt>,
1183  then all rows beginnning with <tt>row_start</tt> and
1184  ending with <tt>row_end</tt> are deleted (inclusive). If
1185  <tt>row_start</tt> is greater than <tt>row_end</tt>, then
1186  rows from the start of the table until <tt>row_end</tt> are
1187  deleted, as well as all rows from <tt>row_start</tt>
1188  through the end of the table.
1189 
1190  If either <tt>row_start</tt> or <tt>row_end</tt> are beyond the
1191  end of the table (greater than or equal to the value given by
1192  \ref get_nlines() ), an exception is thrown.
1193  */
1194  void delete_rows(size_t row_start, size_t row_end) {
1195  if (row_start>=nlines || row_end>=nlines) {
1196  O2SCL_ERR2("Row specifications beyond end of table in ",
1197  "table::delete_rows(size_t,size_t).",exc_einval);
1198  }
1199  size_t new_nlines=0;
1200  for(size_t i=0;i<nlines;i++) {
1201  if ((row_start<=row_end && (i<row_start || i>row_end)) ||
1202  (row_start>row_end && (i<row_start && i>row_end))) {
1203  for(aiter it=atree.begin();it!=atree.end();it++) {
1204  it->second.dat[new_nlines]=it->second.dat[i];
1205  }
1206  new_nlines++;
1207  }
1208  }
1209  nlines=new_nlines;
1210  if (intp_set==true) {
1211  delete si;
1212  intp_set=false;
1213  }
1214  return;
1215  }
1216 
1217  /** \brief Read a new set of names from \c newheads
1218 
1219  This function reads a set of white-space delimited column
1220  names from the string \c newheads, and creates a new column
1221  for each name which is specified.
1222 
1223  For example
1224  \code
1225  table t;
1226  t.line_of_names("position velocity acceleration");
1227  \endcode
1228  will create three new columns with the names "position",
1229  "velocity", and "acceleration".
1230  */
1231  void line_of_names(std::string newheads) {
1232  int ret=0;
1233  std::string head;
1234 
1235  std::istringstream is(newheads);
1236  while(is >> head) {
1237  new_column(head);
1238  }
1239 
1240  if (ret!=0) {
1241  O2SCL_ERR2("At least one new column failed in ",
1242  "table::line_of_names().",exc_efailed);
1243  }
1244 
1245  return;
1246  }
1247 
1248  /** \brief Read a line of data from the first \c nv entries in
1249  a vector and store as a new row in the table
1250 
1251  The type <tt>vec2_t</tt> can be any type with an
1252  <tt>operator[]</tt> method.
1253  */
1254  template<class vec2_t> void line_of_data(size_t nv, const vec2_t &v) {
1255  if (maxlines==0) inc_maxlines(1);
1256  if (nlines>=maxlines) inc_maxlines(maxlines);
1257 
1258  if (intp_set) {
1259  intp_set=false;
1260  delete si;
1261  }
1262 
1263  if (nlines<maxlines && nv<=(atree.size())) {
1264 
1265  set_nlines(nlines+1);
1266  for(size_t i=0;i<nv;i++) {
1267  (*this).set(i,nlines-1,v[i]);
1268  }
1269 
1270  return;
1271  }
1272 
1273  O2SCL_ERR("Not enough lines or columns in line_of_data().",exc_einval);
1274  return;
1275  }
1276 
1277  /** \brief Read a line of data and store in a new row of the
1278  table
1279 
1280  The type <tt>vec2_t</tt> can be any type with an
1281  <tt>operator[]</tt> method.
1282  */
1283  template<class vec2_t> void line_of_data(const vec2_t &v) {
1284  line_of_data(v.size(),v);
1285  return;
1286  }
1287  //@}
1288 
1289  // --------------------------------------------------------
1290  /** \name Lookup and search methods */
1291  //@{
1292 
1293  /** \brief Look for a value in an ordered column
1294  \f$ {\cal O}(\log(C) \log(R)) \f$
1295 
1296  This uses the function search_vec::ordered_lookup(), which
1297  offers caching and assumes the vector is monotonic. If you
1298  don't have monotonic data, you can still use the
1299  table::lookup() function, which is more general.
1300  */
1301  size_t ordered_lookup(std::string scol, double val) const {
1302  int ret;
1303  if (!std::isfinite(val)) {
1304  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
1305  "' not finite for column '"+
1306  scol+"' in table::ordered_lookup()").c_str(),exc_einval);
1307  return exc_einval;
1308  }
1309  aciter it=atree.find(scol);
1310  if (it==atree.end()) {
1311  O2SCL_ERR((((std::string)"Column '")+scol+
1312  " not found in table::ordered_lookup().").c_str(),
1313  exc_enotfound);
1314  return exc_enotfound;
1315  }
1316 
1317  search_vec<vec_t> se(nlines,it->second.dat);
1318  ret=se.ordered_lookup(val);
1319  return ret;
1320  }
1321 
1322  /** \brief Exhaustively search column \c col for the value \c val
1323  \f$ {\cal O}(R \log(C)) \f$
1324  */
1325  size_t lookup(std::string scol, double val) const {
1326  if (!std::isfinite(val)) {
1327  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
1328  "' not finite for column '"+
1329  scol+"' in table::lookup()").c_str(),exc_einval);
1330  return exc_einval;
1331  }
1332  aciter it=atree.find(scol);
1333  if (it==atree.end()) {
1334  O2SCL_ERR((((std::string)"Column '")+scol+" not found in "+
1335  "table::lookup().").c_str(),exc_enotfound);
1336  return exc_enotfound;
1337 
1338  }
1339 
1340  // Note that we cannot use the vector lookup() method here, because
1341  // the vector size may be larger than the actual table size.
1342 
1343  const vec_t &ov=it->second.dat;
1344  size_t row=0, i=0;
1345 
1346  // Find first finite row
1347  while(!std::isfinite(ov[i]) && i<nlines-1) i++;
1348  if (i==nlines-1) {
1349  O2SCL_ERR2("Entire array not finite in ",
1350  "table::lookup()",exc_einval);
1351  return 0;
1352  }
1353 
1354  // Beginning with that row, look for the closest value
1355  double best=ov[i], bdiff=fabs(ov[i]-val);
1356  for(;i<nlines;i++) {
1357  if (std::isfinite(ov[i]) && fabs(ov[i]-val)<bdiff) {
1358  row=i;
1359  best=ov[i];
1360  bdiff=fabs(ov[i]-val);
1361  }
1362  }
1363 
1364  return row;
1365  }
1366 
1367  /// Search column \c col for the value \c val and return value in \c col2
1368  double lookup_val(std::string scol, double val, std::string scol2) const {
1369  int i, indx=0;
1370  if (!std::isfinite(val)) {
1371  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
1372  "' not finite for column '"+
1373  scol+"' in table::lookup_val()").c_str(),exc_einval);
1374  return exc_einval;
1375  }
1376  aciter it=atree.find(scol);
1377  if (it==atree.end()) {
1378  O2SCL_ERR((((std::string)"Column '")+scol+" not found in "+
1379  "table::lookup().").c_str(),exc_enotfound);
1380  return exc_enotfound;
1381  }
1382  return get(scol2,it->second.dat->lookup(val));
1383  }
1384 
1385  /** \brief Exhaustively search column \c col for the value \c val
1386  \f$ {\cal O}(R \log(C)) \f$
1387  */
1388  size_t lookup(int icol, double val) const {
1389  return lookup(get_column_name(icol),val);
1390  }
1391 
1392  /** \brief Exhaustively search column \c col for many occurences
1393  of \c val \f$ {\cal O}(R \log(C)) \f$
1394  */
1395  size_t mlookup(std::string scol, double val, std::vector<size_t> &results,
1396  double threshold=0.0) const {
1397  size_t i;
1398  if (!std::isfinite(val)) {
1399  O2SCL_ERR((((std::string)"Value '")+dtos(val)+
1400  "' not finite for column '"+
1401  scol+"' in table::mlookup()").c_str(),exc_einval);
1402  return exc_einval;
1403  }
1404  aciter it=atree.find(scol);
1405  if (it==atree.end()) {
1406  O2SCL_ERR((((std::string)"Column '")+scol+" not found in "+
1407  "table::mlookup().").c_str(),exc_enotfound);
1408  return exc_enotfound;
1409  }
1410  if (threshold==0.0) {
1411  for(i=0;i<nlines;i++) {
1412  if (it->second.dat[i]==val) {
1413  results.push_back(i);
1414  }
1415  }
1416  } else {
1417  for(i=0;i<nlines;i++) {
1418  if (fabs(it->second.dat[i]-val)<threshold) {
1419  results.push_back(i);
1420  }
1421  }
1422  }
1423  return results.size();
1424  }
1425  //@}
1426 
1427  // --------------------------------------------------------
1428  /** \name Interpolation, differentiation, integration, max, min */
1429  //@{
1430 
1431  /// Set the base interpolation objects
1432  void set_interp_type(size_t interp_type) {
1433  itype=interp_type;
1434  if (intp_set) {
1435  delete si;
1436  intp_set=false;
1437  }
1438  return;
1439  }
1440 
1441  /** \brief Get the interpolation type
1442  */
1443  size_t get_interp_type() const {
1444  return itype;
1445  }
1446 
1447  /** \brief Interpolate \c x0 from \c sx into \c sy
1448 
1449  This function is \f$ {\cal O}(\log(R) \log(C)) \f$
1450  but can be as bad as \f$ {\cal O}(C \log(R) \f$ if the
1451  relevant columns are not well ordered.
1452  */
1453  double interp(std::string sx, double x0, std::string sy) {
1454  double ret;
1455  aiter itx=atree.find(sx), ity=atree.find(sy);
1456  if (itx==atree.end() || ity==atree.end()) {
1457  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1458  "' not found in table::interp().").c_str(),
1459  exc_enotfound);
1460  return 0.0;
1461  }
1462  if (!std::isfinite(x0)) {
1463  O2SCL_ERR("x0 not finite in table::interp().",exc_einval);
1464  return exc_einval;
1465  }
1466  if (intp_set==false || sx!=intp_colx || sy!=intp_coly) {
1467  if (intp_set==true) {
1468  delete si;
1469  } else {
1470  intp_set=true;
1471  }
1472  si=new interp_vec<vec_t>(nlines,itx->second.dat,
1473  ity->second.dat,itype);
1474  intp_colx=sx;
1475  intp_coly=sy;
1476  }
1477  ret=si->eval(x0);
1478  return ret;
1479  }
1480 
1481  /** \brief Interpolate \c x0 from \c sx into \c sy
1482 
1483  This function is \f$ {\cal O}(\log(R) \log(C)) \f$
1484  but can be as bad as \f$ {\cal O}(C \log(R) \f$ if the
1485  relevant columns are not well ordered.
1486  */
1487  double interp_const(std::string sx, double x0, std::string sy) const {
1488  double ret;
1489  aciter itx=atree.find(sx), ity=atree.find(sy);
1490  if (itx==atree.end() || ity==atree.end()) {
1491  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1492  "' not found in table::interp_const().").c_str(),
1493  exc_enotfound);
1494  return 0.0;
1495  }
1496  if (!std::isfinite(x0)) {
1497  O2SCL_ERR("x0 not finite in table::interp_const().",exc_einval);
1498  return exc_einval;
1499  }
1500  interp_vec<vec_t> sic(nlines,itx->second.dat,ity->second.dat,itype);
1501 
1502  ret=sic.interp(x0);
1503  return ret;
1504  }
1505 
1506  /** \brief Interpolate \c x0 from \c ix into \c iy
1507  \f$ {\cal O}(\log(R)) \f$
1508  */
1509  double interp(size_t ix, double x0, size_t iy) {
1510  return interp(get_column_name(ix),x0,get_column_name(iy));
1511  }
1512 
1513  /** \brief Interpolate \c x0 from \c ix into \c iy
1514  \f$ {\cal O}(\log(R)) \f$
1515  */
1516  double interp_const(size_t ix, double x0, size_t iy) const {
1517  return interp_const(get_column_name(ix),x0,get_column_name(iy));
1518  }
1519 
1520  /** \brief Make a new column \c yp which is the
1521  derivative \f$ y^{\prime}(x) \f$ .
1522  \f$ {\cal O}(R \log(C)) \f$
1523  */
1524  void deriv(std::string x, std::string y, std::string yp) {
1525  aiter itx, ity, ityp;
1526  new_column(yp);
1527 
1528  itx=atree.find(x);
1529  ity=atree.find(y);
1530  ityp=atree.find(yp);
1531 
1532  if (itx==atree.end() || ity==atree.end() || ityp==atree.end()) {
1533  O2SCL_ERR("Column not found in table::deriv().",exc_enotfound);
1534  return;
1535  }
1536 
1537  size_t ix=lookup_column(x);
1538  size_t iy=lookup_column(y);
1539  for(int i=0;i<((int)nlines);i++) {
1540  ityp->second.dat[i]=deriv(ix,(itx->second.dat)[i],iy);
1541  }
1542 
1543  return;
1544  }
1545 
1546  /** \brief The first derivative of the function sy(sx) at sx=x0.
1547 
1548  O(log(C)*log(R)) but can be as bad as O(log(C)*R) if
1549  the relevant columns are not well ordered.
1550  */
1551  double deriv(std::string sx, double x0, std::string sy) {
1552  double ret;
1553  aiter itx=atree.find(sx), ity=atree.find(sy);
1554  if (itx==atree.end() || ity==atree.end()) {
1555  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1556  "' not found in table::deriv().").c_str(),
1557  exc_enotfound);
1558  return 0.0;
1559  }
1560  if (!std::isfinite(x0)) {
1561  O2SCL_ERR("x0 not finite in table::deriv().",exc_einval);
1562  return exc_einval;
1563  }
1564  if (intp_set==false || sx!=intp_colx || sy!=intp_coly) {
1565  if (intp_set==true) {
1566  delete si;
1567  } else {
1568  intp_set=true;
1569  }
1570  si=new interp_vec<vec_t>
1571  (nlines,itx->second.dat,ity->second.dat,itype);
1572 
1573  intp_colx=sx;
1574  intp_coly=sy;
1575  }
1576  ret=si->deriv(x0);
1577  return ret;
1578  }
1579 
1580  /** \brief The first derivative of the function sy(sx) at sx=x0.
1581 
1582  O(log(C)*log(R)) but can be as bad as O(log(C)*R) if
1583  the relevant columns are not well ordered.
1584  */
1585  double deriv_const(std::string sx, double x0, std::string sy) const {
1586  double ret;
1587  aciter itx=atree.find(sx), ity=atree.find(sy);
1588  if (itx==atree.end() || ity==atree.end()) {
1589  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1590  "' not found in table::deriv_const().").c_str(),
1591  exc_enotfound);
1592  return 0.0;
1593  }
1594  if (!std::isfinite(x0)) {
1595  O2SCL_ERR("x0 not finite in table::deriv_const().",exc_einval);
1596  return exc_einval;
1597  }
1598  interp_vec<vec_t> sic
1599  (nlines,itx->second.dat,ity->second.dat,itype);
1600  ret=sic.deriv(x0);
1601  return ret;
1602  }
1603 
1604  /** \brief The first derivative of the function iy(ix) at ix=x0.
1605 
1606  O(log(R)) but can be as bad as O(R) if the relevant columns
1607  are not well ordered.
1608  */
1609  double deriv(size_t ix, double x0, size_t iy) {
1610  return deriv(get_column_name(ix),x0,get_column_name(iy));
1611  }
1612 
1613  /** \brief The first derivative of the function iy(ix) at ix=x0.
1614 
1615  O(log(R)) but can be as bad as O(R) if
1616  the relevant columns are not well ordered.
1617  */
1618  double deriv_const(size_t ix, double x0, size_t iy) const {
1619  return deriv_const(get_column_name(ix),x0,get_column_name(iy));
1620  }
1621 
1622  /** \brief Make a new column \c yp which is
1623  \f$ y^{\prime \prime}(x) \f$ - O(log(C)*R).
1624  */
1625  void deriv2(std::string x, std::string y, std::string yp) {
1626  aiter itx, ity, ityp;
1627  new_column(yp);
1628 
1629  itx=atree.find(x);
1630  ity=atree.find(y);
1631  ityp=atree.find(yp);
1632 
1633  if (itx==atree.end() || ity==atree.end() || ityp==atree.end()) {
1634  O2SCL_ERR("Column not found in table::deriv2().",exc_enotfound);
1635  return;
1636  }
1637 
1638  size_t ix=lookup_column(x);
1639  size_t iy=lookup_column(y);
1640  for(int i=0;i<((int)nlines);i++) {
1641  ityp->second.dat[i]=deriv2(ix,itx->second.dat[i],iy);
1642  }
1643 
1644  return;
1645  }
1646 
1647  /** \brief The second derivative of the function sy(sx) at sx=x0.
1648 
1649  O(log(C)*log(R)) but can be as bad as O(log(C)*R) if
1650  the relevant columns are not well ordered.
1651  */
1652  double deriv2(std::string sx, double x0, std::string sy) {
1653  double ret;
1654  aiter itx=atree.find(sx), ity=atree.find(sy);
1655  if (itx==atree.end() || ity==atree.end()) {
1656  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1657  "' not found in table::deriv2().").c_str(),
1658  exc_enotfound);
1659  return 0.0;
1660  }
1661  if (!std::isfinite(x0)) {
1662  O2SCL_ERR("x0 not finite in table::deriv2().",exc_einval);
1663  return exc_einval;
1664  }
1665  if (intp_set==false || sx!=intp_colx || sy!=intp_coly) {
1666  if (intp_set==true) {
1667  delete si;
1668  } else {
1669  intp_set=true;
1670  }
1671  si=new interp_vec<vec_t>
1672  (nlines,itx->second.dat,ity->second.dat,itype);
1673 
1674  intp_colx=sx;
1675  intp_coly=sy;
1676  }
1677  ret=si->deriv2(x0);
1678  return ret;
1679  }
1680 
1681  /** \brief The second derivative of the function sy(sx) at sx=x0.
1682 
1683  O(log(C)*log(R)) but can be as bad as O(log(C)*R) if
1684  the relevant columns are not well ordered.
1685  */
1686  double deriv2_const(std::string sx, double x0, std::string sy) const {
1687  double ret;
1688  aciter itx=atree.find(sx), ity=atree.find(sy);
1689  if (itx==atree.end() || ity==atree.end()) {
1690  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1691  "' not found in table::deriv2_const().").c_str(),
1692  exc_enotfound);
1693  return 0.0;
1694  }
1695  if (!std::isfinite(x0)) {
1696  O2SCL_ERR("x0 not finite in table::deriv2_const().",exc_einval);
1697  return exc_einval;
1698  }
1699  interp_vec<vec_t> sic
1700  (nlines,itx->second.dat,ity->second.dat,itype);
1701  ret=sic.deriv2(x0);
1702  return ret;
1703  }
1704 
1705  /** \brief The second derivative of the function iy(ix) at ix=x0.
1706 
1707  O(log(R)) but can be as bad as O(R) if
1708  the relevant columns are not well ordered.
1709  */
1710  double deriv2(size_t ix, double x0, size_t iy) {
1711  return deriv2(get_column_name(ix),x0,get_column_name(iy));
1712  }
1713 
1714  /** \brief The second derivative of the function iy(ix) at ix=x0.
1715 
1716  O(log(R)) but can be as bad as O(R) if
1717  the relevant columns are not well ordered.
1718  */
1719  double deriv2_const(size_t ix, double x0, size_t iy) const {
1720  return deriv2_const(get_column_name(ix),x0,get_column_name(iy));
1721  }
1722 
1723  /** \brief The integral of the function sy(sx) from sx=x1 to sx=x2.
1724 
1725  O(log(C)*log(R)) but can be as bad as O(log(C)*R) if
1726  the relevant columns are not well ordered.
1727  */
1728  double integ(std::string sx, double x1, double x2, std::string sy) {
1729  double ret;
1730  aiter itx=atree.find(sx), ity=atree.find(sy);
1731  if (itx==atree.end() || ity==atree.end()) {
1732  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1733  "' not found in table::integ().").c_str(),
1734  exc_enotfound);
1735  return 0.0;
1736  }
1737  if (!std::isfinite(x1) || !std::isfinite(x2)) {
1738  std::string msg=((std::string)"Value x1=")+dtos(x1)+" or x2="+
1739  dtos(x2)+" not finite in table.integ().";
1740  O2SCL_ERR(msg.c_str(),exc_einval);
1741  }
1742  if (intp_set==false || sx!=intp_colx || sy!=intp_coly) {
1743  if (intp_set==true) {
1744  delete si;
1745  } else {
1746  intp_set=true;
1747  }
1748  si=new interp_vec<vec_t>
1749  (nlines,itx->second.dat,ity->second.dat,itype);
1750 
1751  intp_colx=sx;
1752  intp_coly=sy;
1753  }
1754  ret=si->integ(x1,x2);
1755  return ret;
1756  }
1757 
1758  /** \brief The integral of the function sy(sx) from sx=x1 to sx=x2.
1759 
1760  O(log(C)*log(R)) but can be as bad as O(log(C)*R) if
1761  the relevant columns are not well ordered.
1762  */
1763  double integ_const(std::string sx, double x1, double x2,
1764  std::string sy) const {
1765  double ret;
1766  aciter itx=atree.find(sx), ity=atree.find(sy);
1767  if (itx==atree.end() || ity==atree.end()) {
1768  O2SCL_ERR((((std::string)"Columns '")+sx+"' or '"+sy+
1769  "' not found in table::integ_const().").c_str(),
1770  exc_enotfound);
1771  return 0.0;
1772  }
1773  if (!std::isfinite(x1) || !std::isfinite(x2)) {
1774  O2SCL_ERR("x1 or x2 not finite in table::integ_const().",exc_einval);
1775  return exc_einval;
1776  }
1777  interp_vec<vec_t> sic
1778  (nlines,itx->second.dat,ity->second.dat,itype);
1779  ret=sic.integ(x1,x2);
1780  return ret;
1781  }
1782 
1783  /** \brief The integral of the function iy(ix) from ix=x1 to ix=x2.
1784 
1785  O(log(R)) but can be as bad as O(R) if
1786  the relevant columns are not well ordered.
1787  */
1788  double integ(size_t ix, double x1, double x2, size_t iy) {
1789  return integ(get_column_name(ix),x1,x2,
1790  get_column_name(iy));
1791  }
1792 
1793  /** \brief The integral of the function iy(ix) from ix=x1 to ix=x2.
1794 
1795  O(log(R)) but can be as bad as O(R) if
1796  the relevant columns are not well ordered.
1797  */
1798  double integ_const(size_t ix, double x1, double x2, size_t iy) const {
1799  return integ_const(get_column_name(ix),x1,x2,
1800  get_column_name(iy));
1801  }
1802 
1803  /** \brief The integral of the function iy(ix)
1804 
1805  O(log(R)) but can be as bad as O(R) if the relevant columns
1806  are not well ordered.
1807  */
1808  void integ(std::string x, std::string y, std::string ynew) {
1809  aiter itx, ity, itynew;
1810  new_column(ynew);
1811 
1812  itx=atree.find(x);
1813  ity=atree.find(y);
1814  itynew=atree.find(ynew);
1815 
1816  if (itx==atree.end() || ity==atree.end() || itynew==atree.end()) {
1817  O2SCL_ERR("Column not found in table::integ().",exc_enotfound);
1818  return;
1819  }
1820 
1821  size_t ix=lookup_column(x);
1822  size_t iy=lookup_column(y);
1823  for(size_t i=0;i<nlines;i++) {
1824  itynew->second.dat[i]=integ(ix,(itx->second.dat)[0],
1825  (itx->second.dat)[i],iy);
1826  }
1827 
1828  return;
1829  }
1830 
1831  /** \brief Return column maximum. Makes no assumptions about
1832  ordering \f$ {\cal O}(R) \f$
1833  */
1834  double max(std::string scol) const {
1835  double ret=0.0;
1836  int i;
1837  if (is_column(scol)==false) {
1838  O2SCL_ERR((((std::string)"Column '")+scol+
1839  "' not found in table::max().").c_str(),exc_enotfound);
1840  return 0.0;
1841  }
1842  const vec_t &dcol=get_column(scol);
1843  bool setb=false;
1844  for(i=0;i<((int)nlines);i++) {
1845  if (std::isfinite(dcol[i])) {
1846  if (setb==false) {
1847  ret=dcol[i];
1848  setb=true;
1849  } else if (dcol[i]>ret) {
1850  ret=dcol[i];
1851  }
1852  }
1853  }
1854  if (setb==false) {
1855  O2SCL_ERR((((std::string)"No finite values in column '")+scol+
1856  "' in table::max().").c_str(),exc_efailed);
1857  return 0.0;
1858  }
1859  return ret;
1860  }
1861 
1862  /** \brief Return column minimum. Makes no assumptions about
1863  ordering \f$ {\cal O}(R) \f$
1864  */
1865  double min(std::string scol) const {
1866  double ret=0.0;
1867  int i;
1868  if (is_column(scol)==false) {
1869  O2SCL_ERR((((std::string)"Column '")+scol+
1870  "' not found in table::min().").c_str(),exc_enotfound);
1871  return 0.0;
1872  }
1873  const vec_t &dcol=get_column(scol);
1874  bool setb=false;
1875  for(i=0;i<((int)nlines);i++) {
1876  if (std::isfinite(dcol[i])) {
1877  if (setb==false) {
1878  ret=dcol[i];
1879  setb=true;
1880  } else if (dcol[i]<ret) {
1881  ret=dcol[i];
1882  }
1883  }
1884  }
1885  if (setb==false) {
1886  O2SCL_ERR((((std::string)"No finite values in column '")+scol+
1887  "' in table::min().").c_str(),exc_efailed);
1888  return 0.0;
1889  }
1890  return ret;
1891  }
1892  //@}
1893 
1894  // --------------------------------------------------------
1895  /** \name Subtable method */
1896  //@{
1897 
1898  /** \brief Make a subtable
1899 
1900  Uses the columns specified in \c list from the row \c top
1901  to the row of index \c bottom to generate a new table
1902  which is a copy of part of the original.
1903  */
1904  void subtable(std::string list, size_t top,
1905  size_t bottom, table<vec_t> &tnew) const {
1906 
1907  tnew.clear_all();
1908  int sublines, i;
1909  std::string head;
1910  aciter it;
1911 
1912  if (top>bottom) {
1913  size_t tmp=bottom;
1914  bottom=top;
1915  top=tmp;
1916  }
1917  sublines=bottom-top+1;
1918  if (nlines==0) {
1919  O2SCL_ERR2("Can't make a subtable of an empty table. ",
1920  "Returning 0 in table::subtable().",
1921  exc_einval);
1922  return;
1923  }
1924  if (bottom+1>nlines) {
1925  O2SCL_ERR2("Requested row beyond nlines. Adjusting ",
1926  "and continuing in table::subtable().",exc_einval);
1927  bottom=nlines-1;
1928  }
1929 
1930  std::istringstream is(list);
1931 
1932  tnew.set_nlines(sublines);
1933  while(is >> head) {
1934  it=atree.find(head);
1935  if (it==atree.end()) {
1936  O2SCL_ERR
1937  ((((std::string)"Couldn't find column named ")+head+
1938  " in table::subtable(). Returning 0.").c_str(),
1939  exc_einval);
1940  }
1941  tnew.new_column(head);
1942  vec_t &dcol=tnew.get_column(head);
1943  for(i=0;i<sublines;i++) {
1944  dcol[i]=it->second.dat[i+top];
1945  }
1946  }
1947  if (tnew.get_ncolumns()==0) {
1948  O2SCL_ERR("Subtable has no columns in table::subtable().",
1949  exc_einval);
1950  }
1951  //}
1952  tnew.nlines=sublines;
1953 
1954  return;
1955  }
1956  //@}
1957 
1958  // --------------------------------------------------------
1959  /** \name Clear methods */
1960  //@{
1961 
1962  /** \brief Zero the data entries but keep the column names
1963  and nlines fixed
1964  */
1965  void zero_table() {
1966  aiter it;
1967  for(it=atree.begin();it!=atree.end();it++) {
1968  for(int j=0;j<((int)nlines);j++) {
1969  it->second.dat[j]=0.0;
1970  }
1971  }
1972 
1973  if (intp_set) {
1974  intp_set=false;
1975  delete si;
1976  }
1977 
1978  return;
1979  }
1980 
1981  /** \brief Clear everything
1982  */
1983  void clear() {
1984  clear_table();
1985  clear_constants();
1986  return;
1987  }
1988 
1989  /** \brief Clear the table and the column names (but leave constants)
1990  */
1991  void clear_table() {
1992  atree.clear();
1993  alist.clear();
1994  nlines=0;
1995  if (intp_set==true) {
1996  delete si;
1997  intp_set=false;
1998  }
1999  return;
2000  }
2001 
2002  /** \brief Remove all of the data by setting the number
2003  of lines to zero
2004 
2005  This leaves the column names intact and does not remove
2006  the constants.
2007  */
2008  void clear_data() {
2009  nlines=0;
2010  if (intp_set==true) {
2011  delete si;
2012  intp_set=false;
2013  }
2014  return;
2015  }
2016 
2017  /// CLear all constants
2019  constants.clear();
2020  return;
2021  }
2022  //@}
2023 
2024  // --------------------------------------------------------
2025  /** \name Sorting methods */
2026  //@{
2027 
2028  /** \brief Sort the entire table by the column \c scol
2029 
2030  \note This function works by allocating space for an entirely
2031  new chunk of memory for the data in the table.
2032  */
2033  void sort_table(std::string scol) {
2034 
2035  size_t ncols=get_ncolumns(), nlins=get_nlines();
2036 
2037  // Make a copy of the table
2038  boost::numeric::ublas::matrix<double> data_copy(ncols,nlins);
2039  for(size_t i=0;i<ncols;i++) {
2040  for(size_t j=0;j<nlins;j++) {
2041  data_copy(i,j)=get(i,j);
2042  }
2043  }
2044 
2045  permutation order(nlins);
2046  aiter it=atree.find(scol);
2047  vec_t &data=it->second.dat;
2048  vector_sort_index(nlins,data,order);
2049  for(size_t i=0;i<ncols;i++) {
2050  for(size_t j=0;j<nlins;j++) {
2051  set(i,j,data_copy(i,order[j]));
2052  }
2053  }
2054 
2055  if (intp_set) {
2056  intp_set=false;
2057  delete si;
2058  }
2059 
2060  return;
2061  }
2062 
2063  /** \brief Individually sort the column \c scol
2064  */
2065  void sort_column(std::string scol) {
2066  int i;
2067  aiter it=atree.find(scol);
2068  if (it==atree.end()) {
2069  O2SCL_ERR((((std::string)"Column '")+scol+
2070  " not found in table::sort_column().").c_str(),
2071  exc_enotfound);
2072  return;
2073  }
2074 
2075  vector_sort_double(nlines,it->second.dat);
2076 
2077  if (intp_set && (scol==intp_colx || scol==intp_coly)) {
2078  intp_set=false;
2079  delete si;
2080  }
2081 
2082  return;
2083  }
2084  //@}
2085 
2086  // --------------------------------------------------------
2087  /** \name Summary method */
2088  //@{
2089  /** \brief Output a summary of the information stored
2090 
2091  Outputs the number of constants, the number of columns,
2092  a list of the column names, and the number of lines of
2093  data.
2094  */
2095  virtual void summary(std::ostream *out, size_t ncol=79) const {
2096 
2097  if (constants.size()==1) {
2098  (*out) << "1 constant:" << std::endl;
2099  } else {
2100  (*out) << constants.size() << " constants:" << std::endl;
2101  }
2102  std::map<std::string,double>::const_iterator mit;
2103  for(mit=constants.begin();mit!=constants.end();mit++) {
2104  (*out) << mit->first << " " << mit->second << std::endl;
2105  }
2106 
2107  // Output number of columns and preprend column numbers
2108  size_t nh=get_ncolumns(), nh2;
2109 
2110  if (nh==0) {
2111 
2112  (*out) << "No columns." << std::endl;
2113 
2114  } else {
2115 
2116  if (nh==1) {
2117  (*out) << "1 column: " << std::endl;
2118  } else {
2119  (*out) << nh << " columns: " << std::endl;
2120  }
2121  std::vector<std::string> h(nh);
2122  for(size_t i=0;i<nh;i++) {
2123  h[i]=szttos(i)+". "+get_column_name(i);
2124  }
2125 
2126  std::vector<std::string> h2;
2127  // Convert to string with width 'ncol'
2128  screenify(nh,h,h2,ncol);
2129  nh2=h2.size();
2130 
2131  // Output column names
2132  for(size_t i=0;i<nh2;i++) {
2133  (*out) << h2[i] << std::endl;
2134  }
2135 
2136  }
2137 
2138  if (get_nlines()==0) (*out) << "No lines of data." << std::endl;
2139  else if (get_nlines()==1) (*out) << "One line of data." << std::endl;
2140  (*out) << get_nlines() << " lines of data." << std::endl;
2141 
2142  return;
2143  }
2144  //@}
2145 
2146  /// \name Constant manipulation
2147  //@{
2148  /** \brief Add a constant, or if the constant already exists, change
2149  its value
2150  */
2151  virtual void add_constant(std::string name, double val) {
2152  if (constants.find(name)!=constants.end()) {
2153  constants.find(name)->second=val;
2154  return;
2155  }
2156  constants.insert(make_pair(name,val));
2157  return;
2158  }
2159 
2160  /** \brief Set a constant equal to a value, but don't add it if
2161  not already present
2162 
2163  If \c err_on_notfound is <tt>true</tt> (the default), then
2164  this function throws an exception if a constant with
2165  name \c name is not found. If \c err_on_notfound is
2166  <tt>false</tt>, then if a constant with name \c name
2167  is not found this function just silently returns
2168  \ref o2scl::exc_enotfound.
2169  */
2170  virtual int set_constant(std::string name, double val,
2171  bool err_on_notfound=true) {
2172  if (constants.find(name)!=constants.end()) {
2173  constants.find(name)->second=val;
2174  return 0;
2175  }
2176  if (err_on_notfound) {
2177  std::string err=((std::string)"No constant with name '")+name+
2178  "' in table::set_constant().";
2179  O2SCL_ERR(err.c_str(),exc_enotfound);
2180  }
2181  return exc_enotfound;
2182  }
2183 
2184  /// Test if \c name is a constant
2185  virtual bool is_constant(std::string name) const {
2186  if (constants.find(name)==constants.end()) {
2187  return false;
2188  }
2189  return true;
2190  }
2191 
2192  /// Get a constant
2193  virtual double get_constant(std::string name) const {
2194  if (constants.find(name)==constants.end()) {
2195  std::string err=((std::string)"No constant with name '")+name+
2196  "' in table::get_constant().";
2197  O2SCL_ERR(err.c_str(),exc_einval);
2198  }
2199  return constants.find(name)->second;
2200  }
2201 
2202  /// Get the number of constants
2203  virtual size_t get_nconsts() const {
2204  return constants.size();
2205  }
2206 
2207  /// Get a constant by index
2208  virtual void get_constant(size_t ix, std::string &name, double &val) const {
2209  if (ix<constants.size()) {
2210  std::map<std::string,double>::const_iterator cit=constants.begin();
2211  for(size_t i=0;i<ix;i++) cit++;
2212  name=cit->first;
2213  val=cit->second;
2214  return;
2215  }
2216  O2SCL_ERR("Index too large in table::get_constant().",exc_eindex);
2217  return;
2218  }
2219 
2220  /// Remove a constant
2221  virtual void remove_constant(std::string name) {
2222  constants.erase(name);
2223  return;
2224  }
2225  //@}
2226 
2227  /// \name Miscellaneous methods
2228  //@{
2229  /// Clear the current table and read from a generic data file
2230  virtual int read_generic(std::istream &fin, int verbose=0) {
2231 
2232  double data;
2233  std::string line;
2234  std::string cname;
2235 
2236  // Read first line and into list
2237  std::vector<std::string> onames, nnames;
2238  getline(fin,line);
2239  std::istringstream is(line);
2240  while (is >> cname) {
2241  onames.push_back(cname);
2242  if (verbose>2) {
2243  std::cout << "Read possible column name: " << cname << std::endl;
2244  }
2245  }
2246 
2247  // Count number of likely numbers in the first row
2248  size_t n_nums=0;
2249  for(size_t i=0;i<onames.size();i++) {
2250  if (is_number(onames[i])) n_nums++;
2251  }
2252 
2253  int irow=0;
2254 
2255  if (n_nums==onames.size()) {
2256 
2257  if (verbose>0) {
2258  std::cout << "First row looks like it contains numerical values."
2259  << std::endl;
2260  std::cout << "Creating generic column names: ";
2261  }
2262 
2263  for(size_t i=0;i<onames.size();i++) {
2264  nnames.push_back(((std::string)"c")+szttos(i+1));
2265  if (verbose>0) std::cout << nnames[i] << " ";
2266 
2267  }
2268  if (verbose>0) std::cout << std::endl;
2269 
2270  // Make columns
2271  for(size_t i=0;i<nnames.size();i++) {
2272  new_column(nnames[i]);
2273  }
2274 
2275  // Add first row of data
2276  for(size_t i=0;i<onames.size();i++) {
2277  set(i,irow,o2scl::stod(onames[i]));
2278  }
2279  irow++;
2280 
2281  } else {
2282 
2283  // Ensure good column names
2284  for(size_t i=0;i<onames.size();i++) {
2285  std::string temps=onames[i];
2286  make_fp_varname(temps);
2287  make_unique_name(temps,nnames);
2288  nnames.push_back(temps);
2289  if (temps!=onames[i] && verbose>0) {
2290  std::cout << "Converted column named '" << onames[i] << "' to '"
2291  << temps << "'." << std::endl;
2292  }
2293  }
2294 
2295  // Make columns
2296  for(size_t i=0;i<nnames.size();i++) {
2297  new_column(nnames[i]);
2298  }
2299 
2300  }
2301 
2302  // Read remaining rows
2303  while ((fin) >> data) {
2304  set(0,irow,data);
2305  for(size_t i=1;i<get_ncolumns();i++) {
2306  (fin) >> data;
2307  set(i,irow,data);
2308  }
2309  irow++;
2310  }
2311 
2312  if (intp_set) {
2313  intp_set=false;
2314  delete si;
2315  }
2316 
2317  return 0;
2318  }
2319 
2320  /** \brief Return 0 if the tree and list are properly synchronized
2321  */
2322  void check_synchro() const {
2323  if (atree.size()!=alist.size()) {
2324  O2SCL_ERR2("Size of table and list do not match in ",
2325  "table::check_synchro().",exc_esanity);
2326  return;
2327  }
2328  for(aciter it=atree.begin();it!=atree.end();it++) {
2329  if (it->second.index!=alist[it->second.index]->second.index) {
2330  O2SCL_ERR((((std::string)"Problem with iterator for entry '")+
2331  it->first+"' in list in table::check_synchro().").c_str(),
2332  exc_esanity);
2333  }
2334  }
2335  for(int i=0;i<((int)atree.size());i++) {
2336  if (alist[i]->second.index!=i) {
2337  O2SCL_ERR((((std::string)"Problem with index of entry ")+
2338  itos(i)+" in list in table::check_synchro().").c_str(),
2339  exc_esanity);
2340  return;
2341  }
2342  }
2343  return;
2344  }
2345 
2346  /// Return the type, \c "table".
2347  virtual const char *type() { return "table"; }
2348  //@}
2349 
2350  /** \name Parsing mathematical functions specified as strings
2351  */
2352  //@{
2353  /** \brief Create new columns or recompute from a list of functions
2354 
2355  The list should be a space-delimited list of entries of the
2356  form <tt>name=function</tt> where <tt>name</tt> is the
2357  column name and <tt>function</tt> the function specifing the
2358  values for the column. If a column named <tt>name</tt> is
2359  already present, it is overwritten. Otherwise, a new column
2360  is created.
2361 
2362  \comment
2363  The formulas in \c list may depend on any of the column names
2364  that will be defined later in \c list. For example, for a
2365  table initially containing two columns, \c x and \c y, the
2366  calls
2367  \code
2368  function_columns("a=2*z z=x+y");
2369  \endcode
2370  \code
2371  function_columns("z=x+y a=2*z");
2372  \endcode
2373  both work.
2374  Circular dependencies do not work, for example
2375  \code
2376  function_columns("a=2*z z=a*3");
2377  \endcode
2378  will cause the error handler to be thrown.
2379  \endcomment
2380  */
2381  void functions_columns(std::string list) {
2382 
2383  // Separate the list into names and functions
2384  std::vector<std::string> funcs, names;
2385  {
2386  std::string stemp;
2387  std::istringstream is(list);
2388  while(is >> stemp) funcs.push_back(stemp);
2389  for(size_t i=0;i<(funcs.size());i++) {
2390  names.push_back(funcs[i].substr(0,funcs[i].find("=")));
2391  funcs[i]=funcs[i].substr(funcs[i].find("=")+1,
2392  funcs[i].length()-funcs[i].find("=")-1);
2393  if (names[i].length()==0 || funcs[i].length()==0) {
2394  O2SCL_ERR2("Name or function blank in ",
2395  "table::functions_columns().",exc_einval);
2396  }
2397  }
2398  }
2399 
2400  std::map<std::string,double> vars;
2401  std::map<std::string,double>::const_iterator mit;
2402  for(mit=constants.begin();mit!=constants.end();mit++) {
2403  vars[mit->first]=mit->second;
2404  }
2405 
2406  std::vector<calculator> calcs(funcs.size());
2407  std::vector<vec_t> newcols(funcs.size());
2408 
2409  for(size_t j=0;j<funcs.size();j++) {
2410  calcs[j].compile(funcs[j].c_str(),&vars);
2411  newcols[j].resize(maxlines);
2412  }
2413 
2414  // Calculate all of the columns in the newcols list:
2415  for(size_t i=0;i<nlines;i++) {
2416 
2417  // Record the values of the variables for this line:
2418  for(size_t j=0;j<atree.size();j++) {
2419  vars[get_column_name(j)]=(*this)[j][i];
2420  }
2421 
2422  // Evaluate the new columns
2423  for(size_t j=0;j<funcs.size();j++) {
2424  newcols[j][i]=calcs[j].eval(&vars);
2425  }
2426  }
2427 
2428  for(size_t j=0;j<funcs.size();j++) {
2429  if (!is_column(names[j])) {
2430  new_column(names[j]);
2431  }
2432  swap_column_data(names[j],newcols[j]);
2433  }
2434 
2435  return;
2436  }
2437 
2438  /** \brief Make a column from the function specified in
2439  <tt>function</tt> and add it to the table.
2440 
2441  If a column named \c scol already exists, the data already
2442  present is overwritten with the result. Otherwise, a new
2443  column is created and filled with the result.
2444  */
2445  void function_column(std::string function, std::string scol) {
2446  int ret, i, j;
2447  std::string vlist;
2448  aiter it;
2449 
2450  // Create new column if necessary
2451  if (!is_column(scol)) {
2452  new_column(scol);
2453  }
2454 
2455  // Find vector reference
2456  aiter it2=atree.find(scol);
2457  vec_t &colp=it2->second.dat;
2458 
2459  // Fill vector with result of function
2460  function_vector(function,colp);
2461 
2462  return;
2463  }
2464 
2465  /** \brief Compute a column from a function specified
2466  in a string
2467 
2468  The type \c resize_vec_t must have <tt>resize()</tt> and
2469  <tt>size()</tt> methods. If \c vec does not have enough space to
2470  hold the number of entries given by \ref get_nlines(), it is
2471  resized.
2472 
2473  \comment
2474  This function must return an int rather than void because
2475  of the presence of the 'throw_on_err' mechanism
2476  \endcomment
2477  */
2478  template<class resize_vec_t>
2479  int function_vector(std::string function, resize_vec_t &vec,
2480  bool throw_on_err=true) {
2481 
2482  // Parse function
2483  calculator calc;
2484  std::map<std::string,double> vars;
2485  std::map<std::string,double>::const_iterator mit;
2486  for(mit=constants.begin();mit!=constants.end();mit++) {
2487  vars[mit->first]=mit->second;
2488  }
2489  calc.compile(function.c_str(),&vars);
2490 
2491  // Resize vector if necessary
2492  if (vec.size()<nlines) vec.resize(nlines);
2493 
2494  // Create space for column values
2495  std::vector<double> vals(atree.size());
2496 
2497  // Create column from function
2498  for(size_t j=0;j<nlines;j++) {
2499  for(aciter it=atree.begin();it!=atree.end();it++) {
2500  vars[it->first]=it->second.dat[j];
2501  }
2502  vec[j]=calc.eval(&vars);
2503  }
2504 
2505  return 0;
2506  }
2507 
2508  /** \brief Compute a value by applying a function to a row
2509  */
2510  double row_function(std::string function, size_t row) const {
2511 
2512  // Parse function
2513  calculator calc;
2514  std::map<std::string,double> vars;
2515  std::map<std::string,double>::const_iterator mit;
2516  for(mit=constants.begin();mit!=constants.end();mit++) {
2517  vars[mit->first]=mit->second;
2518  }
2519  calc.compile(function.c_str(),&vars);
2520 
2521  for(aciter it=atree.begin();it!=atree.end();it++) {
2522  vars[it->first]=it->second.dat[row];
2523  }
2524 
2525  double dret=calc.eval(&vars);
2526  return dret;
2527  }
2528 
2529  /** \brief Find a row which maximizes a function
2530  */
2531  size_t function_find_row(std::string function) const {
2532 
2533  // Parse function
2534  calculator calc;
2535  std::map<std::string,double> vars;
2536  std::map<std::string,double>::const_iterator mit;
2537  for(mit=constants.begin();mit!=constants.end();mit++) {
2538  vars[mit->first]=mit->second;
2539  }
2540  calc.compile(function.c_str(),&vars);
2541 
2542  double best_val=0.0;
2543  size_t best_row=0;
2544  for(size_t row=0;row<nlines-1;row++) {
2545  for(aciter it=atree.begin();it!=atree.end();it++) {
2546  vars[it->first]=it->second.dat[row];
2547  }
2548  double dtemp=calc.eval(&vars);
2549  if (row==0) {
2550  best_val=dtemp;
2551  } else {
2552  if (dtemp>best_val) {
2553  best_val=dtemp;
2554  best_row=row;
2555  }
2556  }
2557  }
2558 
2559  return best_row;
2560  }
2561  //@}
2562 
2563  // ---------
2564  // Allow HDF I/O functions to access table data
2565  friend void o2scl_hdf::hdf_output
2566  (o2scl_hdf::hdf_file &hf, table<> &t, std::string name);
2567 
2568  template<class vecf_t> friend void o2scl_hdf::hdf_input
2569  (o2scl_hdf::hdf_file &hf, table<vecf_t> &t, std::string name);
2570 
2571  friend void o2scl_hdf::hdf_output_data
2572  (o2scl_hdf::hdf_file &hf, table<> &t);
2573 
2574  template<class vecf_t> friend void o2scl_hdf::hdf_input_data
2576 
2577  // ---------
2578 
2579 #ifndef DOXYGEN_INTERNAL
2580 
2581  protected:
2582 
2583  /** \brief The list of constants
2584  */
2585  std::map<std::string,double> constants;
2586 
2587  /** \brief Set the elements of alist with the appropriate
2588  iterators from atree. \f$ {\cal O}(C) \f$
2589 
2590  Generally, the end-user shouldn't need this method. It is
2591  only used in delete_column() to rearrange the list when
2592  a column is deleted from the tree.
2593  */
2594  void reset_list() {
2595  aiter it;
2596  for(it=atree.begin();it!=atree.end();it++) {
2597  alist[it->second.index]=it;
2598  }
2599  return;
2600  }
2601 
2602  /** \brief Ensure a variable name does not match a function or contain
2603  non-alphanumeric characters
2604  */
2605  void make_fp_varname(std::string &s) {
2606  if (s=="abs" || s=="acos" || s=="acosh" || s=="asin" ||
2607  s=="asinh" || s=="atan" || s=="atan2" || s=="atanh" ||
2608  s=="ceil" || s=="cos" || s=="cosh" || s=="cot" || s=="csc" ||
2609  s=="eval" || s=="exp" || s=="floor" || s=="if" || s=="int" ||
2610  s=="log" || s=="log10" || s=="max" || s=="min" || s=="sec" ||
2611  s=="sin" || s=="sinh" || s=="sqrt" || s=="tan" || s=="tanh") {
2612  s=((std::string)"v_")+s;
2613  } else if (s[0]>='0' && s[0]<='9') {
2614  s=((std::string)"v_")+s;
2615  }
2616 
2617  for(size_t i=0;i<s.length();i++) {
2618  if (!isalpha(s[i]) && !isdigit(s[i]) && s[i]!='_') s[i]='_';
2619  }
2620 
2621  return;
2622  }
2623 
2624  /// Make sure a name is unique
2625  void make_unique_name(std::string &colx, std::vector<std::string> &cnames) {
2626  bool done;
2627 
2628  do {
2629  done=true;
2630  for(size_t i=0;i<cnames.size();i++) {
2631  if (colx==cnames[i]) {
2632  done=false;
2633  i=cnames.size();
2634  }
2635  }
2636  if (done==false) {
2637  colx+='_';
2638  }
2639  } while (done==false);
2640 
2641  return;
2642  }
2643 
2644  /** \brief Column structure for \ref table [protected]
2645 
2646  This struct is used internally by \ref table to organize the
2647  columns and need not be instantiated by the casual end-user.
2648  */
2649  class col {
2650  public:
2651  /// Pointer to column
2652  vec_t dat;
2653  /// Column index
2654  int index;
2655  };
2656 
2657  /// \name Iterator types
2658  //@{
2659  /// Map iterator type
2660  typedef typename std::map<std::string,col,
2661  std::greater<std::string> >::iterator aiter;
2662  /// Const map iterator type
2663  typedef typename std::map<std::string,col,
2664  std::greater<std::string> >::const_iterator
2666  /// Vector iterator type
2667  typedef typename std::vector<aiter>::iterator aviter;
2668  //@}
2669 
2670  /// \name Actual data
2671  //@{
2672  /// The size of allocated memory
2673  size_t maxlines;
2674  /// The size of presently used memory
2675  size_t nlines;
2676  /// The tree of columns
2677  std::map<std::string,col,std::greater<std::string> > atree;
2678  /// The list of tree iterators
2679  std::vector<aiter> alist;
2680  //@}
2681 
2682  /// \name Column manipulation methods
2683  //@{
2684  /// Return the iterator for a column
2685  aiter get_iterator(std::string lname) {
2686  aiter it=atree.find(lname);
2687  if (it==atree.end()) {
2688  O2SCL_ERR((((std::string)"Column '")+lname+
2689  " not found in table::get_iterator().").c_str(),
2690  exc_enotfound);
2691  }
2692  return it;
2693  }
2694  /// Return the column structure for a column
2695  col *get_col_struct(std::string lname) {
2696  aiter it=atree.find(lname);
2697  if (it==atree.end()) {
2698  O2SCL_ERR((((std::string)"Column '")+lname+
2699  " not found in table::get_col_struct().").c_str(),
2700  exc_enotfound);
2701  return 0;
2702  }
2703  return &(it->second);
2704  }
2705  /// Return the beginning of the column tree
2706  aiter begin() { return atree.begin(); }
2707  /// Return the end of the column tree
2708  aiter end() { return atree.end(); }
2709  //@}
2710 
2711  /// An empty vector for get_column()
2712  vec_t empty_col;
2713 
2714  /// \name Interpolation
2715  //@{
2716  /// True if the interpolation object is up-to-date
2717  bool intp_set;
2718 
2719  /// Current interpolation type
2720  size_t itype;
2721 
2722  /// Interpolation object
2724 
2725  /// The last x-column interpolated
2726  std::string intp_colx;
2727 
2728  /// The last y-column interpolated
2729  std::string intp_coly;
2730  //@}
2731 
2732 #endif
2733 
2734  };
2735 
2736 #ifndef DOXYGEN_NO_O2NS
2737 }
2738 #endif
2739 
2740 #endif
void delete_rows(size_t row_start, size_t row_end)
Delete all rows between row_start and row_end .
Definition: table.h:1194
size_t mlookup(std::string scol, double val, std::vector< size_t > &results, double threshold=0.0) const
Exhaustively search column col for many occurences of val .
Definition: table.h:1395
virtual void delete_column(std::string scol)
Delete column named scol .
Definition: table.h:816
size_t nlines
The size of presently used memory.
Definition: table.h:2675
aiter begin()
Return the beginning of the column tree.
Definition: table.h:2706
void deriv(std::string x, std::string y, std::string yp)
Make a new column yp which is the derivative . .
Definition: table.h:1524
double max(std::string scol) const
Return column maximum. Makes no assumptions about ordering .
Definition: table.h:1834
void clear_table()
Clear the table and the column names (but leave constants)
Definition: table.h:1991
const vec_t & operator[](std::string scol) const
Returns the column named scol (const version). .
Definition: table.h:672
void line_of_data(const vec2_t &v)
Read a line of data and store in a new row of the table.
Definition: table.h:1283
void copy_to_column(vec2_t &v, std::string scol)
Copy to a column from a generic vector object.
Definition: table.h:966
The main O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl names...
Definition: anneal.h:42
std::string intp_coly
The last y-column interpolated.
Definition: table.h:2729
size_t get_nlines() const
Return the number of lines.
Definition: table.h:457
double integ(size_t ix, double x1, double x2, size_t iy)
The integral of the function iy(ix) from ix=x1 to ix=x2.
Definition: table.h:1788
interp_vec< vec_t > * si
Interpolation object.
Definition: table.h:2723
double min(std::string scol) const
Return column minimum. Makes no assumptions about ordering .
Definition: table.h:1865
double deriv(std::string sx, double x0, std::string sy)
The first derivative of the function sy(sx) at sx=x0.
Definition: table.h:1551
double integ_const(size_t ix, double x1, double x2, size_t iy) const
The integral of the function iy(ix) from ix=x1 to ix=x2.
Definition: table.h:1798
void hdf_input_data(hdf_file &hf, o2scl::table< vec_t > &t)
Internal function for inputting a o2scl::table object.
Definition: hdf_io.h:95
void compile(const char *expr, std::map< std::string, double > *vars=0, bool debug=false, std::map< std::string, int > opPrec=opPrecedence)
Compile expression expr using variables specified in vars.
void copy_rows(std::string func, table< vec2_t > &dest)
Copy all rows matching a particular condition to a new table.
Definition: table.h:1153
virtual double deriv2(const double x0) const
Give the value of the second derivative .
Definition: interp.h:1831
void subtable(std::string list, size_t top, size_t bottom, table< vec_t > &tnew) const
Make a subtable.
Definition: table.h:1904
void zero_table()
Zero the data entries but keep the column names and nlines fixed.
Definition: table.h:1965
Data table table class.
Definition: table.h:49
void set_nlines(size_t il)
Set the number of lines.
Definition: table.h:467
void functions_columns(std::string list)
Create new columns or recompute from a list of functions.
Definition: table.h:2381
void new_row(size_t n)
Insert a row before row n.
Definition: table.h:1055
sanity check failed - shouldn&#39;t happen
Definition: err_hnd.h:65
int function_vector(std::string function, resize_vec_t &vec, bool throw_on_err=true)
Compute a column from a function specified in a string.
Definition: table.h:2479
aiter get_iterator(std::string lname)
Return the iterator for a column.
Definition: table.h:2685
double deriv_const(std::string sx, double x0, std::string sy) const
The first derivative of the function sy(sx) at sx=x0.
Definition: table.h:1585
invalid argument supplied by user
Definition: err_hnd.h:59
void deriv2(std::string x, std::string y, std::string yp)
Make a new column yp which is - O(log(C)*R).
Definition: table.h:1625
virtual int set_constant(std::string name, double val, bool err_on_notfound=true)
Set a constant equal to a value, but don&#39;t add it if not already present.
Definition: table.h:2170
void set_nlines_auto(size_t il)
Set the number of lines, increasing the size more agressively.
Definition: table.h:559
double deriv(size_t ix, double x0, size_t iy)
The first derivative of the function iy(ix) at ix=x0.
Definition: table.h:1609
std::string intp_colx
The last x-column interpolated.
Definition: table.h:2726
virtual void remove_constant(std::string name)
Remove a constant.
Definition: table.h:2221
double integ_const(std::string sx, double x1, double x2, std::string sy) const
The integral of the function sy(sx) from sx=x1 to sx=x2.
Definition: table.h:1763
A class for representing permutations.
Definition: permutation.h:70
void make_fp_varname(std::string &s)
Ensure a variable name does not match a function or contain non-alphanumeric characters.
Definition: table.h:2605
double interp_const(size_t ix, double x0, size_t iy) const
Interpolate x0 from ix into iy .
Definition: table.h:1516
virtual double deriv(const double x0) const
Give the value of the derivative .
Definition: interp.h:1820
int new_column(std::string name, size_t sz, vec2_t &v)
Add a new column by copying data from another vector.
Definition: table.h:730
virtual size_t get_nconsts() const
Get the number of constants.
Definition: table.h:2203
table & operator=(const table &t)
Copy constructor.
Definition: table.h:260
double interp_const(std::string sx, double x0, std::string sy) const
Interpolate x0 from sx into sy.
Definition: table.h:1487
std::map< std::string, col, std::greater< std::string > >::const_iterator aciter
Const map iterator type.
Definition: table.h:2665
void check_synchro() const
Return 0 if the tree and list are properly synchronized.
Definition: table.h:2322
Generic "not found" result.
Definition: err_hnd.h:117
void insert_table(table< vec2_t > &source, std::string src_index, bool allow_extrap=true, std::string dest_index="")
Insert columns from a source table into the new table by interpolation (or extrapolation) ...
Definition: table.h:1006
vec_t empty_col
An empty vector for get_column()
Definition: table.h:2712
generic failure
Definition: err_hnd.h:61
std::vector< aiter > alist
The list of tree iterators.
Definition: table.h:2679
const vec_t & get_column(std::string scol) const
Returns a reference to the column named col. .
Definition: table.h:619
size_t get_interp_type() const
Get the interpolation type.
Definition: table.h:1443
double integ(std::string sx, double x1, double x2, std::string sy)
The integral of the function sy(sx) from sx=x1 to sx=x2.
Definition: table.h:1728
virtual double get_constant(std::string name) const
Get a constant.
Definition: table.h:2193
void clear_data()
Remove all of the data by setting the number of lines to zero.
Definition: table.h:2008
void reset_list()
Set the elements of alist with the appropriate iterators from atree. .
Definition: table.h:2594
std::map< std::string, double > constants
The list of constants.
Definition: table.h:2585
void vector_sort_index(size_t n, const vec_t &data, vec_size_t &order)
Create a permutation which sorts a vector (in increasing order)
Definition: vector.h:801
size_t get_maxlines()
Return the maximum number of lines before a reallocation is required.
Definition: table.h:489
Cubic spline for natural boundary conditions.
Definition: interp.h:72
double interp(std::string sx, double x0, std::string sy)
Interpolate x0 from sx into sy.
Definition: table.h:1453
size_t maxlines
The size of allocated memory.
Definition: table.h:2673
void sort_column(std::string scol)
Individually sort the column scol.
Definition: table.h:2065
double lookup_val(std::string scol, double val, std::string scol2) const
Search column col for the value val and return value in col2.
Definition: table.h:1368
void line_of_names(std::string newheads)
Read a new set of names from newheads.
Definition: table.h:1231
void init_column(std::string scol, double val)
Initialize all values of column named scol to val .
Definition: table.h:870
#define O2SCL_ERR2(d, d2, n)
Set an error, two-string version.
Definition: err_hnd.h:281
Column structure for table [protected].
Definition: table.h:2649
The O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl namespace ...
Definition: table.h:53
std::string dtos(double x, int prec=6, bool auto_prec=false)
Convert a double to a string.
double deriv2(std::string sx, double x0, std::string sy)
The second derivative of the function sy(sx) at sx=x0.
Definition: table.h:1652
size_t ordered_lookup(std::string scol, double val) const
Look for a value in an ordered column .
Definition: table.h:1301
virtual double integ(const double x1, const double x2) const
Give the value of the integral .
Definition: interp.h:1840
virtual void copy_column(std::string src, std::string dest)
Copy data from column named src to column named dest, creating a new column if necessary ...
Definition: table.h:924
col * get_col_struct(std::string lname)
Return the column structure for a column.
Definition: table.h:2695
double interp(size_t ix, double x0, size_t iy)
Interpolate x0 from ix into iy .
Definition: table.h:1509
void get_row(std::string scol, double val, resize_vec_t &row) const
Returns a copy of the row with value val in column col. .
Definition: table.h:505
table(const table &t)
Copy constructor.
Definition: table.h:214
virtual const char * type()
Return the type, "table".
Definition: table.h:2347
void screenify(size_t nin, const string_arr_t &in_cols, std::vector< std::string > &out_cols, size_t max_size=80)
Reformat the columns for output of width size.
Definition: misc.h:124
double eval(std::map< std::string, double > *vars=0)
Evalate the previously compiled expression using variables specified in vars.
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
void make_unique_name(std::string &colx, std::vector< std::string > &cnames)
Make sure a name is unique.
Definition: table.h:2625
void line_of_data(size_t nv, const vec2_t &v)
Read a line of data from the first nv entries in a vector and store as a new row in the table...
Definition: table.h:1254
void copy_row(size_t src, size_t dest)
Copy the data in row src to row dest.
Definition: table.h:1073
virtual void add_constant(std::string name, double val)
Add a constant, or if the constant already exists, change its value.
Definition: table.h:2151
void delete_row(std::string scol, double val)
Delete the row with the entry closest to the value val in column scol .
Definition: table.h:1087
void set_interp_type(size_t interp_type)
Set the base interpolation objects.
Definition: table.h:1432
bool is_number(std::string s)
Return true if the string s is likely a integral or floating point number.
size_t ordered_lookup(const double x0) const
Find the index of x0 in the ordered array x.
Definition: search_vec.h:212
Evaluate a mathematical expression in a string.
double deriv2(size_t ix, double x0, size_t iy)
The second derivative of the function iy(ix) at ix=x0.
Definition: table.h:1710
void delete_rows(std::string func)
Delete all rows where func evaluates to a number greater than 0.5 .
Definition: table.h:1118
double deriv2_const(size_t ix, double x0, size_t iy) const
The second derivative of the function iy(ix) at ix=x0.
Definition: table.h:1719
void delete_row(size_t irow)
Delete the row of index irow .
Definition: table.h:1097
size_t get_ncolumns() const
Return the number of columns.
Definition: table.h:449
virtual bool is_constant(std::string name) const
Test if name is a constant.
Definition: table.h:2185
void new_column(std::string head)
Add a new column owned by the table table .
Definition: table.h:690
void clear()
Clear everything.
Definition: table.h:1983
virtual void summary(std::ostream *out, size_t ncol=79) const
Output a summary of the information stored.
Definition: table.h:2095
aiter end()
Return the end of the column tree.
Definition: table.h:2708
void column_to_vector(std::string scol, resize_vec_t &v) const
Copy a column to a generic vector object.
Definition: table.h:952
void function_column(std::string function, std::string scol)
Make a column from the function specified in function and add it to the table.
Definition: table.h:2445
void integ(std::string x, std::string y, std::string ynew)
The integral of the function iy(ix)
Definition: table.h:1808
bool is_column(std::string scol) const
Return true if scol is a column in the current table table .
Definition: table.h:899
Searching class for monotonic data with caching.
Definition: search_vec.h:79
size_t lookup(int icol, double val) const
Exhaustively search column col for the value val .
Definition: table.h:1388
std::map< std::string, col, std::greater< std::string > >::iterator aiter
Map iterator type.
Definition: table.h:2661
virtual void get_constant(size_t ix, std::string &name, double &val) const
Get a constant by index.
Definition: table.h:2208
Store data in an O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$sc...
Definition: hdf_file.h:96
void set_row(size_t row, size_vec_t &v)
Set an entire row of data.
Definition: table.h:401
table(size_t cmaxlines=0)
Create a new table with space for nlines<=cmaxlines.
Definition: table.h:200
bool intp_set
True if the interpolation object is up-to-date.
Definition: table.h:2717
double row_function(std::string function, size_t row) const
Compute a value by applying a function to a row.
Definition: table.h:2510
std::map< std::string, col, std::greater< std::string > > atree
The tree of columns.
Definition: table.h:2677
void get_row(size_t irow, resize_vec_t &row) const
Returns a copy of row number irow. .
Definition: table.h:531
size_t function_find_row(std::string function) const
Find a row which maximizes a function.
Definition: table.h:2531
Invalid index for array or matrix.
Definition: err_hnd.h:123
size_t itype
Current interpolation type.
Definition: table.h:2720
double stod(std::string s, bool err_on_fail=true)
Convert a string to a double.
virtual int read_generic(std::istream &fin, int verbose=0)
Clear the current table and read from a generic data file.
Definition: table.h:2230
void add_col_from_table(table< vec2_t > &source, std::string src_index, std::string src_col, std::string dest_index, std::string dest_col="")
Insert a column from a separate table, interpolating it into a new column.
Definition: table.h:984
std::string itos(int x)
Convert an integer to a string.
static const double x2[5]
Definition: inte_qng_gsl.h:66
virtual double eval(const double x0) const
Give the value of the function .
Definition: interp.h:1802
std::string get_column_name(size_t icol) const
Returns the name of column col .
Definition: table.h:758
static const double x1[5]
Definition: inte_qng_gsl.h:48
std::string szttos(size_t x)
Convert a size_t to a string.
void hdf_input(hdf_file &hf, o2scl::table< vec_t > &t, std::string name)
Input a o2scl::table object from a hdf_file.
Definition: hdf_io.h:59
vec_t dat
Pointer to column.
Definition: table.h:2652
std::vector< aiter >::iterator aviter
Vector iterator type.
Definition: table.h:2667
int index
Column index.
Definition: table.h:2654
void clear_constants()
CLear all constants.
Definition: table.h:2018
void vector_sort_double(size_t n, vec_t &data)
Sort a vector of doubles (in increasing order)
Definition: vector.h:852
double deriv2_const(std::string sx, double x0, std::string sy) const
The second derivative of the function sy(sx) at sx=x0.
Definition: table.h:1686
double deriv_const(size_t ix, double x0, size_t iy) const
The first derivative of the function iy(ix) at ix=x0.
Definition: table.h:1618
size_t lookup_column(std::string lname) const
Find the index for column named name .
Definition: table.h:911
size_t lookup(std::string scol, double val) const
Exhaustively search column col for the value val .
Definition: table.h:1325
Interpolation class for general vectors.
Definition: interp.h:1558
void inc_maxlines(size_t llines)
Manually increase the maximum number of lines.
Definition: table.h:582
virtual void swap_column_data(std::string scol, vec_t &v)
Swap the data in column scol with that in vector v.
Definition: table.h:777
std::string get_sorted_name(size_t icol) const
Returns the name of column col in sorted order. .
Definition: table.h:854
void sort_table(std::string scol)
Sort the entire table by the column scol.
Definition: table.h:2033
virtual void rename_column(std::string src, std::string dest)
Rename column named src to dest .
Definition: table.h:796

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