$search
00001 00008 /***************************************************************************** 00009 ** Ifdefs 00010 *****************************************************************************/ 00011 00012 #ifndef ECL_CONTAINERS_COMMON_FORMATTERS_HPP_ 00013 #define ECL_CONTAINERS_COMMON_FORMATTERS_HPP_ 00014 00015 /***************************************************************************** 00016 ** Includes 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 ** Namespaces 00027 *****************************************************************************/ 00028 00029 namespace ecl { 00030 namespace formatters { 00031 00032 /***************************************************************************** 00033 ** Using 00034 *****************************************************************************/ 00035 00036 /***************************************************************************** 00037 ** Interface [FloatContainerFormatter] 00038 *****************************************************************************/ 00039 00066 template <typename Container > 00067 class ECL_LOCAL FloatContainerFormatter { 00068 public: 00069 /****************************************** 00070 ** Typedefs 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; } // Permanent 00111 FloatContainerFormatter& width(const int w) { prm_width = w; return *this; } // Permanent 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; } // Permanent 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 } //temporary 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 ** Streamer 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 ** Compute min,max coefficients 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 // for (size_t i = 1; i < N; ++i ) { 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 ** Set format width 00240 **********************/ 00241 formatter.format.width(formatter.digits(min_coeff,max_coeff)); 00242 } else { 00243 formatter.format.width(*(formatter.width_ptr)); 00244 } 00245 00246 /********************* 00247 ** Stream 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 ** Reset if temporary 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 } // namespace formatters 00272 } // namespace ecl 00273 00274 #endif /* ECL_CONTAINERS_COMMON_FORMATTERS_HPP_ */