Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.merge.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for merge,
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#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
41
42template
49
50template
58
59template
60void
61inplace_merge (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
64
65template
66void
67inplace_merge (BidirIter<lt_comp<assign<base<cpy_ctor> > > >,
71
72#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
73
74} // namespace std
75
76
78struct Less
79{
80 static std::size_t funcalls_;
81
82 // dummy arguments provided to prevent the class from being
83 // default constructible and implicit conversion from int
84 Less (int /* dummy */, int /* dummy */) {
85 funcalls_ = 0;
86 }
87
88 // return a type other than bool but one that is implicitly
89 // convertible to bool to detect incorrect assumptions
90 conv_to_bool operator() (const UserClass &x,
91 const UserClass &y) /* non-const */ {
92 ++funcalls_;
93 return conv_to_bool::make (x.data_.val_ < y.data_.val_);
94 }
95
96private:
97 void operator= (Less&); // not assignable
98};
99
100std::size_t Less::funcalls_;
101
102
104// ordinary (non-template) base to minimize code bloat
106{
107 const char* iter_names [3];
108
109 virtual ~MergeBase () { }
110
111 // invokes inplace_merge with iterators initialized
112 // to the specified arguments and (optionally) with
113 // a predicate object
114 virtual void
116 RW_ASSERT (!"test logic error");
117 }
118
119 // invokes merge
120 virtual UserClass*
121 merge (const UserClass*, const UserClass*, const UserClass*,
122 const UserClass*, UserClass*, UserClass*, const Less*) const {
123 RW_ASSERT (!"test logic error");
124 return 0;
125 }
126};
127
128template <class InputIterator1, class InputIterator2, class OutputIterator>
130{
131 Merge () {
132 iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
133 iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
134 iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
135 }
136
137 virtual UserClass*
138 merge (const UserClass *xsrc1, const UserClass *xsrc1_end,
139 const UserClass *xsrc2, const UserClass *xsrc2_end,
140 UserClass *xdst, UserClass *xdst_end,
141 const Less *ppred) const {
142
143 const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
144 const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
145 const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
146 const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
147
148 const OutputIterator result (xdst, xdst, xdst_end);
149
150 const OutputIterator ret = ppred ?
151 std::merge (first1, last1, first2, last2, result, *ppred)
152 : std::merge (first1, last1, first2, last2, result);
153
154 // silence EDG eccp 3.7 and prior remark #550-D:
155 // variable was set but never used
156 _RWSTD_UNUSED (ret);
157
158 return ret.cur_;
159 }
160};
161
162template <class BidirectionalIterator>
164{
166 iter_names [0] = type_name (BidirectionalIterator (0, 0, 0),
167 (UserClass*)0);
168 iter_names [1] = 0;
169 iter_names [2] = 0;
170 }
171
172 virtual void
173 inplace_merge (UserClass *xsrc, UserClass *xsrc_mid, UserClass *xsrc_end,
174 const Less *ppred) const {
175
176 const BidirectionalIterator first (xsrc, xsrc, xsrc_end);
177 const BidirectionalIterator mid (xsrc_mid, xsrc, xsrc_end);
178 const BidirectionalIterator last (xsrc_end, xsrc, xsrc_end);
179
180 if (ppred)
181 std::inplace_merge (first, mid, last, *ppred);
182 else
183 std::inplace_merge (first, mid, last);
184 }
185};
186
187
189// ordinary (non-template) function to minimize code bloat
190void test_merge (int line,
191 const char *src1,
192 const char *src2,
193 const std::size_t midinx,
194 bool predicate,
195 const MergeBase &alg)
196{
197 const char* const it1name = alg.iter_names [0];
198 const char* const it2name = alg.iter_names [1];
199 const char* const outname = alg.iter_names [2];
200 const char* const predname = predicate ? "Less" : 0;
201 const bool inplace = 0 == it2name;
202 const char* const algname = inplace ? "inplace_merge" : "merge";
203
204 const std::size_t nsrc1 = std::strlen (src1);
205 const std::size_t nsrc2 = std::strlen (src2);
206
207 UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1);
208 UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2);
209
210 const std::size_t ndst = nsrc1 + nsrc2;
211 UserClass* const xdst = inplace ? xsrc1 : new UserClass [ndst];
212
213 UserClass* const xsrc1_end = xsrc1 + nsrc1;
214 UserClass* const xsrc2_end = xsrc2 + nsrc2;
215 UserClass* const xsrc_mid = xsrc1 + midinx;
216 UserClass* const xdst_end = xdst + ndst;
217
218 const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
219
220 const Less pred (0, 0);
221 const Less* const ppred = predicate ? &pred : 0;
222
223 UserClass* xdst_res = 0;
224
225 if (inplace) { // inplace_merge
226 alg.inplace_merge (xsrc1, xsrc_mid, xsrc1_end, ppred);
227 }
228 else {
229 xdst_res = alg.merge (xsrc1, xsrc1_end,
230 xsrc2, xsrc2_end, xdst, xdst_end, ppred);
231 }
232
233 const std::size_t n_ops_lt = ppred ?
235
236 bool success = true;
237
238 // check output iterator for merge
239 if (!inplace) {
240 success = xdst_res == xdst_end;
241 rw_assert (success, 0, line,
242 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...)"
243 " == first + %zu, got first + %td",
244 __LINE__, algname, it1name, it2name, outname, predicate,
245 predname, src1, src2, ndst, xdst_res - xdst);
246 }
247
248 static const int cwidth = sizeof (*xdst);
249
250 // check that the sequence is sorted
251 success = is_sorted_lt (xdst, xdst_end);
252 rw_assert (success, 0, line,
253 "line %d: %s<%s%{?}, %s, %s%{;}%{?}, %s%{;}> "
254 "(\"%s\", %{?}\"%s\"%{;}%{?}%zu%{;}, ...) ==> \"%{X=*.*}\" "
255 "not sorted",
256 __LINE__, algname, it1name, !inplace, it2name, outname,
257 predicate, predname, src1, !inplace, src2, inplace, midinx,
258 cwidth, int (ndst), -1, xdst);
259
260 // check that the algorithm is stable
261 std::size_t i = 1;
262 for ( ; i < ndst; i++) {
263 if (xdst [i - 1].data_.val_ == xdst [i].data_.val_) {
264 success = xdst [i - 1].origin_ < xdst [i].origin_;
265 if (!success)
266 break;
267 }
268 }
269
270 // to avoid errors in --trace mode
271 i = i < ndst ? i : ndst - 1;
272
273 rw_assert (success, 0, line,
274 "line %d: %s<%s%{?}, %s, %s%{;}%{?}, %s%{;}> "
275 "(\"%s\", %{?}\"%s\"%{;}%{?}%zu%{;}, ...) ==> \"%{X=*.*}\" "
276 "not stable at %zu: got ids %d != %d for values %#c == %#c",
277 __LINE__, algname, it1name, !inplace, it2name, outname,
278 predicate, predname, src1, !inplace, src2, inplace, midinx,
279 cwidth, int (ndst), i, xdst, i, xdst [i - 1].origin_,
280 xdst [i].origin_, xdst [i - 1].data_.val_, xdst [i].data_.val_);
281
282 // check the complexity
283 success = n_ops_lt <= ndst - 1;
284 rw_assert (success, 0, line,
285 "line %d: %s<%s%{?}, %s, %s%{;}%{?}, %s%{;}> "
286 "(\"%s\", %{?}\"%s\"%{;}%{?}%zu%{;}, ...) ==> \"%{X=*.*}\" "
287 "complexity: got %zu, expected <= %zu",
288 __LINE__, algname, it1name, !inplace, it2name, outname,
289 predicate, predname, src1, !inplace, src2, inplace, midinx,
290 cwidth, int (ndst), -1, xdst, n_ops_lt, ndst - 1);
291
292 delete[] xsrc1;
293 delete[] xsrc2;
294
295 if (!inplace)
296 delete[] xdst;
297}
298
299
301void test_merge (const MergeBase &alg, bool predicate)
302{
303 const char* const it1name = alg.iter_names [0];
304 const char* const it2name = alg.iter_names [1];
305 const char* const outname = alg.iter_names [2];
306 const char* const predname = predicate ? "Less" : 0;
307 const char* const algname = it2name ? "merge" : "inplace_merge";
308
309 rw_info (0, 0, 0,
310 "%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
311 outname, algname, it1name, it2name, predicate, predname);
312
313#define TEST(src1, src2) \
314 test_merge (__LINE__, src1, src2, 0, predicate, alg)
315
316 TEST ("ab", "");
317 TEST ("", "ab");
318
319 TEST ("a", "b");
320 TEST ("b", "a");
321 TEST ("aa", "bb");
322 TEST ("bb", "aa");
323
324 TEST ("acegi", "bdfhj");
325 TEST ("aaegi", "bdfjj");
326 TEST ("accgi", "bdhhj");
327 TEST ("aceei", "bffhj");
328 TEST ("acegg", "ddfhj");
329 TEST ("aceii", "bbfhj");
330
331 TEST ("bdfhj", "acegi");
332 TEST ("bdfjj", "aaegi");
333 TEST ("bdhhj", "accgi");
334 TEST ("bffhj", "aceei");
335 TEST ("ddfhj", "acegg");
336 TEST ("bbfhj", "aceii");
337
338 TEST ("abcde", "abcde");
339 TEST ("aacde", "aacde");
340 TEST ("abbde", "abbde");
341 TEST ("abcce", "abcce");
342 TEST ("abcdd", "abcdd");
343 TEST ("abcee", "abcee");
344
345 TEST ("aaegi", "bdfjj");
346 TEST ("accgi", "bdhhj");
347 TEST ("aceei", "bffhj");
348 TEST ("acegg", "ddfhj");
349 TEST ("aceii", "bbfhj");
350
351 TEST ("a","abcdefghij");
352 TEST ("ac","abcdefghi");
353 TEST ("ace","abcdefgh");
354 TEST ("aceg","abcdefg");
355
356 TEST ("j","abcdefghjj");
357 TEST ("gj","abcdeggjj");
358 TEST ("egj","abeeggjj");
359
360 TEST ("abcdefghij","a");
361 TEST ("abcdefghi","ac");
362 TEST ("abcdefgh","ace");
363 TEST ("abcdefg","aceg");
364
365 TEST ("abcdefghjj","j");
366 TEST ("abcdeggjj","gj");
367 TEST ("abeeggjj","egj");
368
369 TEST ("aaaaa", "aaaaa");
370 TEST ("bbbbb", "bbbbb");
371}
372
373
376{
377 const char* const itname = alg.iter_names [0];
378 const char* const predname = predicate ? "Less" : 0;
379 const char* const algname = alg.iter_names [1] ?
380 "merge" : "inplace_merge";
381
382 rw_info (0, 0, 0, "std::%s(%s, %2$s, %2$s%{?}, %s%{;})",
383 algname, itname, predicate, predname);
384
385#undef TEST
386#define TEST(src, mid) \
387 test_merge (__LINE__, src, "", mid, predicate, alg)
388
389 TEST ("a", 0);
390 TEST ("aa", 0);
391 TEST ("a", 1);
392 TEST ("aa", 2);
393
394 TEST ("aa", 1);
395 TEST ("ab", 1);
396 TEST ("ba", 1);
397
398 TEST ("abcdefghij", 5);
399 TEST ("aacdeffhij", 5);
400 TEST ("abbdefggij", 5);
401 TEST ("abccefghhj", 5);
402 TEST ("abcddfghii", 5);
403 TEST ("abceefghjj", 5);
404
405 TEST ("abcdeabcde", 5);
406 TEST ("aacdeaacde", 5);
407 TEST ("abbdeabbde", 5);
408 TEST ("abcceabcce", 5);
409 TEST ("abcddabcdd", 5);
410 TEST ("abceeabcee", 5);
411
412 TEST ("aabcdefghi", 1);
413 TEST ("aaacdefghi", 1);
414 TEST ("babcdefghi", 1);
415 TEST ("babbdefghi", 1);
416
417 TEST ("abcdefghia", 9);
418 TEST ("aacdefghia", 9);
419 TEST ("abcdefghib", 9);
420 TEST ("abbdefghib", 9);
421}
422
423
425/* extern */ int rw_opt_no_merge; // --no-merge
426/* extern */ int rw_opt_no_inplace_merge; // --no-inplace_merge
427/* extern */ int rw_opt_no_predicate; // --no-predicate
428/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
429/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
430/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
431/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
432/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
433
434
436template <class InputIterator1, class InputIterator2, class OutputIterator>
437void gen_merge_test (const InputIterator1&,
438 const InputIterator2&,
439 const OutputIterator&,
440 bool predicate)
441{
443
444 test_merge (alg, predicate);
445}
446
447template <class InputIterator1, class InputIterator2>
448void gen_merge_test (const InputIterator1 &it1,
449 const InputIterator2 &it2,
450 bool predicate)
451{
452 if (0 == rw_opt_no_output_iter)
453 gen_merge_test (it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
454 if (0 == rw_opt_no_fwd_iter)
455 gen_merge_test (it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
456 if (0 == rw_opt_no_bidir_iter)
457 gen_merge_test (it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
458 if (0 == rw_opt_no_rnd_iter)
460 predicate);
461}
462
463template <class InputIterator1>
464void gen_merge_test (const InputIterator1 &it1, bool predicate)
465{
466 if (0 == rw_opt_no_input_iter)
468 if (0 == rw_opt_no_fwd_iter)
470 if (0 == rw_opt_no_bidir_iter)
472 if (0 == rw_opt_no_rnd_iter)
474 predicate);
475}
476
477// generates a specialization of the merge test for each of the required
478// iterator categopries
480{
482 rw_note (0, 0, 0, "InputIterator test disabled");
483 else
485
487 rw_note (0, 0, 0, "ForwardIterator test disabled");
488 else
490
492 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
493 else
495
497 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
498 else
500}
501
502
504template <class BidirectionalIterator>
506{
508
510}
511
512
514static int run_test (int, char*[])
515{
517 rw_note (0, 0, 0, "predicate test disabled");
518
519 const int niters = rw_opt_no_predicate ? 1 : 2;
520
522 if (rw_opt_no_merge)
523 rw_note (0, 0, 0, "merge test disabled");
524 else {
525 for (int i = 0; i != niters; ++i) {
526 gen_merge_test (1 == i);
527 }
528 }
529
532 rw_note (0, 0, 0, "inplace_merge test disabled");
533 }
534 else {
535 for (int i = 0; i != niters; ++i) {
536
538 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
539 else
541
543 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
544 else
546 1 == i);
547 }
548 }
549
550 return 0;
551}
552
553
554
556int main (int argc, char *argv[])
557{
558 return rw_test (argc, argv, __FILE__,
559 "lib.alg.merge",
560 0 /* no comment */,
561 run_test,
562 "|-no-merge# "
563 "|-no-inplace_merge# "
564 "|-no-predicate#"
565 "|-no-InputIterator# "
566 "|-no-OutputIterator# "
567 "|-no-ForwardIterator# "
568 "|-no-BidirectionalIterator# "
569 "|-no-RandomAccessIterator#",
578}
#define i
Definition 17.names.cpp:126
#define y
Definition 17.names.cpp:141
#define line
Definition 17.names.cpp:490
#define last
Definition 17.names.cpp:487
#define x
Definition 17.names.cpp:140
#define BidirectionalIterator
Definition 17.names.cpp:449
#define OutputIterator
Definition 17.names.cpp:515
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define TEST(src1, src2)
int rw_opt_no_fwd_iter
Definition 25.merge.cpp:430
void test_merge(int line, const char *src1, const char *src2, const std::size_t midinx, bool predicate, const MergeBase &alg)
Definition 25.merge.cpp:190
void gen_merge_test(const InputIterator1 &, const InputIterator2 &, const OutputIterator &, bool predicate)
Definition 25.merge.cpp:437
int rw_opt_no_rnd_iter
Definition 25.merge.cpp:432
int rw_opt_no_bidir_iter
Definition 25.merge.cpp:431
int rw_opt_no_merge
Definition 25.merge.cpp:425
int rw_opt_no_input_iter
Definition 25.merge.cpp:428
int rw_opt_no_predicate
Definition 25.merge.cpp:427
int rw_opt_no_inplace_merge
Definition 25.merge.cpp:426
void gen_inplace_merge_test(const BidirectionalIterator &, bool predicate)
Definition 25.merge.cpp:505
int rw_opt_no_output_iter
Definition 25.merge.cpp:429
void test_inplace_merge(const MergeBase &alg, bool predicate)
Definition 25.merge.cpp:375
const char * type_name()
#define main
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
Definition json.h:5363
bool is_sorted_lt(InputIterator first, InputIterator last)
Definition rw_alg_test.h:75
_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
#define RW_ASSERT(expr)
virtual void inplace_merge(UserClass *xsrc, UserClass *xsrc_mid, UserClass *xsrc_end, const Less *ppred) const
Definition 25.merge.cpp:173
static std::size_t funcalls_
Definition 25.heap.cpp:104
Less(int, int)
Definition 25.merge.cpp:84
virtual UserClass * merge(const UserClass *, const UserClass *, const UserClass *, const UserClass *, UserClass *, UserClass *, const Less *) const
Definition 25.merge.cpp:121
virtual void inplace_merge(UserClass *, UserClass *, UserClass *, const Less *) const
Definition 25.merge.cpp:115
const char * iter_names[3]
Definition 25.merge.cpp:107
virtual ~MergeBase()
Definition 25.merge.cpp:109
virtual UserClass * merge(const UserClass *xsrc1, const UserClass *xsrc1_end, const UserClass *xsrc2, const UserClass *xsrc2_end, UserClass *xdst, UserClass *xdst_end, const Less *ppred) const
Definition 25.merge.cpp:138
int origin_
Definition rw_value.h:82
static UserClass from_char(char c)
Definition rw_value.h:221
UserData data_
Definition rw_value.h:79
static _RWSTD_SIZE_T n_total_op_lt_
Definition rw_value.h:133
int val_
Definition rw_value.h:39
static conv_to_bool make(bool val)