Go to the documentation of this file.00001
00008
00009
00010
00011
00012 #ifndef ECL_CONTAINERS_COMMON_FORMATTERS_HPP_
00013 #define ECL_CONTAINERS_COMMON_FORMATTERS_HPP_
00014
00015
00016
00017
00018
00019 #include <cmath>
00020 #include <ecl/config/macros.hpp>
00021 #include <ecl/formatters/common.hpp>
00022 #include <ecl/formatters/number.hpp>
00023 #include <ecl/formatters/floats.hpp>
00024
00025
00026
00027
00028
00029 namespace ecl {
00030 namespace formatters {
00031
00032
00033
00034
00035
00036
00037
00038
00039
00066 template <typename Container >
00067 class ECL_LOCAL FloatContainerFormatter {
00068 public:
00069
00070
00071
00072 typedef typename Container::value_type value_type;
00080 FloatContainerFormatter(const unsigned int p = 2, const int w=-1) :
00081 old_precision(-1),
00082 tmp_width(-1),
00083 prm_width(w),
00084 width_ptr(&prm_width),
00085 format(w,p,ecl::RightAlign,ecl::Fixed),
00086 container(NULL),
00087 ready_to_format(false)
00088 {}
00089
00090 virtual ~FloatContainerFormatter() {}
00091
00100 FloatContainerFormatter& precision(const unsigned int p) { format.precision(p); return *this; }
00111 FloatContainerFormatter& width(const int w) { prm_width = w; return *this; }
00118 unsigned int precision() const { return format.precision(); }
00126 FloatContainerFormatter& operator()(const unsigned int p, const int w) { format.precision(p); prm_width(w); return *this; }
00137 FloatContainerFormatter& operator()(const Container &c) { container = &c; ready_to_format = true; return *this; }
00151 FloatContainerFormatter& operator()(Container &c, const unsigned int p, const int w) {
00152 container = &c;
00153 ready_to_format = true;
00154 old_precision = format.precision();
00155 format.precision(p);
00156 tmp_width = w;
00157 width_ptr = &tmp_width;
00158 return *this;
00159 }
00160
00170 template <typename OutputStream, typename Container_>
00171 friend OutputStream& operator << (OutputStream& ostream, FloatContainerFormatter< Container_ > &formatter) ecl_assert_throw_decl(StandardException);
00172
00173 private:
00174 long digits(value_type min_coeff, value_type max_coeff);
00175
00176 int old_precision;
00177 int tmp_width, prm_width;
00178 int* width_ptr;
00179 Format< value_type > format;
00180 const Container *container;
00181 bool ready_to_format;
00182 };
00183
00192 template <typename Container >
00193 long FloatContainerFormatter<Container>::digits(value_type min_coeff, value_type max_coeff) {
00194 long min_digits, max_digits;
00195 long actual_digits;
00196 min_digits = static_cast<long> ( ceil(log10(fabs(min_coeff)+1)) );
00197 max_digits = static_cast<long> ( ceil(log10(fabs(max_coeff)+1)) );
00198 if ( min_digits < max_digits ) {
00199 actual_digits = max_digits;
00200 } else {
00201 if ( ( min_digits == 0 ) && ( max_digits == 0 ) ) {
00202 min_digits = 1;
00203 }
00204 actual_digits = min_digits;
00205 }
00206 if ( min_coeff < 0 ) { actual_digits += 1; }
00207 actual_digits += 1 + format.precision();
00208 return actual_digits;
00209 }
00210
00211
00212
00213
00214
00215 template <typename OutputStream, typename Container_>
00216 OutputStream& operator << (OutputStream& ostream, FloatContainerFormatter< Container_ > &formatter) ecl_assert_throw_decl(StandardException) {
00217 ecl_assert_throw(formatter.ready_to_format, StandardException(LOC,UsageError,"The formatter cannot print any data - "
00218 "either there is no data available, or you have tried to use the "
00219 "formatter more than once in a single streaming operation. "
00220 "C++ produces unspecified results when functors are used multiply "
00221 "in the same stream sequence, so this is not permitted here.") );
00222
00223 if ( *(formatter.width_ptr) == -1 ) {
00224
00225
00226
00227 typename Container_::value_type min_coeff, max_coeff;
00228 const typename Container_::value_type *cur_coeff;
00229 min_coeff = (*formatter.container)[0];
00230 max_coeff = min_coeff;
00231
00232
00233 for ( unsigned int i = 1; i < formatter.container->size(); ++i) {
00234 cur_coeff = &(*formatter.container)[i];
00235 if ( *cur_coeff > max_coeff ) { max_coeff = *cur_coeff; }
00236 if ( *cur_coeff < min_coeff ) { min_coeff = *cur_coeff; }
00237 }
00238
00239
00240
00241 formatter.format.width(formatter.digits(min_coeff,max_coeff));
00242 } else {
00243 formatter.format.width(*(formatter.width_ptr));
00244 }
00245
00246
00247
00248
00249 typename Container_::const_iterator iter;
00250 ostream << "[ ";
00251 for ( iter = formatter.container->begin(); iter != formatter.container->end(); ++iter ) {
00252 ostream << formatter.format(*iter) << " ";
00253 }
00254 ostream << "]";
00255
00256
00257
00258
00259 if ( formatter.old_precision != -1 ) {
00260 formatter.format.precision(formatter.old_precision);
00261 formatter.old_precision = -1;
00262
00263 }
00264 formatter.width_ptr = &(formatter.prm_width);
00265 formatter.ready_to_format = false;
00266
00267 ostream.flush();
00268 return ostream;
00269 }
00270
00271 }
00272 }
00273
00274 #endif