Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
26.inner.product.cpp
Go to the documentation of this file.
1
29#include <numeric> // for inner_product
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-assign
39template <class T>
40struct plus_asgn: T
41{
43 unused = rhs.unused;
44 return *this;
45 }
46private:
47 // unused member prevents bogus HP aCC warnings (see Onyx #23561)
48 int unused;
49};
50
51template <class T>
52const plus_asgn<T>&
54{
56
57 return lhs;
58}
59
60
62
63// disable explicit instantiation for compilers (like MSVC)
64// that can't handle it
65#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
66
67template
69inner_product (InputIter<plus_asgn<assign<base<cpy_ctor> > > >,
73
74template
76inner_product (InputIter<assign<base<cpy_ctor> > >,
82
83#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
84
85} // namespace std
86
87
90{
91 return UserClass (lhs) *= rhs;
92}
93
94
96template <class T>
97struct conv_to_T
98{
99 static conv_to_T make (T val) {
100 return conv_to_T (val);
101 }
102
103 // strictly convertible to a T value
104 operator T () const {
105 return val_;
106 }
107
108private:
109 // not (publicly) Default-Constructible
110 conv_to_T (T val): val_ (val) { }
111
112 void operator= (conv_to_T); // not Assignable
113 void operator!() const; // not defined
114
115 T val_;
116};
117
118
120struct Accumulator
121{
122 static std::size_t funcalls_;
123
124 // dummy arguments provided to prevent the class from being
125 // default constructible and implicit conversion from int
126 Accumulator (int /* dummy */, int /* dummy */) {
127 funcalls_ = 0;
128 }
129
130 // return a type convertible to UserClass
132 const UserClass &y) /* non-const */ {
133 ++funcalls_;
134 UserClass res (x);
135 res.data_.val_ += y.data_.val_;
137 }
138
139private:
140 void operator= (Accumulator&); // not assignable
141};
142
143std::size_t Accumulator::funcalls_;
144
145
147{
148 static std::size_t funcalls_;
149
150 // dummy arguments provided to prevent the class from being
151 // default constructible and implicit conversion from int
152 Multiplicator (int /* dummy */, int /* dummy */) {
153 funcalls_ = 0;
154 }
155
156 // return a type convertible to UserClass
158 const UserClass &y) /* non-const */ {
159 ++funcalls_;
160 UserClass res (x);
161 res.data_.val_ *= y.data_.val_;
163 }
164
165private:
166 void operator= (Multiplicator&); // not assignable
167};
168
169std::size_t Multiplicator::funcalls_;
170
171
174{
175 virtual ~InnerProductBase() { /* no-op */ }
176
177 const char* iter_names [2];
178
179 // pure virtual
180 virtual UserClass
181 inner_product (const UserClass *xsrc1, const UserClass *xsrc1_end,
182 const UserClass *xsrc2, const UserClass *xsrc2_end,
183 const UserClass& init, const Accumulator *op1,
184 const Multiplicator *op2) const = 0;
185};
186
187template <class InputIterator1, class InputIterator2>
189{
191 iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
192 iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
193 }
194
195 virtual UserClass
196 inner_product (const UserClass *xsrc1, const UserClass *xsrc1_end,
197 const UserClass *xsrc2, const UserClass *xsrc2_end,
198 const UserClass& init, const Accumulator *op1,
199 const Multiplicator *op2) const {
200
201 const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
202 const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
203 const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
204
205 const UserClass res = op1 ?
206 std::inner_product (first1, last1, first2, init, *op1, *op2)
207 : std::inner_product (first1, last1, first2, init);
208
209 // silence EDG eccp 3.7 and prior remark #550-D:
210 // variable was set but never used
212
213 return res;
214 }
215};
216
217
219// exercises inner_product (26.4.2)
220void test_inner_product (const std::size_t N,
221 const InnerProductBase &alg,
222 bool binop)
223{
224 const char* const it1name = alg.iter_names [0];
225 const char* const it2name = alg.iter_names [1];
226 const char* const tname = "UserClass";
227 const char* const op1name = "Plus";
228 const char* const op2name = "Multiple";
229
230 rw_info (0, 0, 0,
231 "std::inner_product (%s, %1$s, %s, %s%{?}, %s, %s%{;})",
232 it1name, it2name, tname, binop, op1name, op2name);
233
234 // construct initial UserClass
235 const UserClass init = UserClass ();
236 int sum = init.data_.val_;
237
239
240 UserClass* const buf1 = new UserClass [N];
241 UserClass* const buf2 = new UserClass [N];
242
243 for (std::size_t i = 0; i != N; ++i) {
244
245 UserClass* const buf1_end = buf1 + i;
246 UserClass* const buf2_end = buf2 + i;
247
248 const Accumulator acc (0, 0);
249 const Multiplicator mult (0, 0);
250
251 const Accumulator* const pbinop1 = binop ? &acc : 0;
252 const Multiplicator* const pbinop2 = binop ? &mult : 0;
253
254 const UserClass res = alg.inner_product (buf1, buf1_end, buf2, buf2_end,
255 init, pbinop1, pbinop2);
256
257 // verify the result 26.4.1, p1
258 bool success = sum == res.data_.val_;
259 rw_assert (success, 0, __LINE__,
260 "inner_product <%s, %s, %s%{?}, %s, %s%{;}>"
261 "({%{X=+*}}, {%{X=+*}}) == %d, got %d",
262 it1name, it2name, tname, binop, op1name, op2name,
263 int (sizeof (*buf1)), int (i), buf1,
264 int (sizeof (*buf2)), int (i), buf2, sum, res.data_.val_);
265
266 sum += (buf1 [i].data_.val_ * buf2 [i].data_.val_);
267
268 if (!success)
269 break;
270 }
271
272 delete[] buf1;
273 delete[] buf2;
274}
275
276
278/* extern */ int rw_opt_nloops = 64; // --nloops
279/* extern */ int rw_opt_no_binary_op; // --no-binary_op
280/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
281/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
282/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
283/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
284
285
287template <class InputIterator1, class InputIterator2>
288void gen_inner_product_test (const std::size_t N,
289 const InputIterator1&,
290 const InputIterator2&,
291 bool binop)
292{
294
295 test_inner_product (N, alg, binop);
296}
297
298
299template <class InputIterator1>
300void gen_inner_product_test (const std::size_t N,
301 const InputIterator1 &it1,
302 bool binop)
303{
304 if (0 == rw_opt_no_input_iter)
306 N, it1, InputIter<UserClass>(0, 0, 0), binop);
307 if (0 == rw_opt_no_fwd_iter)
309 N, it1, ConstFwdIter<UserClass>(0, 0, 0), binop);
310 if (0 == rw_opt_no_bidir_iter)
312 N, it1, ConstBidirIter<UserClass>(0, 0, 0), binop);
313 if (0 == rw_opt_no_rnd_iter)
315 N, it1, ConstRandomAccessIter<UserClass>(0, 0, 0), binop);
316}
317
318// generates a specialization of the inner_product test for each of the required
319// iterator categopries
320void gen_inner_product_test (const std::size_t N,
321 bool binop)
322{
323 rw_info (0, 0, 0,
324 "template <class %s, class %s, class %s%{?}, class %s, "
325 "class %s%{;}> %3$s inner_product (%1$s, %1$s, %2$s, "
326 "%3$s%{?}, %s, %s%{;})",
327 "InputIterator1", "InputIterator2", "UserClass",
328 binop, "BinaryOperation1", "BinaryOperation2", binop,
329 "BinaryOperation1", "BinaryOperation2");
330
332 rw_note (0, 0, 0, "InputIterator test disabled");
333 else
335
337 rw_note (0, 0, 0, "ForwardIterator test disabled");
338 else
340
342 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
343 else
345
347 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
348 else
350 binop);
351}
352
353
355static int
356run_test (int, char*[])
357{
358 const std::size_t N = std::size_t (rw_opt_nloops);
359
360 gen_inner_product_test (N, false);
361
363 rw_note (0, 0, 0,
364 "inner_product with binary operations test disabled");
365 else
367
368 return 0;
369}
370
371
373int main (int argc, char *argv[])
374{
375 return rw_test (argc, argv, __FILE__,
376 "lib.inner.product",
377 0 /* no comment */, run_test,
378 "|-nloops#0 " // must be non-negative
379 "|-no-binary_op#"
380 "|-no-InputIterator# "
381 "|-no-ForwardIterator# "
382 "|-no-BidirectionalIterator# "
383 "|-no-RandomAccessIterator#",
390}
#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 rhs
Definition 17.names.cpp:536
#define res
Definition 17.names.cpp:531
#define x
Definition 17.names.cpp:140
#define lhs
Definition 17.names.cpp:489
#define val
Definition 17.names.cpp:570
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
void test_inner_product(const std::size_t N, const InnerProductBase &alg, bool binop)
int rw_opt_no_fwd_iter
int rw_opt_no_binary_op
void gen_inner_product_test(const std::size_t N, const InputIterator1 &, const InputIterator2 &, bool binop)
int rw_opt_no_rnd_iter
int rw_opt_no_bidir_iter
int rw_opt_no_input_iter
const plus_asgn< T > & operator*(const plus_asgn< T > &lhs, const plus_asgn< T > &rhs)
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
std::mbstate_t init
Definition codecvt1.cpp:80
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_
const char * iter_names[2]
virtual UserClass inner_product(const UserClass *xsrc1, const UserClass *xsrc1_end, const UserClass *xsrc2, const UserClass *xsrc2_end, const UserClass &init, const Accumulator *op1, const Multiplicator *op2) const =0
virtual UserClass inner_product(const UserClass *xsrc1, const UserClass *xsrc1_end, const UserClass *xsrc2, const UserClass *xsrc2_end, const UserClass &init, const Accumulator *op1, const Multiplicator *op2) const
static std::size_t funcalls_
conv_to_T< UserClass > operator()(const UserClass &x, const UserClass &y)
UserData data_
Definition rw_value.h:79
static int(* gen_)()
Definition rw_value.h:122
int val_
Definition rw_value.h:39
static conv_to_T make(T val)
plus_asgn & operator+=(const plus_asgn &rhs)