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