<commit_before>/***************************************************************************
 * Copyright (c) <NAME>, <NAME>, <NAME> and         *
 * <NAME>                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) <NAME>                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#include <numeric>
#include <random>

#include "test_utils.hpp"

static_assert(xsimd::default_arch::supported(), "default arch must be supported");
static_assert(xsimd::supported_architectures::contains<xsimd::default_arch>(), "default arch is supported");
static_assert(xsimd::all_architectures::contains<xsimd::default_arch>(), "default arch is a valid arch");
// static_assert(!(xsimd::x86_arch::supported() && xsimd::arm::supported()), "either x86 or arm, but not both");

struct check_supported
{
    template <class Arch>
    void operator()(Arch) const
    {
        static_assert(Arch::supported(), "not supported?");
    }
};

TEST(arch, supported)
{
    xsimd::supported_architectures::for_each(check_supported {});
}

TEST(arch, name)
{
    constexpr char const* name = xsimd::default_arch::name();
    (void)name;
}

struct check_available
{
    template <class Arch>
    void operator()(Arch) const
    {
        EXPECT_TRUE(Arch::available());
    }
};

TEST(arch, available)
{
    EXPECT_TRUE(xsimd::default_arch::available());
}

struct sum
{
    template <class Arch, class T>
    T operator()(Arch, T const* data, unsigned size)
    {
        using batch = xsimd::batch<T, Arch>;
        batch acc(static_cast<T>(0));
        const unsigned n = size / batch::size * batch::size;
        for (unsigned i = 0; i != n; i += batch::size)
            acc += batch::load_unaligned(data + i);
        T star_acc = xsimd::hadd(acc);
        for (unsigned i = n; i < size; ++i)
            star_acc += data[i];
        return star_acc;
    }
};

TEST(arch, dispatcher)
{
    float data[17] = { 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f, 17.f };
    float ref = std::accumulate(std::begin(data), std::end(data), 0.f);

    // platform specific
    {
        auto dispatched = xsimd::dispatch(sum {});
        float res = dispatched(data, 17);
        EXPECT_EQ(ref, res);
    }

#if XSIMD_WITH_AVX && XSIMD_WITH_SSE2
    static_assert(xsimd::supported_architectures::contains<xsimd::avx>() && xsimd::supported_architectures::contains<xsimd::sse2>(), "consistent supported architectures");
    {
        auto dispatched = xsimd::dispatch<sum, xsimd::arch_list<xsimd::avx, xsimd::sse2>>(sum {});
        float res = dispatched(data, 17);
        EXPECT_EQ(ref, res);
    }
#endif
}

template <class T>
static bool try_load()
{
    static_assert(std::is_same<xsimd::batch<T>, decltype(xsimd::load_aligned(std::declval<T*>()))>::value,
                  "loading the expected type");
    static_assert(std::is_same<xsimd::batch<T>, decltype(xsimd::load_unaligned(std::declval<T*>()))>::value,
                  "loading the expected type");
    return true;
}

template <class... Tys><commit_msg>add test for selected architecture<commit_after>/***************************************************************************
 * Copyright (c) <NAME>, <NAME>, <NAME>cht and         *
 * <NAME>                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) <NAME>                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#include <numeric>
#include <random>

#include "test_utils.hpp"

static_assert(xsimd::default_arch::supported(), "default arch must be supported");
static_assert(xsimd::supported_architectures::contains<xsimd::default_arch>(), "default arch is supported");
static_assert(xsimd::all_architectures::contains<xsimd::default_arch>(), "default arch is a valid arch");
// static_assert(!(xsimd::x86_arch::supported() && xsimd::arm::supported()), "either x86 or arm, but not both");

struct check_supported
{
    template <class Arch>
    void operator()(Arch) const
    {
        static_assert(Arch::supported(), "not supported?");
    }
};

TEST(arch, supported)
{
    xsimd::supported_architectures::for_each(check_supported {});
}

TEST(arch, name)
{
    constexpr char const* name = xsimd::default_arch::name();
    (void)name;
}

struct check_available
{
    template <class Arch>
    void operator()(Arch) const
    {
        EXPECT_TRUE(Arch::available());
    }
};

TEST(arch, available)
{
    EXPECT_TRUE(xsimd::default_arch::available());
}

struct sum
{
    template <class Arch, class T>
    T operator()(Arch, T const* data, unsigned size)
    {
        using batch = xsimd::batch<T, Arch>;
        batch acc(static_cast<T>(0));
        const unsigned n = size / batch::size * batch::size;
        for (unsigned i = 0; i != n; i += batch::size)
            acc += batch::load_unaligned(data + i);
        T star_acc = xsimd::hadd(acc);
        for (unsigned i = n; i < size; ++i)
            star_acc += data[i];
        return star_acc;
    }
};

struct get_arch_version
{
    template <class Arch>
    unsigned operator()(Arch) { return Arch::version(); }
};

TEST(arch, dispatcher)
{
    float data[17] = { 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f, 16.f, 17.f };
    float ref = std::accumulate(std::begin(data), std::end(data), 0.f);

    // platform specific
    {
        auto dispatched = xsimd::dispatch(sum {});
        float res = dispatched(data, 17);
        EXPECT_EQ(ref, res);
    }

#if XSIMD_WITH_AVX && XSIMD_WITH_SSE2
    static_assert(xsimd::supported_architectures::contains<xsimd::avx>() && xsimd::supported_architectures::contains<xsimd::sse2>(), "consistent supported architectures");
    {
        auto dispatched = xsimd::dispatch<sum, xsimd::arch_list<xsimd::avx, xsimd::sse2>>(sum {});
        float res = dispatched(data, 17);
        EXPECT_EQ(ref, res);
    }

    // check that we pick the most appropriate version
    {
        auto dispatched = xsimd::dispatch<get_arch_version,
                                          xsimd::arch_list<xsimd::sse3, xsimd::sse2>>(get_arch_version {});
        unsigned expected = xsimd::available_architectures().best >= xsimd::sse3::version()
            ? xsimd::sse3::version()
            : xsimd::sse2::version();
        EXPECT_EQ(expected, dispatched());
    }
#endif
}

template <class T>
static bool try_load()
{
    static_assert(std::is_same<xsimd::batch<T>, decltype(xsimd::load_aligned(std::declval<T*>()))>::value,
                  "loading the expected type");
    static_assert(std::is_same<xsimd::batch<T>, decltype(xsimd::load_unaligned(std::declval<T*>()))>::value,
                  "loading the expected type");
    return true;
}

template <class... Tys>
{'fraction_non_alphanumeric': 0.18168642951251646, 'fraction_numerical': 0.011725955204216074, 'mean_word_length': 2.6061757719714964, 'pattern_counts': {'":': 0, '<': 60, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6156959', 'n_tokens_mistral': 2374, 'n_tokens_neox': 2261, 'n_words': 499}