<commit_before>/*  This file is part of the Vc library. {{{
Copyright © 2014 <NAME> <<EMAIL>>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the names of contributing organizations nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

}}}*/

#ifndef VC_COMMON_SIMDIZE_H_
#define VC_COMMON_SIMDIZE_H_

#include <tuple>
#include <array>

#include "macros.h"

namespace Vc_VERSIONED_NAMESPACE
{
/**\internal
 * This namespace contains all the required code for implementing simdize<T>. None of this
 * code should be directly accessed by users, though the unit test for simdize<T>
 * certainly may look into some of the details if necessary.
 */
namespace SimdizeDetail
{
using std::is_same;
using std::is_base_of;
using std::false_type;
using std::true_type;
using std::iterator_traits;
using std::conditional;
using std::size_t;

/**\internal
 * Typelist is a simple helper class for supporting multiple parameter packs in one class
 * template.
 */
template <typename... Ts> struct Typelist;

/**\internal
 * The Category identifies how the type argument to simdize<T> has to be transformed.
 */
enum class Category {
    /// No transformation
    None = 0x0,
    /// simple Vector<T> transformation
    ArithmeticVectorizable = 0x1,
    /// transform a forward iterator to return vectorized entries
    ForwardIterator = 0x2,
    /// transform a random access iterator to return vectorized entries
    RandomAccessIterator = 0x6,
    /// transform a class template recursively
    ClassTemplate = 0x8
};

/**\internal
 * iteratorCategories<T>(int()) returns whether iterator_traits<T>::iterator_category is a
 * valid type and whether it is derived from RandomAccessIterator or ForwardIterator.
 */
template <typename T,
          typename ItCat = typename iterator_traits<T>::iterator_category>
constexpr Category iteratorCategories(int)
{
    return is_base_of<std::random_access_iterator_tag, ItCat>::value
               ? Category::RandomAccessIterator
               : is_base_of<std::forward_iterator_tag, ItCat>::value
                     ? Category::ForwardIterator
                     : Category::None;
}
/**\internal
 * This overload is selected if T does not work with iterator_traits.
 */
template <typename T> constexpr Category iteratorCategories(...)
{
    return Category::None;
}

/**\internal
 * Simple trait to identify whether a type T is a class template or not.
 */
template <typename T> struct is_class_template : public false_type
{
};
template <template <typename...> class C, typename... Ts>
struct is_class_template<C<Ts...>> : public true_type
{
};

/**\internal
 * Returns the Category for the given type \p T.
 */
template <typename T> constexpr Category typeCategory()
{
    return (is_same<T, bool>::value || is_same<T, short>::value ||
            is_same<T, unsigned short>::value || is_same<T, int>::value ||
            is_same<T, unsigned int>::value || is_same<T, float>::value ||
            is_same<T, double>::value)
               ? Category::ArithmeticVectorizable
               : iteratorCategories<T>(int()) != Category::None
                     ? iteratorCategories<T>(int())
                     : is_class_template<T>::value ? Category::ClassTemplate
                                                   : Category::None;
}

/**\internal
 * Trait determining the number of data members that get<N>(x) can access.
 * The type \p T either has to provide a std::tuple_size specialization or contain a
 * constexpr tuple_size member.
 */
template <typename T, size_t TupleSize = std::tuple_size<T>::value>
constexpr size_t determine_tuple_size()
{
    return TupleSize;
}
template <typename T, size_t TupleSize = T::tuple_size>
constexpr size_t determine_tuple_size(size_t = T::tuple_size)
{
    return TupleSize;
}

namespace
{
struct Dummy__;
/**\internal
 * Dummy get<N>(x) function to enable compilation of the following code. This code is
 * never meant to be called or used.
 */
template <size_t> Dummy__ get(Dummy__ x);
}  // unnamed namespace

/**\internal
 * The type behind the simdize expression whose member type \c type determines the
 * transformed type.
 *
 * \tparam T The type to be transformed.
 * \tparam N The width the resulting vectorized type should have. A value of 0 lets the
 *           implementation choose the width.
 * \tparam MT The base type to use for mask types. If set to \c void the implementation
 *            chooses the type itself.
 * \tparam Category The type category of \p T. This determines the implementation strategy
 *                  (via template specialization).
 */
template <typename T, size_t N, typename MT, Category = typeCategory<T>()>
struct ReplaceTypes
{
    typedef T type;
};

/**\internal
 * The ReplaceTypes class template is nicer to use as an alias template. This is exported
 * to the outer Vc namespace.
 */
template <typename T, size_t N = 0, typename MT = void>
using simdize = typename SimdizeDetail::ReplaceTypes<T, N, MT>::type;

/**\internal
 * ReplaceTypes specialization for simdizable arithmetic types. This results in either
 * Vector<T> or simdarray<T, N>.
 */
template <typename T, size_t N, typename MT>
struct ReplaceTypes<T, N, MT, Category::ArithmeticVectorizable>
    : public conditional<(N == 0 || Vector<T>::size() == N), Vector<T>, simdarray<T, N>>
{
};

/**\internal
 * ReplaceTypes specialization for bool. This results either in Mask<MT> or
 * simd_mask_array<MT, N>.
 */
template <size_t N, typename MT>
struct ReplaceTypes<bool, N, MT, Category::ArithmeticVectorizable><commit_msg>simdize: only do "no transformation" for Category::None<commit_after>/*  This file is part of the Vc library. {{{
Copyright © 2014 <NAME> <<EMAIL>>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the names of contributing organizations nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

}}}*/

#ifndef VC_COMMON_SIMDIZE_H_
#define VC_COMMON_SIMDIZE_H_

#include <tuple>
#include <array>

#include "macros.h"

namespace Vc_VERSIONED_NAMESPACE
{
/**\internal
 * This namespace contains all the required code for implementing simdize<T>. None of this
 * code should be directly accessed by users, though the unit test for simdize<T>
 * certainly may look into some of the details if necessary.
 */
namespace SimdizeDetail
{
using std::is_same;
using std::is_base_of;
using std::false_type;
using std::true_type;
using std::iterator_traits;
using std::conditional;
using std::size_t;

/**\internal
 * Typelist is a simple helper class for supporting multiple parameter packs in one class
 * template.
 */
template <typename... Ts> struct Typelist;

/**\internal
 * The Category identifies how the type argument to simdize<T> has to be transformed.
 */
enum class Category {
    /// No transformation
    None = 0x0,
    /// simple Vector<T> transformation
    ArithmeticVectorizable = 0x1,
    /// transform a forward iterator to return vectorized entries
    ForwardIterator = 0x2,
    /// transform a random access iterator to return vectorized entries
    RandomAccessIterator = 0x6,
    /// transform a class template recursively
    ClassTemplate = 0x8
};

/**\internal
 * iteratorCategories<T>(int()) returns whether iterator_traits<T>::iterator_category is a
 * valid type and whether it is derived from RandomAccessIterator or ForwardIterator.
 */
template <typename T,
          typename ItCat = typename iterator_traits<T>::iterator_category>
constexpr Category iteratorCategories(int)
{
    return is_base_of<std::random_access_iterator_tag, ItCat>::value
               ? Category::RandomAccessIterator
               : is_base_of<std::forward_iterator_tag, ItCat>::value
                     ? Category::ForwardIterator
                     : Category::None;
}
/**\internal
 * This overload is selected if T does not work with iterator_traits.
 */
template <typename T> constexpr Category iteratorCategories(...)
{
    return Category::None;
}

/**\internal
 * Simple trait to identify whether a type T is a class template or not.
 */
template <typename T> struct is_class_template : public false_type
{
};
template <template <typename...> class C, typename... Ts>
struct is_class_template<C<Ts...>> : public true_type
{
};

/**\internal
 * Returns the Category for the given type \p T.
 */
template <typename T> constexpr Category typeCategory()
{
    return (is_same<T, bool>::value || is_same<T, short>::value ||
            is_same<T, unsigned short>::value || is_same<T, int>::value ||
            is_same<T, unsigned int>::value || is_same<T, float>::value ||
            is_same<T, double>::value)
               ? Category::ArithmeticVectorizable
               : iteratorCategories<T>(int()) != Category::None
                     ? iteratorCategories<T>(int())
                     : is_class_template<T>::value ? Category::ClassTemplate
                                                   : Category::None;
}

/**\internal
 * Trait determining the number of data members that get<N>(x) can access.
 * The type \p T either has to provide a std::tuple_size specialization or contain a
 * constexpr tuple_size member.
 */
template <typename T, size_t TupleSize = std::tuple_size<T>::value>
constexpr size_t determine_tuple_size()
{
    return TupleSize;
}
template <typename T, size_t TupleSize = T::tuple_size>
constexpr size_t determine_tuple_size(size_t = T::tuple_size)
{
    return TupleSize;
}

namespace
{
struct Dummy__;
/**\internal
 * Dummy get<N>(x) function to enable compilation of the following code. This code is
 * never meant to be called or used.
 */
template <size_t> Dummy__ get(Dummy__ x);
template <typename T> struct The_simdization_for_the_requested_type_is_not_implemented;
}  // unnamed namespace

/**\internal
 * The type behind the simdize expression whose member type \c type determines the
 * transformed type.
 *
 * \tparam T The type to be transformed.
 * \tparam N The width the resulting vectorized type should have. A value of 0 lets the
 *           implementation choose the width.
 * \tparam MT The base type to use for mask types. If set to \c void the implementation
 *            chooses the type itself.
 * \tparam Category The type category of \p T. This determines the implementation strategy
 *                  (via template specialization).
 */
template <typename T, size_t N, typename MT, Category = typeCategory<T>()>
struct ReplaceTypes : public The_simdization_for_the_requested_type_is_not_implemented<T>
{
};

/**\internal
 * Specialization of ReplaceTypes that is used for types that should not be transformed by
 * simdize.
 */
template <typename T, size_t N, typename MT> struct ReplaceTypes<T, N, MT, Category::None>
{
    typedef T type;
};

/**\internal
 * The ReplaceTypes class template is nicer to use as an alias template. This is exported
 * to the outer Vc namespace.
 */
template <typename T, size_t N = 0, typename MT = void>
using simdize = typename SimdizeDetail::ReplaceTypes<T, N, MT>::type;

/**\internal
 * ReplaceTypes specialization for simdizable arithmetic types. This results in either
 * Vector<T> or simdarray<T, N>.
 */
template <typename T, size_t N, typename MT>
struct ReplaceTypes<T, N, MT, Category::ArithmeticVectorizable>
    : public conditional<(N == 0 || Vector<T>::size() == N), Vector<T>, simdarray<T, N>>
{
};

/**\internal
 * ReplaceTypes specialization for bool. This results either in Mask<MT> or
 * simd_mask_array<MT, N>.
 */
template <size_t N, typename MT>
struct ReplaceTypes<bool, N, MT, Category::ArithmeticVectorizable>
{'fraction_non_alphanumeric': 0.0870057296456108, 'fraction_numerical': 0.0024050364292282664, 'mean_word_length': 3.776351351351351, 'pattern_counts': {'":': 0, '<': 119, '<?xml version=': 0, '>': 119, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4962680', 'n_tokens_mistral': 3948, 'n_tokens_neox': 3718, 'n_words': 1572}