<commit_before>#ifndef VC_ICC
// ICC ICEs if the following type-traits are in the anonymous namespace
namespace
{
#endif

template <bool C, typename T, typename F>
using Conditional = typename std::conditional<C, T, F>::type;

template <typename T> using Decay = typename std::decay<T>::type;

using std::is_convertible;
using std::is_floating_point;
using std::is_integral;
using std::is_same;

template <typename T> struct IsUnsignedInternal : public std::is_unsigned<T> {};
template <typename T> struct IsUnsignedInternal<Vector<T>> : public std::is_unsigned<T> {};
template <typename T> constexpr bool isUnsigned() { return !std::is_same<Decay<T>, bool>::value && IsUnsignedInternal<Decay<T>>::value; }

template <typename T> struct IsIntegralInternal : public std::is_integral<T> {};
template <typename T> struct IsIntegralInternal<Vector<T>> : public std::is_integral<T> {};
template <typename T> constexpr bool isIntegral() { return IsIntegralInternal<Decay<T>>::value; }

template <typename T> struct IsVectorInternal             { static constexpr bool value = false; };
template <typename T> struct IsVectorInternal<Vector<T> > { static constexpr bool value =  true; };
template <typename T> constexpr bool isVector() { return IsVectorInternal<Decay<T>>::value; }

template <typename T, bool = isIntegral<T>()> struct MakeUnsignedInternal;
template <typename T> struct MakeUnsignedInternal<Vector<T>, true > { using type = Vector<typename std::make_unsigned<T>::type>; };
template <typename T> struct MakeUnsignedInternal<Vector<T>, false> { using type = Vector<T>; };

template <typename Test, typename T>
using CopyUnsigned = typename MakeUnsignedInternal<T, isIntegral<T>() && isUnsigned<Test>()>::type;

/* § 8.5.4 p7:
 * A narrowing conversion is an implicit conversion
 * — from a floating-point type to an integer type, or
 * — from long double to double or float, or from double to float, except where the source is a constant
 *   expression and the actual value after conversion is within the range of values that can be represented
 *   (even if it cannot be represented exactly), or
 * — from an integer type or unscoped enumeration type to a floating-point type, except where the source
 *   is a constant expression and the actual value after conversion will fit into the target type and will
 *   produce the original value when converted back to the original type, or
 * — from an integer type or unscoped enumeration type to an integer type that cannot represent all the
 *   values of the original type, except where the source is a constant expression and the actual value after
 *   conversion will fit into the target type and will produce the original value when converted back to the
 *   original type.
 */
template <typename From, typename To> constexpr bool isNarrowingFloatConversion()
{
    return is_floating_point<From>::value &&
           (is_integral<To>::value || (is_floating_point<To>::value && sizeof(From) > sizeof(To)));
}

static_assert(isNarrowingFloatConversion<double, float>(), "");
static_assert(isNarrowingFloatConversion<long double, float>(), "");
static_assert(isNarrowingFloatConversion<long double, double>(), "");
static_assert(is_convertible<double, float_v>::value, "");
static_assert(false == ((is_convertible<double, float_v>::value ||
                         (isVector<double>() && is_convertible<float_v, double>::value)) &&
                        !isNarrowingFloatConversion<double, float_v::EntryType>()),
              "");

template <typename V, typename W>
using DetermineReturnType =
    Conditional<(is_same<V, int_v>::value || is_same<V, uint_v>::value) &&
                    (is_same<W, float>::value || is_same<W, float_v>::value),
                float_v,
                CopyUnsigned<W, V>>;

template <typename V, typename W, bool VectorOperation> struct TypesForOperatorInternal
{
};

template <typename V, typename W> struct TypesForOperatorInternal<V, W, true>
{
    using type = DetermineReturnType<V, W>;

    // meaningful compiler error when incompatible operands are used:
    static_assert(isVector<W>() ? (is_convertible<V, W>::value || is_convertible<W, V>::value)
                                : (is_convertible<W, type>::value &&
                                   !isNarrowingFloatConversion<W, typename type::EntryType>()),
                  "invalid operands to binary expression. Vc does not allow operands that could "
                  "possibly have different Vector::Size.");
};

template <typename L, typename R>
using TypesForOperator = typename TypesForOperatorInternal<
    Decay<Conditional<isVector<L>(), L, R>>,
    Decay<Conditional<!isVector<L>(), L, R>>,
    (isVector<L>() || isVector<R>()) &&      // one operand has to be a vector
        !is_same<Decay<L>, Decay<R>>::value  // if they're the same type it's already covered by
                                             // Vector::operatorX
    >::type;

#ifndef VC_ICC
}
#endif

#define VC_GENERIC_OPERATOR(op)                                                                    \
    template <typename L, typename R>                                                              \<commit_msg>ensure that the second operand also can somehow become a SIMD vector type<commit_after>#ifndef VC_ICC
// ICC ICEs if the following type-traits are in the anonymous namespace
namespace
{
#endif

template <bool C, typename T, typename F>
using Conditional = typename std::conditional<C, T, F>::type;

template <typename T> using Decay = typename std::decay<T>::type;

using std::is_convertible;
using std::is_floating_point;
using std::is_integral;
using std::is_same;

template <typename T> struct IsUnsignedInternal : public std::is_unsigned<T> {};
template <typename T> struct IsUnsignedInternal<Vector<T>> : public std::is_unsigned<T> {};
template <typename T> constexpr bool isUnsigned() { return !std::is_same<Decay<T>, bool>::value && IsUnsignedInternal<Decay<T>>::value; }

template <typename T> struct IsIntegralInternal : public std::is_integral<T> {};
template <typename T> struct IsIntegralInternal<Vector<T>> : public std::is_integral<T> {};
template <typename T> constexpr bool isIntegral() { return IsIntegralInternal<Decay<T>>::value; }

template <typename T> struct IsVectorInternal             { static constexpr bool value = false; };
template <typename T> struct IsVectorInternal<Vector<T> > { static constexpr bool value =  true; };
template <typename T> constexpr bool isVector() { return IsVectorInternal<Decay<T>>::value; }

template <typename T, bool = isIntegral<T>()> struct MakeUnsignedInternal;
template <typename T> struct MakeUnsignedInternal<Vector<T>, true > { using type = Vector<typename std::make_unsigned<T>::type>; };
template <typename T> struct MakeUnsignedInternal<Vector<T>, false> { using type = Vector<T>; };

template <typename Test, typename T>
using CopyUnsigned = typename MakeUnsignedInternal<T, isIntegral<T>() && isUnsigned<Test>()>::type;

/* § 8.5.4 p7:
 * A narrowing conversion is an implicit conversion
 * — from a floating-point type to an integer type, or
 * — from long double to double or float, or from double to float, except where the source is a constant
 *   expression and the actual value after conversion is within the range of values that can be represented
 *   (even if it cannot be represented exactly), or
 * — from an integer type or unscoped enumeration type to a floating-point type, except where the source
 *   is a constant expression and the actual value after conversion will fit into the target type and will
 *   produce the original value when converted back to the original type, or
 * — from an integer type or unscoped enumeration type to an integer type that cannot represent all the
 *   values of the original type, except where the source is a constant expression and the actual value after
 *   conversion will fit into the target type and will produce the original value when converted back to the
 *   original type.
 */
template <typename From, typename To> constexpr bool isNarrowingFloatConversion()
{
    return is_floating_point<From>::value &&
           (is_integral<To>::value || (is_floating_point<To>::value && sizeof(From) > sizeof(To)));
}

template <typename T> static constexpr bool convertsToSomeVector()
{
    return is_convertible<T, double_v>::value || is_convertible<T, float_v>::value ||
           is_convertible<T, int_v>::value || is_convertible<T, uint_v>::value ||
           is_convertible<T, short_v>::value || is_convertible<T, ushort_v>::value;
}

static_assert(isNarrowingFloatConversion<double, float>(), "");
static_assert(isNarrowingFloatConversion<long double, float>(), "");
static_assert(isNarrowingFloatConversion<long double, double>(), "");
static_assert(is_convertible<double, float_v>::value, "");
static_assert(false == ((is_convertible<double, float_v>::value ||
                         (isVector<double>() && is_convertible<float_v, double>::value)) &&
                        !isNarrowingFloatConversion<double, float_v::EntryType>()),
              "");

template <typename V, typename W>
using DetermineReturnType =
    Conditional<(is_same<V, int_v>::value || is_same<V, uint_v>::value) &&
                    (is_same<W, float>::value || is_same<W, float_v>::value),
                float_v,
                CopyUnsigned<W, V>>;

template <
    typename V,
    typename W,
    bool VectorOperation = isVector<V>() &&           // one operand has to be a vector
                           !is_same<V, W>::value &&   // if they're the same type it's already
                                                      // covered by Vector::operatorX
                           convertsToSomeVector<W>()  // if the other operand is not convertible to
                                                      // a SIMD vector type at all then don't use
                                                      // our operator in overload resolution at all
    >
struct TypesForOperatorInternal
{
};

template <typename V, typename W> struct TypesForOperatorInternal<V, W, true>
{
    using type = DetermineReturnType<V, W>;

    // meaningful compiler error when incompatible operands are used:
    static_assert(isVector<W>() ? (is_convertible<V, W>::value || is_convertible<W, V>::value)
                                : (is_convertible<W, type>::value &&
                                   !isNarrowingFloatConversion<W, typename type::EntryType>()),
                  "invalid operands to binary expression. Vc does not allow operands that could "
                  "possibly have different Vector::Size.");
};

template <typename L, typename R>
using TypesForOperator =
    typename TypesForOperatorInternal<Decay<Conditional< isVector<L>(), L, R>>,
                                      Decay<Conditional<!isVector<L>(), L, R>>>::type;

#ifndef VC_ICC
}
#endif

#define VC_GENERIC_OPERATOR(op)                                                                    \
    template <typename L, typename R>                                                              \
{'fraction_non_alphanumeric': 0.1082986801663352, 'fraction_numerical': 0.0007231965286566625, 'mean_word_length': 3.407569721115538, 'pattern_counts': {'":': 0, '<': 184, '<?xml version=': 0, '>': 186, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 21, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4288524', 'n_tokens_mistral': 3020, 'n_tokens_neox': 2911, 'n_words': 1009}