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

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