Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
26.adjacent.diff.cpp
Go to the documentation of this file.
1
29#include <numeric> // for adjacent_difference
30#include <cstddef> // for 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
38// minus
39template <class T>
40struct minus: T
41{
42private:
43 // unused member prevents bogus HP aCC warnings (see Onyx #23561)
44 int unused;
45};
46
47
48template <class T>
49const minus<T>& operator- (const minus<T>& lhs, const minus<T>& rhs) {
51 return lhs;
52}
53
55
56// disable explicit instantiation for compilers (like MSVC)
57// that can't handle it
58#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
59
60template
62adjacent_difference (InputIter<minus<assign<base<cpy_ctor> > > >,
65
66template
68adjacent_difference (InputIter<assign<base<cpy_ctor> > >,
72
73#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
74
75} // namespace std
76
77
80{
81 return UserClass (lhs)-= rhs;
82}
83
84
86template <class T>
87struct conv_to_T
88{
89 static conv_to_T make (T val) {
90 return conv_to_T (val);
91 }
92
93 // strictly convertible to a T value
94 operator T () const {
95 return val_;
96 }
97
98private:
99 // not (publicly) Default-Constructible
100 conv_to_T (T val): val_ (val) { }
101
102 void operator= (conv_to_T); // not Assignable
103 void operator!() const; // not defined
104
105 T val_;
106};
107
108
110struct Accumulator
111{
112 static std::size_t funcalls_;
113
114 // dummy arguments provided to prevent the class from being
115 // default constructible and implicit conversion from int
116 Accumulator (int /* dummy */, int /* dummy */) {
117 funcalls_ = 0;
118 }
119
120 // return a type convertible to UserClass
122 const UserClass &y) /* non-const */ {
123 ++funcalls_;
124 UserClass res (x);
125 res.data_.val_ -= y.data_.val_;
127 }
128
129private:
130 void operator= (Accumulator&); // not assignable
131};
132
133std::size_t Accumulator::funcalls_;
134
135
138{
139 virtual ~AdjacentDiffBase() {}
140
141 const char* iter_names [2];
142
143 // pure virtual
144 virtual UserClass*
145 adjacent_difference (const UserClass *xsrc, const UserClass *xsrc_end,
146 UserClass *xdst, const UserClass *xdst_end,
147 const Accumulator *op) const = 0;
148};
149
150template <class InputIterator, class OutputIterator>
152{
154 iter_names [0] = type_name (InputIterator (0, 0, 0), (UserClass*)0);
155 iter_names [1] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
156 }
157
158 virtual UserClass*
159 adjacent_difference (const UserClass *xsrc, const UserClass *xsrc_end,
160 UserClass *xdst, const UserClass *xdst_end,
161 const Accumulator *op) const {
162
163 const InputIterator first (xsrc, xsrc, xsrc_end);
164 const InputIterator last (xsrc_end, xsrc, xsrc_end);
165 const OutputIterator result (xdst, xdst, xdst_end);
166
167 const OutputIterator res = op ?
168 std::adjacent_difference (first, last, result, *op)
169 : std::adjacent_difference (first, last, result);
170
171 // silence EDG eccp 3.7 and prior remark #550-D:
172 // variable was set but never used
174
175 return res.cur_;
176 }
177};
178
179
181// exercises adjacent_difference (26.4.4)
182void test_adjacent_difference (const std::size_t N,
183 const AdjacentDiffBase &alg,
184 bool binop,
185 bool same_seq)
186{
187 const char* const itname = alg.iter_names [0];
188 const char* const outname = alg.iter_names [1];
189 const char* const opname = "Minus";
190
191 rw_info (0, 0, 0,
192 "std::adjacent_difference(%s, %1$s, %s%{?}, %s%{;})%{?}, %s%{;}",
193 itname, outname, binop, opname, same_seq, "first == result");
194
196
197 UserClass* const src = new UserClass [N + 1];
198 UserClass* dst = same_seq ? src : new UserClass [N + 1];
199
200 static const int cwidth = sizeof (*src);
201
202 for (std::size_t i = 0; i != N; ++i) {
203
204 UserClass* const src_end = src + i;
205 UserClass* const dst_end = dst + i;
206
207 std::size_t last_n_op_minus_assign =
209
210 const Accumulator acc (0, 0);
211 const Accumulator* const pbinop = binop ? &acc : 0;
212
213 std::size_t k = 0 < i ? i - 1 : 0;
214 int* const tmp_val = new int [i + 1];
215
216 for (; 0 < k; --k)
217 tmp_val [k] = src [k].data_.val_ - src [k - 1].data_.val_;
218
219 tmp_val [0] = src [0].data_.val_;
220
221 const UserClass* const res =
222 alg.adjacent_difference (src, src_end, dst, dst_end, pbinop);
223
224 const std::size_t minus_ops = binop ?
226 : UserClass::n_total_op_minus_assign_ - last_n_op_minus_assign;
227
228 // verify the returned iterator 26.4.4, p2
229 bool success = res == dst_end;
230 rw_assert (success, 0, __LINE__,
231 "adjacent_difference <%s, %s%{?}, %s%{;}>"
232 "({%{X=+*}}, ...) == result + %td, got result + %td",
233 itname, outname, binop, opname,
234 cwidth, int (i), src, dst_end - dst, res - dst);
235
236 for (k = 0; k < i; k++) {
237 success = dst [k].data_.val_ == tmp_val [k];
238 if (!success)
239 break;
240 }
241
242 // verify the result 26.4.4, p1
243 if (0 < i) {
244 // to avoid errors in --trace mode
245 k = k < i ? k : i - 1;
246
247 rw_assert (success, 0, __LINE__,
248 "adjacent_difference <%s, %s%{?}, %s%{;}>"
249 "({%{X=+*}}, ...) ==> {%{X=+*.*}}, expected %d",
250 itname, outname, binop, opname,
251 cwidth, int (i), src, int (i), int (k), dst, tmp_val [k]);
252 }
253
254 delete[] tmp_val;
255
256 if (!success)
257 break;
258
259 // verify the complexity, 26.4.4, p3
260 const std::size_t exp_minus_ops = 0 < i ? i - 1 : 0;
261 success = minus_ops == exp_minus_ops;
262 rw_assert (success, 0, __LINE__,
263 "adjacent_difference <%s, %s%{?}, %s%{;}>"
264 "({%{X=+*}}, ...) complexity: got %zu invocations "
265 "of %s, expected %zu",
266 itname, outname, binop, opname,
267 cwidth, int (i), src, minus_ops,
268 binop ? "BinaryMinus" : "operator-", exp_minus_ops);
269
270 if (!success)
271 break;
272 }
273
274 delete[] src;
275
276 if (!same_seq)
277 delete[] dst;
278}
279
280
282/* extern */ int rw_opt_nloops = 64; // --nloops
283/* extern */ int rw_opt_no_binary_op; // --no-binary_op
284/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
285/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
286/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
287/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
288/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
289
290
292template <class InputIterator, class OutputIterator>
293void gen_adjacent_difference_test (const std::size_t N,
294 const InputIterator&,
295 const OutputIterator&,
296 bool binop)
297{
299
300 // test the algorithm than input and output arrays differ
301 test_adjacent_difference (N, alg, binop, false);
302
303 // test the algorithm than input and output arrays are the same
304 test_adjacent_difference (N, alg, binop, true);
305}
306
307
308template <class InputIterator>
309void gen_adjacent_difference_test (const std::size_t N,
310 const InputIterator &it,
311 bool binop)
312{
313 if (0 == rw_opt_no_output_iter)
315 N, it, OutputIter<UserClass>(0, 0, 0), binop);
316 if (0 == rw_opt_no_fwd_iter)
318 N, it, FwdIter<UserClass>(0, 0, 0), binop);
319 if (0 == rw_opt_no_bidir_iter)
321 N, it, BidirIter<UserClass>(0, 0, 0), binop);
322 if (0 == rw_opt_no_rnd_iter)
324 N, it, RandomAccessIter<UserClass>(0, 0, 0), binop);
325}
326
327// generates a specialization of the partial_sum test for each of the required
328// iterator categopries
329void gen_adjacent_difference_test (const std::size_t N,
330 bool binop)
331{
332 rw_info (0, 0, 0,
333 "template <class %s, class %s%{?}, class %s%{;}> "
334 "%2$s adjacent_difference (%1$s, %1$s, %2$s%{?}, %s%{;})",
335 "InputIterator", "OutputIterator", binop, "BinaryOperation",
336 binop, "BinaryOperation");
337
339 rw_note (0, 0, 0, "OutputIterator test disabled");
340
342 rw_note (0, 0, 0, "InputIterator test disabled");
343 else
345
347 rw_note (0, 0, 0, "ForwardIterator test disabled");
348 else
350 binop);
351
353 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
354 else
356 binop);
357
359 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
360 else
362 ConstRandomAccessIter<UserClass>(0, 0, 0), binop);
363}
364
365
367static int
368run_test (int, char*[])
369{
370 const std::size_t N = std::size_t (rw_opt_nloops);
371
373
375 rw_note (0, 0, 0,
376 "adjacent_difference with binary operation test disabled");
377 else
379
380 return 0;
381}
382
383
385int main (int argc, char *argv[])
386{
387 return rw_test (argc, argv, __FILE__,
388 "lib.adjacent.difference",
389 0 /* no comment */, run_test,
390 "|-nloops#0 " // must be non-negative
391 "|-no-binary_op#"
392 "|-no-InputIterator# "
393 "|-no-OutputIterator# "
394 "|-no-ForwardIterator# "
395 "|-no-BidirectionalIterator# "
396 "|-no-RandomAccessIterator#",
404}
#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 k
Definition 17.names.cpp:128
#define rhs
Definition 17.names.cpp:536
#define res
Definition 17.names.cpp:531
#define last
Definition 17.names.cpp:487
#define x
Definition 17.names.cpp:140
#define lhs
Definition 17.names.cpp:489
#define val
Definition 17.names.cpp:570
#define OutputIterator
Definition 17.names.cpp:515
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const minus< T > & operator-(const minus< T > &lhs, const minus< T > &rhs)
int rw_opt_no_fwd_iter
void test_adjacent_difference(const std::size_t N, const AdjacentDiffBase &alg, bool binop, bool same_seq)
int rw_opt_no_binary_op
void gen_adjacent_difference_test(const std::size_t N, const InputIterator &, const OutputIterator &, bool binop)
int rw_opt_no_rnd_iter
int rw_opt_no_bidir_iter
int rw_opt_no_input_iter
int rw_opt_no_output_iter
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
_TEST_EXPORT int gen_seq()
Definition alg_test.cpp:38
_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
Accumulator(int, int)
conv_to_T< Y > operator()(const Y &x, const Y &y)
static std::size_t funcalls_
virtual UserClass * adjacent_difference(const UserClass *xsrc, const UserClass *xsrc_end, UserClass *xdst, const UserClass *xdst_end, const Accumulator *op) const =0
const char * iter_names[2]
virtual UserClass * adjacent_difference(const UserClass *xsrc, const UserClass *xsrc_end, UserClass *xdst, const UserClass *xdst_end, const Accumulator *op) const
UserData data_
Definition rw_value.h:79
static _RWSTD_SIZE_T n_total_op_minus_assign_
Definition rw_value.h:129
static int(* gen_)()
Definition rw_value.h:122
int val_
Definition rw_value.h:39
static conv_to_T make(T val)