Stxxl
1.3.1
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/stream/stream.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2003-2005 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2009, 2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00008 * Copyright (C) 2010 Johannes Singler <singler@kit.edu> 00009 * 00010 * Distributed under the Boost Software License, Version 1.0. 00011 * (See accompanying file LICENSE_1_0.txt or copy at 00012 * http://www.boost.org/LICENSE_1_0.txt) 00013 **************************************************************************/ 00014 00015 #ifndef STXXL_STREAM_HEADER 00016 #define STXXL_STREAM_HEADER 00017 00018 #include <stxxl/bits/namespace.h> 00019 #include <stxxl/bits/mng/buf_istream.h> 00020 #include <stxxl/bits/mng/buf_ostream.h> 00021 #include <stxxl/bits/common/tuple.h> 00022 #include <stxxl/vector> 00023 #include <stxxl/bits/compat_unique_ptr.h> 00024 00025 00026 #ifndef STXXL_VERBOSE_MATERIALIZE 00027 #define STXXL_VERBOSE_MATERIALIZE STXXL_VERBOSE3 00028 #endif 00029 00030 00031 __STXXL_BEGIN_NAMESPACE 00032 00034 namespace stream 00035 { 00060 00061 00063 // STREAMIFY // 00065 00069 template <class InputIterator_> 00070 class iterator2stream 00071 { 00072 InputIterator_ current_, end_; 00073 00074 public: 00076 typedef typename std::iterator_traits<InputIterator_>::value_type value_type; 00077 00078 iterator2stream(InputIterator_ begin, InputIterator_ end) : 00079 current_(begin), end_(end) { } 00080 00081 iterator2stream(const iterator2stream & a) : current_(a.current_), end_(a.end_) { } 00082 00084 const value_type & operator * () const 00085 { 00086 return *current_; 00087 } 00088 00089 const value_type * operator -> () const 00090 { 00091 return &(*current_); 00092 } 00093 00095 iterator2stream & operator ++ () 00096 { 00097 assert(end_ != current_); 00098 ++current_; 00099 return *this; 00100 } 00101 00103 bool empty() const 00104 { 00105 return (current_ == end_); 00106 } 00107 }; 00108 00109 00114 template <class InputIterator_> 00115 iterator2stream<InputIterator_> streamify(InputIterator_ begin, InputIterator_ end) 00116 { 00117 return iterator2stream<InputIterator_>(begin, end); 00118 } 00119 00121 template <class InputIterator_> 00122 struct streamify_traits 00123 { 00125 typedef iterator2stream<InputIterator_> stream_type; 00126 }; 00127 00132 template <class InputIterator_> 00133 class vector_iterator2stream 00134 { 00135 InputIterator_ current_, end_; 00136 typedef buf_istream<typename InputIterator_::block_type, 00137 typename InputIterator_::bids_container_iterator> buf_istream_type; 00138 00139 typedef typename stxxl::compat_unique_ptr<buf_istream_type>::result buf_istream_unique_ptr_type; 00140 mutable buf_istream_unique_ptr_type in; 00141 00142 void delete_stream() 00143 { 00144 in.reset(); // delete object 00145 } 00146 00147 public: 00148 typedef vector_iterator2stream<InputIterator_> Self_; 00149 00151 typedef typename std::iterator_traits<InputIterator_>::value_type value_type; 00152 00153 vector_iterator2stream(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0) : 00154 current_(begin), end_(end), in(static_cast<buf_istream_type *>(NULL)) 00155 { 00156 begin.flush(); // flush container 00157 typename InputIterator_::bids_container_iterator end_iter = end.bid() + ((end.block_offset()) ? 1 : 0); 00158 00159 if (end_iter - begin.bid() > 0) 00160 { 00161 in.reset(new buf_istream_type(begin.bid(), end_iter, nbuffers ? nbuffers : 00162 (2 * config::get_instance()->disks_number()))); 00163 00164 InputIterator_ cur = begin - begin.block_offset(); 00165 00166 // skip the beginning of the block 00167 for ( ; cur != begin; ++cur) 00168 ++(*in); 00169 } 00170 } 00171 00172 vector_iterator2stream(const Self_ & a) : 00173 current_(a.current_), end_(a.end_), in(a.in.release()) { } 00174 00176 const value_type & operator * () const 00177 { 00178 return **in; 00179 } 00180 00181 const value_type * operator -> () const 00182 { 00183 return &(**in); 00184 } 00185 00187 Self_ & operator ++ () 00188 { 00189 assert(end_ != current_); 00190 ++current_; 00191 ++(*in); 00192 if (empty()) 00193 delete_stream(); 00194 00195 return *this; 00196 } 00197 00199 bool empty() const 00200 { 00201 return (current_ == end_); 00202 } 00203 virtual ~vector_iterator2stream() 00204 { 00205 delete_stream(); // not needed actually 00206 } 00207 }; 00208 00216 00217 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00218 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00219 vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00220 streamify( 00221 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin, 00222 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end, 00223 unsigned_type nbuffers = 0) 00224 { 00225 STXXL_VERBOSE1("streamify for vector_iterator range is called"); 00226 return vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00227 (begin, end, nbuffers); 00228 } 00229 00230 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00231 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00232 struct streamify_traits<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00233 { 00234 typedef vector_iterator2stream<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type; 00235 }; 00236 00244 00245 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00246 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00247 vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00248 streamify( 00249 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin, 00250 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end, 00251 unsigned_type nbuffers = 0) 00252 { 00253 STXXL_VERBOSE1("streamify for const_vector_iterator range is called"); 00254 return vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00255 (begin, end, nbuffers); 00256 } 00257 00258 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00259 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00260 struct streamify_traits<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00261 { 00262 typedef vector_iterator2stream<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > stream_type; 00263 }; 00264 00265 00272 template <class InputIterator_> 00273 class vector_iterator2stream_sr 00274 { 00275 vector_iterator2stream<InputIterator_> * vec_it_stream; 00276 iterator2stream<InputIterator_> * it_stream; 00277 00278 typedef typename InputIterator_::block_type block_type; 00279 00280 public: 00281 typedef vector_iterator2stream_sr<InputIterator_> Self_; 00282 00284 typedef typename std::iterator_traits<InputIterator_>::value_type value_type; 00285 00286 vector_iterator2stream_sr(InputIterator_ begin, InputIterator_ end, unsigned_type nbuffers = 0) 00287 { 00288 if (end - begin < block_type::size) 00289 { 00290 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing iterator2stream<InputIterator_>"); 00291 it_stream = new iterator2stream<InputIterator_>(begin, end); 00292 vec_it_stream = NULL; 00293 } 00294 else 00295 { 00296 STXXL_VERBOSE1("vector_iterator2stream_sr::vector_iterator2stream_sr: Choosing vector_iterator2stream<InputIterator_>"); 00297 it_stream = NULL; 00298 vec_it_stream = new vector_iterator2stream<InputIterator_>(begin, end, nbuffers); 00299 } 00300 } 00301 00302 vector_iterator2stream_sr(const Self_ & a) : vec_it_stream(a.vec_it_stream), it_stream(a.it_stream) { } 00303 00305 const value_type & operator * () const 00306 { 00307 if (it_stream) 00308 return **it_stream; 00309 00310 return **vec_it_stream; 00311 } 00312 00313 const value_type * operator -> () const 00314 { 00315 if (it_stream) 00316 return &(**it_stream); 00317 00318 return &(**vec_it_stream); 00319 } 00320 00322 Self_ & operator ++ () 00323 { 00324 if (it_stream) 00325 ++(*it_stream); 00326 00327 else 00328 ++(*vec_it_stream); 00329 00330 00331 return *this; 00332 } 00333 00335 bool empty() const 00336 { 00337 if (it_stream) 00338 return it_stream->empty(); 00339 00340 return vec_it_stream->empty(); 00341 } 00342 virtual ~vector_iterator2stream_sr() 00343 { 00344 if (it_stream) 00345 delete it_stream; 00346 00347 else 00348 delete vec_it_stream; 00349 } 00350 }; 00351 00353 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00354 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00355 vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00356 streamify_sr( 00357 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin, 00358 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end, 00359 unsigned_type nbuffers = 0) 00360 { 00361 STXXL_VERBOSE1("streamify_sr for vector_iterator range is called"); 00362 return vector_iterator2stream_sr<stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00363 (begin, end, nbuffers); 00364 } 00365 00367 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00368 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00369 vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00370 streamify_sr( 00371 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> begin, 00372 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> end, 00373 unsigned_type nbuffers = 0) 00374 { 00375 STXXL_VERBOSE1("streamify_sr for const_vector_iterator range is called"); 00376 return vector_iterator2stream_sr<stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> > 00377 (begin, end, nbuffers); 00378 } 00379 00380 00382 // MATERIALIZE // 00384 00391 template <class OutputIterator_, class StreamAlgorithm_> 00392 OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ out) 00393 { 00394 STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); 00395 while (!in.empty()) 00396 { 00397 *out = *in; 00398 ++out; 00399 ++in; 00400 } 00401 return out; 00402 } 00403 00404 00414 template <class OutputIterator_, class StreamAlgorithm_> 00415 OutputIterator_ materialize(StreamAlgorithm_ & in, OutputIterator_ outbegin, OutputIterator_ outend) 00416 { 00417 STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); 00418 while ((!in.empty()) && outend != outbegin) 00419 { 00420 *outbegin = *in; 00421 ++outbegin; 00422 ++in; 00423 } 00424 return outbegin; 00425 } 00426 00427 00439 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00440 unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_> 00441 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> 00442 materialize(StreamAlgorithm_ & in, 00443 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outbegin, 00444 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> outend, 00445 unsigned_type nbuffers = 0) 00446 { 00447 STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); 00448 typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator; 00449 typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator; 00450 typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type; 00451 00452 00453 while (outbegin.block_offset()) // go to the beginning of the block 00454 // of the external vector 00455 { 00456 if (in.empty() || outbegin == outend) 00457 return outbegin; 00458 00459 *outbegin = *in; 00460 ++outbegin; 00461 ++in; 00462 } 00463 00464 if (nbuffers == 0) 00465 nbuffers = 2 * config::get_instance()->disks_number(); 00466 00467 outbegin.flush(); // flush container 00468 00469 // create buffered write stream for blocks 00470 buf_ostream_type outstream(outbegin.bid(), nbuffers); 00471 00472 assert(outbegin.block_offset() == 0); 00473 00474 // delay calling block_externally_updated() until the block is 00475 // completely filled (and written out) in outstream 00476 ConstExtIterator prev_block = outbegin; 00477 00478 while (!in.empty() && outend != outbegin) 00479 { 00480 if (outbegin.block_offset() == 0) { 00481 if (prev_block != outbegin) { 00482 prev_block.block_externally_updated(); 00483 prev_block = outbegin; 00484 } 00485 } 00486 00487 *outstream = *in; 00488 ++outbegin; 00489 ++outstream; 00490 ++in; 00491 } 00492 00493 ConstExtIterator const_out = outbegin; 00494 00495 while (const_out.block_offset()) // filling the rest of the block 00496 { 00497 *outstream = *const_out; 00498 ++const_out; 00499 ++outstream; 00500 } 00501 00502 if (prev_block != outbegin) 00503 prev_block.block_externally_updated(); 00504 00505 outbegin.flush(); 00506 00507 return outbegin; 00508 } 00509 00510 00519 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00520 unsigned BlkSize_, typename PgTp_, unsigned PgSz_, class StreamAlgorithm_> 00521 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> 00522 materialize(StreamAlgorithm_ & in, 00523 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> out, 00524 unsigned_type nbuffers = 0) 00525 { 00526 STXXL_VERBOSE_MATERIALIZE(STXXL_PRETTY_FUNCTION_NAME); 00527 typedef stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ExtIterator; 00528 typedef stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> ConstExtIterator; 00529 typedef buf_ostream<typename ExtIterator::block_type, typename ExtIterator::bids_container_iterator> buf_ostream_type; 00530 00531 // on the I/O complexity of "materialize": 00532 // crossing block boundary causes O(1) I/Os 00533 // if you stay in a block, then materialize function accesses only the cache of the 00534 // vector (only one block indeed), amortized complexity should apply here 00535 00536 while (out.block_offset()) // go to the beginning of the block 00537 // of the external vector 00538 { 00539 if (in.empty()) 00540 return out; 00541 00542 *out = *in; 00543 ++out; 00544 ++in; 00545 } 00546 00547 if (nbuffers == 0) 00548 nbuffers = 2 * config::get_instance()->disks_number(); 00549 00550 00551 out.flush(); // flush container 00552 00553 // create buffered write stream for blocks 00554 buf_ostream_type outstream(out.bid(), nbuffers); 00555 00556 assert(out.block_offset() == 0); 00557 00558 // delay calling block_externally_updated() until the block is 00559 // completely filled (and written out) in outstream 00560 ConstExtIterator prev_block = out; 00561 00562 while (!in.empty()) 00563 { 00564 if (out.block_offset() == 0) { 00565 if (prev_block != out) { 00566 prev_block.block_externally_updated(); 00567 prev_block = out; 00568 } 00569 } 00570 00571 // tells the vector that the block was modified 00572 *outstream = *in; 00573 ++out; 00574 ++outstream; 00575 ++in; 00576 } 00577 00578 ConstExtIterator const_out = out; 00579 00580 while (const_out.block_offset()) 00581 { 00582 *outstream = *const_out; // might cause I/Os for loading the page that 00583 ++const_out; // contains data beyond out 00584 ++outstream; 00585 } 00586 00587 if (prev_block != out) 00588 prev_block.block_externally_updated(); 00589 00590 out.flush(); 00591 00592 return out; 00593 } 00594 00595 00600 template <class StreamAlgorithm_> 00601 void discard(StreamAlgorithm_ & in) 00602 { 00603 while (!in.empty()) 00604 { 00605 *in; 00606 ++in; 00607 } 00608 } 00609 00610 00612 // GENERATE // 00614 00618 template <class Generator_, typename T = typename Generator_::value_type> 00619 class generator2stream 00620 { 00621 public: 00623 typedef T value_type; 00624 00625 private: 00626 Generator_ gen_; 00627 value_type current_; 00628 00629 public: 00630 generator2stream(Generator_ g) : 00631 gen_(g), current_(gen_()) { } 00632 00633 generator2stream(const generator2stream & a) : gen_(a.gen_), current_(a.current_) { } 00634 00636 const value_type & operator * () const 00637 { 00638 return current_; 00639 } 00640 00641 const value_type * operator -> () const 00642 { 00643 return ¤t_; 00644 } 00645 00647 generator2stream & operator ++ () 00648 { 00649 current_ = gen_(); 00650 return *this; 00651 } 00652 00654 bool empty() const 00655 { 00656 return false; 00657 } 00658 }; 00659 00663 template <class Generator_> 00664 generator2stream<Generator_> streamify(Generator_ gen_) 00665 { 00666 return generator2stream<Generator_>(gen_); 00667 } 00668 00669 00671 // TRANSFORM // 00673 00674 struct Stopper { }; 00675 00686 template <class Operation_, 00687 class Input1_, 00688 class Input2_ = Stopper, 00689 class Input3_ = Stopper, 00690 class Input4_ = Stopper, 00691 class Input5_ = Stopper, 00692 class Input6_ = Stopper 00693 > 00694 class transform 00695 { 00696 Operation_ & op; 00697 Input1_ & i1; 00698 Input2_ & i2; 00699 Input3_ & i3; 00700 Input4_ & i4; 00701 Input5_ & i5; 00702 Input6_ & i6; 00703 00704 public: 00706 typedef typename Operation_::value_type value_type; 00707 00708 private: 00709 value_type current; 00710 00711 public: 00713 transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_, 00714 Input5_ & i5_, Input5_ & i6_) : 00715 op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_) 00716 { 00717 if (!empty()) 00718 current = op(*i1, *i2, *i3, *i4, *i5, *i6); 00719 } 00720 00722 const value_type & operator * () const 00723 { 00724 return current; 00725 } 00726 00727 const value_type * operator -> () const 00728 { 00729 return ¤t; 00730 } 00731 00733 transform & operator ++ () 00734 { 00735 ++i1; 00736 ++i2; 00737 ++i3; 00738 ++i4; 00739 ++i5; 00740 ++i6; 00741 if (!empty()) 00742 current = op(*i1, *i2, *i3, *i4, *i5, *i6); 00743 00744 return *this; 00745 } 00746 00748 bool empty() const 00749 { 00750 return i1.empty() || i2.empty() || i3.empty() || 00751 i4.empty() || i5.empty() || i6.empty(); 00752 } 00753 }; 00754 00755 // Specializations 00756 00758 // TRANSFORM (1 input stream) // 00760 00767 template <class Operation_, 00768 class Input1_ 00769 > 00770 class transform<Operation_, Input1_, Stopper, Stopper, Stopper, Stopper, Stopper> 00771 { 00772 Operation_ & op; 00773 Input1_ & i1; 00774 00775 public: 00777 typedef typename Operation_::value_type value_type; 00778 00779 private: 00780 value_type current; 00781 00782 public: 00784 transform(Operation_ & o, Input1_ & i1_) : op(o), i1(i1_) 00785 { 00786 if (!empty()) 00787 current = op(*i1); 00788 } 00789 00791 const value_type & operator * () const 00792 { 00793 return current; 00794 } 00795 00796 const value_type * operator -> () const 00797 { 00798 return ¤t; 00799 } 00800 00802 transform & operator ++ () 00803 { 00804 ++i1; 00805 if (!empty()) 00806 current = op(*i1); 00807 00808 return *this; 00809 } 00810 00812 bool empty() const 00813 { 00814 return i1.empty(); 00815 } 00816 }; 00817 00818 00820 // TRANSFORM (2 input streams) // 00822 00830 template <class Operation_, 00831 class Input1_, 00832 class Input2_ 00833 > 00834 class transform<Operation_, Input1_, Input2_, Stopper, Stopper, Stopper, Stopper> 00835 { 00836 Operation_ & op; 00837 Input1_ & i1; 00838 Input2_ & i2; 00839 00840 public: 00842 typedef typename Operation_::value_type value_type; 00843 00844 private: 00845 value_type current; 00846 00847 public: 00849 transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_) : op(o), i1(i1_), i2(i2_) 00850 { 00851 if (!empty()) 00852 current = op(*i1, *i2); 00853 } 00854 00856 const value_type & operator * () const 00857 { 00858 return current; 00859 } 00860 00861 const value_type * operator -> () const 00862 { 00863 return ¤t; 00864 } 00865 00867 transform & operator ++ () 00868 { 00869 ++i1; 00870 ++i2; 00871 if (!empty()) 00872 current = op(*i1, *i2); 00873 00874 return *this; 00875 } 00876 00878 bool empty() const 00879 { 00880 return i1.empty() || i2.empty(); 00881 } 00882 }; 00883 00884 00886 // TRANSFORM (3 input streams) // 00888 00897 template <class Operation_, 00898 class Input1_, 00899 class Input2_, 00900 class Input3_ 00901 > 00902 class transform<Operation_, Input1_, Input2_, Input3_, Stopper, Stopper, Stopper> 00903 { 00904 Operation_ & op; 00905 Input1_ & i1; 00906 Input2_ & i2; 00907 Input3_ & i3; 00908 00909 public: 00911 typedef typename Operation_::value_type value_type; 00912 00913 private: 00914 value_type current; 00915 00916 public: 00918 transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_) : 00919 op(o), i1(i1_), i2(i2_), i3(i3_) 00920 { 00921 if (!empty()) 00922 current = op(*i1, *i2, *i3); 00923 } 00924 00926 const value_type & operator * () const 00927 { 00928 return current; 00929 } 00930 00931 const value_type * operator -> () const 00932 { 00933 return ¤t; 00934 } 00935 00937 transform & operator ++ () 00938 { 00939 ++i1; 00940 ++i2; 00941 ++i3; 00942 if (!empty()) 00943 current = op(*i1, *i2, *i3); 00944 00945 return *this; 00946 } 00947 00949 bool empty() const 00950 { 00951 return i1.empty() || i2.empty() || i3.empty(); 00952 } 00953 }; 00954 00955 00957 // TRANSFORM (4 input streams) // 00959 00969 template <class Operation_, 00970 class Input1_, 00971 class Input2_, 00972 class Input3_, 00973 class Input4_ 00974 > 00975 class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Stopper, Stopper> 00976 { 00977 Operation_ & op; 00978 Input1_ & i1; 00979 Input2_ & i2; 00980 Input3_ & i3; 00981 Input4_ & i4; 00982 00983 public: 00985 typedef typename Operation_::value_type value_type; 00986 00987 private: 00988 value_type current; 00989 00990 public: 00992 transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_) : 00993 op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_) 00994 { 00995 if (!empty()) 00996 current = op(*i1, *i2, *i3, *i4); 00997 } 00998 01000 const value_type & operator * () const 01001 { 01002 return current; 01003 } 01004 01005 const value_type * operator -> () const 01006 { 01007 return ¤t; 01008 } 01009 01011 transform & operator ++ () 01012 { 01013 ++i1; 01014 ++i2; 01015 ++i3; 01016 ++i4; 01017 if (!empty()) 01018 current = op(*i1, *i2, *i3, *i4); 01019 01020 return *this; 01021 } 01022 01024 bool empty() const 01025 { 01026 return i1.empty() || i2.empty() || i3.empty() || i4.empty(); 01027 } 01028 }; 01029 01030 01032 // TRANSFORM (5 input streams) // 01034 01045 template <class Operation_, 01046 class Input1_, 01047 class Input2_, 01048 class Input3_, 01049 class Input4_, 01050 class Input5_ 01051 > 01052 class transform<Operation_, Input1_, Input2_, Input3_, Input4_, Input5_, Stopper> 01053 { 01054 Operation_ & op; 01055 Input1_ & i1; 01056 Input2_ & i2; 01057 Input3_ & i3; 01058 Input4_ & i4; 01059 Input5_ & i5; 01060 01061 public: 01063 typedef typename Operation_::value_type value_type; 01064 01065 private: 01066 value_type current; 01067 01068 public: 01070 transform(Operation_ & o, Input1_ & i1_, Input2_ & i2_, Input3_ & i3_, Input4_ & i4_, 01071 Input5_ & i5_) : 01072 op(o), i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_) 01073 { 01074 if (!empty()) 01075 current = op(*i1, *i2, *i3, *i4, *i5); 01076 } 01077 01079 const value_type & operator * () const 01080 { 01081 return current; 01082 } 01083 01084 const value_type * operator -> () const 01085 { 01086 return ¤t; 01087 } 01088 01090 transform & operator ++ () 01091 { 01092 ++i1; 01093 ++i2; 01094 ++i3; 01095 ++i4; 01096 ++i5; 01097 if (!empty()) 01098 current = op(*i1, *i2, *i3, *i4, *i5); 01099 01100 return *this; 01101 } 01102 01104 bool empty() const 01105 { 01106 return i1.empty() || i2.empty() || i3.empty() || i4.empty() || i5.empty(); 01107 } 01108 }; 01109 01110 01112 // MAKE TUPLE // 01114 01123 template <class Input1_, 01124 class Input2_, 01125 class Input3_ = Stopper, 01126 class Input4_ = Stopper, 01127 class Input5_ = Stopper, 01128 class Input6_ = Stopper 01129 > 01130 class make_tuple 01131 { 01132 Input1_ & i1; 01133 Input2_ & i2; 01134 Input3_ & i3; 01135 Input4_ & i4; 01136 Input5_ & i5; 01137 Input6_ & i6; 01138 01139 public: 01141 typedef typename stxxl::tuple< 01142 typename Input1_::value_type, 01143 typename Input2_::value_type, 01144 typename Input3_::value_type, 01145 typename Input4_::value_type, 01146 typename Input5_::value_type, 01147 typename Input6_::value_type 01148 > value_type; 01149 01150 private: 01151 value_type current; 01152 01153 public: 01155 make_tuple( 01156 Input1_ & i1_, 01157 Input2_ & i2_, 01158 Input3_ & i3_, 01159 Input4_ & i4_, 01160 Input5_ & i5_, 01161 Input6_ & i6_ 01162 ) : 01163 i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), i6(i6_), 01164 current(value_type(*i1, *i2, *i3, *i4, *i5, *i6)) { } 01165 01167 const value_type & operator * () const 01168 { 01169 return current; 01170 } 01171 01172 const value_type * operator -> () const 01173 { 01174 return ¤t; 01175 } 01176 01178 make_tuple & operator ++ () 01179 { 01180 ++i1; 01181 ++i2; 01182 ++i3; 01183 ++i4; 01184 ++i5; 01185 ++i6; 01186 01187 if (!empty()) 01188 current = value_type(*i1, *i2, *i3, *i4, *i5, *i6); 01189 01190 return *this; 01191 } 01192 01194 bool empty() const 01195 { 01196 return i1.empty() || i2.empty() || i3.empty() || 01197 i4.empty() || i5.empty() || i6.empty(); 01198 } 01199 }; 01200 01201 01207 template <class Input1_, 01208 class Input2_ 01209 > 01210 class make_tuple<Input1_, Input2_, Stopper, Stopper, Stopper, Stopper> 01211 { 01212 Input1_ & i1; 01213 Input2_ & i2; 01214 01215 public: 01217 typedef typename stxxl::tuple< 01218 typename Input1_::value_type, 01219 typename Input2_::value_type 01220 > value_type; 01221 01222 private: 01223 value_type current; 01224 01225 public: 01227 make_tuple( 01228 Input1_ & i1_, 01229 Input2_ & i2_ 01230 ) : 01231 i1(i1_), i2(i2_) 01232 { 01233 if (!empty()) 01234 { 01235 current = value_type(*i1, *i2); 01236 } 01237 } 01238 01240 const value_type & operator * () const 01241 { 01242 return current; 01243 } 01244 01245 const value_type * operator -> () const 01246 { 01247 return ¤t; 01248 } 01249 01251 make_tuple & operator ++ () 01252 { 01253 ++i1; 01254 ++i2; 01255 01256 if (!empty()) 01257 current = value_type(*i1, *i2); 01258 01259 return *this; 01260 } 01261 01263 bool empty() const 01264 { 01265 return i1.empty() || i2.empty(); 01266 } 01267 }; 01268 01275 template <class Input1_, 01276 class Input2_, 01277 class Input3_ 01278 > 01279 class make_tuple<Input1_, Input2_, Input3_, Stopper, Stopper, Stopper> 01280 { 01281 Input1_ & i1; 01282 Input2_ & i2; 01283 Input3_ & i3; 01284 01285 public: 01287 typedef typename stxxl::tuple< 01288 typename Input1_::value_type, 01289 typename Input2_::value_type, 01290 typename Input3_::value_type 01291 > value_type; 01292 01293 private: 01294 value_type current; 01295 01296 public: 01298 make_tuple( 01299 Input1_ & i1_, 01300 Input2_ & i2_, 01301 Input3_ & i3_ 01302 ) : 01303 i1(i1_), i2(i2_), i3(i3_), 01304 current(value_type(*i1, *i2, *i3)) { } 01305 01307 const value_type & operator * () const 01308 { 01309 return current; 01310 } 01311 01312 const value_type * operator -> () const 01313 { 01314 return ¤t; 01315 } 01316 01318 make_tuple & operator ++ () 01319 { 01320 ++i1; 01321 ++i2; 01322 ++i3; 01323 01324 if (!empty()) 01325 current = value_type(*i1, *i2, *i3); 01326 01327 return *this; 01328 } 01329 01331 bool empty() const 01332 { 01333 return i1.empty() || i2.empty() || i3.empty(); 01334 } 01335 }; 01336 01344 template <class Input1_, 01345 class Input2_, 01346 class Input3_, 01347 class Input4_ 01348 > 01349 class make_tuple<Input1_, Input2_, Input3_, Input4_, Stopper, Stopper> 01350 { 01351 Input1_ & i1; 01352 Input2_ & i2; 01353 Input3_ & i3; 01354 Input4_ & i4; 01355 01356 public: 01358 typedef typename stxxl::tuple< 01359 typename Input1_::value_type, 01360 typename Input2_::value_type, 01361 typename Input3_::value_type, 01362 typename Input4_::value_type 01363 > value_type; 01364 01365 private: 01366 value_type current; 01367 01368 public: 01370 make_tuple( 01371 Input1_ & i1_, 01372 Input2_ & i2_, 01373 Input3_ & i3_, 01374 Input4_ & i4_ 01375 ) : 01376 i1(i1_), i2(i2_), i3(i3_), i4(i4_), 01377 current(value_type(*i1, *i2, *i3, *i4)) { } 01378 01380 const value_type & operator * () const 01381 { 01382 return current; 01383 } 01384 01385 const value_type * operator -> () const 01386 { 01387 return ¤t; 01388 } 01389 01391 make_tuple & operator ++ () 01392 { 01393 ++i1; 01394 ++i2; 01395 ++i3; 01396 ++i4; 01397 01398 if (!empty()) 01399 current = value_type(*i1, *i2, *i3, *i4); 01400 01401 return *this; 01402 } 01403 01405 bool empty() const 01406 { 01407 return i1.empty() || i2.empty() || i3.empty() || 01408 i4.empty(); 01409 } 01410 }; 01411 01420 template < 01421 class Input1_, 01422 class Input2_, 01423 class Input3_, 01424 class Input4_, 01425 class Input5_ 01426 > 01427 class make_tuple<Input1_, Input2_, Input3_, Input4_, Input5_, Stopper> 01428 { 01429 Input1_ & i1; 01430 Input2_ & i2; 01431 Input3_ & i3; 01432 Input4_ & i4; 01433 Input5_ & i5; 01434 01435 public: 01437 typedef typename stxxl::tuple< 01438 typename Input1_::value_type, 01439 typename Input2_::value_type, 01440 typename Input3_::value_type, 01441 typename Input4_::value_type, 01442 typename Input5_::value_type 01443 > value_type; 01444 01445 private: 01446 value_type current; 01447 01448 public: 01450 make_tuple( 01451 Input1_ & i1_, 01452 Input2_ & i2_, 01453 Input3_ & i3_, 01454 Input4_ & i4_, 01455 Input5_ & i5_ 01456 ) : 01457 i1(i1_), i2(i2_), i3(i3_), i4(i4_), i5(i5_), 01458 current(value_type(*i1, *i2, *i3, *i4, *i5)) { } 01459 01461 const value_type & operator * () const 01462 { 01463 return current; 01464 } 01465 01466 const value_type * operator -> () const 01467 { 01468 return ¤t; 01469 } 01470 01472 make_tuple & operator ++ () 01473 { 01474 ++i1; 01475 ++i2; 01476 ++i3; 01477 ++i4; 01478 ++i5; 01479 01480 if (!empty()) 01481 current = value_type(*i1, *i2, *i3, *i4, *i5); 01482 01483 return *this; 01484 } 01485 01487 bool empty() const 01488 { 01489 return i1.empty() || i2.empty() || i3.empty() || 01490 i4.empty() || i5.empty(); 01491 } 01492 }; 01493 01494 01496 } 01497 01498 __STXXL_END_NAMESPACE 01499 01500 01501 #include <stxxl/bits/stream/choose.h> 01502 #include <stxxl/bits/stream/unique.h> 01503 01504 01505 #endif // !STXXL_STREAM_HEADER 01506 // vim: et:ts=4:sw=4