|
DenseLinAlgPack: Concreate C++ Classes for Dense Blas-Compatible Linear Algebra Version of the Day
|
00001 // @HEADER 00002 // *********************************************************************** 00003 // 00004 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization 00005 // Copyright (2003) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 // @HEADER 00028 00029 #ifndef LINALGPACK_IO_FORMAT_H 00030 #define LINALGPACK_IO_FORMAT_H 00031 00032 #include <ios> 00033 00034 #include "DenseLinAlgPack_IOBasic.hpp" 00035 00036 namespace DenseLinAlgPack { 00037 namespace LinAlgPackIO { 00038 00040 /* * This class is used to encapsulate a set of bit flags. 00041 */ 00042 class bit_flags { 00043 public: 00044 00046 typedef LinAlgPackIO::fmtflags fmtflags; 00047 00049 bit_flags() : flags_((fmtflags)(0x0000)) {} 00050 00052 fmtflags flags() const { 00053 return flags_; 00054 } 00055 00057 fmtflags flags(fmtflags f) { 00058 fmtflags f_tmp = flags_; 00059 flags_ = f; 00060 return f_tmp; 00061 } 00062 00064 fmtflags setf(fmtflags f) { 00065 return flags( (fmtflags)(flags() | f) ); 00066 } 00067 00069 fmtflags setf(fmtflags f, fmtflags mask) { 00070 return flags( (fmtflags)(flags() | (f&mask)) ); 00071 } 00072 00074 void unsetf(fmtflags mask) { 00075 flags( (fmtflags)(flags() & ~mask) ); 00076 } 00077 00078 private: 00079 fmtflags flags_; 00080 00081 }; // end class flags 00082 00084 /* * Memento class that saves the state of a standard stream. 00085 * 00086 * This is a variation of the "Memento" Pattern in Gama et. al. 00087 * 00088 * Allow default copy constructor and assignment operator. 00089 * The default constuctor is private so the only way to 00090 * create an object of this class if from another object 00091 * or from save_format(). 00092 */ 00093 class ios_format_memento { 00094 public: 00096 static ios_format_memento save_format(const std::ios& s); 00097 00099 void set_format(std::ios& s) const; 00100 00101 private: 00102 LinAlgPackIO::fmtflags flags_; 00103 int prec_; 00104 int wdt_; 00105 int fill_; 00106 00108 ios_format_memento() : flags_((fmtflags)(0)), prec_(6), wdt_(0) 00109 , fill_(' ') {} 00110 00111 }; // end class ios_format_memento 00112 00113 template<class T> class bound_format; 00114 template<class T> class const_bound_format; 00115 00117 /* * This class is used to allow some flexiblility in inputing 00118 * and outputing of DVector, DVectorSlice, DMatrix and DMatrixSlice objects. 00119 * It maintains format information for a #std::ios_base# object and adds 00120 * additional format information. 00121 * 00122 * The idea for this class is based on the user-defined manipulator given in 00123 * Stroustrup 1997, p. 635. The main difference is that the non-member funciton 00124 * bind(format,object) is used to create a bound format object and not that 00125 * member function operator(). To use operator() would require a template 00126 * member function and they are not supposed to be allowed in MS VC++ 5.0. 00127 * 00128 * Warning: The default constructor sets the formating flags to false but this 00129 * may not be the default value for the actual ios stream. It is recommended 00130 * that you start with the formating settings of a valid ios stream and then 00131 * change the flags that you want. You can do this on construction with 00132 * 00133 * #format f(cin);#\\ 00134 * 00135 * or after construction using 00136 * 00137 * #format f;#\\ 00138 * #f.copy_format(cin);#\\ 00139 * 00140 * then set the formating using the manipulator like functions. 00141 * 00142 * The default copy constructor and assignment operator functions are allowed. 00143 */ 00144 class format { 00145 public: 00146 00148 typedef LinAlgPackIO::fmtflags fmtflags; 00149 00151 format() : prec_(6), wdt_(0), fill_(' ') {} 00152 00154 format(const std::ios& s) { 00155 copy_format(s); 00156 } 00157 00158 /* * @name Access format flags objects 00159 */ 00160 // @{ 00161 00163 bit_flags& ios_base_flags() { return ios_base_flags_; } 00165 const bit_flags& ios_base_flags() const { return ios_base_flags_; } 00166 00168 bit_flags& extra_flags() { return extra_flags_; } 00170 const bit_flags& extra_flags() const { return extra_flags_; } 00171 00172 // @} 00173 00174 /* * @name Manipulator like functions for standard floating-point number formating. 00175 * 00176 * These member functions are ment to mirror the standard input/output 00177 * manipulator functions. Their names are the same and you can set 00178 * a list of options in one statement like: 00179 * 00180 * #format_obj.showpos().setprecision(6).fixed();#\\ 00181 * 00182 * The primary difference is that #width# presists over all uses in output 00183 * operations while the standard #width# manipulator only applys to the next 00184 * operation. See \Ref{bound_format} and \Ref{operator>>} for details 00185 * on how objects of this class are used to specify formating for input/output 00186 * operations. 00187 */ 00188 // @{ 00189 00191 format& showpoint() { ios_base_flags().setf(std::ios_base::showpoint); return *this; } 00193 format& noshowpoint() { ios_base_flags().unsetf(std::ios_base::showpoint); return *this; } 00195 format& showpos() { ios_base_flags().setf(std::ios_base::showpos); return *this; } 00197 format& noshowpos() { ios_base_flags().unsetf(std::ios_base::showpos); return *this; } 00199 format& skipws() { ios_base_flags().setf(std::ios_base::skipws); return *this; } 00201 format& noskipws() { ios_base_flags().unsetf(std::ios_base::skipws); return *this; } 00203 format& uppercase() { ios_base_flags().setf(std::ios_base::uppercase); return *this; } 00205 format& nouppercase() { ios_base_flags().unsetf(std::ios_base::uppercase); return *this; } 00207 format& internal() { 00208 ios_base_flags().setf(std::ios_base::internal, std::ios_base::adjustfield); 00209 return *this; 00210 } 00212 format& left() { 00213 ios_base_flags().setf(std::ios_base::left, std::ios_base::adjustfield); 00214 return *this; 00215 } 00217 format& right() { 00218 ios_base_flags().setf(std::ios_base::right, std::ios_base::adjustfield); 00219 return *this; 00220 } 00222 format& general() { 00223 ios_base_flags().setf((fmtflags)0, std::ios_base::floatfield); 00224 return *this; 00225 } 00227 format& fixed() { 00228 ios_base_flags().setf(std::ios_base::fixed, std::ios_base::floatfield); 00229 return *this; 00230 } 00232 format& scientific() { 00233 ios_base_flags().setf(std::ios_base::scientific, std::ios_base::floatfield); 00234 return *this; 00235 } 00237 format& setfill(int c) { fill_ = c; return *this; } 00239 format& setprecision(int p) { prec_ = p; return *this; } 00241 format& setw(int w) { wdt_ = w; return *this; } 00242 00243 // @} 00244 00245 /* * @name Manipulator like functions for extra I/O formatin. 00246 * 00247 * These member functions are ment to mirror the type of standard input/output 00248 * manipulator functions accept they are used to set extra flags for 00249 * #DenseLinAlgPack::ignore_dim_bit# and #DenseLinAlgPack::no_insert_newlines_bit#. 00250 * This allows them to be set in the same statement that sets a standard 00251 * option. For example you can write: 00252 * 00253 * #format_obj.showpos().setprecision(6).fixed().ignore_dim().no_insert_newlines();#\\ 00254 * 00255 * Like the member functions that simulate the standard manipulators these 00256 * options presist after input/output operations. 00257 */ 00258 // @{ 00259 00261 format& ignore_dim() 00262 { 00263 extra_flags().setf((fmtflags)(ignore_dim_bit)); 00264 return *this; 00265 } 00267 format& no_ignore_dim() 00268 { 00269 extra_flags().unsetf((fmtflags)(ignore_dim_bit)); 00270 return *this; 00271 } 00273 format& insert_newlines() 00274 { 00275 extra_flags().unsetf((fmtflags)(no_insert_newlines_bit)); 00276 return *this; 00277 } 00279 format& no_insert_newlines() 00280 { 00281 extra_flags().setf((fmtflags)(no_insert_newlines_bit)); 00282 return *this; 00283 } 00284 00285 // @} 00286 00287 /* * @name Other access functions 00288 */ 00289 // @{ 00290 00292 int precision() const { return prec_; } 00294 int precision(int p) { int tmp = prec_; prec_ = p; return tmp; } 00296 int width() const { return wdt_; } 00298 int width(int w) { int tmp = wdt_; wdt_ = w; return tmp; } 00300 int fill() const { return fill_; } 00302 int fill(int c) { int tmp = fill_; fill_ = c; return tmp; } 00303 00304 // @} 00305 00306 /* * @name Utility functions for saving and replacing a streams format state 00307 */ 00308 // @{ 00309 00311 void copy_format(const std::ios& s); 00312 00314 void set_format(std::ios& s) const; 00315 00316 // @} 00317 00318 00319 // ToDo: Enable these once member templates are supported. This is much more 00320 // attractive syntasticaly than using bind() and cbind() 00321 // 00322 // /// 00323 // template<class T> 00324 // bound_format<T> operator()(T& obj); 00325 // 00326 // /// 00327 // template<class T> 00328 // const_bound_format<T> operator()(const T& obj) const; 00329 00330 private: 00331 bit_flags ios_base_flags_; 00332 bit_flags extra_flags_; 00333 int prec_; 00334 int wdt_; 00335 int fill_; 00336 00337 }; // end class LinAlgPackIOFormat 00338 00339 00340 // //////////////////////////////////////////////////////////////////////////////// 00341 // Format binding classes and functions 00342 00343 template<class T> class const_bound_format; 00344 00346 /* * Special I/O manipulator class for non-constant objects. 00347 * 00348 * This class as a special manipulator and is composed of a composition 00349 * of a format object and a templated object that is used in an input 00350 * or output operation. 00351 * 00352 * An object of this class should only be created by using 00353 * the bind(format,obj) function. It object can not default constructed 00354 * or assigned. 00355 * 00356 * Objects of this class can be implicitly converted to const_bound_format 00357 * for use in output operations. 00358 */ 00359 template<class T> 00360 class bound_format { 00361 public: 00362 00364 bound_format(const format& f, T& obj) : f_(f), obj_(obj) {} 00365 00367 const format& f() const { return f_; } 00369 T& obj() { return obj_; } 00371 const T& obj() const { return obj_; } 00372 00373 private: 00374 const format& f_; 00375 T& obj_; 00376 00377 // not defined and not to be called 00378 bound_format(); 00379 bound_format& operator=(const bound_format&); 00380 00381 }; // end class bound_format 00382 00384 /* * Special I/O manipulator class for constant objects. 00385 * 00386 * This class as a special manipulator and is composed of a composition 00387 * of a format object and a const templated object that is used only in 00388 * an output operation. 00389 * 00390 * An object of this class can only be created by using 00391 * the bind(f,obj) operation. It can not be default constructed or assigned. 00392 * It is only to be used in input or output operations. 00393 */ 00394 template<class T> 00395 class const_bound_format { 00396 public: 00397 00399 const_bound_format(const format& f, const T& obj) : f_(f), obj_(obj) {} 00400 00402 const_bound_format(const bound_format<T>& bf) : f_(bf.f()), obj_(bf.obj()) {} 00403 00405 const format& f() const { return f_; } 00407 const T& obj() const { return obj_; } 00408 00409 private: 00410 const format& f_; 00411 const T& obj_; 00412 00413 // not defined and not to be called 00414 const_bound_format(); 00415 const_bound_format& operator=(const const_bound_format&); 00416 00417 }; // end class const_bound_format 00418 00420 /* * Returns a bound_format<T> object using this format object. 00421 * 00422 * Using templated input/output operator functions this function 00423 * is used to bind a format to a non-const target object for a 00424 * input/output stream operation. For example, to bind the format 00425 * for a single output operation using the streams set formating 00426 * and addition formating use something like: 00427 * 00428 * #DVector v(1.0,5);#\\ 00429 * #format f; f.copy_format(cout);#\\ 00430 * #f.width(10).fixed().ignore_dim();#\\ 00431 * #cout << bind(f,v);#\\1 00432 */ 00433 template<class T> 00434 inline bound_format<T> bind(const format& f, T& obj) { 00435 return bound_format<T>(f,obj); 00436 } 00437 00439 /* * Returns a const_bound_format<T> using this format object. 00440 * 00441 * This function works the same as the previous \Ref{bind}#()# function 00442 * accept it is for a const target object. It could not use 00443 * the name #bind# due to ambiguity problems. 00444 */ 00445 template<class T> 00446 inline const_bound_format<T> cbind(const format& f, const T& obj) { 00447 return const_bound_format<T>(f,obj); 00448 } 00449 00450 // /////////////////////////////////////// 00451 // Inline functions for members of format 00452 00453 // Use once member templates are supported. See class format 00454 // 00455 //template<class T> 00456 //inline bound_format<T> format::operator()(T& obj) { 00457 // return bind(*this,obj); 00458 //} 00459 00460 //template<class T> 00461 //inline const_bound_format<T> format::operator()(const T& obj) const { 00462 // return cbind(*this,obj); 00463 //} 00464 00465 } // end namespace LinAlgPackIO 00466 } // end namespace DenseLinAlgPack 00467 00468 #endif // LINALGPACK_IO_FORMAT_H
1.7.4