Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
26.partial.sum.cpp
Go to the documentation of this file.
1
29#include <numeric> // for partial_sum
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// plus
39template <class T>
40struct plus: T
41{
42private:
43 // unused member prevents bogus HP aCC warnings (see Onyx #23561)
44 int unused;
45};
46
47
48template <class T>
49const plus<T>& operator+ (const plus<T>& lhs, const plus<T>& rhs)
50{
52 return lhs;
53}
54
56
57#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
58
59template
61partial_sum (InputIter<plus<assign<base<cpy_ctor> > > >,
64
65template
67partial_sum (InputIter<assign<base<cpy_ctor> > >,
71
72#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
73
74} // namespace std
75
76
79{
80 return UserClass (lhs)+= rhs;
81}
82
83
85template <class T>
86struct conv_to_T
87{
88 static conv_to_T make (T val) {
89 return conv_to_T (val);
90 }
91
92 // strictly convertible to a T value
93 operator T () const {
94 return val_;
95 }
96
97private:
98 // not (publicly) Default-Constructible
99 conv_to_T (T val): val_ (val) { }
100
101 void operator= (conv_to_T); // not Assignable
102 void operator!() const; // not defined
103
104 T val_;
105};
106
107
109struct Accumulator
110{
111 static std::size_t funcalls_;
112
113 // dummy arguments provided to prevent the class from being
114 // default constructible and implicit conversion from int
115 Accumulator (int /* dummy */, int /* dummy */) {
116 funcalls_ = 0;
117 }
118
119 // return a type convertible to UserClass
121 const UserClass &y) /* non-const */ {
122 ++funcalls_;
123 UserClass res (x);
124 res.data_.val_ += y.data_.val_;
126 }
127
128private:
129 void operator= (Accumulator&); // not assignable
130};
131
132std::size_t Accumulator::funcalls_;
133
134
137{
138 virtual ~PartialSumBase() { /* no-op */ }
139
140 const char* iter_names [2];
141
142 // pure virtual
143 virtual UserClass*
144 partial_sum (const UserClass *xsrc, const UserClass *xsrc_end,
145 UserClass *xdst, const UserClass *xdst_end,
146 const Accumulator *op) const = 0;
147};
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 partial_sum (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::partial_sum (first, last, result, *op)
169 : std::partial_sum (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 partial_sum (26.4.3)
182void test_partial_sum (const std::size_t N,
183 const PartialSumBase &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 = "Plus";
190
191 rw_info (0, 0, 0,
192 "std::partial_sum (%s, %1$s, %s%{?}, %s%{;})%{?}, %s%{;}",
193 itname, outname, binop, opname, same_seq, "first == result");
194
196
197 UserClass* const src = new UserClass [N];
198 UserClass* dst = same_seq ? src : new UserClass [N];
199
200 for (std::size_t i = 0; i != N; ++i) {
201
202 UserClass* const src_end = src + i;
203 UserClass* const dst_end = dst + i;
204
205 std::size_t last_n_op_plus = UserClass::n_total_op_plus_assign_;
206
207 const Accumulator acc (0, 0);
208 const Accumulator* const pbinop = binop ? &acc : 0;
209
210 std::size_t k = 0;
211 int* const tmp_val = new int [i];
212 for (; k < i; ++k)
213 tmp_val [k] = src [k].data_.val_;
214
215 const UserClass* const res =
216 alg.partial_sum (src, src_end, dst, dst_end, pbinop);
217
218 const std::size_t plus_ops = binop ? Accumulator::funcalls_ :
219 UserClass::n_total_op_plus_assign_ - last_n_op_plus;
220
221 static const int cwidth = sizeof (*src);
222
223 // verify the returned iterator 26.4.3, p2
224 bool success = res == dst_end;
225 rw_assert (success, 0, __LINE__,
226 "partial_sum<%s, %s%{?}, %s%{;}>"
227 "({%{X=+*}}, ...) == result + %d, got result %td",
228 itname, outname, binop, opname,
229 cwidth, int (i), src, dst_end - dst, res - dst_end);
230
231 int sum = 0;
232 for (k = 0; k < i; ++k) {
233 sum += tmp_val [k];
234 success = dst [k].data_.val_ == sum;
235 if (!success)
236 break;
237 }
238
239 // verify the result 26.4.3, p1
240 if (i > 0) {
241 // to avoid errors in --trace mode
242 k = k < i ? k : i - 1;
243
244 rw_assert (success, 0, __LINE__,
245 "partial_sum<%s, %s%{?}, %s%{;}>"
246 "({%{X=+*}}, ...) ==> {%{X=+*.*}}, expected %d",
247 itname, outname, binop, opname,
248 cwidth, int (i), src,
249 cwidth, int (i), int (k), dst, sum);
250 }
251
252 delete[] tmp_val;
253
254 if (!success)
255 break;
256
257 // verify the complexity, 26.4.3, p3
258 const std::size_t exp_plus_ops = i > 0 ? i - 1 : 0;
259 success = plus_ops == exp_plus_ops;
260 rw_assert (success, 0, __LINE__,
261 "partial_sum <%s, %s%{?}, %s%{;}>"
262 "({%{X=+*}}, ...) complexity: got %zu invocations "
263 "of %s, expected %zu",
264 itname, outname, binop, opname,
265 cwidth, int (i), src, plus_ops,
266 binop ? "BinaryPlus" : "operator+", exp_plus_ops);
267
268 if (!success)
269 break;
270 }
271
272 delete[] src;
273
274 if (!same_seq)
275 delete[] dst;
276}
277
278
280/* extern */ int rw_opt_nloops = 64; // --nloops
281/* extern */ int rw_opt_no_binary_op; // --no-binary_op
282/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
283/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
284/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
285/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
286/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
287
288
290template <class InputIterator, class OutputIterator>
291void gen_partial_sum_test (const std::size_t N,
292 const InputIterator&,
293 const OutputIterator&,
294 bool binop)
295{
297
298 // test the algorithm than input and output arrays differ
299 test_partial_sum (N, alg, binop, false);
300
301 // test the algorithm than input and output arrays are the same
302 test_partial_sum (N, alg, binop, true);
303}
304
305
306template <class InputIterator>
307void gen_partial_sum_test (const std::size_t N,
308 const InputIterator &it,
309 bool binop)
310{
311 if (0 == rw_opt_no_output_iter)
313 N, it, OutputIter<UserClass>(0, 0, 0), binop);
314 if (0 == rw_opt_no_fwd_iter)
316 N, it, FwdIter<UserClass>(0, 0, 0), binop);
317 if (0 == rw_opt_no_bidir_iter)
319 N, it, BidirIter<UserClass>(0, 0, 0), binop);
320 if (0 == rw_opt_no_rnd_iter)
322 N, it, RandomAccessIter<UserClass>(0, 0, 0), binop);
323}
324
325// generates a specialization of the partial_sum test for each of the required
326// iterator categopries
327void gen_partial_sum_test (const std::size_t N,
328 bool binop)
329{
330 rw_info (0, 0, 0,
331 "template <class %s, class %s%{?}, class %s%{;}> "
332 "%2$s partial_sum (%1$s, %1$s, %2$s%{?}, %s%{;})",
333 "InputIterator", "OutputIterator", binop, "BinaryOperation",
334 binop, "BinaryOperation");
335
337 rw_note (0, 0, 0, "OutputIterator test disabled");
338
340 rw_note (0, 0, 0, "InputIterator test disabled");
341 else
343
345 rw_note (0, 0, 0, "ForwardIterator test disabled");
346 else
348
350 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
351 else
353
355 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
356 else
358 binop);
359}
360
361
363static int
364run_test (int, char*[])
365{
366 const std::size_t N = std::size_t (rw_opt_nloops);
367
368 gen_partial_sum_test (N, false);
369
371 rw_note (0, 0, 0,
372 "partial_sum with binary operation test disabled");
373 else
374 gen_partial_sum_test (N, true);
375
376 return 0;
377}
378
379
381int main (int argc, char *argv[])
382{
383 return rw_test (argc, argv, __FILE__,
384 "lib.partial.sum",
385 0 /* no comment */,
386 run_test,
387 "|-nloops#0 " // must be non-negative
388 "|-no-binary_op#"
389 "|-no-InputIterator# "
390 "|-no-OutputIterator# "
391 "|-no-ForwardIterator# "
392 "|-no-BidirectionalIterator# "
393 "|-no-RandomAccessIterator#",
401}
#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 plus< T > & operator+(const plus< T > &lhs, const plus< T > &rhs)
int rw_opt_no_fwd_iter
void gen_partial_sum_test(const std::size_t N, const InputIterator &, const OutputIterator &, bool binop)
int rw_opt_no_binary_op
int rw_opt_no_rnd_iter
int rw_opt_no_bidir_iter
int rw_opt_no_input_iter
int rw_opt_no_output_iter
void test_partial_sum(const std::size_t N, const PartialSumBase &alg, bool binop, bool same_seq)
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 ~PartialSumBase()
virtual UserClass * partial_sum(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 * partial_sum(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 int(* gen_)()
Definition rw_value.h:122
static _RWSTD_SIZE_T n_total_op_plus_assign_
Definition rw_value.h:128
int val_
Definition rw_value.h:39
static conv_to_T make(T val)