00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef TEUCHOS_TABULAR_OUTPUTTER_HPP
00030 #define TEUCHOS_TABULAR_OUTPUTTER_HPP
00031
00032
00033 #include "Teuchos_FancyOStream.hpp"
00034 #include "Teuchos_Array.hpp"
00035 #include "Teuchos_Tuple.hpp"
00036 #include "Teuchos_RCP.hpp"
00037 #include "Teuchos_Time.hpp"
00038 #include "Teuchos_Exceptions.hpp"
00039
00040
00041 namespace Teuchos {
00042
00043
00048 class TabularOutputter {
00049 public:
00050
00053
00055 enum EFieldType { DOUBLE, INT, STRING };
00056 enum { numFieldTypes = 3 };
00057
00059 enum EFieldJustification { LEFT, RIGHT };
00060 enum { numFieldJustifications = 2 };
00061
00063 enum EFloatingOutputType { SCIENTIFIC, GENERAL };
00064 enum { numFloatingOutputTypes = 2 };
00065
00067 class MissingFieldsError : public ExceptionBase
00068 {public:MissingFieldsError(const std::string& what_arg) : ExceptionBase(what_arg) {}};
00069
00071 class InvalidFieldSpecError : public ExceptionBase
00072 {public:InvalidFieldSpecError(const std::string& what_arg) : ExceptionBase(what_arg) {}};
00073
00075 class MissingHeaderError : public ExceptionBase
00076 {public:MissingHeaderError(const std::string& what_arg) : ExceptionBase(what_arg) {}};
00077
00079 class InvalidFieldOutputError : public ExceptionBase
00080 {public:InvalidFieldOutputError(const std::string& what_arg) : ExceptionBase(what_arg) {}};
00081
00083
00085 TabularOutputter(std::ostream &out);
00086
00088 TabularOutputter(const RCP<std::ostream> &out);
00089
00091 void setOStream( const RCP<std::ostream> &out );
00092
00094 void pushFieldSpec( const std::string &fieldName,
00095 const EFieldType fieldType = DOUBLE,
00096 const EFieldJustification fieldJustification = RIGHT,
00097 const EFloatingOutputType floatingOutputType = SCIENTIFIC,
00098 const int width = -1
00099 );
00100
00105 void setFieldTypePrecision( const EFieldType fieldType, const int prec );
00106
00108 void outputHeader();
00109
00111 template<typename T>
00112 void outputField( const T& t );
00113
00115 void nextRow(const bool allowRemainingFields = false);
00116
00117 private:
00118
00119
00120
00121 struct FieldSpec {
00122 FieldSpec(std::string fieldName_in, EFieldType fieldType_in,
00123 EFieldJustification fieldJustification_in,
00124 EFloatingOutputType floatingOutputType_in,
00125 const int outputWidth_in
00126 )
00127 :fieldName(fieldName_in), fieldType(fieldType_in),
00128 fieldJustification(fieldJustification_in),
00129 floatingOutputType(floatingOutputType_in),
00130 outputWidth(outputWidth_in),
00131 precision(-1)
00132 {}
00133 std::string fieldName;
00134 EFieldType fieldType;
00135 EFieldJustification fieldJustification;
00136 EFloatingOutputType floatingOutputType;
00137 int outputWidth;
00138 int precision;
00139 };
00140
00141
00142
00143 static const std::string fieldSpacer_;
00144
00145 Array<FieldSpec> fieldSpecs_;
00146 RCP<FancyOStream> out_;
00147 Tuple<int,numFieldTypes> fieldTypePrecision_;
00148
00149 int currFieldIdx_;
00150
00151 Time timer_;
00152 int numLoops_;
00153
00154
00155
00156 void initialize();
00157
00158 double adjustTime( const double &time_in )
00159 {
00160 return ( time_in > 0.0 ? time_in : -1.0 );
00161 }
00162
00163 public:
00164
00165 void startTimer(const int numLoops)
00166 {
00167 timer_.reset();
00168 timer_.start();
00169 numLoops_ = numLoops;
00170 }
00171
00172 double stopTimer()
00173 {
00174 #ifdef TEUCHOS_DEBUG
00175 TEST_FOR_EXCEPT(numLoops_ == -1);
00176 #endif
00177 timer_.stop();
00178 const double relTime =
00179 adjustTime(timer_.totalElapsedTime()) / numLoops_;
00180 numLoops_ = -1;
00181 return relTime;
00182 }
00183
00184 private:
00185
00186
00187 TabularOutputter();
00188
00189 };
00190
00191
00193 #define TEUCHOS_START_PERF_OUTPUT_TIMER(OUTPUTTER, NUMLOOPS) \
00194 (OUTPUTTER).startTimer(NUMLOOPS); \
00195 for ( int k = 0; k < (NUMLOOPS); ++k )
00196
00197
00201 #define TEUCHOS_END_PERF_OUTPUT_TIMER(OUTPUTTER, VARNAME) \
00202 const double VARNAME = (OUTPUTTER).stopTimer(); \
00203 (OUTPUTTER).outputField(VARNAME)
00204
00205
00206
00207
00208
00209
00210
00211 template<typename T>
00212 void TabularOutputter::outputField( const T& t )
00213 {
00214
00215 using std::setw;
00216
00217 #ifdef TEUCHOS_DEBUG
00218 TEST_FOR_EXCEPTION(
00219 currFieldIdx_ == -1,
00220 MissingHeaderError,
00221 "Error, you can not output a field until you print the header with"
00222 " outputHeader()."
00223 );
00224 TEST_FOR_EXCEPTION(
00225 !(currFieldIdx_ < as<int>(fieldSpecs_.size())),
00226 InvalidFieldOutputError,
00227 "Error, you have already output all of the "
00228 << fieldSpecs_.size() << " fields for this tabular output."
00229 " You must call nextRow() before outputting to the next row."
00230 );
00231 #endif
00232
00233 FieldSpec &fieldSpec = fieldSpecs_[currFieldIdx_];
00234
00235 *out_ << fieldSpacer_ << std::setprecision(fieldSpec.precision);
00236
00237 switch(fieldSpec.fieldJustification) {
00238 case LEFT:
00239 *out_ << std::left;
00240 break;
00241 case RIGHT:
00242 *out_ << std::right;
00243 break;
00244 default: {
00245 TEST_FOR_EXCEPT(true);
00246 }
00247 }
00248
00249 switch(fieldSpec.floatingOutputType) {
00250 case SCIENTIFIC:
00251 *out_ << std::scientific;
00252 break;
00253 case GENERAL:
00254 *out_ << std::fixed;
00255 break;
00256 default: {
00257 TEST_FOR_EXCEPT(true);
00258 }
00259 }
00260
00261 *out_ << setw(fieldSpec.outputWidth) << t;
00262
00263 ++currFieldIdx_;
00264
00265 }
00266
00267
00268
00269 }
00270
00271
00272 #endif // TEUCHOS_TABULAR_OUTPUTTER_HPP