Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.nth.element.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for nth_element,
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
43void
47
48template
49void
54
55#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
56
57} // namespace std
58
59
61template <class T>
63{
64 static std::size_t funcalls_;
65
66 // dummy arguments provided to prevent the class from being
67 // default constructible and implicit conversion from int
68 StrictWeakLess (int /* dummy */, int /* dummy */) {
69 funcalls_ = 0;
70 }
71
72 // return a type other than bool but one that is implicitly
73 // convertible to bool to detect incorrect assumptions
74 conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
75 ++funcalls_;
76 return conv_to_bool::make (x.data_.val_ < y.data_.val_);
77 }
78
79 static const char* name () { return "StrictWeakLess"; }
80
81private:
82 void operator= (StrictWeakLess&); // not assignable
83};
84
85template<class T>
87
88
90// exrcises nth_element
91template <class T, class Predicate>
93 const char *src,
94 const std::size_t N,
95 const std::size_t nth,
96 const T*,
97 const Predicate *ppred)
98{
99 _RWSTD_UNUSED (ppred);
100
101 typedef RandomAccessIter<T> RandIter;
102
103 const RandIter it(0, 0, 0);
104
105 const char* const itname = type_name (it, (T*)0);
106 const char* const fname = "nth_element";
107 const char* const funname = Predicate::name();
108
109 const std::size_t nsrc = src ? std::strlen (src) : N;
110
111 T::gen_ = gen_rnd;
112 T* const xsrc = src ? T::from_char (src, nsrc) : new T[nsrc];
113
114 T* const xsrc_end = xsrc + nsrc;
115
116 // current, first, last
117 const RandIter first = make_iter (xsrc, xsrc, xsrc_end, it);
118 const RandIter nth_it = make_iter (xsrc + nth, xsrc, xsrc_end, it);
119 const RandIter last = make_iter (xsrc_end, xsrc, xsrc_end, it);
120
121 Predicate pred (0, 0);
122
123 const std::size_t last_n_op_lt = T::n_total_op_lt_;
124
125 if (ppred)
126 std::nth_element (first, nth_it, last, pred);
127 else
128 std::nth_element (first, nth_it, last);
129
130 // check the results, 25.3.2, p1
131 bool success = true;
132 std::size_t i = 0;
133 std::size_t j = 0;
134
135 for (i = 0; i < nth; i++) {
136 for (j = nth; j < nsrc; j++) {
137 success = xsrc[i].data_.val_ <= xsrc[j].data_.val_;
138 if (!success)
139 break;
140 }
141
142 if (!success)
143 break;
144 }
145
146 // to avoid errors in --trace mode
147 i = i < nth ? i : nth - 1;
148 j = j < nsrc ? j : nsrc - 1;
149
150 if (src) {
151 rw_assert (success, 0, line,
152 "line %d: %s<%s%{?}, %s%{;}>(\"%s\", %zu, ...) ==> "
153 "\"%{X=*.*}\", got %#c at %zu !< %#c at %zu",
154 __LINE__, fname, itname, ppred, funname, src, nth,
155 int (sizeof (*xsrc)), int (nsrc), -1, xsrc,
156 xsrc[i].data_.val_, i, xsrc[j].data_.val_, j);
157 }
158 else {
159 rw_assert (success, 0, line,
160 "line %d: %s<%s%{?}, %s%{;}>(%zu, %zu, ...) "
161 "got %d at %zu !< %d at %zu",
162 __LINE__, fname, itname, ppred, funname, N, nth,
163 xsrc[i].data_.val_, i, xsrc[j].data_.val_, j);
164 }
165
166 // check the complexity, 25.3.2, p2
167 // it should be linear, i.e. <= K * N, there K << N
168 // after tests on random sequences use K == 8 as upper bound
169 std::size_t n_ops =
170 ppred ? Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
171 std::size_t exp_ops = 8 * nsrc;
172
173 success = n_ops <= exp_ops;
174
175 rw_assert (success, 0, line,
176 "line %d: %s<%s%{?}, %s%{;}>(%{?}\"%s\"%{;}%{?}%zu%{;}, "
177 "%zu, ...): complexity: got %zu, expected no more than %zu",
178 __LINE__, fname, itname, ppred, funname,
179 src, src, !src, N, nth, n_ops, exp_ops);
180
181 delete[] xsrc;
182}
183
184
186/* extern */ int rw_opt_nloops = 256; // --nloops=#
187/* extern */ int rw_opt_no_predicate; // --no-predicate
188/* extern */ int rw_opt_no_complexity; // --no-complexity
189
190
192template <class T, class Predicate>
193void test_nth_element (const T*,
194 const Predicate *ppred)
195{
196 typedef RandomAccessIter<T> RandIter;
197
198 const char* const itname = type_name (RandIter (0, 0, 0), (T*)0);
199 const char* const fname = "nth_element";
200 const char* const funname = Predicate::name();
201
202 rw_info (0, 0, 0,
203 "std::%s (%s, %2$s, %2$s%{?}, %s%{;})",
204 fname, itname, ppred, funname);
205
206#define TEST(src, nth) \
207 test_nth_element (__LINE__, src, 0, nth, (T*)0, ppred)
208
209 TEST ("a", 0);
210 TEST ("aa", 1);
211 TEST ("ab", 0);
212
213 TEST ("jihgfedcba", 0);
214 TEST ("jihgfedcba", 1);
215 TEST ("jihgfedcba", 2);
216 TEST ("jihgfedcba", 3);
217 TEST ("jihgfedcba", 4);
218 TEST ("jihgfedcba", 5);
219 TEST ("jihgfedcba", 6);
220 TEST ("jihgfedcba", 7);
221 TEST ("jihgfedcba", 8);
222 TEST ("jihgfedcba", 9);
223
224 TEST ("abcdefghij", 0);
225 TEST ("abcdefghij", 1);
226 TEST ("abcdefghij", 2);
227 TEST ("abcdefghij", 3);
228 TEST ("abcdefghij", 4);
229 TEST ("abcdefghij", 5);
230 TEST ("abcdefghij", 6);
231 TEST ("abcdefghij", 7);
232 TEST ("abcdefghij", 8);
233 TEST ("abcdefghij", 9);
234
235 TEST ("jijgfgdcda", 5);
236 TEST ("jihifefcbc", 5);
237 TEST ("jiigffdcca", 5);
238 TEST ("jihhfeecbb", 5);
239
240 TEST ("cbbbbbbbba", 5);
241 TEST ("ccbbbbbbaa", 5);
242
243 TEST ("abadedghgj", 5);
244 TEST ("abcbefehih", 5);
245 TEST ("abbdeeghhj", 5);
246 TEST ("abcceffhii", 5);
247
248 TEST ("abbbbbbbbc", 5);
249 TEST ("aabbbbbbcc", 5);
250
251#undef TEST
252
254 rw_note (0, 0, 0,
255 "std::%s (%s, %2$s, %2$s%{?}, %s%{;}): "
256 "complexity test disabled",
257 fname, itname, ppred, funname);
258 }
259 else {
260 rw_info (0, 0, 0,
261 "std::%s (%s, %2$s, %2$s%{?}, %s%{;}): complexity test",
262 fname, itname, ppred, funname);
263
264 const std::size_t N = std::size_t (rw_opt_nloops);
265 for (std::size_t i = 1; i < N; i++)
266 test_nth_element (__LINE__, 0, i, i / 2, (T*)0, ppred);
267 }
268}
269
270
272static int run_test (int, char*[])
273{
274 rw_info (0, 0, 0,
275 "template <class %s> "
276 "void std::nth_element (%1$s, %1$s, %1$s)",
277 "RandomAccessIterator");
278
280
282 rw_note (0, __FILE__, __LINE__,
283 "std::nth_element predicate test disabled");
284 }
285 else {
286 rw_info (0, 0, 0,
287 "template <class %s, class %s> "
288 "void std::nth_element (%1$s, %1$s, %1$s, %2$s)",
289 "RandomAccessIterator", "StrictWeakLess");
290
291 const StrictWeakLess<UserClass> pred(0, 0);
292 test_nth_element ((UserClass*)0, &pred);
293 }
294
295 return 0;
296}
297
298
299
301int main (int argc, char *argv[])
302{
303 return rw_test (argc, argv, __FILE__,
304 "lib.alg.nth_element",
305 0 /* no comment */,
306 run_test,
307 "|-nloops#0 " // must be non-negative
308 "|-no-predicate#"
309 "|-no-complexity",
313}
#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 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
const MyBuffer< char > nsrc[]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define TEST(src, nth)
int rw_opt_no_predicate
void test_nth_element(int line, const char *src, const std::size_t N, const std::size_t nth, const T *, const Predicate *ppred)
int rw_opt_no_complexity
int rw_opt_nloops
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
T * make_iter(T *cur, const T *, const T *, T *)
_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
StrictWeakLess(int, int)
static std::size_t funcalls_
static const char * name()
static conv_to_bool make(bool val)