Skip to content

Commit

Permalink
Merge pull request #89 from Quuxplusone/ajo-unstable-remove
Browse files Browse the repository at this point in the history
Micro-optimize `unstable_remove`.
  • Loading branch information
TBBle committed May 10, 2017
2 parents f3f466d + 201a4c8 commit ee37914
Showing 1 changed file with 57 additions and 27 deletions.
84 changes: 57 additions & 27 deletions SG14/algorithm_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ namespace stdext
destruct(Dst, current);
throw;
}

}

template<class FwdIt, class Sentinel>
Expand All @@ -54,9 +53,8 @@ namespace stdext
destruct(first, current);
throw;
}

}

template<class FwdIt, class Sentinel>
FwdIt uninitialized_default_construct(FwdIt first, Sentinel last)
{
Expand All @@ -80,52 +78,80 @@ namespace stdext
template<class BidirIt, class UnaryPredicate>
BidirIt unstable_remove_if(BidirIt first, BidirIt last, UnaryPredicate p)
{
while (1) {
while ((first != last) && p(*first)) {
while (true) {
// Find the first instance of "p"...
while (true) {
if (first == last) {
return first;
}
if (p(*first)) {
break;
}
++first;
}
if (first == last--) break;
while ((first != last) && !p(*last)) {
// ...and the last instance of "not p"...
while (true) {
--last;
if (first == last) {
return first;
}
if (!p(*last)) {
break;
}
}
if (first == last) break;
*first++ = std::move(*last);
// ...and move the latter over top of the former.
*first = std::move(*last);
++first;
}
return first;
}

template<class BidirIt, class Val>
BidirIt unstable_remove(BidirIt first, BidirIt last, Val v)
BidirIt unstable_remove(BidirIt first, BidirIt last, const Val& v)
{
while (1) {
while ((first != last) && (*first == v)) {
while (true) {
// Find the first instance of "v"...
while (true) {
if (first == last) {
return first;
}
if (*first == v) {
break;
}
++first;
}
if (first == last--) break;
while ((first != last) && !(*last == v)) {
// ...and the last instance of "not v"...
while (true) {
--last;
if (first == last) {
return first;
}
if (!(*last == v)) {
break;
}
}
if (first == last) break;
*first++ = std::move(*last);
// ...and move the latter over top of the former.
*first = std::move(*last);
++first;
}
return first;
}



//this exists as a point of reference for providing a stable comparison vs unstable_remove_if
template<class BidirIt, class UnaryPredicate>
BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p)
{
while (1) {
while (true) {
while ((first != last) && p(*first)) {
++first;
}
if (first == last--) break;
if (first == last) break;
--last;
while ((first != last) && !p(*last)) {
--last;
}
if (first == last) break;
std::iter_swap(first++, last);
std::iter_swap(first, last);
++first;
}
return first;
}
Expand All @@ -135,10 +161,14 @@ namespace stdext
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
first = std::find_if(first, last, p);
if (first != last)
for (ForwardIt i = first; ++i != last; )
if (!p(*i))
*first++ = std::move(*i);
if (first != last) {
for (ForwardIt i = first; ++i != last; ) {
if (!p(*i)) {
*first = std::move(*i);
++first;
}
}
}
return first;
}
}
}

0 comments on commit ee37914

Please sign in to comment.