Vc  1.3.0
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, IT &&indexes);
57 
62  template <typename MT, typename IT>
63  inline void gatherImplementation(const MT *mem, 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 IT adjustIndexParameter(IT &&indexes)
76  {
77  return std::forward<IT>(indexes);
78  }
79 
90  template <typename IT,
91  typename = enable_if<
92  !std::is_pointer<IT>::value && !Traits::is_simd_vector<IT>::value &&
93  std::is_lvalue_reference<decltype(std::declval<IT>()[0])>::value>>
94  static Vc_INTRINSIC decltype(std::addressof(std::declval<IT>()[0]))
95  adjustIndexParameter(IT &&i)
96  {
97  return std::addressof(i[0]);
98  }
99 
107  template <typename IT>
108  static Vc_INTRINSIC
109  enable_if<!std::is_pointer<IT>::value && !Traits::is_simd_vector<IT>::value &&
110  !std::is_lvalue_reference<decltype(std::declval<IT>()[0])>::value,
111  IT>
112  adjustIndexParameter(IT &&i)
113  {
114  return std::forward<IT>(i);
115  }
116 
117 public:
118 #define Vc_ASSERT_GATHER_PARAMETER_TYPES_ \
119  static_assert( \
120  std::is_convertible<MT, EntryType>::value, \
121  "The memory pointer needs to point to a type that can be converted to the " \
122  "EntryType of this SIMD vector type."); \
123  static_assert( \
124  Vc::Traits::has_subscript_operator<IT>::value, \
125  "The indexes argument must be a type that implements the subscript operator."); \
126  static_assert( \
127  !Traits::is_simd_vector<IT>::value || \
128  Traits::simd_vector_size<IT>::value >= Size, \
129  "If you use a SIMD vector for the indexes parameter, the index vector must " \
130  "have at least as many entries as this SIMD vector."); \
131  static_assert( \
132  !std::is_array<T>::value || \
133  (std::rank<T>::value == 1 && \
134  (std::extent<T>::value == 0 || std::extent<T>::value >= Size)), \
135  "If you use a simple array for the indexes parameter, the array must have " \
136  "at least as many entries as this SIMD vector.")
137 
177 
180  template <typename MT, typename IT,
181  typename = enable_if<Traits::has_subscript_operator<IT>::value>>
182  Vc_INTRINSIC Vc_CURRENT_CLASS_NAME(const MT *mem, IT &&indexes)
183  {
184  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
185  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(indexes)));
186  }
187 
189  template <typename MT, typename IT,
190  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
191  Vc_INTRINSIC Vc_CURRENT_CLASS_NAME(const MT *mem, IT &&indexes, MaskArgument mask)
192  {
193  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
194  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(indexes)), mask);
195  }
196 
198  template <typename MT,
199  typename IT,
200  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
201  Vc_INTRINSIC void gather(const MT *mem, IT &&indexes)
202  {
203  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
204  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(indexes)));
205  }
206 
208  template <typename MT,
209  typename IT,
210  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
211  Vc_INTRINSIC void gather(const MT *mem, IT &&indexes, MaskArgument mask)
212  {
213  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
214  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(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_