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

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

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page