Change to search_n

Chris Jefferson caj@cs.york.ac.uk
Tue Mar 1 17:51:00 GMT 2005


Hi :)
> Hi Chris, hi list,
> 
> <snip>
> 
> Its mainly the expressions like (__last - __first >
> __count) that are producing these warnings. These
> expression will fail to work as expected in case
> __first > __last.
> 
I think we just have to careful with these tests :)

<snip>
> According to my tests, my new implementation seems to
> perform better than the old one in most cases (though
> there are circumstances when it performs slightly
> worse) and is testing less elements in all cases.
> Particularly, when the probability of meeting a
> matching element is high, it performs great. In the
> example I have mentioned in a previous mail (test D of
> my article) your implementation is testing 16% of the
> overtaken elements, my old implementation is testing
> 14% of the overtaken elements and my newest one only
> 10.7% of the overtaken elements. I have to admit that
> when the element comparison itself is very fast, then
> my new implementation is not always faster in all
> compilers, but in case that the comparison is
> non-trivial then it really takes off. :)

I'm of the opinion that a slight decrease in performance in some cases 
is acceptable as long as many other cases increase dramatically :)

The main problem I had with my previous version was that i wasn't 
getting much improvement for when the integer parameter was 2..


> Bellow I include a draft of this new implementation
> and I waiting for your comments.
> 
> //---------------------------------------------------
> 
> template <class _RandomAccessIter, class _Integer,
> class _Tp> inline
Only a tiny thing, I think this is perhaps a little large to inline :)
> _RandomAccessIter search_n(_RandomAccessIter __first,
> _RandomAccessIter __last,
>                       _Integer __count, const _Tp&
> __val)
> {
> 	if (__count <= 0)
> 		return __first;
> 	if (__count == 1)
> 		return std::find(__first, __last, __val);
> 
> 	typedef
> std::iterator_traits<_RandomAccessIter>::difference_type
> iter_diff;
> 
> 	iter_diff __tailSize = __last - __first;
> 	iter_diff __pattSize = __count;
> 
> 	if (__tailSize >= __pattSize)
> 	{
> 		_RandomAccessIter __backTrack;
> 
> 		iter_diff __remainder, __prevRemainder;
> 		iter_diff __skipOffset = __pattSize - 1;
> 		
> 		_RandomAccessIter __lookAhead = __first +
> __skipOffset;
> 
> 		for ( ; ; __lookAhead += __pattSize ) // the main
> loop...
> 		{
> 			//__lookAhead here is always pointing to the last
> element of next possible match.
> 			assert( __tailSize >= __pattSize );
> 			__tailSize -= __pattSize;
> 
> 			for ( ; ; ) // the skip loop...
> 			{
> 				if (*__lookAhead == __val)
> 					break;
> 				if (__tailSize < __pattSize)
> 					return __last;
> 				
> 				__lookAhead += __pattSize;
> 				__tailSize -= __pattSize;
> 			}
> 			
> 			assert( __tailSize == (__last - __lookAhead) - 1 );
> 			__remainder = __skipOffset;
> 			
> 			for ( __backTrack = __lookAhead - 1; *__backTrack
> == __val; --__backTrack )
> 			{
> 				if (--__remainder == 0)
> 					return (__lookAhead - __skipOffset); //Success
> 			}
> 
> 			for ( ; ; )
> 			{
> 				if (__remainder > __tailSize)
> 					return __last; //failure
> 
> 				__lookAhead += __remainder;
> 				__tailSize -= __remainder;
> 
> 				if (*__lookAhead == __val)
> 				{
> 					__prevRemainder = __remainder;
> 					__backTrack = __lookAhead;
> 
I know quite a lot of people don't like do { ... } while loops, although 
in this case it looks like the sensible option.
> 					do
> 					{
> 						if (--__remainder == 0)
> 							return (__lookAhead - __skipOffset); //Success
> 
> 					} while ( *--__backTrack == __val);
> 					
> 					//adjust remainder for next comparison
> 					__remainder += __skipOffset - __prevRemainder;
> 				}
> 				else
> 					break;
> 			}
> 
> 			//__lookAhead here is always pointing to the
> element of the last mismatch.
> 			if (__tailSize < __pattSize)
> 				return __last;
> 		}
> 	}
> 	
> 	return __last; //failure
> }

Generally it looks good to me, I don't really have much else to say :) 
My only very slight worry is that as these algorithms are fiddled with 
they get ever larger :)

Chris



More information about the Libstdc++ mailing list