Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
26.class.gslice.cpp
Go to the documentation of this file.
1
27#include <cstdlib> // for strtoul(), size_t
28#include <valarray> // for gslice, valarray
29
30#include <rw_driver.h>
31
32
34// returns a valarray constructed from a string of comma-separated values
35static std::valarray<std::size_t>
36make_array (const char *s)
37{
38 std::size_t buf [256];
39
40 std::size_t i = 0;
41 while (s && *s) {
42
43 char *end;
44 unsigned long val = std::strtoul (s, &end, 10);
45
46 RW_ASSERT ('\0' == *end || ',' == *end);
47
48 if (s == end)
49 break;
50
51 buf [i++] = std::size_t (val);
52
53 if ('\0' == *end)
54 break;
55
56 s = end + 1;
57 }
58
59 return std::valarray<std::size_t>(buf, i);
60}
61
62
64// returns the size of the index array represented by the genreralized slice
65static std::size_t
66get_array_size (const std::gslice &gsl)
67{
68 const std::valarray<std::size_t> sizes = gsl.size ();
69
70 std::size_t asize = sizes.size () ? 1 : 0;
71
72 for (std::size_t i = 0; i != sizes.size (); ++i) {
73 if (sizes [i])
74 asize *= sizes [i];
75 }
76
77 return asize;
78}
79
80
82static std::size_t
83next_index (const std::gslice &gsl, std::valarray<std::size_t> &factors)
84{
85 const std::size_t start = gsl.start ();
86 const std::valarray<std::size_t> asizes = gsl.size ();
87 const std::valarray<std::size_t> astrides = gsl.stride ();
88
89 const std::size_t ndims = asizes.size ();
90
91 std::size_t inx = ndims;
92
93 if (0 == factors.size ()) {
94 factors.resize (ndims);
95
96 return start;
97 }
98
99 for (; inx; --inx) {
100 if ( asizes [inx - 1]
101 && factors [inx - 1] != asizes [inx - 1] - 1)
102 break;
103 }
104
105 if (0 == inx) {
106 factors = 0;
107
108 return start;
109 }
110
111 ++factors [inx - 1];
112
113 if (inx < factors.size ()) {
114 for (std::size_t i = inx; i != ndims; ++i)
115 factors [i] = 0;
116 }
117 else
118 inx = factors.size ();
119
120 std::size_t index = start;
121
122 for (std::size_t i = 0; i != inx; ++i)
123 index += factors [i] * astrides [i];
124
125 return index;
126}
127
128
130// returns a valarray of indices reprsented by the generalized slice
131static std::valarray<std::size_t>
132get_index_array (const std::gslice &gsl)
133{
134 const std::size_t size = get_array_size (gsl);
135
136 std::valarray<std::size_t> indices (size);
137
138 std::valarray<std::size_t> tmpstore;
139
140 for (std::size_t i = 0; i != size; ++i)
141 indices [i] = next_index (gsl, tmpstore);
142
143 return indices;
144}
145
146
148static void
149test_gslice (std::size_t start,
150 const char *sizes,
151 const char *strides)
152{
153 const std::valarray<std::size_t> asizes (make_array (sizes));
154 const std::valarray<std::size_t> astrides (make_array (strides));
155
156 const std::gslice gsl (start, asizes, astrides);
157
158 const std::valarray<std::size_t> indices = get_index_array (gsl);
159
160 std::size_t maxinx = 0;
161
162 for (std::size_t i = 0; i != indices.size (); ++i)
163 if (maxinx < indices [i])
164 maxinx = indices [i];
165
166 std::valarray<std::size_t> va (indices.size () ? maxinx + 1 : 0);
167 for (std::size_t i = 0; i != va.size (); ++i)
168 va [i] = i;
169
170 for (int i = 0; i != 3; ++i) {
171 // repeat each test thrice to verify that operator[](gslice)
172 // doesn't change the observable state of its argument and
173 // that the same result is obtained for a copy of gslice
174
175 const std::valarray<std::size_t> array_slice =
176 i < 2 ? va [gsl] : va [std::gslice (gsl)];
177
178 bool equal = array_slice.size () == indices.size ();
179
180 rw_assert (equal, 0, __LINE__,
181 "size() == %zu, got %zu",
182 indices.size (), array_slice.size ());
183
184 if (equal) {
185 for (std::size_t j = 0; j != array_slice.size (); ++j) {
186
187 equal = array_slice [j] == va [indices [j]];
188
189 rw_assert (equal, 0, __LINE__,
190 "mismatch at %u, index %u: expected %u, got %u",
191 j, indices [j], va [indices [j]],
192 array_slice [j]);
193 }
194 }
195 }
196}
197
198
200static void
201test_gslice (const char *sizes, const char *strides)
202{
203 for (std::size_t i = 0; i != 10; ++i)
204 test_gslice (i, sizes, strides);
205}
206
207
209static int
210run_test (int, char**)
211{
212 test_gslice ("1", "1");
213 test_gslice ("1", "2");
214 test_gslice ("2", "1");
215 test_gslice ("2", "3");
216 test_gslice ("3", "2");
217
218 test_gslice ("1,1", "1,1");
219 test_gslice ("1,1", "1,2");
220 test_gslice ("1,1", "2,1");
221 test_gslice ("1,9", "2,1");
222 test_gslice ("9,1", "2,1");
223
224 test_gslice ("1,1,1", "1,1,1");
225 test_gslice ("1,2,3", "4,5,6");
226 test_gslice ("6,5,4", "3,2,1");
227 test_gslice ("10,11,12", "13,14,15");
228
229 // includes example from class.gslice, p3
230 test_gslice ("2,4,3", "19,4,1");
231
232 // includes example of a degenerate gslice from p5
233 test_gslice ("2,4,3", "1,1,1");
234
235 return 0;
236}
237
238
240int main (int argc, char *argv[])
241{
242 return rw_test (argc, argv, __FILE__,
243 "lib.class.gslice",
244 0 /* no comment */,
245 run_test,
246 "",
247 (void*)0 /* sentinel */);
248}
#define i
Definition 17.names.cpp:126
#define start
Definition 17.names.cpp:547
#define index
Definition 17.names.cpp:482
#define buf
Definition 17.names.cpp:452
#define j
Definition 17.names.cpp:127
#define s
#define inx
Definition 17.names.cpp:484
#define val
Definition 17.names.cpp:570
bool equal(const T &x, const U &y)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const int end
#define main
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.h:3222
_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_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
#define RW_ASSERT(expr)