#ifndef SCAN_HEADER #define SCAN_HEADER /*************************************************************************** * scan.h * * Tue Dec 31 20:27:24 2002 * Copyright 2002 Roman Dementiev * dementiev@mpi-sb.mpg.de ****************************************************************************/ #include "../common/utils.h" #include "../mng/buf_istream.h" #include "../mng/buf_ostream.h" __STXXL_BEGIN_NAMESPACE //! \addtogroup stlalgo //! \{ //! \brief External equivalent of std::for_each //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _functor function object of model of \c std::UnaryFunction concept //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) //! \return function object \c _functor after it has been applied to the each element of the given range //! //! \warning nested stxxl::for_each are not supported template _UnaryFunction for_each(_ExtIterator _begin, _ExtIterator _end, _UnaryFunction _functor,int_type nbuffers) { typedef buf_istream buf_istream_type; _begin.flush(); // flush container // create prefetching stream, buf_istream_type in(_begin.bid(),_end.bid() + ((_end.block_offset())?1:0),nbuffers/2); _ExtIterator _cur = _begin - _begin.block_offset(); // leave part of the block before _begin untouched (e.g. copy) for( ;_cur != _begin;++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; } // apply _functor to the range [_begin,_end) for( ;_cur != _end;++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; _functor(tmp); } // leave part of the block after _end untouched if(_end.block_offset()) { _ExtIterator _last_block_end = _end - _end.block_offset() + _ExtIterator::block_type::size; for( ;_cur != _last_block_end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; } } return _functor; } //! \brief External equivalent of std::for_each (mutating) //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _functor //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) //! \return function object \c _functor after it has been applied to the each element of the given range //! //! \warning nested stxxl::for_each_m are not supported template _UnaryFunction for_each_m(_ExtIterator _begin, _ExtIterator _end, _UnaryFunction _functor,int_type nbuffers) { typedef buf_istream buf_istream_type; typedef buf_ostream buf_ostream_type; _begin.flush(); // flush container // create prefetching stream, buf_istream_type in(_begin.bid(),_end.bid() + ((_end.block_offset())?1:0),nbuffers/2); // create buffered write stream for blocks buf_ostream_type out(_begin.bid(),nbuffers/2); // REMARK: these two streams do I/O while // _functor is being computed (overlapping for free) _ExtIterator _cur = _begin - _begin.block_offset(); // leave part of the block before _begin untouched (e.g. copy) for( ;_cur != _begin;++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; out << tmp; } // apply _functor to the range [_begin,_end) for( ;_cur != _end;++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; _functor(tmp); out << tmp; } // leave part of the block after _end untouched if(_end.block_offset()) { _ExtIterator _last_block_end = _end - _end.block_offset() + _ExtIterator::block_type::size; for( ;_cur != _last_block_end; ++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; out << tmp; } } return _functor; } //! \brief External equivalent of std::generate //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _generator function object of model of \c std::Generator concept //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) template void generate(_ExtIterator _begin, _ExtIterator _end, _Generator _generator,int_type nbuffers) { typedef typename _ExtIterator::block_type block_type; typedef buf_ostream buf_ostream_type; while(_begin.block_offset()) // go to the beginning of the block // of the external vector { if(_begin==_end) return; *_begin = _generator(); ++_begin; } _begin.flush(); // flush container // create buffered write stream for blocks buf_ostream_type outstream(_begin.bid(),nbuffers); assert(_begin.block_offset() == 0); while(_end != _begin) { if(_begin.block_offset() == 0) _begin.touch(); *outstream = _generator(); ++_begin; ++outstream; } typename _ExtIterator::const_iterator out = _begin; while(out.block_offset()) // filling the rest of the block { *outstream = * out; ++out; ++outstream; } _begin.flush(); } //! \brief External equivalent of std::find //! \remark The implementation exploits \c \ buffered streams (computation and I/O overlapped) //! \param _begin object of model of \c ext_random_access_iterator concept //! \param _end object of model of \c ext_random_access_iterator concept //! \param _value value that is equality comparable to the _ExtIterator's value type //! \param nbuffers number of buffers (blocks) for internal use (should be at least 2*D ) //! \return first iterator \c i in the range [_begin,_end) such that *( \c i ) == \c _value, if no //! such exists then \c _end template _ExtIterator find(_ExtIterator _begin, _ExtIterator _end, const _EqualityComparable & _value,int_type nbuffers) { typedef buf_istream buf_istream_type; _begin.flush(); // flush container // create prefetching stream, buf_istream_type in(_begin.bid(),_end.bid() + ((_end.block_offset())?1:0),nbuffers); _ExtIterator _cur = _begin - _begin.block_offset(); // skip part of the block before _begin untouched for( ;_cur != _begin;++_cur) ++in; // search in the the range [_begin,_end) for( ;_cur != _end;++_cur) { typename _ExtIterator::value_type tmp; in >> tmp; if(tmp == _value) return _cur; } return _cur; } //! \} __STXXL_END_NAMESPACE #endif