ostream_mat.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2009 NICTA
00002 // 
00003 // Authors:
00004 // - Conrad Sanderson (conradsand at ieee dot org)
00005 // 
00006 // This file is part of the Armadillo C++ library.
00007 // It is provided without any warranty of fitness
00008 // for any purpose. You can redistribute this file
00009 // and/or modify it under the terms of the GNU
00010 // Lesser General Public License (LGPL) as published
00011 // by the Free Software Foundation, either version 3
00012 // of the License or (at your option) any later version.
00013 // (see http://www.opensource.org/licenses for more info)
00014 
00015 
00016 //! \addtogroup ostream
00017 //! @{
00018 
00019 class arma_ostream_state
00020   {
00021   private:
00022 
00023   const ios::fmtflags   orig_flags;
00024   const std::streamsize orig_precision;
00025   const std::streamsize orig_width;
00026   const char            orig_fill;
00027 
00028 
00029   public:
00030 
00031   inline
00032   arma_ostream_state(const std::ostream& o)
00033    : orig_flags    (o.flags())
00034    , orig_precision(o.precision())
00035    , orig_width    (o.width())
00036    , orig_fill     (o.fill())
00037    {
00038    }
00039 
00040 
00041   inline
00042   void
00043   restore(std::ostream& o) const
00044     {
00045     o.flags    (orig_flags);
00046     o.precision(orig_precision);
00047     o.width    (orig_width);
00048     o.fill     (orig_fill);
00049     }
00050 
00051   };
00052 
00053 
00054 
00055 class arma_ostream
00056   {
00057   public:
00058   
00059   template<typename eT>
00060   inline static u32 modify_stream(std::ostream& o, const Mat<eT>& m);
00061   
00062   template<typename T>
00063   inline static u32 modify_stream(std::ostream& o, const Mat< std::complex<T> >& m);
00064   
00065   template<typename eT>
00066   inline static void print(std::ostream& o, const Mat<eT>& m, const bool modify);
00067 
00068   template<typename T>
00069   inline static void print(std::ostream& o, const Mat< std::complex<T> >& m, const bool modify);
00070   };
00071 
00072 
00073 
00074 template<typename eT>
00075 inline
00076 u32
00077 arma_ostream::modify_stream(std::ostream& o, const Mat<eT>& m)
00078   {
00079   o.unsetf(ios::showbase);
00080   o.unsetf(ios::uppercase);
00081   o.fill(' ');
00082 
00083   u32 cell_width;
00084   
00085   bool use_layout_B = false;
00086   bool use_layout_C = false;
00087   
00088   for(u32 i=0; i<m.n_elem; ++i)
00089     {
00090     const eT val = m.mem[i];
00091     
00092     if(
00093       val >= eT(+100) ||
00094       ( (is_signed<eT>::value == true) && (val <= eT(-100)) ) ||
00095       ( (is_non_integral<eT>::value == true) && (val > eT(0)) && (val <= eT(+1e-4)) ) ||
00096       ( (is_non_integral<eT>::value == true) && (is_signed<eT>::value == true) && (val < eT(0)) && (val >= eT(-1e-4)) ) 
00097       )
00098       {
00099       use_layout_C = true;
00100       break;
00101       }
00102       
00103     if(
00104       (val >= eT(+10)) || ( (is_signed<eT>::value == true) && (val <= eT(-10)) )
00105       )
00106       {
00107       use_layout_B = true;
00108       }
00109     }
00110   
00111   if(use_layout_C == true)
00112     {
00113     o.setf(ios::scientific);
00114     o.unsetf(ios::fixed);
00115     o.precision(4);
00116     cell_width = 13;
00117     }
00118   else
00119   if(use_layout_B == true)
00120     {
00121     o.unsetf(ios::scientific);
00122     o.setf(ios::fixed);
00123     o.precision(4);
00124     cell_width = 10;
00125     }
00126   else
00127     {
00128     o.unsetf(ios::scientific);
00129     o.setf(ios::fixed);
00130     o.precision(4);
00131     cell_width = 9;
00132     }
00133   
00134   return cell_width;
00135   }
00136 
00137 
00138 
00139 //! "better than nothing" settings for complex numbers
00140 template<typename T>
00141 inline
00142 u32
00143 arma_ostream::modify_stream(std::ostream& o, const Mat< std::complex<T> >& m)
00144   {
00145   o.unsetf(ios::showbase);
00146   o.unsetf(ios::uppercase);
00147   o.fill(' ');
00148   
00149   o.setf(ios::scientific);
00150   o.setf(ios::showpos);
00151   o.unsetf(ios::fixed);
00152   
00153   u32 cell_width;
00154   
00155   o.precision(3);
00156   cell_width = 2 + 2*(1 + 3 + o.precision() + 5) + 1;
00157 
00158   return cell_width;
00159   }
00160 
00161 
00162 
00163 //! Print a matrix to the specified stream
00164 template<typename eT>
00165 inline
00166 void
00167 arma_ostream::print(std::ostream& o, const Mat<eT>& m, const bool modify)
00168   {
00169   arma_extra_debug_sigprint();
00170   
00171   const arma_ostream_state stream_state(o);
00172 
00173   u32 cell_width;
00174   
00175   if(modify == true)
00176     {
00177     cell_width = arma_ostream::modify_stream(o, m);
00178     }
00179   else
00180     {
00181     cell_width = o.width();
00182     }
00183   
00184   if(cell_width != 0)
00185     {
00186     for(u32 row=0; row < m.n_rows; ++row)
00187       {
00188       for(u32 col=0; col < m.n_cols; ++col)
00189         {
00190         o.width(cell_width);
00191         o << m.at(row,col);
00192         }
00193       
00194       o << '\n';
00195       }
00196     }
00197   else
00198     {
00199     for(u32 row=0; row < m.n_rows; ++row)
00200       {
00201       for(u32 col=0; col < m.n_cols-1; ++col)
00202         {
00203         o << m.at(row,col) << ' ';
00204         }
00205       
00206       o << m.at(row, m.n_cols-1) << '\n';
00207       }
00208     }
00209   
00210   o.flush();
00211   stream_state.restore(o);
00212   }
00213 
00214 
00215 
00216 //! Print a complex matrix to the specified stream
00217 //! EXPERIMENTAL !
00218 template<typename T>
00219 inline
00220 void
00221 arma_ostream::print(std::ostream& o, const Mat< std::complex<T> >& m, const bool modify)
00222   {
00223   arma_extra_debug_sigprint();
00224   
00225   const arma_ostream_state stream_state(o);
00226 
00227   u32 cell_width;
00228   
00229   if(modify == true)
00230     {
00231     cell_width = arma_ostream::modify_stream(o, m);
00232     }
00233   else
00234     {
00235     cell_width = o.width();
00236     }
00237 
00238 
00239   
00240   if(cell_width != 0)
00241     {
00242     for(u32 row=0; row < m.n_rows; ++row)
00243       {
00244       for(u32 col=0; col < m.n_cols; ++col)
00245         {
00246         std::ostringstream ss;
00247         ss.flags(o.flags());
00248         //ss.imbue(o.getloc());
00249         ss.precision(o.precision());
00250 
00251         ss << '(' << m.at(row,col).real() << ',' << m.at(row,col).imag() << ')';
00252 
00253         o.width(cell_width);
00254         o << ss.str();
00255         }
00256 
00257       o << '\n';
00258       }
00259     }
00260   else
00261     {
00262     for(u32 row=0; row < m.n_rows; ++row)
00263       {
00264       for(u32 col=0; col < m.n_cols-1; ++col)
00265         {
00266         o << '(' << m.at(row,col).real() << ',' << m.at(row,col).imag() << ") ";
00267         }
00268       o << '(' << m.at(row, m.n_cols-1).real() << ',' << m.at(row, m.n_cols-1).imag() << ")\n";
00269       }
00270     }
00271 
00272   
00273   o.flush();
00274   stream_state.restore(o);
00275   }
00276 
00277 
00278 
00279 template<typename eT>
00280 inline
00281 std::ostream&
00282 operator<< (std::ostream& o, const Mat<eT>& m)
00283   {
00284   arma_extra_debug_sigprint();
00285   
00286   arma_ostream::print(o,m,true);
00287   
00288   return o;
00289   }
00290 
00291 
00292 
00293 //! @}