123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878 |
- // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
- // Copyright 2008-2016 National ICT Australia (NICTA)
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // ------------------------------------------------------------------------
- //! \addtogroup arma_ostream
- //! @{
- inline
- arma_ostream_state::arma_ostream_state(const std::ostream& o)
- : orig_flags (o.flags())
- , orig_precision(o.precision())
- , orig_width (o.width())
- , orig_fill (o.fill())
- {
- }
- inline
- void
- arma_ostream_state::restore(std::ostream& o) const
- {
- o.flags (orig_flags);
- o.precision(orig_precision);
- o.width (orig_width);
- o.fill (orig_fill);
- }
- //
- //
- template<typename eT>
- inline
- std::streamsize
- arma_ostream::modify_stream(std::ostream& o, const eT* data, const uword n_elem)
- {
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.unsetf(ios::showpos);
-
- o.fill(' ');
-
- std::streamsize cell_width;
-
- bool use_layout_B = false;
- bool use_layout_C = false;
- bool use_layout_D = false;
-
- for(uword i=0; i<n_elem; ++i)
- {
- const eT val = data[i];
-
- if(arma_isfinite(val) == false) { continue; }
-
- if(
- ( cond_rel< (sizeof(eT) > 4) && (is_same_type<uword,eT>::yes || is_same_type<sword,eT>::yes) >::geq(val, eT(+10000000000)) )
- ||
- ( cond_rel< (sizeof(eT) > 4) && is_same_type<sword,eT>::yes >::leq(val, eT(-10000000000)) )
- )
- {
- use_layout_D = true;
- break;
- }
-
- if(
- ( val >= eT(+100) )
- ||
- //( (is_signed<eT>::value) && (val <= eT(-100)) ) ||
- //( (is_non_integral<eT>::value) && (val > eT(0)) && (val <= eT(+1e-4)) ) ||
- //( (is_non_integral<eT>::value) && (is_signed<eT>::value) && (val < eT(0)) && (val >= eT(-1e-4)) )
- (
- cond_rel< is_signed<eT>::value >::leq(val, eT(-100))
- )
- ||
- (
- cond_rel< is_non_integral<eT>::value >::gt(val, eT(0))
- &&
- cond_rel< is_non_integral<eT>::value >::leq(val, eT(+1e-4))
- )
- ||
- (
- cond_rel< is_non_integral<eT>::value && is_signed<eT>::value >::lt(val, eT(0))
- &&
- cond_rel< is_non_integral<eT>::value && is_signed<eT>::value >::geq(val, eT(-1e-4))
- )
- )
- {
- use_layout_C = true;
- break;
- }
-
- if(
- // (val >= eT(+10)) || ( (is_signed<eT>::value) && (val <= eT(-10)) )
- (val >= eT(+10)) || ( cond_rel< is_signed<eT>::value >::leq(val, eT(-10)) )
- )
- {
- use_layout_B = true;
- }
- }
-
- if(use_layout_D)
- {
- o.setf(ios::scientific);
- o.setf(ios::right);
- o.unsetf(ios::fixed);
- o.precision(4);
- cell_width = 21;
- }
- else
- if(use_layout_C)
- {
- o.setf(ios::scientific);
- o.setf(ios::right);
- o.unsetf(ios::fixed);
- o.precision(4);
- cell_width = 13;
- }
- else
- if(use_layout_B)
- {
- o.unsetf(ios::scientific);
- o.setf(ios::right);
- o.setf(ios::fixed);
- o.precision(4);
- cell_width = 10;
- }
- else
- {
- o.unsetf(ios::scientific);
- o.setf(ios::right);
- o.setf(ios::fixed);
- o.precision(4);
- cell_width = 9;
- }
-
- return cell_width;
- }
- //! "better than nothing" settings for complex numbers
- template<typename T>
- inline
- std::streamsize
- arma_ostream::modify_stream(std::ostream& o, const std::complex<T>* data, const uword n_elem)
- {
- arma_ignore(data);
- arma_ignore(n_elem);
-
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.fill(' ');
-
- o.setf(ios::scientific);
- o.setf(ios::showpos);
- o.setf(ios::right);
- o.unsetf(ios::fixed);
-
- std::streamsize cell_width;
-
- o.precision(3);
- cell_width = 2 + 2*(1 + 3 + o.precision() + 5) + 1;
-
- return cell_width;
- }
- template<typename eT>
- inline
- std::streamsize
- arma_ostream::modify_stream(std::ostream& o, typename SpMat<eT>::const_iterator begin, const uword n_elem, const typename arma_not_cx<eT>::result* junk)
- {
- arma_extra_debug_sigprint();
- arma_ignore(junk);
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.unsetf(ios::showpos);
- o.fill(' ');
- std::streamsize cell_width;
- bool use_layout_B = false;
- bool use_layout_C = false;
- for(typename SpMat<eT>::const_iterator it = begin; it.pos() < n_elem; ++it)
- {
- const eT val = (*it);
-
- if(arma_isfinite(val) == false) { continue; }
-
- if(
- val >= eT(+100) ||
- ( (is_signed<eT>::value) && (val <= eT(-100)) ) ||
- ( (is_non_integral<eT>::value) && (val > eT(0)) && (val <= eT(+1e-4)) ) ||
- ( (is_non_integral<eT>::value) && (is_signed<eT>::value) && (val < eT(0)) && (val >= eT(-1e-4)) )
- )
- {
- use_layout_C = true;
- break;
- }
- if(
- (val >= eT(+10)) || ( (is_signed<eT>::value) && (val <= eT(-10)) )
- )
- {
- use_layout_B = true;
- }
- }
- if(use_layout_C)
- {
- o.setf(ios::scientific);
- o.setf(ios::right);
- o.unsetf(ios::fixed);
- o.precision(4);
- cell_width = 13;
- }
- else
- if(use_layout_B)
- {
- o.unsetf(ios::scientific);
- o.setf(ios::right);
- o.setf(ios::fixed);
- o.precision(4);
- cell_width = 10;
- }
- else
- {
- o.unsetf(ios::scientific);
- o.setf(ios::right);
- o.setf(ios::fixed);
- o.precision(4);
- cell_width = 9;
- }
-
- return cell_width;
- }
- //! "better than nothing" settings for complex numbers
- template<typename T>
- inline
- std::streamsize
- arma_ostream::modify_stream(std::ostream& o, typename SpMat<T>::const_iterator begin, const uword n_elem, const typename arma_cx_only<T>::result* junk)
- {
- arma_ignore(begin);
- arma_ignore(n_elem);
- arma_ignore(junk);
-
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.fill(' ');
-
- o.setf(ios::scientific);
- o.setf(ios::showpos);
- o.setf(ios::right);
- o.unsetf(ios::fixed);
-
- std::streamsize cell_width;
-
- o.precision(3);
- cell_width = 2 + 2*(1 + 3 + o.precision() + 5) + 1;
-
- return cell_width;
- }
- template<typename eT>
- inline
- void
- arma_ostream::print_elem_zero(std::ostream& o, const bool modify)
- {
- typedef typename promote_type<eT, s16>::result promoted_eT;
-
- if(modify)
- {
- const ios::fmtflags save_flags = o.flags();
- const std::streamsize save_precision = o.precision();
-
- o.unsetf(ios::scientific);
- o.setf(ios::fixed);
- o.precision(0);
-
- o << promoted_eT(0);
-
- o.flags(save_flags);
- o.precision(save_precision);
- }
- else
- {
- o << promoted_eT(0);
- }
- }
- template<typename eT>
- inline
- void
- arma_ostream::print_elem(std::ostream& o, const eT& x, const bool modify)
- {
- if(x == eT(0))
- {
- arma_ostream::print_elem_zero<eT>(o, modify);
- }
- else
- {
- arma_ostream::raw_print_elem(o, x);
- }
- }
- template<typename eT>
- inline
- void
- arma_ostream::raw_print_elem(std::ostream& o, const eT& x)
- {
- if(is_signed<eT>::value)
- {
- typedef typename promote_type<eT, s16>::result promoted_eT;
-
- if(arma_isfinite(x))
- {
- o << promoted_eT(x);
- }
- else
- {
- o << ( arma_isinf(x) ? ((x <= eT(0)) ? "-inf" : "inf") : "nan" );
- }
- }
- else
- {
- typedef typename promote_type<eT, u16>::result promoted_eT;
-
- o << promoted_eT(x);
- }
- }
- template<typename T>
- inline
- void
- arma_ostream::print_elem(std::ostream& o, const std::complex<T>& x, const bool modify)
- {
- if( (x.real() == T(0)) && (x.imag() == T(0)) && (modify) )
- {
- o << "(0,0)";
- }
- else
- {
- arma_ostream::raw_print_elem(o, x);
- }
- }
- template<typename T>
- inline
- void
- arma_ostream::raw_print_elem(std::ostream& o, const std::complex<T>& x)
- {
- std::ostringstream ss;
- ss.flags(o.flags());
- //ss.imbue(o.getloc());
- ss.precision(o.precision());
-
- ss << '(';
-
- const T a = x.real();
-
- if(arma_isfinite(a))
- {
- ss << a;
- }
- else
- {
- ss << ( arma_isinf(a) ? ((a <= T(0)) ? "-inf" : "+inf") : "nan" );
- }
-
- ss << ',';
-
- const T b = x.imag();
-
- if(arma_isfinite(b))
- {
- ss << b;
- }
- else
- {
- ss << ( arma_isinf(b) ? ((b <= T(0)) ? "-inf" : "+inf") : "nan" );
- }
-
- ss << ')';
-
- o << ss.str();
- }
- //! Print a matrix to the specified stream
- template<typename eT>
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const Mat<eT>& m, const bool modify)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- const std::streamsize cell_width = modify ? arma_ostream::modify_stream(o, m.memptr(), m.n_elem) : o.width();
-
- const uword m_n_rows = m.n_rows;
- const uword m_n_cols = m.n_cols;
-
- if(m.is_empty() == false)
- {
- if(m_n_cols > 0)
- {
- if(cell_width > 0)
- {
- for(uword row=0; row < m_n_rows; ++row)
- {
- for(uword col=0; col < m_n_cols; ++col)
- {
- // the cell width appears to be reset after each element is printed,
- // hence we need to restore it
- o.width(cell_width);
- arma_ostream::print_elem(o, m.at(row,col), modify);
- }
-
- o << '\n';
- }
- }
- else
- {
- for(uword row=0; row < m_n_rows; ++row)
- {
- for(uword col=0; col < m_n_cols-1; ++col)
- {
- arma_ostream::print_elem(o, m.at(row,col), modify);
- o << ' ';
- }
-
- arma_ostream::print_elem(o, m.at(row, m_n_cols-1), modify);
- o << '\n';
- }
- }
- }
- }
- else
- {
- o << "[matrix size: " << m_n_rows << 'x' << m_n_cols << "]\n";
- }
-
- o.flush();
- stream_state.restore(o);
- }
- //! Print a cube to the specified stream
- template<typename eT>
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const Cube<eT>& x, const bool modify)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- if(x.is_empty() == false)
- {
- for(uword slice=0; slice < x.n_slices; ++slice)
- {
- const Mat<eT> tmp(const_cast<eT*>(x.slice_memptr(slice)), x.n_rows, x.n_cols, false);
-
- o << "[cube slice " << slice << ']' << '\n';
- arma_ostream::print(o, tmp, modify);
- o << '\n';
- }
- }
- else
- {
- o << "[cube size: " << x.n_rows << 'x' << x.n_cols << 'x' << x.n_slices << "]\n";
- }
- stream_state.restore(o);
- }
- //! Print a field to the specified stream
- //! Assumes type oT can be printed, i.e. oT has std::ostream& operator<< (std::ostream&, const oT&)
- template<typename oT>
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const field<oT>& x)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- const std::streamsize cell_width = o.width();
-
- const uword x_n_rows = x.n_rows;
- const uword x_n_cols = x.n_cols;
- const uword x_n_slices = x.n_slices;
-
- if(x.is_empty() == false)
- {
- if(x_n_slices == 1)
- {
- for(uword col=0; col<x_n_cols; ++col)
- {
- o << "[field column " << col << ']' << '\n';
-
- for(uword row=0; row<x_n_rows; ++row)
- {
- o.width(cell_width);
- o << x.at(row,col) << '\n';
- }
-
- o << '\n';
- }
- }
- else
- {
- for(uword slice=0; slice<x_n_slices; ++slice)
- {
- o << "[field slice " << slice << ']' << '\n';
-
- for(uword col=0; col<x_n_cols; ++col)
- {
- o << "[field column " << col << ']' << '\n';
-
- for(uword row=0; row<x_n_rows; ++row)
- {
- o.width(cell_width);
- o << x.at(row,col,slice) << '\n';
- }
-
- o << '\n';
- }
-
- o << '\n';
- }
- }
- }
- else
- {
- o << "[field size: " << x_n_rows << 'x' << x_n_cols << 'x' << x_n_slices << "]\n";
- }
-
- o.flush();
- stream_state.restore(o);
- }
- //! Print a subfield to the specified stream
- //! Assumes type oT can be printed, i.e. oT has std::ostream& operator<< (std::ostream&, const oT&)
- template<typename oT>
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const subview_field<oT>& x)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- const std::streamsize cell_width = o.width();
-
- const uword x_n_rows = x.n_rows;
- const uword x_n_cols = x.n_cols;
- const uword x_n_slices = x.n_slices;
-
- if(x.is_empty() == false)
- {
- if(x_n_slices == 1)
- {
- for(uword col=0; col<x_n_cols; ++col)
- {
- o << "[field column " << col << ']' << '\n';
- for(uword row=0; row<x_n_rows; ++row)
- {
- o.width(cell_width);
- o << x.at(row,col) << '\n';
- }
-
- o << '\n';
- }
- }
- else
- {
- for(uword slice=0; slice<x_n_slices; ++slice)
- {
- o << "[field slice " << slice << ']' << '\n';
-
- for(uword col=0; col<x_n_cols; ++col)
- {
- o << "[field column " << col << ']' << '\n';
-
- for(uword row=0; row<x_n_rows; ++row)
- {
- o.width(cell_width);
- o << x.at(row,col,slice) << '\n';
- }
-
- o << '\n';
- }
-
- o << '\n';
- }
- }
- }
- else
- {
- o << "[field size: " << x_n_rows << 'x' << x_n_cols << 'x' << x_n_slices << "]\n";
- }
-
- o.flush();
- stream_state.restore(o);
- }
- template<typename eT>
- arma_cold
- inline
- void
- arma_ostream::print_dense(std::ostream& o, const SpMat<eT>& m, const bool modify)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- std::streamsize cell_width = o.width();
-
- if(modify)
- {
- if(m.n_nonzero > 0)
- {
- cell_width = arma_ostream::modify_stream<eT>(o, m.begin(), m.n_nonzero);
- }
- else
- {
- eT tmp[1]; tmp[0] = eT(0);
-
- cell_width = arma_ostream::modify_stream(o, &tmp[0], 1);
- }
- }
-
- const uword m_n_rows = m.n_rows;
- const uword m_n_cols = m.n_cols;
-
- if(m.is_empty() == false)
- {
- if(m_n_cols > 0)
- {
- if(cell_width > 0)
- {
- for(uword row=0; row < m_n_rows; ++row)
- {
- for(uword col=0; col < m_n_cols; ++col)
- {
- // the cell width appears to be reset after each element is printed,
- // hence we need to restore it
- o.width(cell_width);
- arma_ostream::print_elem(o, m.at(row,col), modify);
- }
-
- o << '\n';
- }
- }
- else
- {
- for(uword row=0; row < m_n_rows; ++row)
- {
- for(uword col=0; col < m_n_cols-1; ++col)
- {
- arma_ostream::print_elem(o, m.at(row,col), modify);
- o << ' ';
- }
-
- arma_ostream::print_elem(o, m.at(row, m_n_cols-1), modify);
- o << '\n';
- }
- }
- }
- }
- else
- {
- o << "[matrix size: " << m_n_rows << 'x' << m_n_cols << "]\n";
- }
-
- o.flush();
- stream_state.restore(o);
- }
- template<typename eT>
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const SpMat<eT>& m, const bool modify)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.unsetf(ios::showpos);
- o.unsetf(ios::scientific);
- o.setf(ios::right);
- o.setf(ios::fixed);
-
- const uword m_n_nonzero = m.n_nonzero;
- const double density = (m.n_elem > 0) ? (double(m_n_nonzero) / double(m.n_elem) * double(100)) : double(0);
-
- o << "[matrix size: " << m.n_rows << 'x' << m.n_cols << "; n_nonzero: " << m_n_nonzero;
-
- if(density == double(0))
- {
- o.precision(0);
- }
- else
- if(density >= (double(10.0)-std::numeric_limits<double>::epsilon()))
- {
- o.precision(1);
- }
- else
- if(density > (double(0.01)-std::numeric_limits<double>::epsilon()))
- {
- o.precision(2);
- }
- else
- if(density > (double(0.001)-std::numeric_limits<double>::epsilon()))
- {
- o.precision(3);
- }
- else
- if(density > (double(0.0001)-std::numeric_limits<double>::epsilon()))
- {
- o.precision(4);
- }
- else
- {
- o.unsetf(ios::fixed);
- o.setf(ios::scientific);
- o.precision(2);
- }
-
- o << "; density: " << density << "%]\n\n";
-
- if(modify == false) { stream_state.restore(o); }
-
- if(m_n_nonzero > 0)
- {
- const std::streamsize cell_width = modify ? arma_ostream::modify_stream<eT>(o, m.begin(), m_n_nonzero) : o.width();
-
- typename SpMat<eT>::const_iterator begin = m.begin();
- typename SpMat<eT>::const_iterator m_end = m.end();
-
- while(begin != m_end)
- {
- const uword row = begin.row();
-
- // TODO: change the maximum number of spaces before and after each location to be dependent on n_rows and n_cols
-
- if(row < 10) { o << " "; }
- else if(row < 100) { o << " "; }
- else if(row < 1000) { o << " "; }
- else if(row < 10000) { o << " "; }
- else if(row < 100000) { o << ' '; }
-
- const uword col = begin.col();
-
- o << '(' << row << ", " << col << ") ";
-
- if(col < 10) { o << " "; }
- else if(col < 100) { o << " "; }
- else if(col < 1000) { o << " "; }
- else if(col < 10000) { o << " "; }
- else if(col < 100000) { o << ' '; }
-
- if(cell_width > 0) { o.width(cell_width); }
-
- arma_ostream::print_elem(o, eT(*begin), modify);
- o << '\n';
-
- ++begin;
- }
-
- o << '\n';
- }
-
- o.flush();
- stream_state.restore(o);
- }
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const SizeMat& S)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.unsetf(ios::showpos);
-
- o.setf(ios::fixed);
-
- o << S.n_rows << 'x' << S.n_cols;
-
- stream_state.restore(o);
- }
- arma_cold
- inline
- void
- arma_ostream::print(std::ostream& o, const SizeCube& S)
- {
- arma_extra_debug_sigprint();
-
- const arma_ostream_state stream_state(o);
-
- o.unsetf(ios::showbase);
- o.unsetf(ios::uppercase);
- o.unsetf(ios::showpos);
-
- o.setf(ios::fixed);
-
- o << S.n_rows << 'x' << S.n_cols << 'x' << S.n_slices;
-
- stream_state.restore(o);
- }
- //! @}
|