ROOT  6.06/09
Reference Guide
deinterleave.cpp
Go to the documentation of this file.
1 /* This file is part of the Vc library.
2 
3  Copyright (C) 2010-2011 Matthias Kretz <kretz@kde.org>
4 
5  Vc is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as
7  published by the Free Software Foundation, either version 3 of
8  the License, or (at your option) any later version.
9 
10  Vc is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with Vc. If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 
20 #include "unittest.h"
21 #include <iostream>
22 #include <limits>
23 
24 using namespace Vc;
25 
26 
27 /*
28  * V \ M | float | double | ushort | short | uint | int
29  * ---------+----------------------------------------------
30  * float_v | X | | X | X | |
31  * sfloat_v | X | | X | X | |
32  * double_v | | X | | | |
33  * int_v | | | | X | | X
34  * uint_v | | | X | | X |
35  * short_v | | | | X | |
36  * ushort_v | | | X | | |
37  */
38 template<typename A, typename B> struct TPair { typedef A V; typedef B M; };
39 
43 
47 
51 
54 
57 
58 template<typename Pair> void testDeinterleave()
59 {
60  typedef typename Pair::V V;
61  typedef typename Pair::M M;
62  typedef typename V::IndexType I;
63 
64  const bool isSigned = std::numeric_limits<M>::is_signed;
65 
66  const typename V::EntryType offset = isSigned ? -512 : 0;
67  const V _0246 = static_cast<V>(I::IndexesFromZero()) * 2 + offset;
68 
69  M memory[1024];
70  for (int i = 0; i < 1024; ++i) {
71  memory[i] = static_cast<M>(i + offset);
72  }
73 
74  V a, b;
75 
76  for (int i = 0; i < 1024 - 2 * V::Size; ++i) {
77  // note that a 32 bit integer is certainly enough to decide on alignment...
78  // ... but uintptr_t is C99 but not C++ yet
79  // ... and GCC refuses to do the cast, even if I know what I'm doing
80  if (reinterpret_cast<unsigned long>(&memory[i]) & (VectorAlignment - 1)) {
81  Vc::deinterleave(&a, &b, &memory[i], Unaligned);
82  } else {
83  Vc::deinterleave(&a, &b, &memory[i]);
84  }
85  COMPARE(_0246 + i, a);
86  COMPARE(_0246 + i + 1, b);
87  }
88 }
89 
90 template<typename T, size_t N> struct SomeStruct
91 {
92  T d[N];
93 };
94 
95 template<typename V, size_t StructSize> struct Types
96 {
97  typedef typename V::EntryType T;
98  typedef typename V::IndexType I;
99  typedef typename V::AsArg VArg;
100  typedef typename I::AsArg IArg;
101  typedef SomeStruct<T, StructSize> S;
102  typedef const Vc::InterleavedMemoryWrapper<S, V> &Wrapper;
103 };
104 template<typename V, size_t StructSize, size_t N = StructSize> struct TestDeinterleaveGatherCompare;
105 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 8> {
106  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
107  {
108  V v0, v1, v2, v3, v4, v5, v6, v7;
109  (v0, v1, v2, v3, v4, v5, v6, v7) = data_v[indexes];
110  COMPARE(v0, reference + 0) << "N = 8";
111  COMPARE(v1, reference + 1) << "N = 8";
112  COMPARE(v2, reference + 2) << "N = 8";
113  COMPARE(v3, reference + 3) << "N = 8";
114  COMPARE(v4, reference + 4) << "N = 8";
115  COMPARE(v5, reference + 5) << "N = 8";
116  COMPARE(v6, reference + 6) << "N = 8";
117  COMPARE(v7, reference + 7) << "N = 8";
118  TestDeinterleaveGatherCompare<V, StructSize, 7>::test(data_v, indexes, reference);
119  }
120 };
121 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 7> {
122  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
123  {
124  V v0, v1, v2, v3, v4, v5, v6;
125  (v0, v1, v2, v3, v4, v5, v6) = data_v[indexes];
126  COMPARE(v0, reference + 0) << "N = 7";
127  COMPARE(v1, reference + 1) << "N = 7";
128  COMPARE(v2, reference + 2) << "N = 7";
129  COMPARE(v3, reference + 3) << "N = 7";
130  COMPARE(v4, reference + 4) << "N = 7";
131  COMPARE(v5, reference + 5) << "N = 7";
132  COMPARE(v6, reference + 6) << "N = 7";
133  TestDeinterleaveGatherCompare<V, StructSize, 6>::test(data_v, indexes, reference);
134  }
135 };
136 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 6> {
137  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
138  {
139  V v0, v1, v2, v3, v4, v5;
140  (v0, v1, v2, v3, v4, v5) = data_v[indexes];
141  COMPARE(v0, reference + 0) << "N = 6";
142  COMPARE(v1, reference + 1) << "N = 6";
143  COMPARE(v2, reference + 2) << "N = 6";
144  COMPARE(v3, reference + 3) << "N = 6";
145  COMPARE(v4, reference + 4) << "N = 6";
146  COMPARE(v5, reference + 5) << "N = 6";
147  TestDeinterleaveGatherCompare<V, StructSize, 5>::test(data_v, indexes, reference);
148  }
149 };
150 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 5> {
151  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
152  {
153  V v0, v1, v2, v3, v4;
154  (v0, v1, v2, v3, v4) = data_v[indexes];
155  COMPARE(v0, reference + 0) << "N = 5";
156  COMPARE(v1, reference + 1) << "N = 5";
157  COMPARE(v2, reference + 2) << "N = 5";
158  COMPARE(v3, reference + 3) << "N = 5";
159  COMPARE(v4, reference + 4) << "N = 5";
160  TestDeinterleaveGatherCompare<V, StructSize, 4>::test(data_v, indexes, reference);
161  }
162 };
163 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 4> {
164  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
165  {
166  V a, b, c, d;
167  (a, b, c, d) = data_v[indexes];
168  COMPARE(a, reference + 0) << "N = 4";
169  COMPARE(b, reference + 1) << "N = 4";
170  COMPARE(c, reference + 2) << "N = 4";
171  COMPARE(d, reference + 3) << "N = 4";
172  TestDeinterleaveGatherCompare<V, StructSize, 3>::test(data_v, indexes, reference);
173  }
174 };
175 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 3> {
176  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
177  {
178  V a, b, c;
179  (a, b, c) = data_v[indexes];
180  COMPARE(a, reference + 0) << "N = 3";
181  COMPARE(b, reference + 1) << "N = 3";
182  COMPARE(c, reference + 2) << "N = 3";
183  TestDeinterleaveGatherCompare<V, StructSize, 2>::test(data_v, indexes, reference);
184  }
185 };
186 template<typename V, size_t StructSize> struct TestDeinterleaveGatherCompare<V, StructSize, 2> {
187  static void test(typename Types<V, StructSize>::Wrapper data_v, typename Types<V, StructSize>::IArg indexes, const typename V::AsArg reference)
188  {
189  V a, b;
190  (a, b) = data_v[indexes];
191  COMPARE(a, reference + 0) << "N = 2";
192  COMPARE(b, reference + 1) << "N = 2";
193  }
194 };
195 
196 size_t createNMask(size_t N)
197 {
198  size_t NMask = (N >> 1) | (N >> 2);
199  for (size_t shift = 2; shift < sizeof(size_t) * 8; shift *= 2) {
200  NMask |= NMask >> shift;
201  }
202  return NMask;
203 }
204 
205 template<typename V, size_t StructSize> void testDeinterleaveGatherImpl()
206 {
207  typedef typename V::EntryType T;
208  typedef typename V::IndexType I;
209  typedef SomeStruct<T, StructSize> S;
210  typedef Vc::InterleavedMemoryWrapper<S, V> Wrapper;
211  const size_t N = std::min<size_t>(std::numeric_limits<typename I::EntryType>::max(), 1024 * 1024 / sizeof(S));
212  const size_t NMask = createNMask(N);
213 
214  S *data = Vc::malloc<S, Vc::AlignOnVector>(N);
215  for (size_t i = 0; i < N; ++i) {
216  for (size_t j = 0; j < StructSize; ++j) {
217  data[i].d[j] = i * StructSize + j;
218  }
219  }
220  const Wrapper data_v(data);
221 
222  for (int retest = 0; retest < 10000; ++retest) {
223  I indexes = (I::Random() >> 10) & I(NMask);
224  VERIFY(indexes >= 0);
225  VERIFY(indexes < N);
226  const V reference = static_cast<V>(indexes) * V(StructSize);
227 
228  TestDeinterleaveGatherCompare<V, StructSize>::test(data_v, indexes, reference);
229  }
230 }
231 
232 template<typename V> void testDeinterleaveGather()
233 {
234  testDeinterleaveGatherImpl<V, 2>();
235  testDeinterleaveGatherImpl<V, 3>();
236  testDeinterleaveGatherImpl<V, 4>();
237  testDeinterleaveGatherImpl<V, 5>();
238  testDeinterleaveGatherImpl<V, 6>();
239  testDeinterleaveGatherImpl<V, 7>();
240  testDeinterleaveGatherImpl<V, 8>();
241 }
242 
243 template<typename V, size_t StructSize> struct TestInterleavingScatterCompare;
244 #define _IMPL(STRUCTSIZE, _code_) \
245 template<typename V> struct TestInterleavingScatterCompare<V, STRUCTSIZE> { \
246  typedef TestInterleavingScatterCompare<V, STRUCTSIZE - 1> NextTest; \
247  template<typename Wrapper> static void test(Wrapper &data, const typename V::IndexType &i) { \
248  _code_ \
249  } \
250 }
251 _IMPL(2,
252  const V v0 = V::Random();
253  const V v1 = V::Random();
254  V t0;
255  V t1;
256  data[i] = (v0, v1);
257  (t0, t1) = data[i];
258  COMPARE(t0, v0) << 2;
259  COMPARE(t1, v1) << 2;
260  );
261 _IMPL(3,
262  const V v0 = V::Random();
263  const V v1 = V::Random();
264  const V v2 = V::Random();
265  V t0; V t1; V t2;
266  data[i] = (v0, v1, v2);
267  (t0, t1, t2) = data[i];
268  COMPARE(t0, v0) << 3;
269  COMPARE(t1, v1) << 3;
270  COMPARE(t2, v2) << 3;
271  NextTest::test(data, i);
272  );
273 _IMPL(4,
274  const V v0 = V::Random();
275  const V v1 = V::Random();
276  const V v2 = V::Random();
277  const V v3 = V::Random();
278  V t0; V t1; V t2; V t3;
279  data[i] = (v0, v1, v2, v3);
280  (t0, t1, t2, t3) = data[i];
281  COMPARE(t0, v0) << 4;
282  COMPARE(t1, v1) << 4;
283  COMPARE(t2, v2) << 4;
284  COMPARE(t3, v3) << 4;
285  NextTest::test(data, i);
286  );
287 _IMPL(5,
288  const V v0 = V::Random();
289  const V v1 = V::Random();
290  const V v2 = V::Random();
291  const V v3 = V::Random();
292  const V v4 = V::Random();
293  V t0; V t1; V t2; V t3; V t4;
294  data[i] = (v0, v1, v2, v3, v4);
295  (t0, t1, t2, t3, t4) = data[i];
296  COMPARE(t0, v0) << 5;
297  COMPARE(t1, v1) << 5;
298  COMPARE(t2, v2) << 5;
299  COMPARE(t3, v3) << 5;
300  COMPARE(t4, v4) << 5;
301  NextTest::test(data, i);
302  );
303 _IMPL(6,
304  const V v0 = V::Random();
305  const V v1 = V::Random();
306  const V v2 = V::Random();
307  const V v3 = V::Random();
308  const V v4 = V::Random();
309  const V v5 = V::Random();
310  V t0; V t1; V t2; V t3; V t4; V t5;
311  data[i] = (v0, v1, v2, v3, v4, v5);
312  (t0, t1, t2, t3, t4, t5) = data[i];
313  COMPARE(t0, v0) << 6;
314  COMPARE(t1, v1) << 6;
315  COMPARE(t2, v2) << 6;
316  COMPARE(t3, v3) << 6;
317  COMPARE(t4, v4) << 6;
318  COMPARE(t5, v5) << 6;
319  NextTest::test(data, i);
320  );
321 _IMPL(7,
322  const V v0 = V::Random();
323  const V v1 = V::Random();
324  const V v2 = V::Random();
325  const V v3 = V::Random();
326  const V v4 = V::Random();
327  const V v5 = V::Random();
328  const V v6 = V::Random();
329  V t0; V t1; V t2; V t3; V t4; V t5; V t6;
330  data[i] = (v0, v1, v2, v3, v4, v5, v6);
331  (t0, t1, t2, t3, t4, t5, t6) = data[i];
332  COMPARE(t0, v0) << 7;
333  COMPARE(t1, v1) << 7;
334  COMPARE(t2, v2) << 7;
335  COMPARE(t3, v3) << 7;
336  COMPARE(t4, v4) << 7;
337  COMPARE(t5, v5) << 7;
338  COMPARE(t6, v6) << 7;
339  NextTest::test(data, i);
340  );
341 _IMPL(8,
342  const V v0 = V::Random();
343  const V v1 = V::Random();
344  const V v2 = V::Random();
345  const V v3 = V::Random();
346  const V v4 = V::Random();
347  const V v5 = V::Random();
348  const V v6 = V::Random();
349  const V v7 = V::Random();
350  V t0; V t1; V t2; V t3; V t4; V t5; V t6; V t7;
351  data[i] = (v0, v1, v2, v3, v4, v5, v6, v7);
352  (t0, t1, t2, t3, t4, t5, t6, t7) = data[i];
353  COMPARE(t0, v0) << 8;
354  COMPARE(t1, v1) << 8;
355  COMPARE(t2, v2) << 8;
356  COMPARE(t3, v3) << 8;
357  COMPARE(t4, v4) << 8;
358  COMPARE(t5, v5) << 8;
359  COMPARE(t6, v6) << 8;
360  COMPARE(t7, v7) << 8;
361  NextTest::test(data, i);
362  );
363 
364 template<typename V, size_t StructSize> void testInterleavingScatterImpl()
365 {
366  typedef typename V::EntryType T;
367  typedef typename V::IndexType I;
368  typedef SomeStruct<T, StructSize> S;
369  typedef Vc::InterleavedMemoryWrapper<S, V> Wrapper;
370  const size_t N = std::min<size_t>(std::numeric_limits<typename I::EntryType>::max(), 1024 * 1024 / sizeof(S));
371  const size_t NMask = createNMask(N);
372 
373  S *data = Vc::malloc<S, Vc::AlignOnVector>(N);
374  std::memset(data, 0, sizeof(S) * N);
375  Wrapper data_v(data);
376 
377  for (int retest = 0; retest < 10000; ++retest) {
378  I indexes = (I::Random() >> 10) & I(NMask);
379  if (I::Size != 1) {
380  // ensure the indexes are unique
381  while(!(indexes.sorted() == indexes.sorted().rotated(1)).isEmpty()) {
382  indexes = (I::Random() >> 10) & I(NMask);
383  }
384  }
385  VERIFY(indexes >= 0);
386  VERIFY(indexes < N);
387 
388  TestInterleavingScatterCompare<V, StructSize>::test(data_v, indexes);
389  }
390 }
391 
392 template<typename V> void testInterleavingScatter()
393 {
394  testInterleavingScatterImpl<V, 2>();
395  testInterleavingScatterImpl<V, 3>();
396  testInterleavingScatterImpl<V, 4>();
397  testInterleavingScatterImpl<V, 5>();
398  testInterleavingScatterImpl<V, 6>();
399  testInterleavingScatterImpl<V, 7>();
400  testInterleavingScatterImpl<V, 8>();
401 }
402 
403 int main()
404 {
405  runTest(testDeinterleave<float_float>);
406  runTest(testDeinterleave<float_ushort>);
407  runTest(testDeinterleave<float_short>);
408  runTest(testDeinterleave<sfloat_float>);
409  runTest(testDeinterleave<sfloat_ushort>);
410  runTest(testDeinterleave<sfloat_short>);
411  runTest(testDeinterleave<double_double>);
412  runTest(testDeinterleave<int_int>);
413  runTest(testDeinterleave<int_short>);
414  runTest(testDeinterleave<uint_uint>);
415  runTest(testDeinterleave<uint_ushort>);
416  runTest(testDeinterleave<short_short>);
417  runTest(testDeinterleave<ushort_ushort>);
418 
421 }
static double B[]
Vc_ALWAYS_INLINE void deinterleave(V *a, V *b, const M *memory, A align)
Loads two vectors of values from an interleaved array.
Definition: deinterleave.h:69
TPair< float_v, short > float_short
#define _IMPL(STRUCTSIZE, _code_)
const Double_t * v1
Definition: TArcBall.cxx:33
void testDeinterleave()
const char * Size
Definition: TXMLSetup.cxx:56
void testDeinterleaveGather()
double T(double x)
Definition: ChebyshevPol.h:34
TPair< ushort_v, unsigned short > ushort_ushort
TPair< sfloat_v, short > sfloat_short
#define N
TArc * a
Definition: textangle.C:12
TPair< uint_v, unsigned short > uint_ushort
size_t
Definition: TBuffer.cxx:28
TLatex * t1
Definition: textangle.C:20
static double A[]
TPair< float_v, unsigned short > float_ushort
TPair< uint_v, unsigned int > uint_uint
#define COMPARE(a, b)
Definition: unittest.h:509
int main()
#define testAllTypes(name)
Definition: unittest.h:43
TPair< int_v, int > int_int
void testInterleavingScatterImpl()
TPair< sfloat_v, unsigned short > sfloat_ushort
TPair< int_v, short > int_short
void testInterleavingScatter()
TPair< double_v, double > double_double
#define VERIFY(cond)
Definition: unittest.h:515
void testDeinterleaveGatherImpl()
Class used by TMap to store (key,value) pairs.
Definition: TMap.h:106
void Random()
Definition: utils.cpp:154
static const float S
Definition: mandel.cpp:113
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Definition: vector.h:440
TPair< float_v, float > float_float
Definition: casts.h:28
size_t createNMask(size_t N)
#define I(x, y, z)
TPair< short_v, short > short_short
TPair< sfloat_v, float > sfloat_float
#define runTest(name)
Definition: unittest.h:42