Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:25:47

0001 /*  This file is part of the Vc library. {{{
0002 Copyright © 2013-2015 Matthias Kretz <kretz@kde.org>
0003 
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006     * Redistributions of source code must retain the above copyright
0007       notice, this list of conditions and the following disclaimer.
0008     * Redistributions in binary form must reproduce the above copyright
0009       notice, this list of conditions and the following disclaimer in the
0010       documentation and/or other materials provided with the distribution.
0011     * Neither the names of contributing organizations nor the
0012       names of its contributors may be used to endorse or promote products
0013       derived from this software without specific prior written permission.
0014 
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025 
0026 }}}*/
0027 
0028 #ifndef VC_COMMON_MAKECONTAINER_H_
0029 #define VC_COMMON_MAKECONTAINER_H_
0030 
0031 #include "../vector.h"
0032 #include <initializer_list>
0033 
0034 namespace Vc_VERSIONED_NAMESPACE
0035 {
0036 
0037     namespace
0038     {
0039         template<typename Container, typename T> struct make_container_helper
0040         {
0041             static constexpr Container help(std::initializer_list<T> list) { return { list }; }
0042         };
0043 
0044         template <typename T_, typename Abi, typename Alloc,
0045                   template <class, class> class Container>
0046         struct make_container_helper<Container<Vector<T_, Abi>, Alloc>,
0047                                      typename Vector<T_, Abi>::EntryType> {
0048             typedef Vector<T_, Abi> V;
0049             typedef typename V::EntryType T;
0050             typedef Container<V, Alloc> C;
0051             static inline C help(std::initializer_list<T> list) {
0052                 const std::size_t size = (list.size() + (V::Size - 1)) / V::Size;
0053                 C v(size);
0054                 auto containerIt = v.begin();
0055                 auto init = std::begin(list);
0056                 const auto initEnd = std::end(list);
0057                 for (std::size_t i = 0; i < size - 1; ++i) {
0058                     *containerIt++ = V(init, Vc::Unaligned);
0059                     init += V::Size;
0060                 }
0061                 Vc_ASSERT(all_of(*containerIt == V::Zero()));
0062                 int j = 0;
0063                 while (init != initEnd) {
0064                     (*containerIt)[j++] = *init++;
0065                 }
0066                 return v;
0067             }
0068         };
0069 
0070         template <typename T_, typename Abi, std::size_t N,
0071                   template <class, std::size_t> class Container>
0072         struct make_container_helper<Container<Vector<T_, Abi>, N>,
0073                                      typename Vector<T_, Abi>::EntryType> {
0074             typedef Vector<T_, Abi> V;
0075             typedef typename V::EntryType T;
0076             static constexpr std::size_t size = (N + (V::Size - 1)) / V::Size;
0077             typedef Container<
0078                 V,
0079 #if defined Vc_CLANG && Vc_CLANG < 0x30700 // TODO: when did Vc_APPLECLANG fix it?
0080                 // clang before 3.7.0 has a bug when returning std::array<__m256x, 1>. So
0081                 // increase it to std::array<__m256x, 2> and fill it with zeros. Better
0082                 // than returning garbage.
0083                 (size == 1 && std::is_same<Abi, VectorAbi::Avx>::value) ? 2 :
0084 #endif
0085                                                                         size> C;
0086             static inline C help(std::initializer_list<T> list) {
0087                 Vc_ASSERT(N == list.size())
0088                 Vc_ASSERT(size == (list.size() + (V::Size - 1)) / V::Size)
0089                 C v;
0090                 auto containerIt = v.begin();
0091                 auto init = std::begin(list);
0092                 const auto initEnd = std::end(list);
0093                 for (std::size_t i = 0; i < size - 1; ++i) {
0094                     *containerIt++ = V(init, Vc::Unaligned);
0095                     init += V::Size;
0096                 }
0097                 Vc_ASSERT(all_of(*containerIt == V::Zero()));
0098                 int j = 0;
0099                 while (init != initEnd) {
0100                     (*containerIt)[j++] = *init++;
0101                 }
0102                 return v;
0103             }
0104         };
0105     } // anonymous namespace
0106 
0107     /**
0108      * \ingroup Containers
0109      * \headerfile makeContainer.h <Vc/Utils>
0110      *
0111      * Construct a container of Vc vectors from a std::initializer_list of scalar entries.
0112      *
0113      * \tparam Container The container type to construct.
0114      * \tparam T The scalar type to use for the initializer_list.
0115      *
0116      * \param list An initializer list of arbitrary size. The type of the entries is important!
0117      * If you pass a list of integers you will get a container filled with Vc::int_v objects.
0118      * If, instead, you want to have a container of Vc::float_v objects, be sure the include a
0119      * period (.) and the 'f' postfix in the literals. Alternatively, you can pass the
0120      * type as second template argument to makeContainer.
0121      *
0122      * \return Returns a container of the requested class filled with the minimum number of SIMD
0123      * vectors to hold the values in the initializer list.
0124      * If the number of values in \p list does not match the number of values in the
0125      * returned container object, the remaining values in the returned object will be
0126      * zero-initialized.
0127      *
0128      * Example:
0129      * \code
0130      * auto data = Vc::makeContainer<std::vector<float_v>>({ 1.f, 2.f, 3.f, 4.f, 5.f });
0131      * // data.size() == 5 if float_v::Size == 1 (i.e. Vc_IMPL=Scalar)
0132      * // data.size() == 2 if float_v::Size == 4 (i.e. Vc_IMPL=SSE)
0133      * // data.size() == 1 if float_v::Size == 8 (i.e. Vc_IMPL=AVX)
0134      * \endcode
0135      */
0136     template<typename Container, typename T>
0137     constexpr auto makeContainer(std::initializer_list<T> list) -> decltype(make_container_helper<Container, T>::help(list))
0138     {
0139         return make_container_helper<Container, T>::help(list);
0140     }
0141 
0142     template<typename Container, typename T>
0143     constexpr auto make_container(std::initializer_list<T> list) -> decltype(makeContainer<Container, T>(list))
0144     {
0145         return makeContainer<Container, T>(list);
0146     }
0147 
0148 }  // namespace Vc
0149 
0150 #endif // VC_COMMON_MAKECONTAINER_H_