summaryrefslogtreecommitdiffstats
path: root/third_party/xsimd/include/xsimd/types/xsimd_neon_register.hpp
blob: 0ef4b381d3687cba09e4ac1e91284bead39f1a8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/***************************************************************************
 * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *
 * Martin Renou                                                             *
 * Copyright (c) QuantStack                                                 *
 * Copyright (c) Serge Guelton                                              *
 *                                                                          *
 * Distributed under the terms of the BSD 3-Clause License.                 *
 *                                                                          *
 * The full license is in the file LICENSE, distributed with this software. *
 ****************************************************************************/

#ifndef XSIMD_NEON_REGISTER_HPP
#define XSIMD_NEON_REGISTER_HPP

#include "xsimd_generic_arch.hpp"
#include "xsimd_register.hpp"

#if XSIMD_WITH_NEON
#include <arm_neon.h>
#endif

namespace xsimd
{
    /**
     * @ingroup architectures
     *
     * NEON instructions for arm32
     */
    struct neon : generic
    {
        static constexpr bool supported() noexcept { return XSIMD_WITH_NEON; }
        static constexpr bool available() noexcept { return true; }
        static constexpr bool requires_alignment() noexcept { return true; }
        static constexpr std::size_t alignment() noexcept { return 16; }
        static constexpr unsigned version() noexcept { return generic::version(7, 0, 0); }
        static constexpr char const* name() noexcept { return "arm32+neon"; }
    };

#if XSIMD_WITH_NEON
    namespace types
    {
        namespace detail
        {
            template <size_t S>
            struct neon_vector_type_impl;

            template <>
            struct neon_vector_type_impl<8>
            {
                using signed_type = int8x16_t;
                using unsigned_type = uint8x16_t;
            };

            template <>
            struct neon_vector_type_impl<16>
            {
                using signed_type = int16x8_t;
                using unsigned_type = uint16x8_t;
            };

            template <>
            struct neon_vector_type_impl<32>
            {
                using signed_type = int32x4_t;
                using unsigned_type = uint32x4_t;
            };

            template <>
            struct neon_vector_type_impl<64>
            {
                using signed_type = int64x2_t;
                using unsigned_type = uint64x2_t;
            };

            template <class T>
            using signed_neon_vector_type = typename neon_vector_type_impl<8 * sizeof(T)>::signed_type;

            template <class T>
            using unsigned_neon_vector_type = typename neon_vector_type_impl<8 * sizeof(T)>::unsigned_type;

            template <class T>
            using neon_vector_type = typename std::conditional<std::is_signed<T>::value,
                                                               signed_neon_vector_type<T>,
                                                               unsigned_neon_vector_type<T>>::type;

            using char_neon_vector_type = typename std::conditional<std::is_signed<char>::value,
                                                                    signed_neon_vector_type<char>,
                                                                    unsigned_neon_vector_type<char>>::type;
        }

        XSIMD_DECLARE_SIMD_REGISTER(signed char, neon, detail::neon_vector_type<signed char>);
        XSIMD_DECLARE_SIMD_REGISTER(unsigned char, neon, detail::neon_vector_type<unsigned char>);
        XSIMD_DECLARE_SIMD_REGISTER(char, neon, detail::char_neon_vector_type);
        XSIMD_DECLARE_SIMD_REGISTER(short, neon, detail::neon_vector_type<short>);
        XSIMD_DECLARE_SIMD_REGISTER(unsigned short, neon, detail::neon_vector_type<unsigned short>);
        XSIMD_DECLARE_SIMD_REGISTER(int, neon, detail::neon_vector_type<int>);
        XSIMD_DECLARE_SIMD_REGISTER(unsigned int, neon, detail::neon_vector_type<unsigned int>);
        XSIMD_DECLARE_SIMD_REGISTER(long int, neon, detail::neon_vector_type<long int>);
        XSIMD_DECLARE_SIMD_REGISTER(unsigned long int, neon, detail::neon_vector_type<unsigned long int>);
        XSIMD_DECLARE_SIMD_REGISTER(long long int, neon, detail::neon_vector_type<long long int>);
        XSIMD_DECLARE_SIMD_REGISTER(unsigned long long int, neon, detail::neon_vector_type<unsigned long long int>);
        XSIMD_DECLARE_SIMD_REGISTER(float, neon, float32x4_t);
        XSIMD_DECLARE_INVALID_SIMD_REGISTER(double, neon);

        namespace detail
        {
            template <size_t S>
            struct get_unsigned_type;

            template <>
            struct get_unsigned_type<1>
            {
                using type = uint8_t;
            };

            template <>
            struct get_unsigned_type<2>
            {
                using type = uint16_t;
            };

            template <>
            struct get_unsigned_type<4>
            {
                using type = uint32_t;
            };

            template <>
            struct get_unsigned_type<8>
            {
                using type = uint64_t;
            };

            template <size_t S>
            using get_unsigned_type_t = typename get_unsigned_type<S>::type;

            template <class T, class A>
            struct neon_bool_simd_register
            {
                using type = simd_register<get_unsigned_type_t<sizeof(T)>, A>;
            };
        }

        template <class T>
        struct get_bool_simd_register<T, neon>
            : detail::neon_bool_simd_register<T, neon>
        {
        };

    }
#endif

}

#endif