Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.partitions.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for partition, stable_partition
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
46partition (BidirIter<assign<base<cpy_ctor> > >,
49
50template
52stable_partition (BidirIter<assign<base<cpy_ctor> > >,
55
56#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
57
58} // namespace std
59
60
62template <class T>
64{
65 static std::size_t funcalls_;
66
67 // dummy argument provide to prevent implicit conversions
68 GreaterThanPredicate (int value, int /* dummy */)
69 : value_(value) {
70 funcalls_ = 0;
71 }
72
73 // return a type other than bool but one that is implicitly
74 // convertible to bool to detect incorrect assumptions
76 ++funcalls_;
77 return conv_to_bool::make (value_ < arg.data_.val_);
78 }
79
80 static const char* name () { return "GreaterThanPredicate"; }
81
82private:
83 const int value_;
84 void operator= (GreaterThanPredicate&); // not assignable
85};
86
87template<class T> std::size_t GreaterThanPredicate<T>::funcalls_;
88
89
91// exercises std::partition() and std::stable_partition()
92template <class T, class Iterator, class Predicate>
94 const char *src,
95 const char *dst,
96 const int value,
97 const std::size_t offset,
98 const Iterator &it,
99 const Predicate *,
100 const T*,
101 bool stable)
102{
103 const char* const itname = type_name (it, (T*)0);
104 const char* const fname = stable ? "stable_partition" : "partition";
105 const char* const funname = Predicate::name();
106
107 const std::size_t nsrc = std::strlen (src);
108 const std::size_t ndst = std::strlen (dst);
109
110 T* const xsrc = T::from_char (src, nsrc);
111 T* const xdst = T::from_char (dst, ndst);
112
113 T* const xsrc_end = xsrc + nsrc;
114
115 const Iterator first = make_iter (xsrc, xsrc, xsrc_end, it);
116 const Iterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
117
118 const std::size_t last_n_op_assign = T::n_total_op_assign_;
119 const std::size_t t_n_ctors = T::n_total_def_ctor_ + T::n_total_copy_ctor_;
120 const std::size_t t_n_dtors = T::n_total_dtor_;
121
122 const Predicate pred (value, 0 /* dummy */);
123
124 const Iterator res =
125 stable ? std::stable_partition (first, last, pred)
126 : std::partition (first, last, pred);
127
128 // check that there is no leaked objects
129 const std::size_t t_n_objs_diff =
130 T::n_total_def_ctor_ + T::n_total_copy_ctor_
131 - t_n_ctors - T::n_total_dtor_ + t_n_dtors;
132
133 static const int cwidth = sizeof (T);
134
135 bool success = 0 == t_n_objs_diff;
136 rw_assert (success, 0, line,
137 "line %d: std::%s <%s, %s>(\"%s\", ...) ==> \"%{X=*.*}\", "
138 "number of objects changed on %d: %s detected",
139 __LINE__, fname, itname, funname, src,
140 cwidth, int (nsrc), -1, xsrc, t_n_objs_diff,
141 t_n_objs_diff > 0 ? "memory leak" : "unexpected dtor call");
142
143 // check that the returned iterator points to the expected element
144 success = res.cur_ == first.cur_ + offset;
145 rw_assert (success, 0, line,
146 "line %d: std::%s <%s, %s>(\"%s\", ...) ==> \"%{X=*.*}\", "
147 "returned iterator it = first + %td, expected first + %zu",
148 __LINE__, fname, itname, funname, src,
149 cwidth, int (nsrc), -1, xsrc, res.cur_ - first.cur_, offset);
150
151 // check 25.2.12, p2 & p5
152 // "left" part of the array there the predicate should be true
153 std::size_t i = 0;
154 for ( ; i < offset; i++) {
155 success = xsrc[i].data_.val_ > value;
156 if (!success)
157 break;
158 }
159
160 rw_assert (success, 0, line,
161 "line %d: std::%s <%s, %s>(\"%s\", ...) "
162 "==> \"%{X=*.*}\", at %zu got: %#c !> %#c",
163 __LINE__, fname, itname, funname, src,
164 cwidth, int (nsrc), -1, xsrc, i + 1,
165 xsrc[i].data_.val_, value);
166
167
168 // "right" part of the array there the predicate should be false
169 for ( ; i < nsrc; i++) {
170 success = xsrc[i].data_.val_ <= value;
171 if (!success)
172 break;
173 }
174
175 rw_assert (success, 0, line,
176 "line %d: std::%s <%s, %s>(\"%s\", ...) "
177 "==> \"%{X=*.*}\", at %zu got: %#c !<= %#c",
178 __LINE__, fname, itname, funname, src,
179 cwidth, int (nsrc), -1, xsrc, i + 1,
180 xsrc[i].data_.val_, value);
181
182
183 // check the complexity, 25.2.12 p3 & p6
184 // first check number of swaps, 2 assignments per swap
185
186 // add 1 in case of stable_partition to avoid the assertion failing
187 // when i == 0 (only one element presents in the sequence)
188 // is this one extra assignment an algorithm bug??
189 // the standard talks about swaps only, not about assignments
190 // and there are 0 swaps (1 swap equals 2 assignments) in this case...
191 std::size_t exp_assigns = stable ? 2 * nsrc * ::ilog2 (nsrc) + 1 : nsrc;
192 std::size_t op_assigns = T::n_total_op_assign_ - last_n_op_assign;
193
194 success = op_assigns <= exp_assigns;
195 rw_assert (success, 0, line,
196 "line %d: std::%s <%s, %s>(\"%s\", ...): complexity: "
197 "got %zu assignments, expected no more than %zu",
198 __LINE__, fname, itname, funname, src,
199 op_assigns, exp_assigns);
200
201 // second check the number of the predicate calls
202 success = Predicate::funcalls_ == nsrc;
203 rw_assert (success, 0, line,
204 "line %d: std::%s <%s, %s>(\"%s\", ...): complexity: "
205 "got %zu applications of the predicate, "
206 "expected no more than %zu",
207 __LINE__, fname, itname, funname, src,
208 Predicate::funcalls_, nsrc);
209
210 if (stable) {
211
212 // check the stable_partition is really stable 25.2.12, p5
213 for (i = 0; i < nsrc; i++) {
214 success = xsrc[i].data_.val_ == xdst[i].data_.val_;
215 if (!success)
216 break;
217 }
218
219 rw_assert (success, 0, line,
220 "line %d: std::%s <%s, %s>(\"%s\", ...) ==> \"%{X=*.*}\", "
221 "expected \"%{X=*.*}\", realtive order broken at %zu, "
222 "%#c != %#c",
223 __LINE__, fname, itname, funname, src,
224 cwidth, int (nsrc), int (i), xsrc,
225 cwidth, int (ndst), int (i), xdst,
226 i, xsrc[i].data_.val_, xdst[i].data_.val_);
227 }
228
229 delete[] xsrc;
230 delete[] xdst;
231}
232
233
235template <class T, class Iterator>
236void test_partitions (const Iterator &it,
237 const T* ,
238 bool stable)
239{
240 const char* const itname = type_name (it, (T*)0);
241 const char* const fname =
242 stable ? "stable_partition" : "partition";
243 const char* const funname = GreaterThanPredicate<T>::name();
244
245 rw_info (0, 0, 0,
246 "%s %s (%1$s, %1$s, %s)",
247 itname, fname, funname);
248
249#define TEST(src, dest, mid, offet) \
250 test_partitions (__LINE__, src, dest, mid, offet, it, \
251 (GreaterThanPredicate<T>*)0, (T*)0, stable)
252
253 // stable_partition fails this test
254 TEST ("abcdefghij", "abcdefghij", 0, 10);
255
256 TEST ("abcdefghij", "bcdefghija", 'a', 9);
257 TEST ("abcdefghij", "cdefghijab", 'b', 8);
258 TEST ("abcdefghij", "defghijabc", 'c', 7);
259 TEST ("abcdefghij", "efghijabcd", 'd', 6);
260 TEST ("abcdefghij", "fghijabcde", 'e', 5);
261 TEST ("abcdefghij", "ghijabcdef", 'f', 4);
262 TEST ("abcdefghij", "hijabcdefg", 'g', 3);
263 TEST ("abcdefghij", "ijabcdefgh", 'h', 2);
264 TEST ("abcdefghij", "jabcdefghi", 'i', 1);
265 TEST ("abcdefghij", "abcdefghij", 'j', 0);
266
267 // stable_partition fails this test
268 TEST ("jihgfedcba", "jihgfedcba", 0, 10);
269
270 TEST ("jihgfedcba", "jihgfedcba", 'a', 9);
271 TEST ("jihgfedcba", "jihgfedcba", 'b', 8);
272 TEST ("jihgfedcba", "jihgfedcba", 'c', 7);
273 TEST ("jihgfedcba", "jihgfedcba", 'd', 6);
274 TEST ("jihgfedcba", "jihgfedcba", 'e', 5);
275 TEST ("jihgfedcba", "jihgfedcba", 'f', 4);
276 TEST ("jihgfedcba", "jihgfedcba", 'g', 3);
277 TEST ("jihgfedcba", "jihgfedcba", 'h', 2);
278 TEST ("jihgfedcba", "jihgfedcba", 'i', 1);
279 TEST ("jihgfedcba", "jihgfedcba", 'j', 0);
280
281 // stable_partition fails this test
282 TEST ("a", "a", 0, 1);
283
284 TEST ("a", "a", 'a', 0);
285}
286
287
289/* extern */ int rw_opt_no_partition; // --no-partition
290/* extern */ int rw_opt_no_stable_partition; // --no-stable_partition
291/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
292/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
293
294
295template <class T>
296void test_partitions (const T*, bool stable)
297{
298 rw_info (0, 0, 0,
299 "template <class %s, class %s> %1$s %s (%1$s, %1$s, %2$s)",
300 "BidirectionalIterator", "Predicate",
301 stable ? "stable_partition" : "partition");
302
304 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
305 }
306 else {
307 test_partitions (BidirIter<T>(), (T*)0, stable);
308 }
309
310 if (rw_opt_no_rnd_iter) {
311 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
312 }
313 else {
314 test_partitions (RandomAccessIter<T>(), (T*)0, stable);
315 }
316}
317
318
320static int run_test (int, char*[])
321{
323 rw_note (0, __FILE__, __LINE__, "std::partition test disabled");
324 }
325 else {
326 test_partitions ((UserClass*)0, false);
327 }
328
330 rw_note (0, __FILE__, __LINE__,
331 "std::stable_partition test disabled");
332 }
333 else {
334 test_partitions ((UserClass*)0, true);
335 }
336
337 return 0;
338}
339
340
342int main (int argc, char *argv[])
343{
344 return rw_test (argc, argv, __FILE__,
345 "lib.alg.partitions",
346 0 /* no comment */, run_test,
347 "|-no-partition# "
348 "|-no-stable_partition# "
349 "|-no-BidirectionalIterator# "
350 "|-no-RandomAccessIterator",
355}
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define last
Definition 17.names.cpp:487
#define offset
Definition 17.names.cpp:508
const MyBuffer< char > nsrc[]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
void test_partitions(int line, const char *src, const char *dst, const int value, const std::size_t offset, const Iterator &it, const Predicate *, const T *, bool stable)
int rw_opt_no_rnd_iter
#define TEST(src, dest, mid, offet)
int rw_opt_no_bidir_iter
int rw_opt_no_stable_partition
int rw_opt_no_partition
T value(const T &val)
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)
_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 std::size_t funcalls_
GreaterThanPredicate(int value, int)
static const char * name()
conv_to_bool operator()(const T &arg)
const value_type * cur_
static conv_to_bool make(bool val)
int arg
Definition locale.cpp:2806