formatters.hpp
Go to the documentation of this file.
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_ */


ecl_containers
Author(s): Daniel Stonier (d.stonier@gmail.com)
autogenerated on Thu Jan 2 2014 11:12:25