diff --git a/ChangeLog b/ChangeLog index 9b97bcb3..fdf5742d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-02-03 Tatsuhiro Tsujikawa + + Extracted the algorithm to find the longest incremental sequence + as max_sequence template. + * src/LongestSequencePieceSelector.cc + * src/a2algo.h + * test/Makefile.am + * test/a2algoTest.cc + 2009-02-03 Tatsuhiro Tsujikawa Removed TEXT_HTTP_SERVER_LISTEN_PORT from translation texts. diff --git a/src/LongestSequencePieceSelector.cc b/src/LongestSequencePieceSelector.cc index 55436c55..6e57ead5 100644 --- a/src/LongestSequencePieceSelector.cc +++ b/src/LongestSequencePieceSelector.cc @@ -33,6 +33,7 @@ */ /* copyright --> */ #include "LongestSequencePieceSelector.h" +#include "a2algo.h" namespace aria2 { @@ -40,30 +41,12 @@ bool LongestSequencePieceSelector::select (size_t& index, const std::deque& candidateIndexes) const { - size_t maxlen = 0; - size_t maxfirst = 0; - size_t i = 0; - size_t lenA = candidateIndexes.size(); - - while(i < lenA) { - size_t first = i; - size_t len = 1; - size_t prev = first; - ++i; - while(i < lenA && candidateIndexes[prev]+1 == candidateIndexes[i]) { - ++len; - prev = i; - ++i; - } - if(maxlen < len) { - maxlen = len; - maxfirst = first; - } - } - if(maxlen == 0) { + std::pair::const_iterator, size_t> p = + max_sequence(candidateIndexes.begin(), candidateIndexes.end()); + if(p.second == 0) { return false; } else { - index = candidateIndexes[maxfirst+maxlen-1]; + index = *(p.first)+p.second-1; return true; } } diff --git a/src/a2algo.h b/src/a2algo.h index 81c3c34d..ff2484ad 100644 --- a/src/a2algo.h +++ b/src/a2algo.h @@ -50,6 +50,40 @@ OutputIterator ncopy(InputIterator first, InputIterator last, return x; } +// Find the longest incremental sequence(such as 5,6,7,8,9) in the +// range [first, last) and returns the pair of the iterator points the +// first element of the sequence and the length of the sequence. The +// incremental sequence is such that value[i]+1 == value[j] for i,j +// that satisfy i+1=j in a range. +// +// For example, the longest incremental sequence in { +// 1,2,3,4,7,10,11,12,13,14,15,100,112,113,114} is +// {10,11,12,13,14,15}. Therefore, returns the iterator points to 10 +// and the length 6. +template +std::pair max_sequence(InputIterator first, + InputIterator last) +{ + InputIterator maxfirst = last; + size_t maxlen = 0; + while(first != last) { + InputIterator seqfirst = first; + size_t len = 1; + InputIterator prev = seqfirst; + ++first; + while(first != last && *prev+1 == *first) { + ++len; + prev = first; + ++first; + } + if(maxlen < len) { + maxlen = len; + maxfirst = seqfirst; + } + } + return std::pair(maxfirst, maxlen); +} + } // namespace aria2 #endif // _D_A2_ALGO_H_ diff --git a/test/Makefile.am b/test/Makefile.am index 88bbfd2d..9419eae7 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -67,7 +67,8 @@ aria2c_SOURCES = AllTest.cc\ BencodeTest.cc\ SequentialPickerTest.cc\ RarestPieceSelectorTest.cc\ - LongestSequencePieceSelectorTest.cc + LongestSequencePieceSelectorTest.cc\ + a2algoTest.cc if HAVE_LIBZ aria2c_SOURCES += GZipDecoderTest.cc diff --git a/test/Makefile.in b/test/Makefile.in index 0d9e7eb4..4e34d313 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -193,7 +193,7 @@ am__aria2c_SOURCES_DIST = AllTest.cc TestUtil.cc TestUtil.h \ OptionParserTest.cc SimpleDNSCacheTest.cc \ DownloadHelperTest.cc BencodeTest.cc SequentialPickerTest.cc \ RarestPieceSelectorTest.cc LongestSequencePieceSelectorTest.cc \ - GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \ + a2algoTest.cc GZipDecoderTest.cc Sqlite3MozCookieParserTest.cc \ MessageDigestHelperTest.cc \ IteratableChunkChecksumValidatorTest.cc \ IteratableChecksumValidatorTest.cc BtAllowedFastMessageTest.cc \ @@ -362,9 +362,9 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) TestUtil.$(OBJEXT) \ SimpleDNSCacheTest.$(OBJEXT) DownloadHelperTest.$(OBJEXT) \ BencodeTest.$(OBJEXT) SequentialPickerTest.$(OBJEXT) \ RarestPieceSelectorTest.$(OBJEXT) \ - LongestSequencePieceSelectorTest.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_5) + LongestSequencePieceSelectorTest.$(OBJEXT) \ + a2algoTest.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) $(am__objects_4) $(am__objects_5) aria2c_OBJECTS = $(am_aria2c_OBJECTS) am__DEPENDENCIES_1 = aria2c_DEPENDENCIES = ../src/libaria2c.a ../src/download_helper.o \ @@ -589,7 +589,7 @@ aria2c_SOURCES = AllTest.cc TestUtil.cc TestUtil.h SocketCoreTest.cc \ OptionParserTest.cc SimpleDNSCacheTest.cc \ DownloadHelperTest.cc BencodeTest.cc SequentialPickerTest.cc \ RarestPieceSelectorTest.cc LongestSequencePieceSelectorTest.cc \ - $(am__append_1) $(am__append_2) $(am__append_3) \ + a2algoTest.cc $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) #aria2c_CXXFLAGS = ${CPPUNIT_CFLAGS} -I../src -I../lib -Wall -D_FILE_OFFSET_BITS=64 @@ -823,6 +823,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UriListParserTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UtilTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XORCloserTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2algoTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/a2functionalTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array_funTest.Po@am__quote@ diff --git a/test/a2algoTest.cc b/test/a2algoTest.cc new file mode 100644 index 00000000..aa814c7d --- /dev/null +++ b/test/a2algoTest.cc @@ -0,0 +1,44 @@ +#include "a2algo.h" + +#include + +#include "array_fun.h" + +namespace aria2 { + +class a2algoTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(a2algoTest); + CPPUNIT_TEST(testSelect); + CPPUNIT_TEST_SUITE_END(); +public: + void setUp() {} + + void tearDown() {} + + void testSelect(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION(a2algoTest); + +void a2algoTest::testSelect() +{ + size_t A[] = { 1,2,3,4,7,10,11,12,13,14,15,100,112,113,114 }; + + std::pair p = max_sequence(&A[0], &A[arrayLength(A)]); + CPPUNIT_ASSERT_EQUAL(&A[5], p.first); + CPPUNIT_ASSERT_EQUAL((size_t)6, p.second); + + + p = max_sequence(&A[0], &A[0]); + CPPUNIT_ASSERT_EQUAL(&A[0], p.first); + CPPUNIT_ASSERT_EQUAL((size_t)0, p.second); + + + p = max_sequence(&A[0], &A[4]); + CPPUNIT_ASSERT_EQUAL(&A[0], p.first); + CPPUNIT_ASSERT_EQUAL((size_t)4, p.second); +} + +} // namespace aria2