Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.partial.sort.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for partial_sort, partial_sort_copy
30#include <cstring> // for strlen, size_t
31
32#include <rw_alg_test.h>
33#include <rw_value.h> // for UserClass
34#include <rw_driver.h> // for rw_test()
35
36
39
40// disable explicit instantiation for compilers (like MSVC)
41// that can't handle it
42#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
43
44template
45void
49
50template
51void
56
57template
59partial_sort_copy (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
63
64template
66partial_sort_copy (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
71
72#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
73
74} // namespace std
75
76
78template <class T>
79struct Less
80{
81 static std::size_t funcalls_;
82
83 // dummy arguments provided to prevent the class from being
84 // default constructible and implicit conversion from int
85 Less (int /* dummy */, int /* dummy */) {
86 funcalls_ = 0;
87 }
88
89 // return a type other than bool but one that is implicitly
90 // convertible to bool to detect incorrect assumptions
91 conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
92 ++funcalls_;
93 return conv_to_bool::make (x.data_.val_ < y.data_.val_);
94 }
95
96 static const char* name () { return "Less"; }
97
98private:
99 void operator= (Less&); // not assignable
100};
101
102template<class T> std::size_t Less<T>::funcalls_;
103
104
106template <class Iterator, class CopyIterator, class T, class Predicate>
108 const char *src,
109 const std::size_t N,
110 const std::size_t mid,
111 const Iterator &it,
112 const CopyIterator &itc,
113 const T* ,
114 const Predicate *ppred,
115 bool copy)
116{
117 typedef RandomAccessIter<T> RandIter;
118 const RandIter rand_it(0, 0, 0);
119
120 const char* const itname =
121 copy ? type_name (itc, (T*)0) : type_name (it, (T*)0);
122 const char* const outname = "RandomAccessIterator";
123 const char* const fname = copy ? "partial_sort_copy" : "partial_sort";
124 const char* const funname = ppred ? Predicate::name() : "operator<()";
125
126 // generate random values for each default constructed T
127 T::gen_ = gen_rnd;
128
129 const std::size_t nsrc = src ? std::strlen (src) : N;
130
131 T* const xsrc = src ? T::from_char (src, nsrc) : new T[nsrc];
132 T* const xdst = new T [mid];
133 T* res_x = copy ? xdst : xsrc;
134
135 T* const xsrc_end = xsrc + nsrc;
136 T* const xdst_end = xdst + mid;
137
138 const Iterator first = make_iter (xsrc, xsrc, xsrc_end, it);
139 const Iterator middle = make_iter (xsrc + mid, xsrc, xsrc_end, it);
140 const Iterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
141
142 CopyIterator first_c = make_iter (xsrc, xsrc, xsrc_end, itc);
143 CopyIterator last_c = make_iter (xsrc_end, xsrc, xsrc_end, itc);
144
145 RandIter res_first = make_iter (xdst, xdst, xdst_end, rand_it);
146 RandIter res_last = make_iter (xdst_end, xdst, xdst_end, rand_it);
147
148 const Predicate pred (0, 0);
149 RandIter result (0, 0, 0);
150
151 std::size_t last_n_op_lt = T::n_total_op_lt_;
152
153 if (copy) {
154 if (ppred)
155 result = std::partial_sort_copy (
156 first_c, last_c, res_first, res_last, pred);
157 else
158 result = std::partial_sort_copy (
159 first_c, last_c, res_first, res_last);
160 }
161 else {
162 if (ppred)
163 std::partial_sort (first, middle, last, pred);
164 else
165 std::partial_sort (first, middle, last);
166 }
167
168 bool success = true;
169 // check the returned iterator for copy version
170 if (copy) {
171 success = result.cur_ == res_first.cur_ + mid;
172 rw_assert (success, 0, line,
173 "line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> (): "
174 "returned iterator it is invalid: got result + %td, "
175 "expected result + %zu",
176 __LINE__, fname, itname, copy, outname, ppred, funname,
177 result.cur_ - res_first.cur_, mid);
178 }
179
180 // check that the array is sorted
181 success = is_sorted_lt (res_x, res_x + mid);
182 if (src) {
183 rw_assert (success, 0, line,
184 "line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
185 "(\"%s\", %zu, ...): ==> \"%{X=*.*}\" not sorted",
186 __LINE__, fname, itname, copy, outname, ppred, funname,
187 src, mid, int (sizeof (*res_x)), int (mid), -1, res_x);
188 }
189 else {
190 rw_assert (success, 0, line,
191 "line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
192 "(%zu, %zu, ...): not sorted",
193 __LINE__, fname, itname, copy, outname, ppred, funname,
194 nsrc, mid);
195 }
196
197 // check that any element in the sorted range <= that any element
198 // in the rest part of the array
199 int max_el = res_x[0].data_.val_;
200 std::size_t j = 1;
201 for ( ; j < mid; j++)
202 max_el = max_el < res_x[j].data_.val_ ? res_x[j].data_.val_ : max_el;
203
204 if (copy) {
205 std::size_t tmp = 0;
206 for (j = 0; j < nsrc; j++)
207 if (max_el > xsrc[j].data_.val_)
208 tmp++;
209
210 success = tmp <= mid;
211 }
212 else {
213 for (j = mid; j < nsrc; j++) {
214 success = max_el <= xsrc[j].data_.val_;
215 if (! success)
216 break;
217 }
218 }
219
220 // to avoid error in trace mode
221 j = j < nsrc ? j : nsrc - 1;
222
223 if (src) {
224 rw_assert (success, 0, line,
225 "line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
226 "(\"%s\", %zu, ...): ==> \"%{X=*.*}\" got less element "
227 "%{?}%#c%{;} in the unsorted part", __LINE__, fname,
228 itname, copy, outname, ppred, funname, src, mid,
229 int (sizeof (*res_x)), int (copy ? mid : nsrc), -1, res_x,
230 !copy, xsrc[j].data_.val_);
231 }
232 else {
233 rw_assert (success, 0, line,
234 "line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> "
235 "(%zu, %zu, ...): got less element in the unsorted part",
236 __LINE__, fname, itname, copy, outname, ppred, funname,
237 nsrc, mid);
238 }
239
240 // verify 25.3.1.1, p2 and 25.3.1.2, p3
241 // the complexity of our implementation is no worse than
242 // 3.33 * N * log (N) (hence the magic 7 and 2)
243 std::size_t n_ops =
244 ppred ? Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
245 std::size_t exp_ops = 7 * nsrc * ::ilog2 (mid > 1 ? mid : 2);
246 success = 2 * n_ops <= exp_ops;
247 rw_assert (success, 0, line,
248 "line %d: %s<%s%{?}, %s%{;}%{?}, %s%{;}> (): complexity "
249 "for length %zu is %zu, expected no more than %zu",
250 __LINE__, fname, itname, copy, outname, ppred, funname,
251 nsrc, n_ops, exp_ops / 2);
252
253 delete[] xsrc;
254 delete[] xdst;
255}
256
257
259/* extern */ int rw_opt_nloops = 256; // --nloops=#
260/* extern */ int rw_opt_no_partial_sort; // --no-partial_sort
261/* extern */ int rw_opt_no_partial_sort_copy; // --no-partial_sort_copy
262/* extern */ int rw_opt_no_predicate; // --no-predicate
263/* extern */ int rw_opt_no_complexity; // --no-complexity
264/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
265/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
266/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
267/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
268
269
271template <class Iterator, class CopyIterator, class T, class Predicate>
272void test_partial_sort (const std::size_t N,
273 const Iterator &it,
274 const CopyIterator &itc,
275 const T* ,
276 const Predicate *ppred,
277 bool copy)
278{
279 const char* const itname =
280 copy ? type_name (itc, (T*)0) : type_name (it, (T*)0);
281 const char* const outname = "RandomAccessIterator";
282 const char* const fname = copy ? "partial_sort_copy" : "partial_sort";
283 const char* const funname = ppred ? Predicate::name() : "operator<()";
284
285 rw_info (0, 0, 0,
286 "%{?}%s %{;}std::%s (%s, %4$s, %s%{?}, %2$s%{;}%{?}, %s%{;})",
287 copy, outname, fname, itname, copy ? outname : itname,
288 copy, ppred, funname);
289
290#define TEST(src, mid) \
291 test_partial_sort (__LINE__, src, 0, mid, it, itc, (T*)0, ppred, copy)
292
293 TEST ("a", 1);
294
295 TEST ("ba", 1);
296 TEST ("cba", 1);
297 TEST ("dcba", 2);
298 TEST ("edcba", 2);
299 TEST ("fedcba", 3);
300 TEST ("gfedcba", 3);
301 TEST ("hgfedcba", 4);
302 TEST ("ihgfedcba", 4);
303 TEST ("jihgfedcba", 5);
304
305 TEST ("ab", 1);
306 TEST ("abc", 1);
307 TEST ("abcd", 2);
308 TEST ("abcde", 2);
309 TEST ("abcdef", 3);
310 TEST ("abcdefg", 3);
311 TEST ("abcdefgh", 4);
312 TEST ("abcdefghi", 4);
313 TEST ("abcdefghij", 5);
314
315 TEST ("aa", 1);
316 TEST ("aabb", 2);
317 TEST ("bbccaa", 3);
318 TEST ("ddbbccaa", 4);
319 TEST ("ddeebbccaa", 5);
320
321 TEST ("aa", 2);
322 TEST ("aabb", 4);
323 TEST ("bbccaa", 6);
324 TEST ("ddbbccaa", 8);
325 TEST ("ddeebbccaa", 10);
326
327 TEST ("aaaaaaaaaa", 5);
328 TEST ("ababababab", 4);
329 TEST ("bababababa", 4);
330
331#undef TEST
332
334 rw_note (0, 0, 0,
335 "%{?}%s %{;}std::%s (%s, %4$s, %s%{?}, %2$s%{;}%{?}, %s%{;})"
336 ": complexity test disabled",
337 copy, outname, fname, itname, copy ? outname : itname,
338 copy, ppred, funname);
339 }
340 else {
341
342 rw_info (0, 0, 0,
343 "%{?}%s %{;}std::%s (%s, %4$s, %s%{?}, %2$s%{;}%{?}, %s%{;})"
344 ": complexity test",
345 copy, outname, fname, itname, copy ? outname : itname,
346 copy, ppred, funname);
347
348 for (std::size_t i = 1; i < N; i++)
349 test_partial_sort (__LINE__, 0, i, i > 1 ? i / 2 : 1, it, itc,
350 (T*)0, ppred, copy);
351 }
352}
353
354
356template <class T, class Predicate>
357void test_partial_sort (const std::size_t N,
358 const T* ,
359 const Predicate *ppred,
360 bool copy)
361{
362 rw_info (0, 0, 0,
363 "template <class %s%{?}, class %s%{;}%{?}, class %s%{;}> "
364 "%s std::partial_sort%{?}_copy%{;} (%1$s%{?}, %1$s%{;}, %1$s"
365 "%{?}, %3$s, %3$s%{;}%{?}, %5$s%{;})",
366 copy ? "InputIterator" : "RandomAccessIterator",
367 copy, "RandomAccessIterator", ppred, "StrictWeakComp",
368 copy ? "RandomAccessIterator" : "void",
369 copy, !copy, copy, ppred);
370
371 static const InputIter<T> input_iter (0, 0, 0);
372 static const FwdIter<T> fwd_iter (0, 0, 0);
373 static const BidirIter<T> bidir_iter (0, 0, 0);
374 static const RandomAccessIter<T> rand_iter (0, 0, 0);
375
376 if (! copy) {
377 test_partial_sort (N, rand_iter, rand_iter,
378 (T*)0, ppred, false);
379 return;
380 }
381
383 rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
384 }
385 else {
386 test_partial_sort (N, rand_iter, input_iter,
387 (T*)0, ppred, true);
388 }
389
390 if (rw_opt_no_fwd_iter) {
391 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
392 }
393 else {
394 test_partial_sort (N, rand_iter, fwd_iter,
395 (T*)0, ppred, true);
396 }
397
399 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
400 }
401 else {
402 test_partial_sort (N, rand_iter, bidir_iter,
403 (T*)0, ppred, true);
404 }
405
406 if (rw_opt_no_rnd_iter) {
407 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
408 }
409 else {
410 test_partial_sort (N, rand_iter, rand_iter,
411 (T*)0, ppred, true);
412 }
413}
414
415
417template <class T>
418void test_partial_sort (const std::size_t N,
419 const T* ,
420 bool copy)
421{
422 test_partial_sort (N, (T*)0, (Less<T>*)0, copy);
423
425 rw_note (0, __FILE__, __LINE__,
426 "std::partial_sort%{?}_copy%{;} predicate test disabled",
427 copy);
428 }
429 else {
430 const Less<T> pred(0, 0);
431 test_partial_sort (N, (T*)0, &pred, copy);
432 }
433}
434
435
438static int run_test (int, char*[])
439{
440 const std::size_t N = std::size_t (rw_opt_nloops);
441
443 rw_note (0, __FILE__, __LINE__,
444 "std::partial_sort test disabled");
445 }
446 else {
447 test_partial_sort (N, (UserClass*)0, false);
448 }
449
451 rw_note (0, __FILE__, __LINE__,
452 "std::partial_sort_copy test disabled");
453 }
454 else {
455 test_partial_sort (N, (UserClass*)0, true);
456 }
457
458 return 0;
459}
460
461
462
464int main (int argc, char *argv[])
465{
466 return rw_test (argc, argv, __FILE__,
467 "lib.partial.sort",
468 0 /* no comment */,
469 run_test,
470 "|-nloops#0 " // must be non-negative
471 "|-no-partial_sort# "
472 "|-no-partial_sort_copy# "
473 "|-no-InputIterator# "
474 "|-no-ForwardIterator# "
475 "|-no-BidirectionalIterator# "
476 "|-no-RandomAccessIterator# "
477 "|-no-predicate",
487}
#define N
Definition 17.names.cpp:157
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
#define y
Definition 17.names.cpp:141
#define middle
Definition 17.names.cpp:496
#define line
Definition 17.names.cpp:490
#define last
Definition 17.names.cpp:487
#define x
Definition 17.names.cpp:140
#define j
Definition 17.names.cpp:127
#define tmp
Definition 17.names.cpp:553
volatile int result
const MyBuffer< char > nsrc[]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
int rw_opt_no_fwd_iter
int rw_opt_no_rnd_iter
void test_partial_sort(int line, const char *src, const std::size_t N, const std::size_t mid, const Iterator &it, const CopyIterator &itc, const T *, const Predicate *ppred, bool copy)
int rw_opt_no_bidir_iter
int rw_opt_no_partial_sort
int rw_opt_no_input_iter
int rw_opt_no_predicate
#define TEST(src, mid)
int rw_opt_no_complexity
int rw_opt_no_partial_sort_copy
int rw_opt_nloops
const char * type_name()
#define main
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
Definition json.h:5363
T * make_iter(T *cur, const T *, const T *, T *)
_TEST_EXPORT unsigned ilog2(_RWSTD_SIZE_T)
bool is_sorted_lt(InputIterator first, InputIterator last)
Definition rw_alg_test.h:75
_TEST_EXPORT int gen_rnd()
Definition alg_test.cpp:66
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
static const char * name()
conv_to_bool operator()(const T &x, const T &y)
Definition 25.heap.cpp:114
static std::size_t funcalls_
Definition 25.heap.cpp:104
Less(int, int)
static conv_to_bool make(bool val)