Vc  1.3.0
SIMD Vector Classes for C++
algorithms.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2013-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_COMMON_ALGORITHMS_H_
29 #define VC_COMMON_ALGORITHMS_H_
30 
31 #include "macros.h"
32 
33 namespace Vc_VERSIONED_NAMESPACE
34 {
44 template<typename Mask> constexpr bool all_of(const Mask &m) { return m.isFull(); }
48 constexpr bool all_of(bool b) { return b; }
49 
53 template<typename Mask> constexpr bool any_of(const Mask &m) { return m.isNotEmpty(); }
57 constexpr bool any_of(bool b) { return b; }
58 
62 template<typename Mask> constexpr bool none_of(const Mask &m) { return m.isEmpty(); }
66 constexpr bool none_of(bool b) { return !b; }
67 
72 template<typename Mask> constexpr bool some_of(const Mask &m) { return m.isMix(); }
76 constexpr bool some_of(bool) { return false; }
78 
79 template <typename InputIt, typename UnaryFunction>
80 inline enable_if<std::is_arithmetic<typename InputIt::value_type>::value &&
81  Traits::is_functor_argument_immutable<
82  UnaryFunction, Vector<typename InputIt::value_type>>::value,
83  UnaryFunction>
84 simd_for_each(InputIt first, InputIt last, UnaryFunction f)
85 {
87  typedef Scalar::Vector<typename InputIt::value_type> V1;
88  for (; reinterpret_cast<std::uintptr_t>(std::addressof(*first)) &
89  (V::MemoryAlignment - 1) &&
90  first != last;
91  ++first) {
92  f(V1(std::addressof(*first), Vc::Aligned));
93  }
94  const auto lastV = last - (V::Size + 1);
95  for (; first < lastV; first += V::Size) {
96  f(V(std::addressof(*first), Vc::Aligned));
97  }
98  for (; first != last; ++first) {
99  f(V1(std::addressof(*first), Vc::Aligned));
100  }
101  return std::move(f);
102 }
103 
104 template <typename InputIt, typename UnaryFunction>
105 inline enable_if<std::is_arithmetic<typename InputIt::value_type>::value &&
106  !Traits::is_functor_argument_immutable<
107  UnaryFunction, Vector<typename InputIt::value_type>>::value,
108  UnaryFunction>
109 simd_for_each(InputIt first, InputIt last, UnaryFunction f)
110 {
112  typedef Scalar::Vector<typename InputIt::value_type> V1;
113  for (; reinterpret_cast<std::uintptr_t>(std::addressof(*first)) &
114  (V::MemoryAlignment - 1) &&
115  first != last;
116  ++first) {
117  V1 tmp(std::addressof(*first), Vc::Aligned);
118  f(tmp);
119  tmp.store(std::addressof(*first), Vc::Aligned);
120  }
121  const auto lastV = last - (V::Size + 1);
122  for (; first < lastV; first += V::Size) {
123  V tmp(std::addressof(*first), Vc::Aligned);
124  f(tmp);
125  tmp.store(std::addressof(*first), Vc::Aligned);
126  }
127  for (; first != last; ++first) {
128  V1 tmp(std::addressof(*first), Vc::Aligned);
129  f(tmp);
130  tmp.store(std::addressof(*first), Vc::Aligned);
131  }
132  return std::move(f);
133 }
134 
135 template <typename InputIt, typename UnaryFunction>
136 inline enable_if<!std::is_arithmetic<typename InputIt::value_type>::value, UnaryFunction>
137 simd_for_each(InputIt first, InputIt last, UnaryFunction f)
138 {
139  return std::for_each(first, last, std::move(f));
140 }
141 
143 template <typename InputIt, typename UnaryFunction>
144 inline enable_if<std::is_arithmetic<typename InputIt::value_type>::value &&
145  Traits::is_functor_argument_immutable<
146  UnaryFunction, Vector<typename InputIt::value_type>>::value,
147  UnaryFunction>
148 simd_for_each_n(InputIt first, std::size_t count, UnaryFunction f)
149 {
150  typename std::make_signed<size_t>::type len = count;
152  typedef Scalar::Vector<typename InputIt::value_type> V1;
153  for (; reinterpret_cast<std::uintptr_t>(std::addressof(*first)) &
154  (V::MemoryAlignment - 1) &&
155  len != 0;
156  --len, ++first) {
157  f(V1(std::addressof(*first), Vc::Aligned));
158  }
159  for (; len >= int(V::Size); len -= V::Size, first += V::Size) {
160  f(V(std::addressof(*first), Vc::Aligned));
161  }
162  for (; len != 0; --len, ++first) {
163  f(V1(std::addressof(*first), Vc::Aligned));
164  }
165  return std::move(f);
166 }
167 
168 template <typename InputIt, typename UnaryFunction>
169 inline enable_if<std::is_arithmetic<typename InputIt::value_type>::value &&
170  !Traits::is_functor_argument_immutable<
171  UnaryFunction, Vector<typename InputIt::value_type>>::value,
172  UnaryFunction>
173 simd_for_each_n(InputIt first, std::size_t count, UnaryFunction f)
174 {
175  typename std::make_signed<size_t>::type len = count;
177  typedef Scalar::Vector<typename InputIt::value_type> V1;
178  for (; reinterpret_cast<std::uintptr_t>(std::addressof(*first)) &
179  (V::MemoryAlignment - 1) &&
180  len != 0;
181  --len, ++first) {
182  V1 tmp(std::addressof(*first), Vc::Aligned);
183  f(tmp);
184  tmp.store(std::addressof(*first), Vc::Aligned);
185  }
186  for (; len >= int(V::Size); len -= V::Size, first += V::Size) {
187  V tmp(std::addressof(*first), Vc::Aligned);
188  f(tmp);
189  tmp.store(std::addressof(*first), Vc::Aligned);
190  }
191  for (; len != 0; --len, ++first) {
192  V1 tmp(std::addressof(*first), Vc::Aligned);
193  f(tmp);
194  tmp.store(std::addressof(*first), Vc::Aligned);
195  }
196  return std::move(f);
197 }
198 
199 #ifdef Vc_CXX17
200 template <typename InputIt, typename UnaryFunction>
201 inline enable_if<!std::is_arithmetic<typename InputIt::value_type>::value, UnaryFunction>
202 simd_for_each_n(InputIt first, std::size_t count, UnaryFunction f)
203 {
204  return std::for_each_n(first, count, std::move(f));
205 }
206 #endif
207 
208 } // namespace Vc
209 
210 #endif // VC_COMMON_ALGORITHMS_H_
The main vector class for expressing data parallelism.
Definition: types.h:44
constexpr bool any_of(bool b)
Returns b.
Definition: algorithms.h:57
bool isFull() const
Returns a logical AND of all components.
constexpr bool none_of(bool b)
Returns !b.
Definition: algorithms.h:66
constexpr bool all_of(bool b)
Returns b.
Definition: algorithms.h:48
constexpr AlignedTag Aligned
Use this object for a flags parameter to request aligned loads and stores.
constexpr bool some_of(bool)
Returns false.
Definition: algorithms.h:76
The main SIMD mask class.
Definition: mask.h:41
bool isNotEmpty() const
Returns a logical OR of all components.
constexpr std::size_t MemoryAlignment
Specifies the most conservative memory alignment necessary for aligned loads and stores of Vector typ...
Definition: vector.h:218
bool isEmpty() const
Returns true if components are false, false otherwise.
bool isMix() const
Returns !isFull() && !isEmpty().