Vc  1.3.2-dev
SIMD Vector Classes for C++
gatherinterface.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2014-2015 Matthias Kretz <kretz@kde.org>
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6  * Redistributions of source code must retain the above copyright
7  notice, this list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright
9  notice, this list of conditions and the following disclaimer in the
10  documentation and/or other materials provided with the distribution.
11  * Neither the names of contributing organizations nor the
12  names of its contributors may be used to endorse or promote products
13  derived from this software without specific prior written permission.
14 
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 }}}*/
27 
28 #ifndef Vc_CURRENT_CLASS_NAME
29 #error "incorrect use of common/gatherinterface.h: Vc_CURRENT_CLASS_NAME must be defined to the current class name for declaring constructors."
30 #endif
31 
33 // gathers
34 // A gather takes the following arguments:
35 // 1. A const pointer to memory of any type that can convert to EntryType
36 // 2. An indexes “vector”. The requirement is that the type implements the subscript operator,
37 // stores «Size» valid index values, and each offset to the pointer above yields a valid
38 // memory location for reading.
39 // 3. Optionally the third argument may be a mask. The mask disables several memory reads and
40 // thus removes the requirements in (2.) for the disabled entries.
41 
42 private:
53  // enable_if<std::can_convert<MT, EntryType>::value &&
54  // has_subscript_operator<IT>::value>
55  template <typename MT, typename IT>
56  inline void gatherImplementation(const MT *mem, const IT &indexes);
57 
62  template <typename MT, typename IT>
63  inline void gatherImplementation(const MT *mem, const IT &indexes, MaskArgument mask);
64 
73  template <typename IT, typename = enable_if<std::is_pointer<IT>::value ||
74  Traits::is_simd_vector<IT>::value>>
75  static Vc_INTRINSIC const IT &adjustIndexParameter(const IT &indexes)
76  {
77  return indexes;
78  }
79 
90  template <
91  typename IT,
92  typename = enable_if<
93  !std::is_pointer<IT>::value && !Traits::is_simd_vector<IT>::value &&
94  std::is_lvalue_reference<decltype(std::declval<const IT &>()[0])>::value>>
95  static Vc_INTRINSIC decltype(std::addressof(std::declval<const IT &>()[0]))
96  adjustIndexParameter(const IT &i)
97  {
98  return std::addressof(i[0]);
99  }
100 
108  template <typename IT>
109  static Vc_INTRINSIC enable_if<
110  !std::is_pointer<IT>::value && !Traits::is_simd_vector<IT>::value &&
111  !std::is_lvalue_reference<decltype(std::declval<const IT &>()[0])>::value,
112  IT>
113  adjustIndexParameter(const IT &i)
114  {
115  return i;
116  }
117 
118 public:
119 #define Vc_ASSERT_GATHER_PARAMETER_TYPES_ \
120  static_assert( \
121  std::is_convertible<MT, EntryType>::value, \
122  "The memory pointer needs to point to a type that can be converted to the " \
123  "EntryType of this SIMD vector type."); \
124  static_assert( \
125  Vc::Traits::has_subscript_operator<IT>::value, \
126  "The indexes argument must be a type that implements the subscript operator."); \
127  static_assert( \
128  !Traits::is_simd_vector<IT>::value || \
129  Traits::simd_vector_size<IT>::value >= Size, \
130  "If you use a SIMD vector for the indexes parameter, the index vector must " \
131  "have at least as many entries as this SIMD vector."); \
132  static_assert( \
133  !std::is_array<T>::value || \
134  (std::rank<T>::value == 1 && \
135  (std::extent<T>::value == 0 || std::extent<T>::value >= Size)), \
136  "If you use a simple array for the indexes parameter, the array must have " \
137  "at least as many entries as this SIMD vector.")
138 
178 
181  template <typename MT, typename IT,
182  typename = enable_if<Traits::has_subscript_operator<IT>::value>>
183  Vc_INTRINSIC Vc_CURRENT_CLASS_NAME(const MT *mem, const IT &indexes)
184  {
185  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
186  gatherImplementation(mem, adjustIndexParameter(indexes));
187  }
188 
190  template <typename MT, typename IT,
191  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
192  Vc_INTRINSIC Vc_CURRENT_CLASS_NAME(const MT *mem, const IT &indexes,
193  MaskArgument mask)
194  {
195  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
196  gatherImplementation(mem, adjustIndexParameter(indexes), mask);
197  }
198 
200  template <typename MT, typename IT,
201  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
202  Vc_INTRINSIC void gather(const MT *mem, const IT &indexes)
203  {
204  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
205  gatherImplementation(mem, adjustIndexParameter(indexes));
206  }
207 
209  template <typename MT, typename IT,
210  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
211  Vc_INTRINSIC void gather(const MT *mem, const IT &indexes, MaskArgument mask)
212  {
213  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
214  gatherImplementation(mem, adjustIndexParameter(indexes), mask);
215  }
217 
220 
233  template <typename S1, typename IT>
234  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
235  "instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array,
236  const EntryType S1::*member1,
237  IT indexes)
238  {
239  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
240  array, indexes)[member1]
241  .gatherArguments());
242  }
243 
257  template <typename S1, typename IT>
258  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
259  "instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array,
260  const EntryType S1::*member1,
261  IT indexes, MaskArgument mask)
262  {
263  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
264  array, indexes)[member1]
265  .gatherArguments(),
266  mask);
267  }
268 
283  template <typename S1, typename S2, typename IT>
284  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
285  "instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array,
286  const S2 S1::*member1,
287  const EntryType S2::*member2,
288  IT indexes)
289  {
290  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
291  array, indexes)[member1][member2]
292  .gatherArguments());
293  }
294 
310  template <typename S1, typename S2, typename IT>
311  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
312  "instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array,
313  const S2 S1::*member1,
314  const EntryType S2::*member2,
315  IT indexes, MaskArgument mask)
316  {
317  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
318  array, indexes)[member1][member2]
319  .gatherArguments(),
320  mask);
321  }
322 
334  template <typename S1, typename IT1, typename IT2>
335  Vc_DEPRECATED(
336  "use the subscript operator to Vc::array or Vc::vector "
337  "instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array,
338  const EntryType *const S1::*ptrMember1,
339  IT1 outerIndexes, IT2 innerIndexes)
340  {
341  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
342  array, outerIndexes)[ptrMember1][innerIndexes]
343  .gatherArguments());
344  }
345 
358  template <typename S1, typename IT1, typename IT2>
359  Vc_DEPRECATED(
360  "use the subscript operator to Vc::array or Vc::vector "
361  "instead.") inline Vc_CURRENT_CLASS_NAME(const S1 *array,
362  const EntryType *const S1::*ptrMember1,
363  IT1 outerIndexes, IT2 innerIndexes,
364  MaskArgument mask)
365  {
366  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
367  array, outerIndexes)[ptrMember1][innerIndexes]
368  .gatherArguments(),
369  mask);
370  }
371 
384  template <typename S1, typename IT>
385  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
386  "instead.") inline void gather(const S1 *array,
387  const EntryType S1::*member1, IT indexes)
388  {
389  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
390  array, indexes)[member1]
391  .gatherArguments());
392  }
393 
407  template <typename S1, typename IT>
408  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
409  "instead.") inline void gather(const S1 *array,
410  const EntryType S1::*member1,
411  IT indexes,
412  MaskArgument mask)
413  {
414  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
415  array, indexes)[member1]
416  .gatherArguments(),
417  mask);
418  }
419 
434  template <typename S1, typename S2, typename IT>
435  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
436  "instead.") inline void gather(const S1 *array, const S2 S1::*member1,
437  const EntryType S2::*member2, IT indexes)
438  {
439  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
440  array, indexes)[member1][member2]
441  .gatherArguments());
442  }
443 
459  template <typename S1, typename S2, typename IT>
460  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
461  "instead.") inline void gather(const S1 *array, const S2 S1::*member1,
462  const EntryType S2::*member2, IT indexes,
463  MaskArgument mask)
464  {
465  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
466  array, indexes)[member1][member2]
467  .gatherArguments(),
468  mask);
469  }
470 
482  template <typename S1, typename IT1, typename IT2>
483  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
484  "instead.") inline void gather(const S1 *array,
485  const EntryType *const S1::*ptrMember1,
486  IT1 outerIndexes, IT2 innerIndexes)
487  {
488  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
489  array, outerIndexes)[ptrMember1][innerIndexes]
490  .gatherArguments());
491  }
492 
505  template <typename S1, typename IT1, typename IT2>
506  Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
507  "instead.") inline void gather(const S1 *array,
508  const EntryType *const S1::*ptrMember1,
509  IT1 outerIndexes, IT2 innerIndexes,
510  MaskArgument mask)
511  {
512  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
513  array, outerIndexes)[ptrMember1][innerIndexes]
514  .gatherArguments(),
515  mask);
516  }
518 
525  template <typename MT, typename IT>
527  Vc_INTRINSIC void gather(const Common::GatherArguments<MT, IT> &args)
528  {
529  gather(args.address, adjustIndexParameter(args.indexes));
530  }
531 
532  template <typename MT, typename IT>
533  Vc_INTRINSIC void gather(const Common::GatherArguments<MT, IT> &args, MaskArgument mask)
534  {
535  gather(args.address, adjustIndexParameter(args.indexes), mask);
536  }
538 
539 #undef Vc_ASSERT_GATHER_PARAMETER_TYPES_