Skip to content

Commit

Permalink
2014-11-11 François Dumont <[email protected]>
Browse files Browse the repository at this point in the history
	PR libstdc++/61107
	* include/bits/stl_algo.h (__inplace_stable_partition): Delete.
	(__stable_partition_adaptive): Return __first if range length is 1.
	(__stable_partition): Adapt.
	* testsuite/util/testsuite_new_operators.h: New.
	* testsuite/25_algorithms/stable_sort/1.cc: Test algo in simulated
	constraint memory context.
	* testsuite/25_algorithms/inplace_merge/1.cc: Likewise.
	* testsuite/25_algorithms/stable_partition/1.cc: Likewise.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217370 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
fdumont committed Nov 11, 2014
1 parent 7c40780 commit abad5ed
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 79 deletions.
12 changes: 12 additions & 0 deletions libstdc++-v3/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
2014-11-11 François Dumont <[email protected]>

PR libstdc++/61107
* include/bits/stl_algo.h (__inplace_stable_partition): Delete.
(__stable_partition_adaptive): Return __first if range length is 1.
(__stable_partition): Adapt.
* testsuite/util/testsuite_new_operators.h: New.
* testsuite/25_algorithms/stable_sort/1.cc: Test algo in simulated
constraint memory context.
* testsuite/25_algorithms/inplace_merge/1.cc: Likewise.
* testsuite/25_algorithms/stable_partition/1.cc: Likewise.

2014-11-11 Francois-Xavier Coudert <[email protected]>

PR target/63610
Expand Down
97 changes: 37 additions & 60 deletions libstdc++-v3/include/bits/stl_algo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1511,34 +1511,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

// partition

/// This is a helper function...
/// Requires __len != 0 and !__pred(*__first),
/// same as __stable_partition_adaptive.
template<typename _ForwardIterator, typename _Predicate, typename _Distance>
_ForwardIterator
__inplace_stable_partition(_ForwardIterator __first,
_Predicate __pred, _Distance __len)
{
if (__len == 1)
return __first;
_ForwardIterator __middle = __first;
std::advance(__middle, __len / 2);
_ForwardIterator __left_split =
std::__inplace_stable_partition(__first, __pred, __len / 2);
// Advance past true-predicate values to satisfy this
// function's preconditions.
_Distance __right_len = __len - __len / 2;
_ForwardIterator __right_split =
std::__find_if_not_n(__middle, __right_len, __pred);
if (__right_len)
__right_split = std::__inplace_stable_partition(__middle,
__pred,
__right_len);
std::rotate(__left_split, __middle, __right_split);
std::advance(__left_split, std::distance(__middle, __right_split));
return __left_split;
}

/// This is a helper function...
/// Requires __first != __last and !__pred(__first)
/// and __len == distance(__first, __last).
Expand All @@ -1554,10 +1526,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Pointer __buffer,
_Distance __buffer_size)
{
if (__len == 1)
return __first;

if (__len <= __buffer_size)
{
_ForwardIterator __result1 = __first;
_Pointer __result2 = __buffer;

// The precondition guarantees that !__pred(__first), so
// move that element to the buffer before starting the loop.
// This ensures that we only call __pred once per element.
Expand All @@ -1575,31 +1551,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*__result2 = _GLIBCXX_MOVE(*__first);
++__result2;
}

_GLIBCXX_MOVE3(__buffer, __result2, __result1);
return __result1;
}
else
{
_ForwardIterator __middle = __first;
std::advance(__middle, __len / 2);
_ForwardIterator __left_split =
std::__stable_partition_adaptive(__first, __middle, __pred,
__len / 2, __buffer,
__buffer_size);
// Advance past true-predicate values to satisfy this
// function's preconditions.
_Distance __right_len = __len - __len / 2;
_ForwardIterator __right_split =
std::__find_if_not_n(__middle, __right_len, __pred);
if (__right_len)
__right_split =
std::__stable_partition_adaptive(__right_split, __last, __pred,
__right_len,
__buffer, __buffer_size);
std::rotate(__left_split, __middle, __right_split);
std::advance(__left_split, std::distance(__middle, __right_split));
return __left_split;
}

_ForwardIterator __middle = __first;
std::advance(__middle, __len / 2);
_ForwardIterator __left_split =
std::__stable_partition_adaptive(__first, __middle, __pred,
__len / 2, __buffer,
__buffer_size);

// Advance past true-predicate values to satisfy this
// function's preconditions.
_Distance __right_len = __len - __len / 2;
_ForwardIterator __right_split =
std::__find_if_not_n(__middle, __right_len, __pred);

if (__right_len)
__right_split =
std::__stable_partition_adaptive(__right_split, __last, __pred,
__right_len,
__buffer, __buffer_size);

std::rotate(__left_split, __middle, __right_split);
std::advance(__left_split, std::distance(__middle, __right_split));
return __left_split;
}

template<typename _ForwardIterator, typename _Predicate>
Expand All @@ -1618,16 +1596,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_DistanceType;

_Temporary_buffer<_ForwardIterator, _ValueType> __buf(__first, __last);
if (__buf.size() > 0)
return
std::__stable_partition_adaptive(__first, __last, __pred,
_DistanceType(__buf.requested_size()),
__buf.begin(),
_DistanceType(__buf.size()));
else
return
std::__inplace_stable_partition(__first, __pred,
_DistanceType(__buf.requested_size()));
return
std::__stable_partition_adaptive(__first, __last, __pred,
_DistanceType(__buf.requested_size()),
__buf.begin(),
_DistanceType(__buf.size()));
}

/**
Expand Down Expand Up @@ -2471,6 +2444,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__gnu_cxx::__ops::__val_comp_iter(__comp));
__len11 = std::distance(__first, __first_cut);
}

_BidirectionalIterator __new_middle
= std::__rotate_adaptive(__first_cut, __middle, __second_cut,
__len1 - __len11, __len22, __buffer,
Expand All @@ -2496,12 +2470,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__len1 == 0 || __len2 == 0)
return;

if (__len1 + __len2 == 2)
{
if (__comp(__middle, __first))
std::iter_swap(__first, __middle);
return;
}

_BidirectionalIterator __first_cut = __first;
_BidirectionalIterator __second_cut = __middle;
_Distance __len11 = 0;
Expand All @@ -2524,6 +2500,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__gnu_cxx::__ops::__val_comp_iter(__comp));
__len11 = std::distance(__first, __first_cut);
}

std::rotate(__first_cut, __middle, __second_cut);
_BidirectionalIterator __new_middle = __first_cut;
std::advance(__new_middle, std::distance(__middle, __second_cut));
Expand Down
37 changes: 29 additions & 8 deletions libstdc++-v3/testsuite/25_algorithms/inplace_merge/1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <algorithm>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>
#include <testsuite_new_operators.h>

using __gnu_test::test_container;
using __gnu_test::bidirectional_iterator_wrapper;
Expand Down Expand Up @@ -66,17 +67,27 @@ test3()
{
bool test __attribute__((unused)) = true;

S s[4];
S s[8];
s[0].a = 0;
s[1].a = 1;
s[2].a = 0;
s[3].a = 1;
s[2].a = 2;
s[3].a = 3;
s[4].a = 0;
s[5].a = 1;
s[6].a = 2;
s[7].a = 3;

s[0].b = 0;
s[1].b = 0;
s[2].b = 1;
s[3].b = 1;
inplace_merge(s, s + 2, s + 4);
VERIFY( s[0].b == 0 && s[1].b == 1 && s[2].b == 0 && s[3].b == 1 );
s[1].b = 1;
s[2].b = 2;
s[3].b = 3;
s[4].b = 4;
s[5].b = 5;
s[6].b = 6;
s[7].b = 7;

inplace_merge(s, s + 4, s + 8);
VERIFY( s[0].b == 0 && s[1].b == 4 && s[2].b == 1 && s[3].b == 5 );
}

int
Expand All @@ -85,5 +96,15 @@ main()
test1();
test2();
test3();

__gnu_test::set_new_limit(sizeof(S) * 4);
test3();

__gnu_test::set_new_limit(sizeof(S));
test3();

__gnu_test::set_new_limit(0);
test3();

return 0;
}
34 changes: 27 additions & 7 deletions libstdc++-v3/testsuite/25_algorithms/stable_partition/1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <algorithm>
#include <functional>
#include <testsuite_new_operators.h>
#include <testsuite_hooks.h>

bool test __attribute__((unused)) = true;
Expand All @@ -27,6 +28,9 @@ const int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
const int B[] = {2, 4, 6, 8, 10, 12, 14, 16, 1, 3, 5, 7, 9, 11, 13, 15, 17};
const int N = sizeof(A) / sizeof(int);

// Index of the middle element that should be returned by the algo.
const int M = 8;

struct Pred
{
bool
Expand All @@ -36,20 +40,36 @@ struct Pred

// 25.2.12 stable_partition()
void
test02()
test01()
{
using std::stable_partition;
using std::stable_partition;

int s1[N];
std::copy(A, A + N, s1);
int s1[N];
std::copy(A, A + N, s1);

stable_partition(s1, s1 + N, Pred());
VERIFY(std::equal(s1, s1 + N, B));
VERIFY( stable_partition(s1, s1 + N, Pred()) == s1 + M );
VERIFY( std::equal(s1, s1 + N, B) );
}

int
main()
{
test02();
test01();

// stable_partition rely on an internal buffer if possible. Try to limit the
// size of this buffer to see if algo is robust.

// Limit to half of the necessary buffer.
__gnu_test::set_new_limit(sizeof(A) / 2);
test01();

// Limit to just 1 element.
__gnu_test::set_new_limit(sizeof(int));
test01();

// Limit to 0
__gnu_test::set_new_limit(0);
test01();

return 0;
}
19 changes: 15 additions & 4 deletions libstdc++-v3/testsuite/25_algorithms/stable_sort/1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// 25.3.1.2 [lib.stable.sort]

#include <algorithm>
#include <testsuite_new_operators.h>
#include <testsuite_hooks.h>
#include <testsuite_iterators.h>

Expand All @@ -30,21 +31,22 @@ typedef test_container<int, random_access_iterator_wrapper> Container;
void
test1()
{
int array[]={0};
int array[] = { 0 };
Container con(array, array);
stable_sort(con.begin(), con.end());
}

void
test2()
{
int array[] = {6, 5, 4, 3, 2, 1, 0};
int array[] = { 6, 5, 4, 3, 2, 1, 0 };
Container con(array, array + 7);
stable_sort(con.begin(), con.end());
VERIFY(array[0] == 0 && array[1] == 1 && array[2] == 2 &&
array[3] == 3 && array[4] == 4 && array[5] == 5 &&
array[6] == 6);
}

struct S
{
int i;
Expand Down Expand Up @@ -72,8 +74,7 @@ operator<(const S& s1, const S& s2)
void
test3()
{

S array[] = {-1, -2, 1, 2, -3 ,-5 ,3 , -4, 5, 4};
S array[] = { -1, -2, 1, 2, -3 ,-5 ,3 , -4, 5, 4 };
test_container<S, random_access_iterator_wrapper> con(array,array + 10);
stable_sort(con.begin(), con.end());
for(int i = 0; i < 10; ++i)
Expand All @@ -85,5 +86,15 @@ main()
{
test1();
test2();

test3();

__gnu_test::set_new_limit(sizeof(S) * 5);
test3();

__gnu_test::set_new_limit(sizeof(S));
test3();

__gnu_test::set_new_limit(0);
test3();
}
Loading

0 comments on commit abad5ed

Please sign in to comment.