Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
26.indirect.array.cpp
Go to the documentation of this file.
1
28#include <cstdlib> // for strtol(), size_t
29#include <valarray> // for indirect_array, valarray
30
31#include <rw_driver.h>
32
33
35// returns a valarray constructed from a string of comma-separated values
36// if there are fewer than n values in the string the remaining values are
37// taken to be the same as the last one, i.e., the call
38// make_array("1,2,3", 5) returns valarray({1,2,3,3})
39template <class T>
40std::valarray<T>
41make_array (const char *s, std::size_t n = 0)
42{
43 if (0 == s || '\0' == *s)
44 return n ? std::valarray<T>(T (), n) : std::valarray<T>();
45
46 T buf [256];
47
48 for (std::size_t i = 0; ; ++i) {
49
50 char *end;
51 long val = std::strtol (s, &end, 0);
52
53 RW_ASSERT (s < end);
54 RW_ASSERT ('\0' == *end || ',' == *end);
55
56 buf [i] = T (val);
57
58 if ('\0' == *end) {
59 while (++i < n)
60 buf [i] = buf [i - 1];
61
62 return std::valarray<T>(buf, i);
63 }
64
65 s = end + 1;
66 }
67}
68
69
71static void
72test_indirect_array (int line,
73 const char *array,
74 const char *inxs,
75 const char *opname,
76 const char *args,
77 const char *result,
78 int nmatch)
79
80{
81 typedef int T;
82
83 const char tname[] = "int";
84
85 /* */ std::valarray<T> asrc (make_array<int>(array));
86 const std::valarray<std::size_t> ainx (make_array<std::size_t> (inxs));
87 const std::valarray<T> aarg (make_array<int>(args));
88
89 if (0 == opname)
90 opname = "";
91
92 // construct the expected result
93 const std::valarray<T> expect =
94 make_array<int>(result, *opname ? 0 : asrc.size ());
95
96 // create an indirect array object from the source array
97 // and the array of indices
98 const std::indirect_array<T> ia (asrc [ainx]);
99
100 // iterate over the series of assignment operators, invoking
101 // each in sequence on the source array, modifying it in place
102 for (const char *op = opname; *op; ) {
103
104 // skip optional whitespace
105 for ( ; ' ' == *op; ++op);
106
107 switch (*op) {
108 // invoke fill assignment embedded within a series
109 // of compound assignments, e.g., "*=,,+=" meaning
110 // ia *= aarg; ia = aarg [0]; ia += aarg
111 case ',': ia = aarg.size () ? aarg [0] : 0; break;
112
113 // invoke ordinary assignment
114 case '=': ia = aarg; op += 1; break;
115
116 // invoke computed assignment
117 case '*': ia *= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
118 case '/': ia /= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
119 case '%': ia %= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
120 case '+': ia += aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
121 case '-': ia -= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
122 case '^': ia ^= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
123 case '&': ia &= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
124 case '|': ia |= aarg; RW_ASSERT ('=' == op [1]); op += 2; break;
125 case '<': ia <<= aarg; RW_ASSERT ('=' == op [2]); op += 3; break;
126 case '>': ia >>= aarg; RW_ASSERT ('=' == op [2]); op += 3; break;
127 default:
128 RW_ASSERT (!"unknown operator");
129 }
130
131 // skip optional whitespace
132 for ( ; ' ' == *op; ++op);
133
134 // assignment operators are separated by commas
135 if (',' == *op)
136 ++op;
137 else
138 break;
139 }
140
141 if ('\0' == *opname) {
142 // fill assignment
143 ia = aarg.size () ? aarg [0] : 0;
144 }
145
146 int nequal = 0;
147 for (std::size_t i = 0; i != asrc.size (); ++i, ++nequal) {
148 if (asrc [i] != expect [i])
149 break;
150 }
151
152 if (-1 == nmatch)
153 nmatch = int (asrc.size ());
154
155 const int* const expect_begin = expect.size () ? &expect [0] : 0;
156 const int* const actual_begin = asrc.size () ? &asrc [0] : 0;
157
158 rw_assert (nequal == nmatch, 0, line,
159 "valarray<%s>({%s})[valarray<size_t>({%s})] %s "
160 "valarray<%1$s>({%s}) %c= {%{*.*Ad}}, got {%{*.*Ad}}",
161 tname, array, inxs, opname, result,
162 nmatch == int (asrc.size ()) ? '=' : '!',
163 int (sizeof (int)), int (expect.size ()), expect_begin,
164 int (sizeof (int)), int (asrc.size ()), actual_begin);
165}
166
167
169static int
170run_test (int, char**)
171{
172#define TEST(array, inx, op, arg, res, nmatch) \
173 test_indirect_array (__LINE__, array, inx, op, arg, res, nmatch)
174
176 // exercise indirect_array<T>::operator=(T), fill assignment
177 rw_info (0, 0, __LINE__,
178 "std::indirect_array<int>::operator=(int)");
179
180 // +-- source array
181 // | +-- array of indices (indirect_array ctor argument)
182 // | | +-- zero for fill assignment
183 // | | | +-- argument of fill assignment
184 // | | | | +-- expected result
185 // | | | | | +-- number of matching elements
186 // | | | | | |
187 // V V V V V V
188 TEST ("", "", 0, "0", "", -1);
189 TEST ("1", "", 0, "0", "1", -1);
190
191 TEST ("1", "0", 0, "2", "2", -1);
192 TEST ("1,2", "0", 0, "3", "3,2", -1);
193 TEST ("1,2,3", "0", 0, "4", "4,2,3", -1);
194 TEST ("1,2,3,4", "0", 0, "5", "5,2,3,4", -1);
195 TEST ("1,2,3,4,5", "0", 0, "6", "6,2,3,4,5", -1);
196
197 TEST ("1,2,3,4,5", "0,1", 0, "6", "6,6,3,4,5", -1);
198 TEST ("1,2,3,4,5", "0,2", 0, "6", "6,2,6,4,5", -1);
199 TEST ("1,2,3,4,5", "0,3", 0, "6", "6,2,3,6,5", -1);
200 TEST ("1,2,3,4,5", "0,4", 0, "6", "6,2,3,4,6", -1);
201
202 TEST ("1,2,3,4,5", "0,1,2", 0, "6", "6,6,6,4,5", -1);
203 TEST ("1,2,3,4,5", "0,1,3", 0, "6", "6,6,3,6,5", -1);
204 TEST ("1,2,3,4,5", "0,1,4", 0, "6", "6,6,3,4,6", -1);
205
206 TEST ("1,2,3,4,5", "0,2,1", 0, "6", "6,6,6,4,5", -1);
207 TEST ("1,2,3,4,5", "0,2,3", 0, "6", "6,2,6,6,5", -1);
208 TEST ("1,2,3,4,5", "0,2,4", 0, "6", "6,2,6,4,6", -1);
209
210 TEST ("1,2,3,4,5", "0,3,1", 0, "6", "6,6,3,6,5", -1);
211 TEST ("1,2,3,4,5", "0,3,2", 0, "6", "6,2,6,6,5", -1);
212 TEST ("1,2,3,4,5", "0,3,4", 0, "6", "6,2,3,6,6", -1);
213
214#define INFO(op) \
215 rw_info (0, 0, __LINE__, \
216 "std::indirect_array<int>::operator%s(std::valarray<int>)", op);
217
218 INFO ("=");
219
220 // +-- source array
221 // | +-- array of indices (indirect_array ctor argument)
222 // | | +-- assignment operators to test (0 for none)
223 // | | | +-- argument of assignment (0 for none)
224 // | | | | +-- expected result
225 // | | | | | +-- number of matching elements
226 // | | | | | |
227 // V V V V V V
228 TEST ("", "", "=", "", "", -1 /* all */);
229 TEST ("1", "", "=", "", "1", -1 /* all */);
230 TEST ("1", "0", "=", "2", "2", -1 /* all */);
231 TEST ("1", "0", "=", "3", "3", -1 /* all */);
232 TEST ("2", "0", "=", "4", "1", 0 /* mismatch at offset 0 */);
233
234 TEST ("1,2", "", "=", "", "1,2", -1);
235 TEST ("1,2", "0", "=", "3", "3,2", -1);
236 TEST ("1,2", "1", "=", "3", "1,3", -1);
237
238 TEST ("1,2,3", "", "=", "", "1,2,3", -1);
239 TEST ("1,2,3", "0,1", "=", "5,4", "5,4,3", -1);
240 TEST ("1,2,3", "0,2", "=", "5,4", "5,2,4", -1);
241 TEST ("1,2,3", "1,0", "=", "5,4", "4,5,3", -1);
242 TEST ("1,2,3", "1,2", "=", "5,4", "1,5,4", -1);
243 TEST ("1,2,3", "2,0", "=", "5,4", "4,2,5", -1);
244 TEST ("1,2,3", "2,1", "=", "5,4", "1,4,5", -1);
245
246 TEST ("1,2,3,4", "", "=", "", "1,2,3,4", -1);
247 TEST ("1,2,3,4", "0", "=", "9", "9,2,3,4", -1);
248 TEST ("1,2,3,4", "1", "=", "9", "1,9,3,4", -1);
249 TEST ("1,2,3,4", "2", "=", "9", "1,2,9,4", -1);
250 TEST ("1,2,3,4", "3", "=", "9", "1,2,3,9", -1);
251
252 TEST ("1,2,3,4", "0,1", "=", "8,9", "8,9,3,4", -1);
253 TEST ("1,2,3,4", "0,2", "=", "8,9", "8,2,9,4", -1);
254 TEST ("1,2,3,4", "0,3", "=", "8,9", "8,2,3,9", -1);
255
256 TEST ("1,2,3,4", "1,0", "=", "8,9", "9,8,3,4", -1);
257 TEST ("1,2,3,4", "1,2", "=", "8,9", "1,8,9,4", -1);
258 TEST ("1,2,3,4", "1,3", "=", "8,9", "1,8,3,9", -1);
259
260 TEST ("1,2,3,4", "2,0", "=", "8,9", "9,2,8,4", -1);
261 TEST ("1,2,3,4", "2,1", "=", "8,9", "1,9,8,4", -1);
262 TEST ("1,2,3,4", "2,3", "=", "8,9", "1,2,8,9", -1);
263
264 TEST ("1,2,3,4", "3,0", "=", "8,9", "9,2,3,8", -1);
265 TEST ("1,2,3,4", "3,1", "=", "8,9", "1,9,3,8", -1);
266 TEST ("1,2,3,4", "3,2", "=", "8,9", "1,2,9,8", -1);
267
269 // exercise indirect_array::operator*=()
270 INFO ("*=");
271
272 TEST ("", "", "*=", "", "", -1);
273 TEST ("1", "", "*=", "", "1", -1);
274 TEST ("1", "0", "*=", "9", "9", -1);
275
276 TEST ("1,2", "", "*=", "", "1, 2", -1);
277 TEST ("1,2", "0", "*=", "9", "9, 2", -1);
278 TEST ("1,2", "1", "*=", "9", "1,18", -1);
279
280 TEST ("1,2", "0,1", "*=", "8,9", "8,18", -1);
281 TEST ("1,2", "1,0", "*=", "8,9", "9,16", -1);
282
283 TEST ("1,2,3", "", "*=", "", "1, 2, 3", -1);
284 TEST ("1,2,3", "0,1", "*=", "8,9", "8,18, 3", -1);
285 TEST ("1,2,3", "0,2", "*=", "8,9", "8, 2,27", -1);
286
287 TEST ("1,2,3", "1,0", "*=", "8,9", "9,16, 3", -1);
288 TEST ("1,2,3", "1,2", "*=", "8,9", "1,16,27", -1);
289
290 TEST ("1,2,3", "2,0", "*=", "8,9", "9, 2,24", -1);
291 TEST ("1,2,3", "2,1", "*=", "8,9", "1,18,24", -1);
292
293 TEST ("1,2,3,4", "0", "*=", "0", "0,2,3,4", -1);
294 TEST ("1,2,3,4", "1", "*=", "0", "1,0,3,4", -1);
295 TEST ("1,2,3,4", "2", "*=", "0", "1,2,0,4", -1);
296 TEST ("1,2,3,4", "3", "*=", "0", "1,2,3,0", -1);
297
298 TEST ("1,2,3,4", "0,1", "*=", "5,6", "5,12, 3, 4", -1);
299 TEST ("1,2,3,4", "0,2", "*=", "5,6", "5, 2,18, 4", -1);
300 TEST ("1,2,3,4", "0,3", "*=", "5,6", "5, 2, 3,24", -1);
301
302 TEST ("1,2,3,4", "1,0", "*=", "5,6", "6,10, 3, 4", -1);
303 TEST ("1,2,3,4", "1,2", "*=", "5,6", "1,10,18, 4", -1);
304 TEST ("1,2,3,4", "1,3", "*=", "5,6", "1,10, 3,24", -1);
305
306 TEST ("1,2,3,4", "2,0", "*=", "5,6", "6, 2,15, 4", -1);
307 TEST ("1,2,3,4", "2,1", "*=", "5,6", "1,12,15, 4", -1);
308 TEST ("1,2,3,4", "2,3", "*=", "5,6", "1, 2,15,24", -1);
309
311 // exercise indirect_array::operator/=()
312 INFO ("/=");
313
314 TEST ("10", "0", "/=", "2", " 5", -1);
315 TEST ("10,20", "0", "/=", "2", " 5,20", -1);
316 TEST ("10,20", "1", "/=", "2", "10,10", -1);
317
318 TEST ("10,20", "0,1", "/=", "5,4", "2,5", -1);
319 TEST ("10,20", "1,0", "/=", "5,4", "2,4", -1);
320
321 TEST ("10,20,30", "0,1", "/=", "5,4", "2, 5,30", -1);
322 TEST ("10,20,30", "0,2", "/=", "5,4", "2,20, 7", -1);
323
324 TEST ("10,20,30", "1,0", "/=", "5,4", " 2,4,30", -1);
325 TEST ("10,20,30", "1,2", "/=", "5,4", "10,4, 7", -1);
326
327 TEST ("10,20,30", "2,0", "/=", "5,4", " 2,20, 6", -1);
328 TEST ("10,20,30", "2,1", "/=", "5,4", "10, 5, 6", -1);
329
330 // exercise compound assignment, i.e.,
331 // ({1,2,3,4,5}[{0,2,4}] *= {6,7,8}) /= {6,7,8}
332 TEST (" 1, 2, 3, 4, 5", "0,2,4", "*=,/=", "6,7,8", "1, 2, 3, 4, 5", -1);
333 // ({1,2,3,4,5}[{0,2,4}] /= {6,7,8}) *= {6,7,8}
334 TEST ("10,20,30,40,50", "0,2,4", "/=,*=", "9,8,7", "9,20,24,40,49", -1);
335
337 // exercise indirect_array::operator%=()
338 INFO ("%=");
339
340 TEST ("10,11,12,13,14,15", "1,3,5", "%=", "6,7,8", "10,5,12,6,14,7", -1);
341
343 // exercise indirect_array::operator+=()
344 INFO ("+=");
345
346 TEST ("1,2,3,4,5,6", "1,3,5", "+=", "7,8,9", "1,9,3,12,5,15", -1);
347
348 // exercise compound assignment, i.e.,
349 // ({1,2,3,4,5,6}[{1,3,5}] += {7,8,9}) += {7,8,9}
350 TEST ("1,2,3,4,5,6", "1,3,5", "+=,+=", "7,8,9", "1,16,3,20,5,24", -1);
351 // ({1,2,3,4,5,6}[{1,3,5}] += {7,8,9}) -= {7,8,9}
352 TEST ("1,2,3,4,5,6", "1,3,5", "+=,-=", "7,8,9", "1,2,3,4,5,6", -1);
353 // ({1,2,3,4,5,6}[{1,3,5}] += {7,8,9}) /= {7,8,9}
354 TEST ("1,2,3,4,5,6", "1,3,5", "+=,/=", "7,8,9", "1,1,3,1,5,1", -1);
355
357 // exercise indirect_array::operator-=()
358 INFO ("-=");
359
360 TEST ("9,8,7,6,5,4", "0,1,2", "-=", "9,8,7", "0,0,0,6,5,4", -1);
361 TEST ("9,8,7,6,5,4", "1,2,3", "-=", "8,7,6", "9,0,0,0,5,4", -1);
362 TEST ("9,8,7,6,5,4", "2,3,4", "-=", "7,6,5", "9,8,0,0,0,4", -1);
363 TEST ("9,8,7,6,5,4", "3,4,5", "-=", "6,5,4", "9,8,7,0,0,0", -1);
364 TEST ("9,8,7,6,5,4", "0,2,4", "-=", "3,2,1", "6,8,5,6,4,4", -1);
365
367 // exercise indirect_array::operator^=()
368 INFO ("^=");
369
370 TEST ("1,3,5,7,9", "0,2,4", "^=", "2,4,5", "3,3,1,7,12", -1);
371
373 // exercise indirect_array::operator&=()
374 INFO ("&=");
375
376 TEST ("1,3,5,7,9", "0,2,4", "&=", "3,1,7", "1,3,1,7,1", -1);
377
379 // exercise indirect_array::operator|=()
380 INFO ("|=");
381
382 TEST ("1,3,5,7,9", "0,2,4", "|=", "3,1,7", "3,3,5,7,15", -1);
383
385 // exercise indirect_array::operator<<=()
386 INFO ("<<=");
387
388 TEST ("1,3,5,7,9", "0,1,2", "<<=", "1,1,1", "2,6,10, 7, 9", -1);
389 TEST ("1,3,5,7,9", "1,2,3", "<<=", "1,1,1", "1,6,10,14, 9", -1);
390 TEST ("1,3,5,7,9", "2,3,4", "<<=", "1,1,1", "1,3,10,14,18", -1);
391
392 // exercise a compound assignment, i.e.,
393 // ({1,3,5,7,9}[{2,3,4}] <<= {1,1,1}) >>= {1,1,1}
394 TEST ("1,3,5,7,9", "2,3,4", "<<=,>>=", "1,1,1", "1,3,5,7,9", -1);
395
397 // exercise indirect_array::operator>>=()
398 INFO (">>=");
399
400 TEST ("2,6,10, 7, 9", "0,1,2", ">>=", "1,1,1", "1,3,5,7,9", -1);
401 TEST ("1,6,10,14, 9", "1,2,3", ">>=", "1,1,1", "1,3,5,7,9", -1);
402 TEST ("1,3,10,14,18", "2,3,4", ">>=", "1,1,1", "1,3,5,7,9", -1);
403
404 // exercise a compound assignment, i.e.,
405 // ({10,20,30,40,50}[{1,3,5}] >>= {1,1,1}) <<= {1,1,1}
406 TEST ("10,11,12,13,14", "0,2,4", ">>=,<<=", "1,2,3", "10,11,12,13,8", -1);
407 return 0;
408}
409
410
412int main (int argc, char *argv[])
413{
414 // FIXME: add command line options to enable/disable each operator
415 return rw_test (argc, argv, __FILE__,
416 "valarray.indirect.array",
417 0 /* no comment */,
418 run_test,
419 "",
420 (void*)0 /* sentinel */);
421}
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
#define line
Definition 17.names.cpp:490
#define buf
Definition 17.names.cpp:452
#define s
#define n
Definition 17.names.cpp:130
#define val
Definition 17.names.cpp:570
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define INFO(op)
std::valarray< T > make_array(const char *s, std::size_t n=0)
#define TEST(array, inx, op, arg, res, nmatch)
const int end
#define main
A TOML array.
Definition array.hpp:258
_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_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
#define RW_ASSERT(expr)