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