1 /****************************************************************************
2  * Copyright (C) 2017 Intel Corporation.   All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  ****************************************************************************/
23 #pragma once
24 
25 #include "simdlib_types.hpp"
26 
27 // For documentation, please see the following include...
28 // #include "simdlib_interface.hpp"
29 
30 namespace SIMDImpl
31 {
32     namespace SIMD128Impl
33     {
34 #if SIMD_ARCH >= SIMD_ARCH_AVX
35         struct AVXImpl
36         {
37 #define __SIMD_LIB_AVX_HPP__
38 #include "simdlib_128_avx.inl"
39 #undef __SIMD_LIB_AVX_HPP__
40         }; // struct AVXImpl
41 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX
42 
43 #if SIMD_ARCH >= SIMD_ARCH_AVX2
44         struct AVX2Impl : AVXImpl
45         {
46 #define __SIMD_LIB_AVX2_HPP__
47 #include "simdlib_128_avx2.inl"
48 #undef __SIMD_LIB_AVX2_HPP__
49         }; // struct AVX2Impl
50 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX2
51 
52 #if SIMD_ARCH >= SIMD_ARCH_AVX512
53         struct AVX512Impl : AVX2Impl
54         {
55 #if defined(SIMD_OPT_128_AVX512)
56 #define __SIMD_LIB_AVX512_HPP__
57 #include "simdlib_128_avx512.inl"
58 #if defined(SIMD_ARCH_KNIGHTS)
59 #include "simdlib_128_avx512_knights.inl"
60 #else // optimize for core
61 #include "simdlib_128_avx512_core.inl"
62 #endif // defined(SIMD_ARCH_KNIGHTS)
63 #undef __SIMD_LIB_AVX512_HPP__
64 #endif     // SIMD_OPT_128_AVX512
65         }; // struct AVX2Impl
66 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX512
67 
68         struct Traits : SIMDImpl::Traits
69         {
70 #if SIMD_ARCH == SIMD_ARCH_AVX
71             using IsaImpl = AVXImpl;
72 #elif SIMD_ARCH == SIMD_ARCH_AVX2
73             using IsaImpl = AVX2Impl;
74 #elif SIMD_ARCH == SIMD_ARCH_AVX512
75             using IsaImpl = AVX512Impl;
76 #else
77 #error Invalid value for SIMD_ARCH
78 #endif
79 
80             using Float   = SIMD128Impl::Float;
81             using Double  = SIMD128Impl::Double;
82             using Integer = SIMD128Impl::Integer;
83             using Vec4    = SIMD128Impl::Vec4;
84             using Mask    = SIMD128Impl::Mask;
85         };
86     } // namespace SIMD128Impl
87 
88     namespace SIMD256Impl
89     {
90 #if SIMD_ARCH >= SIMD_ARCH_AVX
91         struct AVXImpl
92         {
93 #define __SIMD_LIB_AVX_HPP__
94 #include "simdlib_256_avx.inl"
95 #undef __SIMD_LIB_AVX_HPP__
96         }; // struct AVXImpl
97 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX
98 
99 #if SIMD_ARCH >= SIMD_ARCH_AVX2
100         struct AVX2Impl : AVXImpl
101         {
102 #define __SIMD_LIB_AVX2_HPP__
103 #include "simdlib_256_avx2.inl"
104 #undef __SIMD_LIB_AVX2_HPP__
105         }; // struct AVX2Impl
106 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX2
107 
108 #if SIMD_ARCH >= SIMD_ARCH_AVX512
109         struct AVX512Impl : AVX2Impl
110         {
111 #if defined(SIMD_OPT_256_AVX512)
112 #define __SIMD_LIB_AVX512_HPP__
113 #include "simdlib_256_avx512.inl"
114 #if defined(SIMD_ARCH_KNIGHTS)
115 #include "simdlib_256_avx512_knights.inl"
116 #else // optimize for core
117 #include "simdlib_256_avx512_core.inl"
118 #endif // defined(SIMD_ARCH_KNIGHTS)
119 #undef __SIMD_LIB_AVX512_HPP__
120 #endif     // SIMD_OPT_256_AVX512
121         }; // struct AVX2Impl
122 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX512
123 
124         struct Traits : SIMDImpl::Traits
125         {
126 #if SIMD_ARCH == SIMD_ARCH_AVX
127             using IsaImpl = AVXImpl;
128 #elif SIMD_ARCH == SIMD_ARCH_AVX2
129             using IsaImpl = AVX2Impl;
130 #elif SIMD_ARCH == SIMD_ARCH_AVX512
131             using IsaImpl = AVX512Impl;
132 #else
133 #error Invalid value for SIMD_ARCH
134 #endif
135 
136             using Float   = SIMD256Impl::Float;
137             using Double  = SIMD256Impl::Double;
138             using Integer = SIMD256Impl::Integer;
139             using Vec4    = SIMD256Impl::Vec4;
140             using Mask    = SIMD256Impl::Mask;
141         };
142     } // namespace SIMD256Impl
143 
144     namespace SIMD512Impl
145     {
146 #if SIMD_ARCH >= SIMD_ARCH_AVX
147         template <typename SIMD256T>
148         struct AVXImplBase
149         {
150 #define __SIMD_LIB_AVX_HPP__
151 #include "simdlib_512_emu.inl"
152 #include "simdlib_512_emu_masks.inl"
153 #undef __SIMD_LIB_AVX_HPP__
154         }; // struct AVXImplBase
155         using AVXImpl = AVXImplBase<SIMD256Impl::AVXImpl>;
156 #endif // #if SIMD_ARCH >= SIMD_ARCH_AVX
157 
158 #if SIMD_ARCH >= SIMD_ARCH_AVX2
159         using AVX2Impl = AVXImplBase<SIMD256Impl::AVX2Impl>;
160 #endif // #if SIMD_ARCH >= SIMD_ARCH_AVX2
161 
162 #if SIMD_ARCH >= SIMD_ARCH_AVX512
163         struct AVX512Impl : AVXImplBase<SIMD256Impl::AVX512Impl>
164         {
165 #define __SIMD_LIB_AVX512_HPP__
166 #include "simdlib_512_avx512.inl"
167 #include "simdlib_512_avx512_masks.inl"
168 #if defined(SIMD_ARCH_KNIGHTS)
169 #include "simdlib_512_avx512_knights.inl"
170 #include "simdlib_512_avx512_masks_knights.inl"
171 #else // optimize for core
172 #include "simdlib_512_avx512_core.inl"
173 #include "simdlib_512_avx512_masks_core.inl"
174 #endif // defined(SIMD_ARCH_KNIGHTS)
175 #undef __SIMD_LIB_AVX512_HPP__
176         }; // struct AVX512ImplBase
177 #endif     // #if SIMD_ARCH >= SIMD_ARCH_AVX512
178 
179         struct Traits : SIMDImpl::Traits
180         {
181 #if SIMD_ARCH == SIMD_ARCH_AVX
182             using IsaImpl = AVXImpl;
183 #elif SIMD_ARCH == SIMD_ARCH_AVX2
184             using IsaImpl = AVX2Impl;
185 #elif SIMD_ARCH == SIMD_ARCH_AVX512
186             using IsaImpl = AVX512Impl;
187 #else
188 #error Invalid value for SIMD_ARCH
189 #endif
190 
191             using Float   = SIMD512Impl::Float;
192             using Double  = SIMD512Impl::Double;
193             using Integer = SIMD512Impl::Integer;
194             using Vec4    = SIMD512Impl::Vec4;
195             using Mask    = SIMD512Impl::Mask;
196         };
197     } // namespace SIMD512Impl
198 } // namespace SIMDImpl
199 
200 template <typename Traits>
201 struct SIMDBase : Traits::IsaImpl
202 {
203     using CompareType = typename Traits::CompareType;
204     using ScaleFactor = typename Traits::ScaleFactor;
205     using RoundMode   = typename Traits::RoundMode;
206     using SIMD        = typename Traits::IsaImpl;
207     using Float       = typename Traits::Float;
208     using Double      = typename Traits::Double;
209     using Integer     = typename Traits::Integer;
210     using Vec4        = typename Traits::Vec4;
211     using Mask        = typename Traits::Mask;
212 }; // struct SIMDBase
213 
214 using SIMD128 = SIMDBase<SIMDImpl::SIMD128Impl::Traits>;
215 using SIMD256 = SIMDBase<SIMDImpl::SIMD256Impl::Traits>;
216 using SIMD512 = SIMDBase<SIMDImpl::SIMD512Impl::Traits>;
217 
218 template <typename SIMD_T>
219 using CompareType = typename SIMD_T::CompareType;
220 template <typename SIMD_T>
221 using ScaleFactor = typename SIMD_T::ScaleFactor;
222 template <typename SIMD_T>
223 using RoundMode = typename SIMD_T::RoundMode;
224 template <typename SIMD_T>
225 using Float = typename SIMD_T::Float;
226 template <typename SIMD_T>
227 using Double = typename SIMD_T::Double;
228 template <typename SIMD_T>
229 using Integer = typename SIMD_T::Integer;
230 template <typename SIMD_T>
231 using Vec4 = typename SIMD_T::Vec4;
232 template <typename SIMD_T>
233 using Mask = typename SIMD_T::Mask;
234 
235