Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.heap.cpp
Go to the documentation of this file.
1
29// MSVC 6.0 gets an ICE in std::__adjust_heap() in <algorithm.cc>
30#if defined (_MSC_VER) && _MSC_VER <= 1300
31# define _RWSTD_NO_EXPLICIT_INSTANTIATION
32#endif
33
34#include <algorithm> // for make_heap, sort_heap, push_heap, pop_heap
35#include <cstring> // for strlen, size_t
36
37#include <rw_alg_test.h>
38#include <rw_value.h> // for UserClass
39#include <rw_driver.h> // for rw_test()
40
41
44
45#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
46
47// 25.3.6.1 - push_heap [lib.push.heap]
48template
49void
52
53template
54void
58
59// 25.3.6.2 - pop_heap [lib.pop.heap]
60template
61void
64
65template
66void
70
71// 25.3.6.3 - make_heap [lib.make.heap]
72template
73void
76
77template
78void
82
83// 25.3.6.4 - sort_heap [lib.sort.heap]
84template
85void
88
89template
90void
94
95#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
96
97} // namespace std
98
99
101template <class T>
102struct Less
103{
104 static std::size_t funcalls_;
105
106 // dummy arguments provided to prevent the class from being
107 // default constructible and implicit conversion from int
108 Less (int /* dummy */, int /* dummy */) {
109 funcalls_ = 0;
110 }
111
112 // return a type other than bool but one that is implicitly
113 // convertible to bool to detect incorrect assumptions
114 conv_to_bool operator() (const T &x, const T &y) /* non-const */ {
115 ++funcalls_;
116 return conv_to_bool::make (x.data_.val_ < y.data_.val_);
117 }
118
119 static const char* name () { return "Less"; }
120
121private:
122 void operator= (Less&); // not assignable
123};
124
125template<class T> std::size_t Less<T>::funcalls_;
126
127
129// helper function to verify that the sequence is a valid heap
130template <class T>
131bool is_heap (const T* seq, const std::size_t len)
132{
133 std::size_t parent = 0;
134 for (std::size_t child = 1; child < len; ++child) {
135
136 if (seq [parent].data_.val_ < seq [child].data_.val_)
137 return false;
138
139 if ((child & 1) == 0)
140 ++parent;
141 }
142
143 return true;
144}
145
146
148// exercises push_heap, pop_heap, make_heap, sort_heap: 25.3.6.1 - 25.3.6.4
149template <class T, class Predicate>
151 const char *src,
152 const T*,
153 const Predicate *ppred,
154 const std::size_t finx)
155{
156 static const char* const fnames[] = {
157 "make_heap", "push_heap", "pop_heap", "sort_heap"
158 };
159
160 typedef RandomAccessIter<T> RandIter;
161 RandIter rand_iter (0, 0, 0);
162
163 const char* const itname = type_name (rand_iter, (T*)0);
164 const char* const fname = fnames[finx];
165 const char* const funname = Predicate::name();
166
167 const std::size_t nsrc = std::strlen (src);
168
169 T* const xsrc = T::from_char (src, nsrc);
170 T* const xsrc_end = xsrc + nsrc;
171
172 int val = xsrc[0].data_.val_;
173
174 const RandIter first = make_iter (xsrc, xsrc, xsrc_end, rand_iter);
175 const RandIter last = make_iter (xsrc_end, xsrc, xsrc_end, rand_iter);
176
177 const Predicate pred (0, 0);
178
179 const std::size_t last_n_op_lt = T::n_total_op_lt_;
180
181 // for convenience
182#define HEAP_OP(opname) \
183 if (ppred) opname (first, last, pred); else opname (first, last)
184
185 std::size_t ops = 0;
186
187 // exercise heap operation and compute the expected complexity
188 switch (finx) {
189 case 0: HEAP_OP (std::make_heap); ops = 3 * nsrc; break;
190 case 1: HEAP_OP (std::push_heap); ops = ilog2 (nsrc); break;
191 case 2: HEAP_OP (std::pop_heap); ops = 2 * ilog2 (nsrc); break;
192 case 3: HEAP_OP (std::sort_heap); ops = nsrc * ilog2 (nsrc); break;
193 }
194
195 const std::size_t n_ops_lt = ppred ?
196 Predicate::funcalls_ : T::n_total_op_lt_ - last_n_op_lt;
197
198 const std::size_t len = 2 != finx ? nsrc : nsrc - 1;
199 static const int cwidth = sizeof (T);
200
201 if (2 == finx) { // pop_heap special verification
202 // verify that the maximal element is in
203 // the end of the sequence: 25.3.6.2, p2
204 rw_assert (val == xsrc[nsrc - 1].data_.val_, 0, line,
205 "line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
206 "\"%{X=*.*}\", last is %#c, expected %#c",
207 __LINE__, fname, itname, ppred, funname, src,
208 cwidth, int (nsrc), -1, xsrc,
209 xsrc [nsrc - 1].data_.val_, val);
210 }
211
212 if (3 == finx) { // sort_heap special verification
213 // verify that we got a sorted sequence: 25.3.6.4, p1
214 rw_assert (is_sorted_lt (xsrc, xsrc_end), 0, line,
215 "line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
216 "\"%{X=*.*}\" is not sorted",
217 __LINE__, fname, itname, ppred, funname, src,
218 cwidth, int (nsrc), -1, xsrc);
219 }
220 else {
221 // verify that we got a heap:
222 // 25.3.6.1, p2; 25.3.6.2, p2; 25.3.6.3, p1
223 rw_assert (is_heap (xsrc, len), 0, line,
224 "line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
225 "\"%{X=*.*}\" is not a heap",
226 __LINE__, fname, itname, ppred, funname, src,
227 cwidth, int (len), -1, xsrc);
228 }
229
230 // verify the complexity:
231 // 25.3.6.1, p3; 25.3.6.2, p3; 25.3.6.3, p2; 25.3.6.4, p2
232 rw_assert (n_ops_lt <= ops, 0, line,
233 "line %d std::%s <%s%{?}, %s%{;}> (\"%s\", ...) ==> "
234 "\"%{X=*.*}\" complexity: got %zu invocations of %s, "
235 "expected no more %zu",
236 __LINE__, fname, itname, ppred, funname, src,
237 cwidth, int (nsrc), -1, xsrc, n_ops_lt,
238 ppred ? "predicate" : "operator< ()", ops);
239
240 delete[] xsrc;
241}
242
243
245template <class T, class Predicate>
246void test_make_heap (const T*,
247 const Predicate *ppred)
248{
249 rw_info (0, 0, 0,
250 "std::make_heap (%s, %1$s%{?}, %s%{;})",
251 "RandomAccessIterator", 0 != ppred, Predicate::name ());
252
253#define TEST(src) \
254 test_heap_operation (__LINE__, src, (T*)0, ppred, 0)
255
256 TEST ("a");
257 TEST ("ab");
258 TEST ("ba");
259
260 TEST ("abcde");
261 TEST ("acbed");
262 TEST ("cbade");
263 TEST ("debca");
264 TEST ("ecace");
265 TEST ("accee");
266 TEST ("caced");
267
268 TEST ("abcdefghij");
269 TEST ("bcdeafghij");
270 TEST ("dcbeafihgj");
271 TEST ("badcfehgji");
272 TEST ("ebadcfhijg");
273
274 TEST ("jihgfedcba");
275 TEST ("ijhgefdcab");
276
277 TEST ("ababababab");
278 TEST ("babbbababb");
279
280#undef TEST
281}
282
283
285template <class T, class Predicate>
286void test_push_heap (const T*,
287 const Predicate *ppred)
288{
289 rw_info (0, 0, 0,
290 "std::push_heap (%s, %1$s%{?}, %s%{;})",
291 "RandomAccessIterator", 0 != ppred, Predicate::name ());
292
293#define TEST(src) \
294 test_heap_operation (__LINE__, src, (T*)0, ppred, 1)
295
296 TEST ("a");
297 TEST ("ab");
298 TEST ("ba");
299
300 TEST ("bac");
301 TEST ("cba");
302 TEST ("aac");
303
304 TEST ("ecdaba");
305 TEST ("ecdabc");
306 TEST ("ecdabe");
307
308 TEST ("jighefcadj");
309 TEST ("jighefcada");
310 TEST ("jighefcadh");
311
312 TEST ("jhigcfbeda");
313 TEST ("jhigcfbedj");
314 TEST ("jhigcfbedh");
315 TEST ("jhigcfbedf");
316 TEST ("jhigcfbede");
317 TEST ("jhigcfbedg");
318
319 TEST ("bbbbbaaaaa");
320 TEST ("bbbbbaaaab");
321
322#undef TEST
323}
324
325
327template <class T, class Predicate>
328void test_pop_heap (const T*,
329 const Predicate *ppred)
330{
331 rw_info (0, 0, 0,
332 "std::pop_heap (%s, %1$s%{?}, %s%{;})",
333 "RandomAccessIterator", 0 != ppred, Predicate::name ());
334
335#define TEST(src) \
336 test_heap_operation (__LINE__, src, (T*)0, ppred, 2)
337
338 TEST ("a");
339 TEST ("ba");
340
341 TEST ("aaa");
342 TEST ("cba");
343 TEST ("caa");
344
345 TEST ("ecdab");
346 TEST ("ecdab");
347 TEST ("ecdab");
348
349 TEST ("jighefcadb");
350 TEST ("jighcfdbea");
351 TEST ("jhigcfbeda");
352 TEST ("jihgfedacb");
353 TEST ("iihegfabdc");
354 TEST ("iihgfedcba");
355 TEST ("iihgefdcab");
356
357 TEST ("bbbbbaaaaa");
358
359#undef TEST
360}
361
362
364template <class T, class Predicate>
365void test_sort_heap (const T*,
366 const Predicate *ppred)
367{
368 rw_info (0, 0, 0,
369 "std::sort_heap (%s, %1$s%{?}, %s%{;})",
370 "RandomAccessIterator", 0 != ppred, Predicate::name());
371
372#define TEST(src) \
373 test_heap_operation (__LINE__, src, (T*)0, ppred, 3)
374
375 TEST ("a");
376 TEST ("ba");
377
378 TEST ("aaa");
379 TEST ("cba");
380 TEST ("caa");
381
382 TEST ("ecdab");
383 TEST ("ecdab");
384 TEST ("ecdab");
385
386 TEST ("jighefcadb");
387 TEST ("jighcfdbea");
388 TEST ("jhigcfbeda");
389 TEST ("jihgfedacb");
390 TEST ("iihegfabdc");
391 TEST ("iihgfedcba");
392 TEST ("iihgefdcab");
393
394 TEST ("bbbbbaaaaa");
395
396#undef TEST
397}
398
399
401/* extern */ int rw_opt_no_make_heap; // --no-make_heap
402/* extern */ int rw_opt_no_push_heap; // --no-push_heap
403/* extern */ int rw_opt_no_pop_heap; // --no-pop_heap
404/* extern */ int rw_opt_no_sort_heap; // --no-sort_heap
405/* extern */ int rw_opt_no_predicate; // --no-predicate
406
407
409template <class T, class Predicate>
411 const Predicate *ppred)
412{
414 rw_note (0, __FILE__, __LINE__,
415 "std::make_heap test disabled");
416 }
417 else {
418 test_make_heap ((T*)0, ppred);
419 }
420
422 rw_note (0, __FILE__, __LINE__,
423 "std::push_heap test disabled");
424 }
425 else {
426 test_push_heap ((T*)0, ppred);
427 }
428
429 if (rw_opt_no_pop_heap) {
430 rw_note (0, __FILE__, __LINE__,
431 "std::pop_heap test disabled");
432 }
433 else {
434 test_pop_heap ((T*)0, ppred);
435 }
436
438 rw_note (0, __FILE__, __LINE__,
439 "std::sort_heap test disabled");
440 }
441 else {
442 test_sort_heap ((T*)0, ppred);
443 }
444}
445
446
448static int run_test (int, char*[])
449{
451
453 rw_note (0, __FILE__, __LINE__,
454 "heap operations predicate test disabled");
455 }
456 else {
458 }
459
460 return 0;
461}
462
463
464
466int main (int argc, char *argv[])
467{
468 return rw_test (argc, argv, __FILE__,
469 "lib.alg.heap.operations",
470 0 /* no comment */, run_test,
471 "|-no-make_heap#"
472 "|-no-push_heap#"
473 "|-no-pop_heap#"
474 "|-no-sort_heap#"
475 "|-no-predicate",
481}
#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 len
Definition 17.names.cpp:488
#define val
Definition 17.names.cpp:570
const MyBuffer< char > nsrc[]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
int rw_opt_no_sort_heap
Definition 25.heap.cpp:404
void test_heap_operation(int line, const char *src, const T *, const Predicate *ppred, const std::size_t finx)
Definition 25.heap.cpp:150
void test_sort_heap(const T *, const Predicate *ppred)
Definition 25.heap.cpp:365
void test_pop_heap(const T *, const Predicate *ppred)
Definition 25.heap.cpp:328
#define HEAP_OP(opname)
int rw_opt_no_push_heap
Definition 25.heap.cpp:402
int rw_opt_no_predicate
Definition 25.heap.cpp:405
void test_push_heap(const T *, const Predicate *ppred)
Definition 25.heap.cpp:286
int rw_opt_no_make_heap
Definition 25.heap.cpp:401
bool is_heap(const T *seq, const std::size_t len)
Definition 25.heap.cpp:131
int rw_opt_no_pop_heap
Definition 25.heap.cpp:403
void test_heap_operations(const T *, const Predicate *ppred)
Definition 25.heap.cpp:410
#define TEST(src)
void test_make_heap(const T *, const Predicate *ppred)
Definition 25.heap.cpp:246
const char *const fnames[]
Definition 25.remove.cpp:77
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 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()
Definition 25.heap.cpp:119
static std::size_t funcalls_
Definition 25.heap.cpp:104
Less(int, int)
Definition 25.heap.cpp:108
static conv_to_bool make(bool val)