00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2006, 2007, 2008, 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
,
O2scl Sourceforge Project Page