Vc  1.2.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 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7  * Redistributions of source code must retain the above copyright
8  notice, this list of conditions and the following disclaimer.
9  * Redistributions in binary form must reproduce the above copyright
10  notice, this list of conditions and the following disclaimer in the
11  documentation and/or other materials provided with the distribution.
12  * Neither the names of contributing organizations nor the
13  names of its contributors may be used to endorse or promote products
14  derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 }}}*/
28 
29 #ifndef Vc_CURRENT_CLASS_NAME
30 #error "incorrect use of common/gatherinterface.h: Vc_CURRENT_CLASS_NAME must be defined to the current class name for declaring constructors."
31 #endif
32 
34 // gathers
35 // A gather takes the following arguments:
36 // 1. A const pointer to memory of any type that can convert to EntryType
37 // 2. An indexes “vector”. The requirement is that the type implements the subscript operator,
38 // stores «Size» valid index values, and each offset to the pointer above yields a valid
39 // memory location for reading.
40 // 3. Optionally the third argument may be a mask. The mask disables several memory reads and
41 // thus removes the requirements in (2.) for the disabled entries.
42 
43 private:
54  // enable_if<std::can_convert<MT, EntryType>::value &&
55  // has_subscript_operator<IT>::value>
56  template <typename MT, typename IT>
57  inline void gatherImplementation(const MT *mem, IT &&indexes);
58 
63  template <typename MT, typename IT>
64  inline void gatherImplementation(const MT *mem, IT &&indexes, MaskArgument mask);
65 
74  template <typename IT, typename = enable_if<std::is_pointer<IT>::value ||
75  Traits::is_simd_vector<IT>::value>>
76  static Vc_INTRINSIC IT adjustIndexParameter(IT &&indexes)
77  {
78  return std::forward<IT>(indexes);
79  }
80 
91  template <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<IT>()[0])>::value>>
95  static Vc_INTRINSIC decltype(std::addressof(std::declval<IT>()[0]))
96  adjustIndexParameter(IT &&i)
97  {
98  return std::addressof(i[0]);
99  }
100 
108  template <typename IT>
109  static Vc_INTRINSIC
110  enable_if<!std::is_pointer<IT>::value && !Traits::is_simd_vector<IT>::value &&
111  !std::is_lvalue_reference<decltype(std::declval<IT>()[0])>::value,
112  IT>
113  adjustIndexParameter(IT &&i)
114  {
115  return std::forward<IT>(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, IT &&indexes)
184  {
185  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
186  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(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, IT &&indexes, MaskArgument mask)
193  {
194  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
195  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(indexes)), mask);
196  }
197 
199  template <typename MT,
200  typename IT,
201  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
202  Vc_INTRINSIC void gather(const MT *mem, IT &&indexes)
203  {
204  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
205  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(indexes)));
206  }
207 
209  template <typename MT,
210  typename IT,
211  typename = enable_if<Vc::Traits::has_subscript_operator<IT>::value>>
212  Vc_INTRINSIC void gather(const MT *mem, IT &&indexes, MaskArgument mask)
213  {
214  Vc_ASSERT_GATHER_PARAMETER_TYPES_;
215  gatherImplementation(mem, adjustIndexParameter(std::forward<IT>(indexes)), mask);
216  }
218 
221 
234  template <typename S1, typename IT>
235  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector instead.")
236  Vc_CURRENT_CLASS_NAME(const S1 *array, const EntryType S1::*member1,
237  Vc_ALIGNED_PARAMETER(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  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector instead.")
259  Vc_CURRENT_CLASS_NAME(const S1 *array, const EntryType S1::*member1,
260  Vc_ALIGNED_PARAMETER(IT) indexes, MaskArgument mask)
261  {
262  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
263  array, indexes)[member1]
264  .gatherArguments(),
265  mask);
266  }
267 
282  template <typename S1, typename S2, typename IT>
283  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector instead.")
284  Vc_CURRENT_CLASS_NAME(const S1 *array, const S2 S1::*member1,
285  const EntryType S2::*member2,
286  Vc_ALIGNED_PARAMETER(IT) indexes)
287  {
288  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
289  array, indexes)[member1][member2]
290  .gatherArguments());
291  }
292 
308  template <typename S1, typename S2, typename IT>
309  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector instead.")
310  Vc_CURRENT_CLASS_NAME(const S1 *array, const S2 S1::*member1,
311  const EntryType S2::*member2,
312  Vc_ALIGNED_PARAMETER(IT) indexes, MaskArgument mask)
313  {
314  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
315  array, indexes)[member1][member2]
316  .gatherArguments(),
317  mask);
318  }
319 
331  template <typename S1, typename IT1, typename IT2>
332  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector instead.")
333  Vc_CURRENT_CLASS_NAME(const S1 *array, const EntryType *const S1::*ptrMember1,
334  Vc_ALIGNED_PARAMETER(IT1) outerIndexes,
335  Vc_ALIGNED_PARAMETER(IT2) innerIndexes)
336  {
337  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
338  array, outerIndexes)[ptrMember1][innerIndexes]
339  .gatherArguments());
340  }
341 
354  template <typename S1, typename IT1, typename IT2>
355  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector instead.")
356  Vc_CURRENT_CLASS_NAME(const S1 *array, const EntryType *const S1::*ptrMember1,
357  Vc_ALIGNED_PARAMETER(IT1) outerIndexes,
358  Vc_ALIGNED_PARAMETER(IT2) innerIndexes, MaskArgument mask)
359  {
360  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
361  array, outerIndexes)[ptrMember1][innerIndexes]
362  .gatherArguments(),
363  mask);
364  }
365 
378  template <typename S1, typename IT>
379  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
380  "instead.") void gather(const S1 *array,
381  const EntryType S1::*member1,
382  Vc_ALIGNED_PARAMETER(IT) indexes)
383  {
384  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
385  array, indexes)[member1]
386  .gatherArguments());
387  }
388 
402  template <typename S1, typename IT>
403  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
404  "instead.") void gather(const S1 *array,
405  const EntryType S1::*member1,
406  Vc_ALIGNED_PARAMETER(IT) indexes,
407  MaskArgument mask)
408  {
409  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
410  array, indexes)[member1]
411  .gatherArguments(),
412  mask);
413  }
414 
429  template <typename S1, typename S2, typename IT>
430  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
431  "instead.") void gather(const S1 *array, const S2 S1::*member1,
432  const EntryType S2::*member2,
433  Vc_ALIGNED_PARAMETER(IT) indexes)
434  {
435  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
436  array, indexes)[member1][member2]
437  .gatherArguments());
438  }
439 
455  template <typename S1, typename S2, typename IT>
456  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
457  "instead.") void gather(const S1 *array, const S2 S1::*member1,
458  const EntryType S2::*member2,
459  Vc_ALIGNED_PARAMETER(IT) indexes,
460  MaskArgument mask)
461  {
462  gather(Common::SubscriptOperation<S1, IT, std::ratio<1, 1>, true>(
463  array, indexes)[member1][member2]
464  .gatherArguments(),
465  mask);
466  }
467 
479  template <typename S1, typename IT1, typename IT2>
480  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
481  "instead.") void gather(const S1 *array,
482  const EntryType *const S1::*ptrMember1,
483  Vc_ALIGNED_PARAMETER(IT1) outerIndexes,
484  Vc_ALIGNED_PARAMETER(IT2) innerIndexes)
485  {
486  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
487  array, outerIndexes)[ptrMember1][innerIndexes]
488  .gatherArguments());
489  }
490 
503  template <typename S1, typename IT1, typename IT2>
504  inline Vc_DEPRECATED("use the subscript operator to Vc::array or Vc::vector "
505  "instead.") void gather(const S1 *array,
506  const EntryType *const S1::*ptrMember1,
507  Vc_ALIGNED_PARAMETER(IT1) outerIndexes,
508  Vc_ALIGNED_PARAMETER(IT2) innerIndexes,
509  MaskArgument mask)
510  {
511  gather(Common::SubscriptOperation<S1, IT1, std::ratio<1, 1>, true>(
512  array, outerIndexes)[ptrMember1][innerIndexes]
513  .gatherArguments(),
514  mask);
515  }
517 
524  template <typename MT, typename IT>
526  Vc_INTRINSIC void gather(const Common::GatherArguments<MT, IT> &args)
527  {
528  gather(args.address, adjustIndexParameter(args.indexes));
529  }
530 
531  template <typename MT, typename IT>
532  Vc_INTRINSIC void gather(const Common::GatherArguments<MT, IT> &args, MaskArgument mask)
533  {
534  gather(args.address, adjustIndexParameter(args.indexes), mask);
535  }
537 
538 #undef Vc_ASSERT_GATHER_PARAMETER_TYPES_