columnify.h

Go to the documentation of this file.
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_COLUMNIFY_H
00024 #define O2SCL_COLUMNIFY_H
00025 /** \file columnify.h
00026     \brief Functions to create output in columns
00027 */
00028 
00029 #include <iostream>
00030 #include <string>
00031 #include <vector>
00032 #include <o2scl/misc.h>
00033 
00034 #ifndef DOXYGENP
00035 namespace o2scl {
00036 #endif
00037 
00038   /** 
00039       \brief Create nicely formatted columns from a table of strings
00040 
00041 
00042     
00043       This is a brute-force approach of order \f$ \mathrm{ncols} \times
00044       \mathrm{nrows} \f$.
00045       
00046       \todo Move the screenify() functionality from misc.h into this class?
00047   */
00048   class columnify {
00049   
00050   public:
00051   
00052     columnify() {
00053     }
00054 
00055     /// Align the left-hand sides
00056     static const int align_left=1;
00057     /// Align the right-hand sides
00058     static const int align_right=2;
00059     /// Center, slightly to the left if spacing is uneven
00060     static const int align_lmid=3;
00061     /// Center, slightly to the right if spacing is uneven
00062     static const int align_rmid=4;
00063     /// Align with decimal points
00064     static const int align_dp=5;
00065     /** \brief Align negative numbers to the left and use a space for 
00066         positive numbers
00067     */
00068     static const int align_lnum=6;
00069   
00070     /** \brief Take \c table and create a new object \c ctable with 
00071         appropriately formatted columns
00072 
00073         The table of strings should be stored in \c table in
00074         "column-major" order, so that \c table has the interpretation
00075         of a set of columns to be aligned. Before calling align(), \c
00076         ctable should be allocated so that at least the first \c nrows
00077         entries can be assigned, and \c align_spec should contain \c
00078         ncols entries specifying the style of alignment for each
00079         column.
00080     */
00081     template<class mat_string_t, class vec_string_t, class vec_int_t>
00082       int align(const mat_string_t &table, size_t ncols, size_t nrows, 
00083                 vec_string_t &ctable, vec_int_t &align_spec) {
00084       
00085       // Make space for the size information
00086       size_t *csizes=new size_t[ncols], *csizes2=new size_t[ncols];
00087       for(size_t i=0;i<ncols;i++) {
00088         csizes[i]=0;
00089         csizes2[i]=0;
00090       }
00091   
00092       // Compute the sizes of all the entries in all of the columns so
00093       // we know how many spaces to add
00094       for(size_t i=0;i<ncols;i++) {
00095         for(size_t j=0;j<nrows;j++) {
00096           if (align_spec[i]==align_dp) {
00097             size_t loc=table[i][j].find('.');
00098             std::string left, right;
00099             if (loc!=std::string::npos) {
00100               left=table[i][j].substr(0,loc+1);
00101               right=table[i][j].substr(loc+1,
00102                                        table[i][j].length()-loc-1);
00103             } else {
00104               left=table[i][j]+' ';
00105               right="";
00106             }
00107             if (left.length()>csizes[i]) csizes[i]=left.length();
00108             if (right.length()>csizes2[i]) csizes2[i]=right.length();
00109           } else {
00110             if (table[i][j].length()>csizes[i]) csizes[i]=table[i][j].length();
00111           }
00112         }
00113       }
00114 
00115       // Go through row by row, adding enough spaces to make one string
00116       // per row
00117       for(size_t j=0;j<nrows;j++) {
00118 
00119         std::string tmp="";
00120 
00121         for(size_t i=0;i<ncols;i++) {
00122 
00123           // Handle each alignment case separately
00124           if (align_spec[i]==align_right) {
00125 
00126             for(size_t k=table[i][j].length();k<csizes[i];k++) {
00127               tmp+=' ';
00128             }
00129             tmp+=table[i][j];
00130             if (i!=ncols-1) tmp+=' ';
00131 
00132           } else if (align_spec[i]==align_left) {
00133 
00134             tmp+=table[i][j];
00135             for(size_t k=table[i][j].length();k<csizes[i];k++) {
00136               tmp+=' ';
00137             }
00138             if (i!=ncols-1) tmp+=' ';
00139 
00140           } else if (align_spec[i]==align_lmid) {
00141 
00142             size_t le=(csizes[i]-table[i][j].length())/2;
00143             size_t ri=csizes[i]-table[i][j].length()-le;
00144             for(size_t k=0;k<le;k++) tmp+=' ';
00145             tmp+=table[i][j];
00146             for(size_t k=0;k<ri;k++) tmp+=' ';
00147             if (i!=ncols-1) tmp+=' ';
00148 
00149           } else if (align_spec[i]==align_rmid) {
00150 
00151             size_t ri=(csizes[i]-table[i][j].length())/2;
00152             size_t le=csizes[i]-table[i][j].length()-ri;
00153             for(size_t k=0;k<le;k++) tmp+=' ';
00154             tmp+=table[i][j];
00155             for(size_t k=0;k<ri;k++) tmp+=' ';
00156             if (i!=ncols-1) tmp+=' ';
00157 
00158           } else if (align_spec[i]==align_dp) {
00159 
00160             size_t loc=table[i][j].find('.');
00161             std::string left, right;
00162             if (loc!=std::string::npos) {
00163               left=table[i][j].substr(0,loc+1);
00164               right=table[i][j].substr(loc+1,
00165                                        table[i][j].length()-loc-1);
00166             } else {
00167               left=table[i][j]+' ';
00168               right="";
00169             }
00170 
00171             for(size_t k=left.length();k<csizes[i];k++) tmp+=' ';
00172             tmp+=left;
00173             tmp+=right;
00174             for(size_t k=right.length();k<csizes2[i];k++) tmp+=' ';
00175             if (i!=ncols-1) tmp+=' ';
00176 
00177           } else if (align_spec[i]==align_lnum) {
00178 
00179             if (table[i][j].length()==csizes[i]) {
00180               tmp+=table[i][j];
00181             } else {
00182               if (table[i][j][0]>='0' && table[i][j][0]<='9') {
00183                 tmp+=' ';
00184                 tmp+=table[i][j];
00185                 for(size_t k=table[i][j].length();k<csizes[i]-1;k++) {
00186                   tmp+=' ';
00187                 }
00188               } else {
00189                 tmp+=table[i][j];
00190                 for(size_t k=table[i][j].length();k<csizes[i];k++) {
00191                   tmp+=' ';
00192                 }
00193               }
00194             }
00195             if (i!=ncols-1) tmp+=' ';
00196           }
00197         
00198         }
00199 
00200         // Add the row to the user-specified array and go to the next row
00201         ctable[j]=tmp;
00202       
00203       }
00204 
00205       // Free the memory assocated with the column widths
00206       delete[] csizes;
00207       delete[] csizes2;
00208   
00209       return 0;
00210     }
00211   
00212   };
00213 
00214   /** 
00215       \brief A operator for naive matrix output
00216 
00217 
00218       
00219       The type \c mat_t can be any matrix type which allows 
00220       individual element access using \c operator()(size_t,size_t).
00221       
00222       This outputs all of the matrix elements using output settings
00223       specified by \c os. The alignment performed by \ref columnify
00224       using columnify::align_dp, i.e. the numbers are aligned by
00225       their decimal points. If the numbers have no decimal points,
00226       then the decimal point is assumed to be to the right of the
00227       last character in the string represetation of the number.
00228 
00229       \todo Might need to test to see what happens if all of the
00230       matrix elements are positive integers and scientific mode
00231       is not set.
00232   */
00233   template<class mat_t> int matrix_out(std::ostream &os, mat_t &A,
00234                                        size_t nrows, size_t ncols) {
00235     
00236     columnify co;
00237     std::string **stab;
00238     stab=o2scl::new_2d_array<std::string>(ncols,nrows);
00239     std::vector<std::string> ctable(nrows);
00240     std::vector<int> alig(ncols);
00241     
00242     for(size_t j=0;j<ncols;j++) {
00243       alig[j]=columnify::align_dp;
00244       for(size_t i=0;i<nrows;i++) {
00245         stab[j][i]=dtos(A(i,j),os);
00246       }
00247     }
00248     co.align(stab,ncols,nrows,ctable,alig);
00249     for(size_t i=0;i<nrows;i++) {
00250       os << ctable[i] << std::endl;
00251     }
00252     
00253     o2scl::delete_2d_array(stab,ncols);
00254 
00255     return 0;
00256   }
00257 
00258   /** 
00259       \brief A operator for naive complex matrix output
00260   */
00261   template<class mat_t> int matrix_cx_out(std::ostream &os, mat_t &A,
00262                                           size_t nrows, size_t ncols) {
00263     
00264     columnify co;
00265     std::string **stab;
00266     stab=o2scl::new_2d_array<std::string>(ncols,nrows);
00267     std::vector<std::string> ctable(nrows);
00268     std::vector<int> alig(ncols);
00269     
00270     for(size_t j=0;j<ncols;j++) {
00271       alig[j]=columnify::align_left;
00272       for(size_t i=0;i<nrows;i++) {
00273         stab[j][i]=((std::string)"(")+dtos(A(i,j).dat[0],os)+
00274           ((std::string)",")+dtos(A(i,j).dat[1],os)+((std::string)")");
00275       }
00276     }
00277     co.align(stab,ncols,nrows,ctable,alig);
00278     for(size_t i=0;i<nrows;i++) {
00279       os << ctable[i] << std::endl;
00280     }
00281     
00282     o2scl::delete_2d_array(stab,ncols);
00283 
00284     return 0;
00285   }
00286 
00287   /** 
00288       \brief A operator for naive 2-d array output
00289 
00290 
00291       
00292       The type \c mat_t can be any 2d-array type which allows 
00293       individual element access using \c [size_t][size_t]
00294       
00295       This outputs all of the matrix elements using output settings
00296       specified by \c os. The alignment performed by \ref columnify
00297       using columnify::align_dp, i.e. the numbers are aligned by
00298       their decimal points. If the numbers have no decimal points,
00299       then the decimal point is assumed to be to the right of the
00300       last character in the string represetation of the number.
00301 
00302       \todo If all of the matrix elements are positive integers 
00303       and scientific mode is not set, then we can avoid printing
00304       the extra spaces.
00305   */
00306   template<class mat_t> int array_2d_out(std::ostream &os, mat_t &A,
00307                                          size_t nrows, size_t ncols) {
00308     
00309     columnify co;
00310     std::string **stab;
00311     stab=o2scl::new_2d_array<std::string>(ncols,nrows);
00312     std::vector<std::string> ctable(nrows);
00313     std::vector<int> alig(ncols);
00314     
00315     for(size_t j=0;j<ncols;j++) {
00316       alig[j]=columnify::align_dp;
00317       for(size_t i=0;i<nrows;i++) {
00318         stab[j][i]=dtos(A[i][j],os);
00319       }
00320     }
00321     co.align(stab,ncols,nrows,ctable,alig);
00322     for(size_t i=0;i<nrows;i++) {
00323       os << ctable[i] << std::endl;
00324     }
00325     
00326     o2scl::delete_2d_array(stab,ncols);
00327 
00328     return 0;
00329   }
00330 
00331 #ifndef DOXYGENP
00332 }
00333 #endif
00334 
00335 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.