update to Vc 0.7.3-dev
authormkretz <mkretz@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 7 Oct 2013 07:56:58 +0000 (07:56 +0000)
committermkretz <mkretz@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 7 Oct 2013 07:56:58 +0000 (07:56 +0000)
* the previous Vc copy came from the development branch leading up to Vc 0.7
* this update contains a large number of fixes
* most importantly it fixes the issue with the latest XCode clang
  compiler supporting only a template recursion depth of 128

99 files changed:
Vc/CMakeLists.txt
Vc/cmake/AddCompilerFlag.cmake
Vc/cmake/AddTargetProperty.cmake [new file with mode: 0644]
Vc/cmake/CheckCCompilerFlag.cmake
Vc/cmake/CheckCXXCompilerFlag.cmake
Vc/cmake/OptimizeForArchitecture.cmake
Vc/cmake/VcMacros.cmake
Vc/include/Vc/Allocator [new file with mode: 0644]
Vc/include/Vc/IO
Vc/include/Vc/Memory
Vc/include/Vc/Utils
Vc/include/Vc/Vc
Vc/include/Vc/avx/casts.h
Vc/include/Vc/avx/const.h
Vc/include/Vc/avx/const_data.h
Vc/include/Vc/avx/debug.h
Vc/include/Vc/avx/deinterleave.tcc
Vc/include/Vc/avx/forceToRegisters.tcc
Vc/include/Vc/avx/helperimpl.h
Vc/include/Vc/avx/helperimpl.tcc
Vc/include/Vc/avx/interleavedmemory.tcc [new file with mode: 0644]
Vc/include/Vc/avx/intrinsics.h
Vc/include/Vc/avx/limits.h
Vc/include/Vc/avx/macros.h
Vc/include/Vc/avx/mask.h
Vc/include/Vc/avx/mask.tcc
Vc/include/Vc/avx/math.h
Vc/include/Vc/avx/prefetches.tcc
Vc/include/Vc/avx/shuffle.h
Vc/include/Vc/avx/sorthelper.h
Vc/include/Vc/avx/types.h
Vc/include/Vc/avx/vector.h
Vc/include/Vc/avx/vector.tcc
Vc/include/Vc/avx/vectorhelper.h
Vc/include/Vc/avx/vectorhelper.tcc
Vc/include/Vc/avx/writemaskedvector.h
Vc/include/Vc/avx/writemaskedvector.tcc
Vc/include/Vc/common/aliasingentryhelper.h
Vc/include/Vc/common/bitscanintrinsics.h
Vc/include/Vc/common/deinterleave.h
Vc/include/Vc/common/exponential.h
Vc/include/Vc/common/fix_clang_emmintrin.h [new file with mode: 0644]
Vc/include/Vc/common/iif.h [new file with mode: 0644]
Vc/include/Vc/common/interleavedmemory.h [new file with mode: 0644]
Vc/include/Vc/common/logarithm.h
Vc/include/Vc/common/macros.h
Vc/include/Vc/common/memory.h
Vc/include/Vc/common/memorybase.h
Vc/include/Vc/common/memoryfwd.h
Vc/include/Vc/common/operators.h
Vc/include/Vc/common/storage.h
Vc/include/Vc/common/support.h
Vc/include/Vc/common/trigonometric.h
Vc/include/Vc/common/types.h
Vc/include/Vc/common/undomacros.h
Vc/include/Vc/common/vectortuple.h [new file with mode: 0644]
Vc/include/Vc/common/windows_fix_intrin.h
Vc/include/Vc/cpuid.h
Vc/include/Vc/global.h
Vc/include/Vc/internal/namespace.h
Vc/include/Vc/limits
Vc/include/Vc/scalar/helperimpl.h
Vc/include/Vc/scalar/helperimpl.tcc
Vc/include/Vc/scalar/interleavedmemory.tcc [new file with mode: 0644]
Vc/include/Vc/scalar/mask.h
Vc/include/Vc/scalar/math.h
Vc/include/Vc/scalar/types.h
Vc/include/Vc/scalar/vector.h
Vc/include/Vc/scalar/vector.tcc
Vc/include/Vc/scalar/writemaskedvector.h
Vc/include/Vc/sse/casts.h
Vc/include/Vc/sse/const.h
Vc/include/Vc/sse/const_data.h
Vc/include/Vc/sse/debug.h
Vc/include/Vc/sse/deinterleave.tcc
Vc/include/Vc/sse/forceToRegisters.tcc
Vc/include/Vc/sse/helperimpl.h
Vc/include/Vc/sse/helperimpl.tcc
Vc/include/Vc/sse/interleavedmemory.tcc [new file with mode: 0644]
Vc/include/Vc/sse/intrinsics.h
Vc/include/Vc/sse/limits.h
Vc/include/Vc/sse/mask.h
Vc/include/Vc/sse/math.h
Vc/include/Vc/sse/prefetches.tcc
Vc/include/Vc/sse/shuffle.h
Vc/include/Vc/sse/types.h
Vc/include/Vc/sse/vector.h
Vc/include/Vc/sse/vector.tcc
Vc/include/Vc/sse/vectorhelper.h
Vc/include/Vc/sse/vectorhelper.tcc
Vc/include/Vc/support.h [new file with mode: 0644]
Vc/include/Vc/vector.h
Vc/include/Vc/version.h
Vc/src/avx_sorthelper.cpp [moved from Vc/src/avx/sorthelper.cpp with 78% similarity]
Vc/src/const.cpp [new file with mode: 0644]
Vc/src/cpuid.cpp
Vc/src/support.cpp
Vc/src/trigonometric.cpp [new file with mode: 0644]
Vc/src/vector.cpp [deleted file]

index 483f66a..d9b74de 100644 (file)
@@ -1,37 +1,31 @@
-macro(vc_add_target_property _target _prop _value)
-   get_target_property(_oldprop "${_target}" ${_prop})
-   if(NOT _oldprop)
-      set_target_properties("${_target}" PROPERTIES ${_prop} "${_value}")
-   else(NOT _oldprop)
-      set_target_properties("${_target}" PROPERTIES ${_prop} "${_oldprop} ${_value}")
-   endif(NOT _oldprop)
-endmacro()
+include("${Vc_CMAKE_MODULES_DIR}/AddTargetProperty.cmake")
 
 include_directories("${Vc_INCLUDE_DIR}")
 
+string(REPLACE "-Weffc++" "" CXXFLAGS "${CXXFLAGS}")
+set(libvc_compile_flags "-DVC_COMPILE_LIB ${CXXFLAGS} -O3 ${Vc_DEFINITIONS}")
+vc_compile_for_all_implementations(_objs src/trigonometric.cpp FLAGS ${libvc_compile_flags}
+      ONLY SSE2 SSE3 SSSE3 SSE4_1 AVX SSE+XOP+FMA4 AVX+XOP+FMA4)
+set(_srcs src/const.cpp src/cpuid.cpp src/support.cpp ${_objs})
 if(USE_AVX)
-   add_library(Vc STATIC src/vector.cpp src/cpuid.cpp src/support.cpp src/avx/sorthelper.cpp)
+   list(APPEND _srcs src/avx_sorthelper.cpp)
 else()
-   set(_srcs src/vector.cpp src/cpuid.cpp src/support.cpp)
-
    if(NOT Vc_AVX_INTRINSICS_BROKEN)
-      # we'd still like to have avx/sorthelper.cpp built in, but that requires compilation with -mavx (or a comparable flag)
-      foreach(_flag "-xAVX" "-mavx" "-arch:AVX")
-         check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag})
-         if(check_cxx_compiler_flag_${_flag})
+      # we'd still like to have avx_sorthelper.cpp built in, but that requires compilation with -mavx (or a comparable flag)
+      foreach(_flag "-xAVX" "-mavx" "/arch:AVX")
+         AddCompilerFlag("${_flag}" CXX_RESULT _flag_works)
+         if(_flag_works)
             if(_flag STREQUAL "-xAVX")
                set(_flag "${_flag} -diag-disable 10121") # disable the warning "overriding -xSSE4.2 with -xAVX"
             endif()
-            set(_srcs ${_srcs} src/avx/sorthelper.cpp)
-            set_source_files_properties(src/avx/sorthelper.cpp PROPERTIES COMPILE_FLAGS "${_flag}")
+            list(APPEND _srcs src/avx_sorthelper.cpp)
+            set_source_files_properties(src/avx_sorthelper.cpp PROPERTIES COMPILE_FLAGS "${_flag}")
             break()
          endif()
       endforeach()
    endif()
-   add_library(Vc STATIC ${_srcs})
 endif()
-string(REPLACE "-Weffc++" "" CXXFLAGS "${CXXFLAGS}")
-vc_add_target_property(Vc COMPILE_FLAGS "-DVC_COMPILE_LIB ${CXXFLAGS} -O3 ${Vc_DEFINITIONS}")
-vc_add_target_property(Vc LABELS "other")
+add_library(Vc STATIC ${_srcs})
+add_target_property(Vc COMPILE_FLAGS ${libvc_compile_flags})
 
 # vim: ft=cmake sw=3 et
index 75ad694..4acb35c 100644 (file)
@@ -1,10 +1,66 @@
+# - Add a given compiler flag to flags variables.
+# AddCompilerFlag(<flag> [<var>])
+# or
+# AddCompilerFlag(<flag> [C_FLAGS <var>] [CXX_FLAGS <var>] [C_RESULT <var>]
+#                        [CXX_RESULT <var>])
+
+#=============================================================================
+# Copyright 2010-2013 Matthias Kretz <kretz@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
 get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
 include("${_currentDir}/CheckCCompilerFlag.cmake")
 include("${_currentDir}/CheckCXXCompilerFlag.cmake")
+
 macro(AddCompilerFlag _flag)
    string(REGEX REPLACE "[-.+/:= ]" "_" _flag_esc "${_flag}")
-   check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc})
-   check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc})
+
+   if("${_flag}" STREQUAL "-mfma")
+      # Compiling with FMA3 support may fail only at the assembler level.
+      # In that case we need to have such an instruction in the test code
+      set(_code "#include <immintrin.h>
+      __m128 foo(__m128 x) { return _mm_fmadd_ps(x, x, x); }
+      int main() { return 0; }")
+      check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc} "${_code}")
+      check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc} "${_code}")
+   elseif("${_flag}" STREQUAL "-stdlib=libc++")
+      # Compiling with libc++ not only requires a compiler that understands it, but also
+      # the libc++ headers itself
+      set(_code "#include <iostream>
+      int main() { return 0; }")
+      check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc} "${_code}")
+      check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc} "${_code}")
+   else()
+      check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc})
+      check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc})
+   endif()
 
    set(_c_flags "CMAKE_C_FLAGS")
    set(_cxx_flags "CMAKE_CXX_FLAGS")
diff --git a/Vc/cmake/AddTargetProperty.cmake b/Vc/cmake/AddTargetProperty.cmake
new file mode 100644 (file)
index 0000000..c410135
--- /dev/null
@@ -0,0 +1,39 @@
+#=============================================================================
+# Copyright 2010-2013 Matthias Kretz <kretz@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+macro(add_target_property _target _prop _value)
+   get_target_property(_oldprop "${_target}" ${_prop})
+   if(NOT _oldprop)
+      set_target_properties("${_target}" PROPERTIES ${_prop} "${_value}")
+   else(NOT _oldprop)
+      set_target_properties("${_target}" PROPERTIES ${_prop} "${_oldprop} ${_value}")
+   endif(NOT _oldprop)
+endmacro(add_target_property)
index 6ffd017..0cc5f52 100644 (file)
@@ -9,29 +9,53 @@
 #=============================================================================
 # Copyright 2006-2009 Kitware, Inc.
 # Copyright 2006 Alexander Neundorf <neundorf@kde.org>
-# Copyright 2011 Matthias Kretz <kretz@kde.org>
+# Copyright 2011-2013 Matthias Kretz <kretz@kde.org>
 #
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
 #
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #=============================================================================
-# (To distributed this file outside of CMake, substitute the full
-#  License text for the above reference.)
 
 INCLUDE(CheckCSourceCompiles)
 
 MACRO (CHECK_C_COMPILER_FLAG _FLAG _RESULT)
    SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
    SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
-   CHECK_C_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT}
+   if(${ARGC} GREATER 2)
+      SET(TEST_SOURCE "${ARGV2}")
+   else()
+      SET(TEST_SOURCE "int main() { return 0;}")
+   endif()
+   CHECK_C_SOURCE_COMPILES("${TEST_SOURCE}" ${_RESULT}
      # Some compilers do not fail with a bad flag
      FAIL_REGEX "error: bad value (.*) for .* switch"       # GNU
      FAIL_REGEX "argument unused during compilation"        # clang
      FAIL_REGEX "is valid for .* but not for C"             # GNU
      FAIL_REGEX "unrecognized .*option"                     # GNU
+     FAIL_REGEX "ignored for target"                        # GNU
      FAIL_REGEX "ignoring unknown option"                   # MSVC
      FAIL_REGEX "[Uu]nknown option"                         # HP
      FAIL_REGEX "[Ww]arning: [Oo]ption"                     # SunPro
index 667bf34..9f47454 100644 (file)
@@ -9,29 +9,53 @@
 #=============================================================================
 # Copyright 2006-2009 Kitware, Inc.
 # Copyright 2006 Alexander Neundorf <neundorf@kde.org>
-# Copyright 2011 Matthias Kretz <kretz@kde.org>
+# Copyright 2011-2013 Matthias Kretz <kretz@kde.org>
 #
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
 #
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #=============================================================================
-# (To distributed this file outside of CMake, substitute the full
-#  License text for the above reference.)
 
 INCLUDE(CheckCXXSourceCompiles)
 
 MACRO (CHECK_CXX_COMPILER_FLAG _FLAG _RESULT)
    SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
    SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
-   CHECK_CXX_SOURCE_COMPILES("int main() { return 0;}" ${_RESULT}
+   if(${ARGC} GREATER 2)
+      SET(TEST_SOURCE "${ARGV2}")
+   else()
+      SET(TEST_SOURCE "int main() { return 0;}")
+   endif()
+   CHECK_CXX_SOURCE_COMPILES("${TEST_SOURCE}" ${_RESULT}
      # Some compilers do not fail with a bad flag
      FAIL_REGEX "error: bad value (.*) for .* switch"       # GNU
      FAIL_REGEX "argument unused during compilation"        # clang
      FAIL_REGEX "is valid for .* but not for C\\\\+\\\\+"   # GNU
      FAIL_REGEX "unrecognized .*option"                     # GNU
+     FAIL_REGEX "ignored for target"                        # GNU
      FAIL_REGEX "ignoring unknown option"                   # MSVC
      FAIL_REGEX "[Uu]nknown option"                         # HP
      FAIL_REGEX "[Ww]arning: [Oo]ption"                     # SunPro
index 8194283..246889c 100644 (file)
@@ -1,5 +1,37 @@
+#=============================================================================
+# Copyright 2010-2013 Matthias Kretz <kretz@kde.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
 get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
 include("${_currentDir}/AddCompilerFlag.cmake")
+include(CheckIncludeFile)
 
 macro(_my_find _list _value _ret)
    list(FIND ${_list} "${_value}" _found)
@@ -21,7 +53,7 @@ macro(AutodetectHostArchitecture)
       string(REGEX REPLACE ".*vendor_id[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _vendor_id "${_cpuinfo}")
       string(REGEX REPLACE ".*cpu family[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _cpu_family "${_cpuinfo}")
       string(REGEX REPLACE ".*model[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _cpu_model "${_cpuinfo}")
-      string(REGEX REPLACE ".*flags[ \t]*:[ \t]+([a-zA-Z0-9_-]+).*" "\\1" _cpu_flags "${_cpuinfo}")
+      string(REGEX REPLACE ".*flags[ \t]*:[ \t]+([^\n]+).*" "\\1" _cpu_flags "${_cpuinfo}")
    elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
       exec_program("/usr/sbin/sysctl -n machdep.cpu.vendor" OUTPUT_VARIABLE _vendor_id)
       exec_program("/usr/sbin/sysctl -n machdep.cpu.model"  OUTPUT_VARIABLE _cpu_model)
@@ -39,7 +71,11 @@ macro(AutodetectHostArchitecture)
    if(_vendor_id STREQUAL "GenuineIntel")
       if(_cpu_family EQUAL 6)
          # Any recent Intel CPU except NetBurst
-         if(_cpu_model EQUAL 46)     # Xeon 7500 series
+         if(_cpu_model EQUAL 58)
+            set(TARGET_ARCHITECTURE "ivy-bridge")
+         elseif(_cpu_model EQUAL 47) # Xeon E7 4860
+            set(TARGET_ARCHITECTURE "westmere")
+         elseif(_cpu_model EQUAL 46) # Xeon 7500 series
             set(TARGET_ARCHITECTURE "westmere")
          elseif(_cpu_model EQUAL 45) # Xeon TNG
             set(TARGET_ARCHITECTURE "sandy-bridge")
@@ -82,7 +118,11 @@ macro(AutodetectHostArchitecture)
       endif(_cpu_family EQUAL 6)
    elseif(_vendor_id STREQUAL "AuthenticAMD")
       if(_cpu_family EQUAL 21) # 15h
-         set(TARGET_ARCHITECTURE "bulldozer")
+         if(_cpu_model LESS 2)
+            set(TARGET_ARCHITECTURE "bulldozer")
+         else()
+            set(TARGET_ARCHITECTURE "piledriver")
+         endif()
       elseif(_cpu_family EQUAL 20) # 14h
       elseif(_cpu_family EQUAL 18) # 12h
       elseif(_cpu_family EQUAL 16) # 10h
@@ -97,7 +137,7 @@ macro(AutodetectHostArchitecture)
 endmacro()
 
 macro(OptimizeForArchitecture)
-   set(TARGET_ARCHITECTURE "none" CACHE STRING "CPU architecture to optimize for. Using an incorrect setting here can result in crashes of the resulting binary because of invalid instructions used.\nSetting the value to \"auto\" will try to optimize for the architecture where cmake is called.\nOther supported values are: \"none\", \"generic\", \"core\", \"merom\" (65nm Core2), \"penryn\" (45nm Core2), \"nehalem\", \"westmere\", \"sandy-bridge\", \"atom\", \"k8\", \"k8-sse3\", \"barcelona\", \"istanbul\", \"magny-cours\", \"bulldozer\", \"interlagos\".")
+   set(TARGET_ARCHITECTURE "none" CACHE STRING "CPU architecture to optimize for. Using an incorrect setting here can result in crashes of the resulting binary because of invalid instructions used.\nSetting the value to \"auto\" will try to optimize for the architecture where cmake is called.\nOther supported values are: \"none\", \"generic\", \"core\", \"merom\" (65nm Core2), \"penryn\" (45nm Core2), \"nehalem\", \"westmere\", \"sandy-bridge\", \"ivy-bridge\", \"atom\", \"k8\", \"k8-sse3\", \"barcelona\", \"istanbul\", \"magny-cours\", \"bulldozer\", \"interlagos\", \"piledriver\".")
    set(_force)
    if(NOT _last_target_arch STREQUAL "${TARGET_ARCHITECTURE}")
       message(STATUS "target changed from \"${_last_target_arch}\" to \"${TARGET_ARCHITECTURE}\"")
@@ -143,6 +183,11 @@ macro(OptimizeForArchitecture)
       list(APPEND _march_flag_list "corei7")
       list(APPEND _march_flag_list "core2")
       list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4.1" "sse4.2")
+   elseif(TARGET_ARCHITECTURE STREQUAL "ivy-bridge")
+      list(APPEND _march_flag_list "core-avx-i")
+      list(APPEND _march_flag_list "corei7-avx")
+      list(APPEND _march_flag_list "core2")
+      list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4.1" "sse4.2" "avx" "rdrnd" "f16c")
    elseif(TARGET_ARCHITECTURE STREQUAL "sandy-bridge")
       list(APPEND _march_flag_list "sandybridge")
       list(APPEND _march_flag_list "corei7-avx")
@@ -159,12 +204,21 @@ macro(OptimizeForArchitecture)
       list(APPEND _march_flag_list "k8-sse3")
       list(APPEND _march_flag_list "k8")
       list(APPEND _available_vector_units_list "sse" "sse2" "sse3")
+   elseif(TARGET_ARCHITECTURE STREQUAL "piledriver")
+      list(APPEND _march_flag_list "bdver2")
+      list(APPEND _march_flag_list "bdver1")
+      list(APPEND _march_flag_list "bulldozer")
+      list(APPEND _march_flag_list "barcelona")
+      list(APPEND _march_flag_list "core2")
+      list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a" "sse4.1" "sse4.2" "avx" "xop" "fma4" "fma" "f16c")
    elseif(TARGET_ARCHITECTURE STREQUAL "interlagos")
+      list(APPEND _march_flag_list "bdver1")
       list(APPEND _march_flag_list "bulldozer")
       list(APPEND _march_flag_list "barcelona")
       list(APPEND _march_flag_list "core2")
       list(APPEND _available_vector_units_list "sse" "sse2" "sse3" "ssse3" "sse4a" "sse4.1" "sse4.2" "avx" "xop" "fma4")
    elseif(TARGET_ARCHITECTURE STREQUAL "bulldozer")
+      list(APPEND _march_flag_list "bdver1")
       list(APPEND _march_flag_list "bulldozer")
       list(APPEND _march_flag_list "barcelona")
       list(APPEND _march_flag_list "core2")
@@ -205,7 +259,12 @@ macro(OptimizeForArchitecture)
          set(FMA4_FOUND false)
       else()
          _my_find(_available_vector_units_list "avx" AVX_FOUND)
-         _my_find(_available_vector_units_list "fma4" FMA4_FOUND)
+         if(DEFINED Vc_FMA4_INTRINSICS_BROKEN AND Vc_FMA4_INTRINSICS_BROKEN)
+            UserWarning("FMA4 disabled per default because of old/broken compiler")
+            set(FMA4_FOUND false)
+         else()
+            _my_find(_available_vector_units_list "fma4" FMA4_FOUND)
+         endif()
          if(DEFINED Vc_XOP_INTRINSICS_BROKEN AND Vc_XOP_INTRINSICS_BROKEN)
             UserWarning("XOP disabled per default because of old/broken compiler")
             set(XOP_FOUND false)
@@ -292,38 +351,48 @@ macro(OptimizeForArchitecture)
             add_definitions("-D${_flag}")
          endforeach(_flag)
       elseif(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$") # ICC (on Linux)
-         _my_find(_available_vector_units_list "avx"    _found)
+         _my_find(_available_vector_units_list "avx2"    _found)
          if(_found)
-            AddCompilerFlag("-xAVX" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+            AddCompilerFlag("-xCORE-AVX2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
          else(_found)
-            _my_find(_available_vector_units_list "sse4.2" _found)
+            _my_find(_available_vector_units_list "f16c"    _found)
             if(_found)
-               AddCompilerFlag("-xSSE4.2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+               AddCompilerFlag("-xCORE-AVX-I" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
             else(_found)
-               _my_find(_available_vector_units_list "sse4.1" _found)
+               _my_find(_available_vector_units_list "avx"    _found)
                if(_found)
-                  AddCompilerFlag("-xSSE4.1" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                  AddCompilerFlag("-xAVX" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
                else(_found)
-                  _my_find(_available_vector_units_list "ssse3"  _found)
+                  _my_find(_available_vector_units_list "sse4.2" _found)
                   if(_found)
-                     AddCompilerFlag("-xSSSE3" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                     AddCompilerFlag("-xSSE4.2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
                   else(_found)
-                     _my_find(_available_vector_units_list "sse3"   _found)
+                     _my_find(_available_vector_units_list "sse4.1" _found)
                      if(_found)
-                        # If the target host is an AMD machine then we still want to use -xSSE2 because the binary would refuse to run at all otherwise
-                        _my_find(_march_flag_list "barcelona" _found)
-                        if(NOT _found)
-                           _my_find(_march_flag_list "k8-sse3" _found)
-                        endif(NOT _found)
-                        if(_found)
-                           AddCompilerFlag("-xSSE2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
-                        else(_found)
-                           AddCompilerFlag("-xSSE3" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
-                        endif(_found)
+                        AddCompilerFlag("-xSSE4.1" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
                      else(_found)
-                        _my_find(_available_vector_units_list "sse2"   _found)
+                        _my_find(_available_vector_units_list "ssse3"  _found)
                         if(_found)
-                           AddCompilerFlag("-xSSE2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                           AddCompilerFlag("-xSSSE3" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                        else(_found)
+                           _my_find(_available_vector_units_list "sse3"   _found)
+                           if(_found)
+                              # If the target host is an AMD machine then we still want to use -xSSE2 because the binary would refuse to run at all otherwise
+                              _my_find(_march_flag_list "barcelona" _found)
+                              if(NOT _found)
+                                 _my_find(_march_flag_list "k8-sse3" _found)
+                              endif(NOT _found)
+                              if(_found)
+                                 AddCompilerFlag("-xSSE2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                              else(_found)
+                                 AddCompilerFlag("-xSSE3" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                              endif(_found)
+                           else(_found)
+                              _my_find(_available_vector_units_list "sse2"   _found)
+                              if(_found)
+                                 AddCompilerFlag("-xSSE2" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+                              endif(_found)
+                           endif(_found)
                         endif(_found)
                      endif(_found)
                   endif(_found)
@@ -338,7 +407,43 @@ macro(OptimizeForArchitecture)
             endif(_good)
          endforeach(_flag)
          foreach(_flag ${_enable_vector_unit_list})
-            AddCompilerFlag("-m${_flag}" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
+            AddCompilerFlag("-m${_flag}" CXX_RESULT _result)
+            if(_result)
+               set(_header FALSE)
+               if(_flag STREQUAL "sse3")
+                  set(_header "pmmintrin.h")
+               elseif(_flag STREQUAL "ssse3")
+                  set(_header "tmmintrin.h")
+               elseif(_flag STREQUAL "sse4.1")
+                  set(_header "smmintrin.h")
+               elseif(_flag STREQUAL "sse4.2")
+                  set(_header "smmintrin.h")
+               elseif(_flag STREQUAL "sse4a")
+                  set(_header "ammintrin.h")
+               elseif(_flag STREQUAL "avx")
+                  set(_header "immintrin.h")
+               elseif(_flag STREQUAL "fma4")
+                  set(_header "x86intrin.h")
+               elseif(_flag STREQUAL "xop")
+                  set(_header "x86intrin.h")
+               endif()
+               set(_resultVar "HAVE_${_header}")
+               string(REPLACE "." "_" _resultVar "${_resultVar}")
+               if(_header)
+                  CHECK_INCLUDE_FILE("${_header}" ${_resultVar} "-m${_flag}")
+                  if(NOT ${_resultVar})
+                     set(_useVar "USE_${_flag}")
+                     string(TOUPPER "${_useVar}" _useVar)
+                     string(REPLACE "." "_" _useVar "${_useVar}")
+                     message(STATUS "disabling ${_useVar} because ${_header} is missing")
+                     set(${_useVar} FALSE)
+                     list(APPEND _disable_vector_unit_list "${_flag}")
+                  endif()
+               endif()
+               if(NOT _header OR ${_resultVar})
+                  set(Vc_ARCHITECTURE_FLAGS "${Vc_ARCHITECTURE_FLAGS} -m${_flag}")
+               endif()
+            endif()
          endforeach(_flag)
          foreach(_flag ${_disable_vector_unit_list})
             AddCompilerFlag("-mno-${_flag}" CXX_FLAGS Vc_ARCHITECTURE_FLAGS)
index ddfda57..d0c7046 100644 (file)
@@ -5,16 +5,38 @@
 # vc_set_preferred_compiler_flags
 #
 #=============================================================================
-# Copyright 2009-2012   Matthias Kretz <kretz@kde.org>
+# Copyright 2009-2013   Matthias Kretz <kretz@kde.org>
 #
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file CmakeCopyright.txt for details.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
 #
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #=============================================================================
 
+cmake_minimum_required(VERSION 2.8.3)
+
 get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
 include ("${_currentDir}/UserWarning.cmake")
 include ("${_currentDir}/AddCompilerFlag.cmake")
@@ -22,6 +44,7 @@ include ("${_currentDir}/OptimizeForArchitecture.cmake")
 
 macro(vc_determine_compiler)
    if(NOT DEFINED Vc_COMPILER_IS_INTEL)
+      execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE _cxx_compiler_version ERROR_VARIABLE _cxx_compiler_version)
       set(Vc_COMPILER_IS_INTEL false)
       set(Vc_COMPILER_IS_OPEN64 false)
       set(Vc_COMPILER_IS_CLANG false)
@@ -34,12 +57,14 @@ macro(vc_determine_compiler)
       elseif(CMAKE_CXX_COMPILER MATCHES "(opencc|openCC)$")
          set(Vc_COMPILER_IS_OPEN64 true)
          message(STATUS "Detected Compiler: Open64")
-      elseif(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+$")
+      elseif(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+$" OR "${_cxx_compiler_version}" MATCHES "clang")
          set(Vc_COMPILER_IS_CLANG true)
-         message(STATUS "Detected Compiler: Clang")
+         exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE Vc_CLANG_VERSION)
+         string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" Vc_CLANG_VERSION "${Vc_CLANG_VERSION}")
+         message(STATUS "Detected Compiler: Clang ${Vc_CLANG_VERSION}")
       elseif(MSVC)
          set(Vc_COMPILER_IS_MSVC true)
-         message(STATUS "Detected Compiler: MSVC")
+         message(STATUS "Detected Compiler: MSVC ${MSVC_VERSION}")
       elseif(CMAKE_COMPILER_IS_GNUCXX)
          set(Vc_COMPILER_IS_GCC true)
          exec_program(${CMAKE_C_COMPILER} ARGS -dumpversion OUTPUT_VARIABLE Vc_GCC_VERSION)
@@ -82,20 +107,20 @@ macro(vc_set_gnu_buildtype_flags)
    set(CMAKE_CXX_FLAGS_DEBUG          "-g3"          CACHE STRING "Flags used by the compiler during debug builds." FORCE)
    set(CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG" CACHE STRING "Flags used by the compiler during release minsize builds." FORCE)
    set(CMAKE_CXX_FLAGS_RELEASE        "-O3 -DNDEBUG" CACHE STRING "Flags used by the compiler during release builds (/MD /Ob1 /Oi /Ot /Oy /Gs will produce slightly less optimized but smaller files)." FORCE)
-   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} -g" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
+   set(CMAKE_CXX_FLAGS_RELWITHDEBUG   "-O3"          CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
+   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBUG} -g" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
    set(CMAKE_C_FLAGS_DEBUG          "${CMAKE_CXX_FLAGS_DEBUG}"          CACHE STRING "Flags used by the compiler during debug builds." FORCE)
    set(CMAKE_C_FLAGS_MINSIZEREL     "${CMAKE_CXX_FLAGS_MINSIZEREL}"     CACHE STRING "Flags used by the compiler during release minsize builds." FORCE)
    set(CMAKE_C_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE}"        CACHE STRING "Flags used by the compiler during release builds (/MD /Ob1 /Oi /Ot /Oy /Gs will produce slightly less optimized but smaller files)." FORCE)
+   set(CMAKE_C_FLAGS_RELWITHDEBUG   "${CMAKE_CXX_FLAGS_RELWITHDEBUG}"   CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
    set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
-   if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
+   if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebug")
       set(ENABLE_STRICT_ALIASING true CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
       if(NOT ENABLE_STRICT_ALIASING)
-         set(CMAKE_CXX_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE} -fno-strict-aliasing ")
-         set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fno-strict-aliasing ")
-         set(CMAKE_C_FLAGS_RELEASE        "${CMAKE_C_FLAGS_RELEASE} -fno-strict-aliasing ")
-         set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fno-strict-aliasing ")
+         AddCompilerFlag(-fno-strict-aliasing)
       endif(NOT ENABLE_STRICT_ALIASING)
    endif()
+   mark_as_advanced(CMAKE_CXX_FLAGS_RELWITHDEBUG CMAKE_C_FLAGS_RELWITHDEBUG)
 endmacro()
 
 macro(vc_add_compiler_flag VAR _flag)
@@ -125,6 +150,12 @@ macro(vc_check_assembler)
          if(_as_version VERSION_LESS "2.18.93")
             UserWarning("Your binutils is too old (${_as_version}). Some optimizations of Vc will be disabled.")
             add_definitions(-DVC_NO_XGETBV) # old assembler doesn't know the xgetbv instruction
+            set(Vc_AVX_INTRINSICS_BROKEN true)
+            set(Vc_XOP_INTRINSICS_BROKEN true)
+            set(Vc_FMA4_INTRINSICS_BROKEN true)
+         elseif(_as_version VERSION_LESS "2.21.0")
+            UserWarning("Your binutils is too old (${_as_version}) for XOP instructions. They will therefore not be provided in libVc.")
+            set(Vc_XOP_INTRINSICS_BROKEN true)
          endif()
       endif()
    endif(APPLE)
@@ -136,9 +167,9 @@ macro(vc_check_fpmath)
    check_cxx_source_runs("int main() { return sizeof(void*) != 8; }" Vc_VOID_PTR_IS_64BIT)
    if(NOT Vc_VOID_PTR_IS_64BIT)
       exec_program(${CMAKE_C_COMPILER} ARGS -dumpmachine OUTPUT_VARIABLE _gcc_machine)
-      if(_gcc_machine MATCHES "[x34567]86")
+      if(_gcc_machine MATCHES "[x34567]86" OR _gcc_machine STREQUAL "mingw32")
          vc_add_compiler_flag(Vc_DEFINITIONS "-mfpmath=sse")
-      endif(_gcc_machine MATCHES "[x34567]86")
+      endif()
    endif()
 endmacro()
 
@@ -158,6 +189,7 @@ macro(vc_set_preferred_compiler_flags)
    set(Vc_SSE_INTRINSICS_BROKEN false)
    set(Vc_AVX_INTRINSICS_BROKEN false)
    set(Vc_XOP_INTRINSICS_BROKEN false)
+   set(Vc_FMA4_INTRINSICS_BROKEN false)
 
    if(Vc_COMPILER_IS_OPEN64)
       ##################################################################################################
@@ -189,14 +221,22 @@ macro(vc_set_preferred_compiler_flags)
       endif()
 
       vc_check_assembler()
+
+      # Open64 4.5.1 still doesn't ship immintrin.h
+      set(Vc_AVX_INTRINSICS_BROKEN true)
    elseif(Vc_COMPILER_IS_GCC)
       ##################################################################################################
       #                                              GCC                                               #
       ##################################################################################################
       if(_add_warning_flags)
-         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function -ansi -pedantic -Wno-long-long -Wshadow")
-         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function -ansi -pedantic -Wno-long-long -Wshadow")
-         AddCompilerFlag("-Wimplicit")
+         set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function -pedantic -Wno-long-long -Wshadow")
+         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function -pedantic -Wno-long-long -Wshadow")
+         if(NOT WIN32)
+            # the -ansi flag makes MinGW unusable, so maybe it's better to omit it
+            set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
+            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ansi")
+         endif()
+         AddCompilerFlag("-Wundef")
          AddCompilerFlag("-Wold-style-cast")
          AddCompilerFlag("-Wno-variadic-macros")
          if(Vc_GCC_VERSION VERSION_GREATER "4.5.2" AND Vc_GCC_VERSION VERSION_LESS "4.6.4")
@@ -242,9 +282,21 @@ macro(vc_set_preferred_compiler_flags)
          string(REPLACE " -Wparentheses " " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
          string(REPLACE " -Wparentheses " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
          set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -Wno-parentheses")
+
+         UserWarning("GCC 4.4.x shows false positives for -Wstrict-aliasing, thus we rather disable the warning. Use a newer GCC for better warnings.")
+         AddCompilerFlag("-Wno-strict-aliasing")
+
+         UserWarning("GCC 4.4.x shows false positives for -Wuninitialized, thus we rather disable the warning. Use a newer GCC for better warnings.")
+         AddCompilerFlag("-Wno-uninitialized")
+      elseif(Vc_GCC_VERSION VERSION_EQUAL 4.6.0)
+         UserWarning("GCC 4.6.0 miscompiles AVX loads/stores, leading to spurious segfaults. Disabling AVX per default.")
+         set(Vc_AVX_INTRINSICS_BROKEN true)
       elseif(Vc_GCC_VERSION VERSION_EQUAL 4.7.0)
          UserWarning("GCC 4.7.0 miscompiles at -O3, adding -fno-predictive-commoning to the compiler flags as workaround")
          set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -fno-predictive-commoning")
+      elseif(Vc_GCC_VERSION VERSION_EQUAL 4.8.0)
+         UserWarning("GCC 4.8.0 miscompiles at -O3, adding -fno-tree-vectorize to the compiler flags as workaround")
+         set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -fno-tree-vectorize")
       endif()
 
       vc_check_fpmath()
@@ -272,6 +324,18 @@ macro(vc_set_preferred_compiler_flags)
          set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALIAS_FLAGS}")
       endif()
       vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 913")
+      # Disable warning #13211 "Immediate parameter to intrinsic call too large". (sse/vector.tcc rotated(int))
+      vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 13211")
+
+      if(NOT "$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "")
+         # disable warning #2928: the __GXX_EXPERIMENTAL_CXX0X__ macro is disabled when using GNU version 4.6 with the c++0x option
+         # this warning just adds noise about problems in the compiler - but I'm only interested in seeing problems in Vc
+         vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 2928")
+      endif()
+
+      # Intel doesn't implement the XOP or FMA4 intrinsics
+      set(Vc_XOP_INTRINSICS_BROKEN true)
+      set(Vc_FMA4_INTRINSICS_BROKEN true)
    elseif(Vc_COMPILER_IS_MSVC)
       if(_add_warning_flags)
          AddCompilerFlag("/wd4800") # Disable warning "forcing value to bool"
@@ -292,14 +356,31 @@ macro(vc_set_preferred_compiler_flags)
       # get rid of the min/max macros
       set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DNOMINMAX")
 
-      # MSVC doesn't implement the XOP intrinsics
+      # MSVC doesn't implement the XOP or FMA4 intrinsics
       set(Vc_XOP_INTRINSICS_BROKEN true)
+      set(Vc_FMA4_INTRINSICS_BROKEN true)
+
+      if(MSVC_VERSION LESS 1700)
+         UserWarning("MSVC before 2012 has a broken std::vector::resize implementation. STL + Vc code will probably not compile.")
+      endif()
    elseif(Vc_COMPILER_IS_CLANG)
       # for now I don't know of any arguments I want to pass. -march and stuff is tried by OptimizeForArchitecture...
+      if(Vc_CLANG_VERSION VERSION_EQUAL "3.0")
+         UserWarning("Clang 3.0 has serious issues to compile Vc code and will most likely crash when trying to do so.\nPlease update to a recent clang version.")
+      elseif(Vc_CLANG_VERSION VERSION_LESS "3.3")
+         # the LLVM assembler gets FMAs wrong (bug 15040)
+         vc_add_compiler_flag(Vc_DEFINITIONS "-no-integrated-as")
+      endif()
 
       # disable these warnings because clang shows them for function overloads that were discarded via SFINAE
       vc_add_compiler_flag(Vc_DEFINITIONS "-Wno-local-type-template-args")
       vc_add_compiler_flag(Vc_DEFINITIONS "-Wno-unnamed-type-template-args")
+
+      AddCompilerFlag(-stdlib=libc++)
+   endif()
+
+   if(NOT Vc_COMPILER_IS_MSVC)
+      vc_add_compiler_flag(Vc_DEFINITIONS "-ffp-contract=fast")
    endif()
 
    OptimizeForArchitecture()
@@ -319,3 +400,148 @@ macro(vc_set_preferred_compiler_flags)
       endif()
    endif()
 endmacro()
+
+# helper macro for vc_compile_for_all_implementations
+macro(_vc_compile_one_implementation _objs _impl)
+   list(FIND _disabled_targets "${_impl}" _disabled_index)
+   list(FIND _only_targets "${_impl}" _only_index)
+   if(${_disabled_index} EQUAL -1 AND (NOT _only_targets OR ${_only_index} GREATER -1))
+      set(_extra_flags)
+      set(_ok FALSE)
+      foreach(_flag ${ARGN})
+         if(_flag STREQUAL "NO_FLAG")
+            set(_ok TRUE)
+            break()
+         endif()
+         string(REPLACE " " ";" _flag_list "${_flag}")
+         foreach(_flag ${_flag_list})
+            AddCompilerFlag(${_flag} CXX_RESULT _ok)
+            if(NOT _ok)
+               break()
+            endif()
+         endforeach()
+         if(_ok)
+            set(_extra_flags ${_flag_list})
+            break()
+         endif()
+      endforeach()
+
+      set(_outfile_flag -c -o)
+      if(Vc_COMPILER_IS_MSVC)
+         # MSVC for 64bit does not recognize /arch:SSE2 anymore. Therefore we set override _ok if _impl
+         # says SSE
+         if("${_impl}" MATCHES "SSE")
+            set(_ok TRUE)
+         endif()
+         set(_outfile_flag /c /Fo)
+      endif()
+
+      if(_ok)
+         get_filename_component(_out "${_vc_compile_src}" NAME_WE)
+         get_filename_component(_ext "${_vc_compile_src}" EXT)
+         if(Vc_COMPILER_IS_MSVC)
+            set(_out "${_out}_${_impl}${_ext}.obj")
+         else()
+            set(_out "${_out}_${_impl}${_ext}.o")
+         endif()
+         add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_out}
+            COMMAND ${CMAKE_CXX_COMPILER} ${_flags} ${_extra_flags}
+            -DVC_IMPL=${_impl}
+            ${_outfile_flag}${_out} ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
+            MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
+            IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
+            COMMENT "Building CXX object ${_out}"
+            WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+            VERBATIM
+            )
+         list(APPEND ${_objs} "${CMAKE_CURRENT_BINARY_DIR}/${_out}")
+      endif()
+   endif()
+endmacro()
+
+# Generate compile rules for the given C++ source file for all available implementations and return
+# the resulting list of object files in _obj
+# all remaining arguments are additional flags
+# Example:
+#   vc_compile_for_all_implementations(_objs src/trigonometric.cpp FLAGS -DCOMPILE_BLAH EXCLUDE Scalar)
+#   add_executable(executable main.cpp ${_objs})
+macro(vc_compile_for_all_implementations _objs _src)
+   set(${_objs})
+
+   # remove all -march, -msse, etc. flags from the flags we want to pass
+   string(REPLACE "${Vc_ARCHITECTURE_FLAGS}" "" _flags "${Vc_DEFINITIONS}")
+   string(REPLACE "-DVC_IMPL=[^ ]*" "" _flags "${_flags}")
+
+   # capture the -march= switch as -mtune; if there is none skip it
+   if(Vc_ARCHITECTURE_FLAGS MATCHES "-march=")
+      string(REGEX REPLACE "^.*-march=([^ ]*).*$" "-mtune=\\1" _tmp "${Vc_ARCHITECTURE_FLAGS}")
+      set(_flags "${_flags} ${_tmp}")
+   endif()
+
+   unset(_disabled_targets)
+   unset(_only_targets)
+   set(_state 0)
+   foreach(_arg ${ARGN})
+      if(_arg STREQUAL "FLAGS")
+         set(_state 1)
+      elseif(_arg STREQUAL "EXCLUDE")
+         set(_state 2)
+      elseif(_arg STREQUAL "ONLY")
+         set(_state 3)
+      elseif(_state EQUAL 1)
+         set(_flags "${_flags} ${_arg}")
+      elseif(_state EQUAL 2)
+         list(APPEND _disabled_targets "${_arg}")
+      elseif(_state EQUAL 3)
+         list(APPEND _only_targets "${_arg}")
+      else()
+         message(FATAL_ERROR "incorrect argument to vc_compile_for_all_implementations")
+      endif()
+   endforeach()
+
+   # make a semicolon separated list of all flags
+   string(TOUPPER "${CMAKE_BUILD_TYPE}" _tmp)
+   set(_tmp "CMAKE_CXX_FLAGS_${_tmp}")
+   string(REPLACE " " ";" _tmp "${CMAKE_CXX_FLAGS} ${${_tmp}} ${_flags}")
+   set(_flags)
+   foreach(item ${_tmp})
+      if(item MATCHES "^[^']*'[^']*$")
+         if(_str)
+            list(APPEND _flags "${_str} ${item}")
+            unset(_str)
+         else()
+            set(_str "${item}")
+         endif()
+      else()
+         list(APPEND _flags "${item}")
+      endif()
+   endforeach()
+   get_directory_property(_inc INCLUDE_DIRECTORIES)
+   foreach(_i ${_inc})
+      list(APPEND _flags "-I${_i}")
+   endforeach()
+
+   set(_vc_compile_src "${_src}")
+
+   _vc_compile_one_implementation(${_objs} Scalar NO_FLAG)
+   if(NOT Vc_SSE_INTRINSICS_BROKEN)
+      _vc_compile_one_implementation(${_objs} SSE2   "-msse2"   "-xSSE2"   "/arch:SSE2")
+      _vc_compile_one_implementation(${_objs} SSE3   "-msse3"   "-xSSE3"   "/arch:SSE2")
+      _vc_compile_one_implementation(${_objs} SSSE3  "-mssse3"  "-xSSSE3"  "/arch:SSE2")
+      _vc_compile_one_implementation(${_objs} SSE4_1 "-msse4.1" "-xSSE4.1" "/arch:SSE2")
+      _vc_compile_one_implementation(${_objs} SSE4_2 "-msse4.2" "-xSSE4.2" "/arch:SSE2")
+      _vc_compile_one_implementation(${_objs} SSE3+SSE4a  "-msse4a")
+   endif()
+   if(NOT Vc_AVX_INTRINSICS_BROKEN)
+      _vc_compile_one_implementation(${_objs} AVX      "-mavx"    "-xAVX"    "/arch:AVX")
+      if(NOT Vc_XOP_INTRINSICS_BROKEN)
+         if(NOT Vc_FMA4_INTRINSICS_BROKEN)
+            _vc_compile_one_implementation(${_objs} SSE+XOP+FMA4 "-mxop -mfma4"        ""    "")
+            _vc_compile_one_implementation(${_objs} AVX+XOP+FMA4 "-mavx -mxop -mfma4"  ""    "")
+         endif()
+         _vc_compile_one_implementation(${_objs} SSE+XOP+FMA "-mxop -mfma"        ""    "")
+         _vc_compile_one_implementation(${_objs} AVX+XOP+FMA "-mavx -mxop -mfma"  ""    "")
+      endif()
+      _vc_compile_one_implementation(${_objs} AVX+FMA "-mavx -mfma"  ""    "")
+   endif()
+endmacro()
diff --git a/Vc/include/Vc/Allocator b/Vc/include/Vc/Allocator
new file mode 100644 (file)
index 0000000..fdc134f
--- /dev/null
@@ -0,0 +1,239 @@
+/*  This file is part of the Vc library. {{{
+
+    Copyright (C) 2012 Matthias Kretz <kretz@kde.org>
+
+    Vc is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation, either version 3 of
+    the License, or (at your option) any later version.
+
+    Vc is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.
+
+}}}*/
+
+#ifndef VC_ALLOCATOR_H
+#define VC_ALLOCATOR_H
+
+#include <new>
+#include <cstddef>
+#include <cstdlib>
+#include "common/macros.h"
+#ifdef VC_CXX11
+#include <utility>
+#endif
+
+namespace AliRoot {
+namespace Vc
+{
+    using std::size_t;
+    using std::ptrdiff_t;
+
+    /**
+     * \headerfile Allocator <Vc/Allocator>
+     * \ingroup Utilities
+     *
+     * Convenience macro to set the default allocator for a given \p Type to Vc::Allocator.
+     *
+     * \param Type Your type that you want to use with STL containers.
+     *
+     * \note You have to use this macro in the global namespace.
+     */
+#define VC_DECLARE_ALLOCATOR(Type) \
+namespace std \
+{ \
+    template<> class allocator<Type> : public ::AliRoot::Vc::Allocator<Type> \
+    { \
+    public: \
+        template<typename U> struct rebind { typedef ::std::allocator<U> other; }; \
+    }; \
+}
+#ifdef VC_MSVC
+#undef Vc_DECLARE_ALLOCATOR
+#define Vc_DECLARE_ALLOCATOR(Type) \
+namespace std \
+{ \
+    template<> class allocator<Type> : public ::AliRoot::Vc::Allocator<Type> \
+    { \
+    public: \
+        template<typename U> struct rebind { typedef ::std::allocator<U> other; }; \
+        /* MSVC brokenness: the following function is optional - just doesn't compile without it */ \
+        const allocator &select_on_container_copy_construction() const { return *this; } \
+    }; \
+}
+#endif
+
+    /**
+     * \headerfile Allocator <Vc/Allocator>
+     * An allocator that uses global new and supports over-aligned types, as per [C++11 20.6.9].
+     *
+     * Meant as a simple replacement for the allocator defined in the C++ Standard.
+     * Allocation is done using the global new/delete operators. But if the alignment property of \p
+     * T is larger than the size of a pointer, the allocate function allocates slightly more memory
+     * to adjust the pointer for correct alignment.
+     *
+     * If the \p T does not require over-alignment no additional memory will be allocated.
+     *
+     * \tparam T The type of objects to allocate.
+     *
+     * Example:
+     * \code
+     * struct Data {
+     *   Vc::float_v x, y, z;
+     * };
+     *
+     * void fun()
+     * {
+     *   std::vector<Data> dat0; // this will use std::allocator<Data>, which probably ignores the
+     *                           // alignment requirements for Data. Thus any access to dat0 may
+     *                           // crash your program.
+     *
+     *   std::vector<Data, Vc::Allocator<Data> > dat1; // now std::vector will get correctly aligned
+     *                           // memory. Accesses to dat1 are safe.
+     *   ...
+     * \endcode
+     *
+     * %Vc ships a macro to conveniently tell STL to use Vc::Allocator per default for a given type:
+     * \code
+     * struct Data {
+     *   Vc::float_v x, y, z;
+     * };
+     * VC_DECLARE_ALLOCATOR(Data)
+     *
+     * void fun()
+     * {
+     *   std::vector<Data> dat0; // good now
+     *   ...
+     * \endcode
+     *
+     * \ingroup Utilities
+     */
+    template<typename T> class Allocator
+    {
+    private:
+        enum Constants {
+#ifdef VC_HAVE_STD_MAX_ALIGN_T
+            NaturalAlignment = alignof(std::max_align_t),
+#elif defined(VC_HAVE_MAX_ALIGN_T)
+            NaturalAlignment = alignof(::max_align_t),
+#else
+            NaturalAlignment = sizeof(void *) > Vc_ALIGNOF(long double) ? sizeof(void *) :
+                (Vc_ALIGNOF(long double) > Vc_ALIGNOF(long long) ? Vc_ALIGNOF(long double) : Vc_ALIGNOF(long long)),
+#endif
+            Alignment = Vc_ALIGNOF(T),
+            /* The number of extra bytes allocated must be large enough to put a pointer right
+             * before the adjusted address. This pointer stores the original address, which is
+             * required to call ::operator delete in deallocate.
+             *
+             * The address we get from ::operator new is a multiple of NaturalAlignment:
+             *   p = N * NaturalAlignment
+             *
+             * Since all alignments are powers of two, Alignment is a multiple of NaturalAlignment:
+             *   Alignment = k * NaturalAlignment
+             *
+             * two cases:
+             * 1. If p is already aligned to Alignment then allocate will return p + Alignment. In
+             *    this case there are Alignment Bytes available to store a pointer.
+             * 2. If p is not aligned then p + (k - (N modulo k)) * NaturalAlignment will be
+             *    returned. Since NaturalAlignment >= sizeof(void*) the pointer fits.
+             */
+            ExtraBytes = Alignment > NaturalAlignment ? Alignment : 0,
+            AlignmentMask = Alignment - 1
+        };
+    public:
+        typedef size_t    size_type;
+        typedef ptrdiff_t difference_type;
+        typedef T*        pointer;
+        typedef const T*  const_pointer;
+        typedef T&        reference;
+        typedef const T&  const_reference;
+        typedef T         value_type;
+
+        template<typename U> struct rebind { typedef Allocator<U> other; };
+
+        Allocator() throw() { }
+        Allocator(const Allocator&) throw() { }
+        template<typename U> Allocator(const Allocator<U>&) throw() { }
+
+        pointer address(reference x) const { return &x; }
+        const_pointer address(const_reference x) const { return &x; }
+
+        pointer allocate(size_type n, const void* = 0)
+        {
+            if (n > this->max_size()) {
+                throw std::bad_alloc();
+            }
+
+            char *p = static_cast<char *>(::operator new(n * sizeof(T) + ExtraBytes));
+            if (ExtraBytes > 0) {
+                char *const pp = p;
+                p += ExtraBytes;
+                const char *null = 0;
+                p -= ((p - null) & AlignmentMask); // equivalent to p &= ~AlignmentMask;
+                reinterpret_cast<char **>(p)[-1] = pp;
+            }
+            return reinterpret_cast<pointer>(p);
+        }
+
+        void deallocate(pointer p, size_type)
+        {
+            if (ExtraBytes > 0) {
+                p = reinterpret_cast<pointer *>(p)[-1];
+            }
+            ::operator delete(p);
+        }
+
+        size_type max_size() const throw() { return size_t(-1) / sizeof(T); }
+
+#ifdef VC_MSVC
+        // MSVC brokenness: the following function is optional - just doesn't compile without it
+        const Allocator &select_on_container_copy_construction() const { return *this; }
+
+        // MSVC also requires a function that neither C++98 nor C++11 mention
+        // but it doesn't support variadic templates... otherwise the VC_CXX11 clause would be nice
+        void construct(pointer p) { ::new(p) T(); }
+
+        // we still need the C++98 version:
+        void construct(pointer p, const T& __val) { ::new(p) T(__val); }
+        void destroy(pointer p) { p->~T(); }
+#elif defined(VC_CXX11)
+        template<typename U, typename... Args> void construct(U* p, Args&&... args)
+        {
+            ::new(p) U(std::forward<Args>(args)...);
+        }
+        template<typename U> void destroy(U* p) { p->~U(); }
+#else
+        void construct(pointer p, const T& __val) { ::new(p) T(__val); }
+        void destroy(pointer p) { p->~T(); }
+#endif
+    };
+
+    template<typename T> inline bool operator==(const Allocator<T>&, const Allocator<T>&) { return true;  }
+    template<typename T> inline bool operator!=(const Allocator<T>&, const Allocator<T>&) { return false; }
+
+} // namespace Vc
+} // namespace AliRoot
+
+#include "common/undomacros.h"
+#include "vector.h"
+namespace std
+{
+    template<typename T> class allocator<Vc::Vector<T> > : public ::AliRoot::Vc::Allocator<Vc::Vector<T> >
+    {
+    public:
+        template<typename U> struct rebind { typedef ::std::allocator<U> other; };
+#ifdef VC_MSVC
+        // MSVC brokenness: the following function is optional - just doesn't compile without it
+        const allocator &select_on_container_copy_construction() const { return *this; }
+#endif
+    };
+}
+
+#endif // VC_ALLOCATOR_H
+
+// vim: ft=cpp et sw=4 sts=4
index 63668bf..084b8d9 100644 (file)
 #include "Memory"
 #include <iostream>
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(_WIN32) && defined(_GLIBCXX_OSTREAM)
+#define VC_HACK_OSTREAM_FOR_TTY 1
+#endif
+
+#ifdef VC_HACK_OSTREAM_FOR_TTY
 #include <unistd.h>
 #include <ext/stdio_sync_filebuf.h>
 #endif
@@ -42,15 +46,13 @@ namespace
         static const Type normal = { "\033[0m" };
     } // namespace AnsiColor
 
-#ifdef __GNUC__
+#ifdef VC_HACK_OSTREAM_FOR_TTY
     class hacked_ostream : public std::ostream
     {
         public:
             using std::ostream::_M_streambuf;
     };
-    static bool mayUseColor(const std::ostream &os)
-        __attribute__((__const__));
-    static bool mayUseColor(const std::ostream &os)
+    __attribute__((__const__)) bool mayUseColor(const std::ostream &os)
     {
         std::basic_streambuf<char> *hack1 = const_cast<std::basic_streambuf<char> *>(os.*(&hacked_ostream::_M_streambuf));
         __gnu_cxx::stdio_sync_filebuf<char> *hack = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char> *>(hack1);
@@ -61,13 +63,13 @@ namespace
         return 1 == isatty(fileno(file));
     }
 #else
-    static bool mayUseColor(const std::ostream &) { return false; }
+    inline bool mayUseColor(const std::ostream &) { return false; }
 #endif
 } // anonymous namespace
 
 namespace std
 {
-static inline std::ostream &operator<<(std::ostream &out, const AnsiColor::Type &c)
+inline std::ostream &operator<<(std::ostream &out, const AnsiColor::Type &c)
 {
     if (mayUseColor(out)) {
         out << c.data;
@@ -76,7 +78,7 @@ static inline std::ostream &operator<<(std::ostream &out, const AnsiColor::Type
 }
 
 template<typename T>
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vector<T> &v)
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vector<T> &v)
 {
     out << AnsiColor::green << "[";
     out << v[0];
@@ -87,7 +89,7 @@ static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vecto
     return out;
 }
 
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vector<char> &v)
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vector<char> &v)
 {
     out << AnsiColor::green << "[";
     out << int(v[0]);
@@ -97,7 +99,7 @@ static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vecto
     out << "]" << AnsiColor::normal;
     return out;
 }
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vector<unsigned char> &v)
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vector<unsigned char> &v)
 {
     out << AnsiColor::green << "[";
     out << int(v[0]);
@@ -110,7 +112,7 @@ static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vecto
 
 #ifdef VC_HAVE_FMA
 template<typename T>
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::VectorMultiplication<T> &v)
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::VectorMultiplication<T> &v)
 {
     return out << VECTOR_NAMESPACE::Vector<T>(v);
 }
@@ -118,10 +120,10 @@ static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Vecto
 
 #ifdef VC_IMPL_AVX
 template<unsigned int VectorSize, size_t RegisterWidth>
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Mask<VectorSize, RegisterWidth> &m)
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Mask<VectorSize, RegisterWidth> &m)
 #else
 template<unsigned int VectorSize>
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Mask<VectorSize> &m)
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Mask<VectorSize> &m)
 #endif
 {
     out << AnsiColor::blue << "m[";
@@ -138,8 +140,8 @@ static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Mask<
     out << AnsiColor::blue << "]" << AnsiColor::normal;
     return out;
 }
-#if VC_IMPL_SSE
-static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Float8Mask &m)
+#ifdef VC_IMPL_SSE
+inline std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Float8Mask &m)
 {
     out << AnsiColor::blue << "m[";
     for (unsigned int i = 0; i < 8; ++i) {
@@ -158,7 +160,7 @@ static std::ostream &operator<<(std::ostream &out, const VECTOR_NAMESPACE::Float
 #endif
 
 template<typename V, typename Parent, typename RM>
-static std::ostream &operator<<(std::ostream &out, const Vc::MemoryBase<V, Parent, 1, RM> &m )
+inline std::ostream &operator<<(std::ostream &out, const Vc::MemoryBase<V, Parent, 1, RM> &m )
 {
     out << AnsiColor::blue << "{" << AnsiColor::normal;
     for (unsigned int i = 0; i < m.vectorsCount(); ++i) {
@@ -169,7 +171,7 @@ static std::ostream &operator<<(std::ostream &out, const Vc::MemoryBase<V, Paren
 }
 
 template<typename V, typename Parent, typename RM>
-static std::ostream &operator<<(std::ostream &out, const Vc::MemoryBase<V, Parent, 2, RM> &m )
+inline std::ostream &operator<<(std::ostream &out, const Vc::MemoryBase<V, Parent, 2, RM> &m )
 {
     out << AnsiColor::blue << "{" << AnsiColor::normal;
     for (size_t i = 0; i < m.rowsCount(); ++i) {
index 52a83bc..214cc34 100644 (file)
 
 #include "vector.h"
 #include "common/memory.h"
+#include "common/interleavedmemory.h"
+#ifdef VC_IMPL_Scalar
+# include "scalar/interleavedmemory.tcc"
+#elif defined(VC_IMPL_AVX)
+# include "avx/interleavedmemory.tcc"
+#elif defined(VC_IMPL_SSE)
+# include "sse/interleavedmemory.tcc"
+#endif
 
 #endif // INCLUDE_VC_MEMORY
+
+// vim: ft=cpp
index 132109b..ef5a0ea 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "global.h"
 
-#if VC_IMPL_Scalar
+#ifdef VC_IMPL_Scalar
 # define VECTOR_NAMESPACE Scalar
 #else
 # define VECTOR_NAMESPACE SSE
index f23e7f2..47c8c4c 100644 (file)
@@ -23,4 +23,7 @@
 #include "IO"
 #include "Memory"
 #include "Utils"
+#include "Allocator"
 #endif // VC_VC
+
+// vim: ft=cpp
index 8db5d6e..5d833a4 100644 (file)
 
 #include "intrinsics.h"
 #include "types.h"
+#include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
 {
-    template<typename T> static inline INTRINSIC_L T avx_cast(__m128  v) INTRINSIC_R;
-    template<typename T> static inline INTRINSIC_L T avx_cast(__m128i v) INTRINSIC_R;
-    template<typename T> static inline INTRINSIC_L T avx_cast(__m128d v) INTRINSIC_R;
-    template<typename T> static inline INTRINSIC_L T avx_cast(__m256  v) INTRINSIC_R;
-    template<typename T> static inline INTRINSIC_L T avx_cast(__m256i v) INTRINSIC_R;
-    template<typename T> static inline INTRINSIC_L T avx_cast(__m256d v) INTRINSIC_R;
+    template<typename T> static Vc_INTRINSIC_L T avx_cast(param128  v) Vc_INTRINSIC_R;
+    template<typename T> static Vc_INTRINSIC_L T avx_cast(param128i v) Vc_INTRINSIC_R;
+    template<typename T> static Vc_INTRINSIC_L T avx_cast(param128d v) Vc_INTRINSIC_R;
+    template<typename T> static Vc_INTRINSIC_L T avx_cast(param256  v) Vc_INTRINSIC_R;
+    template<typename T> static Vc_INTRINSIC_L T avx_cast(param256i v) Vc_INTRINSIC_R;
+    template<typename T> static Vc_INTRINSIC_L T avx_cast(param256d v) Vc_INTRINSIC_R;
+
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+    template<typename T> static Vc_INTRINSIC T avx_cast(__m128  v) { return avx_cast<T>(param128 (v)); }
+    template<typename T> static Vc_INTRINSIC T avx_cast(__m128i v) { return avx_cast<T>(param128i(v)); }
+    template<typename T> static Vc_INTRINSIC T avx_cast(__m128d v) { return avx_cast<T>(param128d(v)); }
+    template<typename T> static Vc_INTRINSIC T avx_cast(__m256  v) { return avx_cast<T>(param256 (v)); }
+    template<typename T> static Vc_INTRINSIC T avx_cast(__m256i v) { return avx_cast<T>(param256i(v)); }
+    template<typename T> static Vc_INTRINSIC T avx_cast(__m256d v) { return avx_cast<T>(param256d(v)); }
+#endif
 
     // 128 -> 128
-    template<> inline __m128  INTRINSIC avx_cast(__m128  v) { return v; }
-    template<> inline __m128  INTRINSIC avx_cast(__m128i v) { return _mm_castsi128_ps(v); }
-    template<> inline __m128  INTRINSIC avx_cast(__m128d v) { return _mm_castpd_ps(v); }
-    template<> inline __m128i INTRINSIC avx_cast(__m128  v) { return _mm_castps_si128(v); }
-    template<> inline __m128i INTRINSIC avx_cast(__m128i v) { return v; }
-    template<> inline __m128i INTRINSIC avx_cast(__m128d v) { return _mm_castpd_si128(v); }
-    template<> inline __m128d INTRINSIC avx_cast(__m128  v) { return _mm_castps_pd(v); }
-    template<> inline __m128d INTRINSIC avx_cast(__m128i v) { return _mm_castsi128_pd(v); }
-    template<> inline __m128d INTRINSIC avx_cast(__m128d v) { return v; }
+    template<> Vc_INTRINSIC m128  avx_cast(param128  v) { return v; }
+    template<> Vc_INTRINSIC m128  avx_cast(param128i v) { return _mm_castsi128_ps(v); }
+    template<> Vc_INTRINSIC m128  avx_cast(param128d v) { return _mm_castpd_ps(v); }
+    template<> Vc_INTRINSIC m128i avx_cast(param128  v) { return _mm_castps_si128(v); }
+    template<> Vc_INTRINSIC m128i avx_cast(param128i v) { return v; }
+    template<> Vc_INTRINSIC m128i avx_cast(param128d v) { return _mm_castpd_si128(v); }
+    template<> Vc_INTRINSIC m128d avx_cast(param128  v) { return _mm_castps_pd(v); }
+    template<> Vc_INTRINSIC m128d avx_cast(param128i v) { return _mm_castsi128_pd(v); }
+    template<> Vc_INTRINSIC m128d avx_cast(param128d v) { return v; }
 
     // 128 -> 256
-    template<> inline __m256  INTRINSIC avx_cast(__m128  v) { return _mm256_castps128_ps256(v); }
-    template<> inline __m256  INTRINSIC avx_cast(__m128i v) { return _mm256_castps128_ps256(_mm_castsi128_ps(v)); }
-    template<> inline __m256  INTRINSIC avx_cast(__m128d v) { return _mm256_castps128_ps256(_mm_castpd_ps(v)); }
-    template<> inline __m256i INTRINSIC avx_cast(__m128  v) { return _mm256_castsi128_si256(_mm_castps_si128(v)); }
-    template<> inline __m256i INTRINSIC avx_cast(__m128i v) { return _mm256_castsi128_si256(v); }
-    template<> inline __m256i INTRINSIC avx_cast(__m128d v) { return _mm256_castsi128_si256(_mm_castpd_si128(v)); }
-    template<> inline __m256d INTRINSIC avx_cast(__m128  v) { return _mm256_castpd128_pd256(_mm_castps_pd(v)); }
-    template<> inline __m256d INTRINSIC avx_cast(__m128i v) { return _mm256_castpd128_pd256(_mm_castsi128_pd(v)); }
-    template<> inline __m256d INTRINSIC avx_cast(__m128d v) { return _mm256_castpd128_pd256(v); }
+    // FIXME: the following casts leave the upper 128bits undefined. With GCC and ICC I've never
+    // seen the cast not do what I want though: after a VEX-coded SSE instruction the register's
+    // upper 128bits are zero. Thus using the same register as AVX register will have the upper
+    // 128bits zeroed. MSVC, though, implements _mm256_castxx128_xx256 with a 128bit move to memory
+    // + 256bit load. Thus the upper 128bits are really undefined. But there is no intrinsic to do
+    // what I want (i.e. alias the register, disallowing the move to memory in-between). I'm stuck,
+    // do we really want to rely on specific compiler behavior here?
+    template<> Vc_INTRINSIC m256  avx_cast(param128  v) { return _mm256_castps128_ps256(v); }
+    template<> Vc_INTRINSIC m256  avx_cast(param128i v) { return _mm256_castps128_ps256(_mm_castsi128_ps(v)); }
+    template<> Vc_INTRINSIC m256  avx_cast(param128d v) { return _mm256_castps128_ps256(_mm_castpd_ps(v)); }
+    template<> Vc_INTRINSIC m256i avx_cast(param128  v) { return _mm256_castsi128_si256(_mm_castps_si128(v)); }
+    template<> Vc_INTRINSIC m256i avx_cast(param128i v) { return _mm256_castsi128_si256(v); }
+    template<> Vc_INTRINSIC m256i avx_cast(param128d v) { return _mm256_castsi128_si256(_mm_castpd_si128(v)); }
+    template<> Vc_INTRINSIC m256d avx_cast(param128  v) { return _mm256_castpd128_pd256(_mm_castps_pd(v)); }
+    template<> Vc_INTRINSIC m256d avx_cast(param128i v) { return _mm256_castpd128_pd256(_mm_castsi128_pd(v)); }
+    template<> Vc_INTRINSIC m256d avx_cast(param128d v) { return _mm256_castpd128_pd256(v); }
+
+#ifdef VC_MSVC
+    static Vc_INTRINSIC Vc_CONST m256  zeroExtend(param128  v) { return _mm256_permute2f128_ps   (_mm256_castps128_ps256(v), _mm256_castps128_ps256(v), 0x80); }
+    static Vc_INTRINSIC Vc_CONST m256i zeroExtend(param128i v) { return _mm256_permute2f128_si256(_mm256_castsi128_si256(v), _mm256_castsi128_si256(v), 0x80); }
+    static Vc_INTRINSIC Vc_CONST m256d zeroExtend(param128d v) { return _mm256_permute2f128_pd   (_mm256_castpd128_pd256(v), _mm256_castpd128_pd256(v), 0x80); }
+#else
+    static Vc_INTRINSIC Vc_CONST m256  zeroExtend(param128  v) { return _mm256_castps128_ps256(v); }
+    static Vc_INTRINSIC Vc_CONST m256i zeroExtend(param128i v) { return _mm256_castsi128_si256(v); }
+    static Vc_INTRINSIC Vc_CONST m256d zeroExtend(param128d v) { return _mm256_castpd128_pd256(v); }
+#ifdef VC_ICC
+    static Vc_INTRINSIC Vc_CONST m256  zeroExtend(__m128  v) { return _mm256_castps128_ps256(v); }
+    static Vc_INTRINSIC Vc_CONST m256i zeroExtend(__m128i v) { return _mm256_castsi128_si256(v); }
+    static Vc_INTRINSIC Vc_CONST m256d zeroExtend(__m128d v) { return _mm256_castpd128_pd256(v); }
+#endif
+#endif
 
     // 256 -> 128
-    template<> inline __m128  INTRINSIC avx_cast(__m256  v) { return _mm256_castps256_ps128(v); }
-    template<> inline __m128  INTRINSIC avx_cast(__m256i v) { return _mm256_castps256_ps128(_mm256_castsi256_ps(v)); }
-    template<> inline __m128  INTRINSIC avx_cast(__m256d v) { return _mm256_castps256_ps128(_mm256_castpd_ps(v)); }
-    template<> inline __m128i INTRINSIC avx_cast(__m256  v) { return _mm256_castsi256_si128(_mm256_castps_si256(v)); }
-    template<> inline __m128i INTRINSIC avx_cast(__m256i v) { return _mm256_castsi256_si128(v); }
-    template<> inline __m128i INTRINSIC avx_cast(__m256d v) { return _mm256_castsi256_si128(_mm256_castpd_si256(v)); }
-    template<> inline __m128d INTRINSIC avx_cast(__m256  v) { return _mm256_castpd256_pd128(_mm256_castps_pd(v)); }
-    template<> inline __m128d INTRINSIC avx_cast(__m256i v) { return _mm256_castpd256_pd128(_mm256_castsi256_pd(v)); }
-    template<> inline __m128d INTRINSIC avx_cast(__m256d v) { return _mm256_castpd256_pd128(v); }
+    template<> Vc_INTRINSIC m128  avx_cast(param256  v) { return _mm256_castps256_ps128(v); }
+    template<> Vc_INTRINSIC m128  avx_cast(param256i v) { return _mm256_castps256_ps128(_mm256_castsi256_ps(v)); }
+    template<> Vc_INTRINSIC m128  avx_cast(param256d v) { return _mm256_castps256_ps128(_mm256_castpd_ps(v)); }
+    template<> Vc_INTRINSIC m128i avx_cast(param256  v) { return _mm256_castsi256_si128(_mm256_castps_si256(v)); }
+    template<> Vc_INTRINSIC m128i avx_cast(param256i v) { return _mm256_castsi256_si128(v); }
+    template<> Vc_INTRINSIC m128i avx_cast(param256d v) { return _mm256_castsi256_si128(_mm256_castpd_si256(v)); }
+    template<> Vc_INTRINSIC m128d avx_cast(param256  v) { return _mm256_castpd256_pd128(_mm256_castps_pd(v)); }
+    template<> Vc_INTRINSIC m128d avx_cast(param256i v) { return _mm256_castpd256_pd128(_mm256_castsi256_pd(v)); }
+    template<> Vc_INTRINSIC m128d avx_cast(param256d v) { return _mm256_castpd256_pd128(v); }
 
     // 256 -> 256
-    template<> inline __m256  INTRINSIC avx_cast(__m256  v) { return v; }
-    template<> inline __m256  INTRINSIC avx_cast(__m256i v) { return _mm256_castsi256_ps(v); }
-    template<> inline __m256  INTRINSIC avx_cast(__m256d v) { return _mm256_castpd_ps(v); }
-    template<> inline __m256i INTRINSIC avx_cast(__m256  v) { return _mm256_castps_si256(v); }
-    template<> inline __m256i INTRINSIC avx_cast(__m256i v) { return v; }
-    template<> inline __m256i INTRINSIC avx_cast(__m256d v) { return _mm256_castpd_si256(v); }
-    template<> inline __m256d INTRINSIC avx_cast(__m256  v) { return _mm256_castps_pd(v); }
-    template<> inline __m256d INTRINSIC avx_cast(__m256i v) { return _mm256_castsi256_pd(v); }
-    template<> inline __m256d INTRINSIC avx_cast(__m256d v) { return v; }
+    template<> Vc_INTRINSIC m256  avx_cast(param256  v) { return v; }
+    template<> Vc_INTRINSIC m256  avx_cast(param256i v) { return _mm256_castsi256_ps(v); }
+    template<> Vc_INTRINSIC m256  avx_cast(param256d v) { return _mm256_castpd_ps(v); }
+    template<> Vc_INTRINSIC m256i avx_cast(param256  v) { return _mm256_castps_si256(v); }
+    template<> Vc_INTRINSIC m256i avx_cast(param256i v) { return v; }
+    template<> Vc_INTRINSIC m256i avx_cast(param256d v) { return _mm256_castpd_si256(v); }
+    template<> Vc_INTRINSIC m256d avx_cast(param256  v) { return _mm256_castps_pd(v); }
+    template<> Vc_INTRINSIC m256d avx_cast(param256i v) { return _mm256_castsi256_pd(v); }
+    template<> Vc_INTRINSIC m256d avx_cast(param256d v) { return v; }
 
     // simplify splitting 256-bit registers in 128-bit registers
-    inline __m128  INTRINSIC lo128(__m256  v) { return avx_cast<__m128>(v); }
-    inline __m128d INTRINSIC lo128(__m256d v) { return avx_cast<__m128d>(v); }
-    inline __m128i INTRINSIC lo128(__m256i v) { return avx_cast<__m128i>(v); }
-    inline __m128  INTRINSIC hi128(__m256  v) { return _mm256_extractf128_ps(v, 1); }
-    inline __m128d INTRINSIC hi128(__m256d v) { return _mm256_extractf128_pd(v, 1); }
-    inline __m128i INTRINSIC hi128(__m256i v) { return _mm256_extractf128_si256(v, 1); }
+    Vc_INTRINSIC Vc_CONST m128  lo128(param256  v) { return avx_cast<m128>(v); }
+    Vc_INTRINSIC Vc_CONST m128d lo128(param256d v) { return avx_cast<m128d>(v); }
+    Vc_INTRINSIC Vc_CONST m128i lo128(param256i v) { return avx_cast<m128i>(v); }
+    Vc_INTRINSIC Vc_CONST m128  hi128(param256  v) { return _mm256_extractf128_ps(v, 1); }
+    Vc_INTRINSIC Vc_CONST m128d hi128(param256d v) { return _mm256_extractf128_pd(v, 1); }
+    Vc_INTRINSIC Vc_CONST m128i hi128(param256i v) { return _mm256_extractf128_si256(v, 1); }
 
     // simplify combining 128-bit registers in 256-bit registers
-    inline __m256  INTRINSIC concat(__m128  a, __m128  b) { return _mm256_insertf128_ps   (avx_cast<__m256 >(a), b, 1); }
-    inline __m256d INTRINSIC concat(__m128d a, __m128d b) { return _mm256_insertf128_pd   (avx_cast<__m256d>(a), b, 1); }
-    inline __m256i INTRINSIC concat(__m128i a, __m128i b) { return _mm256_insertf128_si256(avx_cast<__m256i>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256  concat(param128  a, param128  b) { return _mm256_insertf128_ps   (avx_cast<m256 >(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256d concat(param128d a, param128d b) { return _mm256_insertf128_pd   (avx_cast<m256d>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256i concat(param128i a, param128i b) { return _mm256_insertf128_si256(avx_cast<m256i>(a), b, 1); }
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+    Vc_INTRINSIC Vc_CONST m256  concat(__m128  a, param128  b) { return _mm256_insertf128_ps   (avx_cast<m256 >(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256d concat(__m128d a, param128d b) { return _mm256_insertf128_pd   (avx_cast<m256d>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256i concat(__m128i a, param128i b) { return _mm256_insertf128_si256(avx_cast<m256i>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256  concat(param128  a, __m128  b) { return _mm256_insertf128_ps   (avx_cast<m256 >(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256d concat(param128d a, __m128d b) { return _mm256_insertf128_pd   (avx_cast<m256d>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256i concat(param128i a, __m128i b) { return _mm256_insertf128_si256(avx_cast<m256i>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256  concat(__m128  a, __m128  b) { return _mm256_insertf128_ps   (avx_cast<m256 >(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256d concat(__m128d a, __m128d b) { return _mm256_insertf128_pd   (avx_cast<m256d>(a), b, 1); }
+    Vc_INTRINSIC Vc_CONST m256i concat(__m128i a, __m128i b) { return _mm256_insertf128_si256(avx_cast<m256i>(a), b, 1); }
+#endif
 
     template<typename From, typename To> struct StaticCastHelper {};
-    template<> struct StaticCastHelper<float         , int           > { static _M256I  cast(const _M256   v) { return _mm256_cvttps_epi32(v); } };
-    template<> struct StaticCastHelper<double        , int           > { static _M256I  cast(const _M256D  v) { return avx_cast<_M256I>(_mm256_cvttpd_epi32(v)); } };
-    template<> struct StaticCastHelper<int           , int           > { static _M256I  cast(const _M256I  v) { return v; } };
-    template<> struct StaticCastHelper<unsigned int  , int           > { static _M256I  cast(const _M256I  v) { return v; } };
-    template<> struct StaticCastHelper<short         , int           > { static _M256I  cast(const __m128i v) { return concat(_mm_srai_epi32(_mm_unpacklo_epi16(v, v), 16), _mm_srai_epi32(_mm_unpackhi_epi16(v, v), 16)); } };
-    template<> struct StaticCastHelper<float         , unsigned int  > { static _M256I  cast(const _M256   v) {
+    template<> struct StaticCastHelper<float         , int           > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256  v) { return _mm256_cvttps_epi32(v); } };
+    template<> struct StaticCastHelper<double        , int           > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256d v) { return avx_cast<m256i>(_mm256_cvttpd_epi32(v)); } };
+    template<> struct StaticCastHelper<int           , int           > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256i v) { return v; } };
+    template<> struct StaticCastHelper<unsigned int  , int           > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256i v) { return v; } };
+    template<> struct StaticCastHelper<short         , int           > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param128i   v) { return concat(_mm_srai_epi32(_mm_unpacklo_epi16(v, v), 16), _mm_srai_epi32(_mm_unpackhi_epi16(v, v), 16)); } };
+    template<> struct StaticCastHelper<float         , unsigned int  > { static inline Vc_CONST m256i  cast(param256  v) {
         return _mm256_castps_si256(_mm256_blendv_ps(
                 _mm256_castsi256_ps(_mm256_cvttps_epi32(v)),
-                _mm256_castsi256_ps(_mm256_add_epi32(_mm256_cvttps_epi32(_mm256_sub_ps(v, _mm256_set2power31_ps())), _mm256_set2power31_epu32())),
+                _mm256_castsi256_ps(_mm256_add_epi32(m256i(_mm256_cvttps_epi32(_mm256_sub_ps(v, _mm256_set2power31_ps()))), _mm256_set2power31_epu32())),
                 _mm256_cmpge_ps(v, _mm256_set2power31_ps())
                 ));
 
     } };
-    template<> struct StaticCastHelper<double        , unsigned int  > { static _M256I  cast(const _M256D  v) { return avx_cast<_M256I>(_mm256_cvttpd_epi32(v)); } };
-    template<> struct StaticCastHelper<int           , unsigned int  > { static _M256I  cast(const _M256I  v) { return v; } };
-    template<> struct StaticCastHelper<unsigned int  , unsigned int  > { static _M256I  cast(const _M256I  v) { return v; } };
-    template<> struct StaticCastHelper<unsigned short, unsigned int  > { static _M256I  cast(const __m128i v) { return concat(_mm_srli_epi32(_mm_unpacklo_epi16(v, v), 16), _mm_srli_epi32(_mm_unpackhi_epi16(v, v), 16)); } };
-    template<> struct StaticCastHelper<float         , float         > { static _M256   cast(const _M256   v) { return v; } };
-    template<> struct StaticCastHelper<double        , float         > { static _M256   cast(const _M256D  v) { return avx_cast<_M256>(_mm256_cvtpd_ps(v)); } };
-    template<> struct StaticCastHelper<int           , float         > { static _M256   cast(const _M256I  v) { return _mm256_cvtepi32_ps(v); } };
-    template<> struct StaticCastHelper<unsigned int  , float         > { static _M256   cast(const _M256I  v) {
+    template<> struct StaticCastHelper<double        , unsigned int  > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256d v) { return avx_cast<m256i>(_mm256_cvttpd_epi32(v)); } };
+    template<> struct StaticCastHelper<int           , unsigned int  > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256i v) { return v; } };
+    template<> struct StaticCastHelper<unsigned int  , unsigned int  > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param256i v) { return v; } };
+    template<> struct StaticCastHelper<unsigned short, unsigned int  > { static Vc_ALWAYS_INLINE Vc_CONST m256i  cast(param128i   v) { return concat(_mm_srli_epi32(_mm_unpacklo_epi16(v, v), 16), _mm_srli_epi32(_mm_unpackhi_epi16(v, v), 16)); } };
+    template<> struct StaticCastHelper<float         , float         > { static Vc_ALWAYS_INLINE Vc_CONST m256   cast(param256  v) { return v; } };
+    template<> struct StaticCastHelper<double        , float         > { static Vc_ALWAYS_INLINE Vc_CONST m256   cast(param256d v) { return avx_cast<m256>(_mm256_cvtpd_ps(v)); } };
+    template<> struct StaticCastHelper<int           , float         > { static Vc_ALWAYS_INLINE Vc_CONST m256   cast(param256i v) { return _mm256_cvtepi32_ps(v); } };
+    template<> struct StaticCastHelper<unsigned int  , float         > { static inline Vc_CONST m256   cast(param256i v) {
         return _mm256_blendv_ps(
                 _mm256_cvtepi32_ps(v),
                 _mm256_add_ps(_mm256_cvtepi32_ps(_mm256_sub_epi32(v, _mm256_set2power31_epu32())), _mm256_set2power31_ps()),
                 _mm256_castsi256_ps(_mm256_cmplt_epi32(v, _mm256_setzero_si256()))
                 );
     } };
-    template<> struct StaticCastHelper<short         , float         > { static _M256   cast(const __m128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<short, int>::cast(v)); } };
-    template<> struct StaticCastHelper<unsigned short, float         > { static _M256   cast(const __m128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<unsigned short, unsigned int>::cast(v)); } };
-    template<> struct StaticCastHelper<float         , double        > { static _M256D  cast(const _M256   v) { return _mm256_cvtps_pd(avx_cast<__m128>(v)); } };
-    template<> struct StaticCastHelper<double        , double        > { static _M256D  cast(const _M256D  v) { return v; } };
-    template<> struct StaticCastHelper<int           , double        > { static _M256D  cast(const _M256I  v) { return _mm256_cvtepi32_pd(avx_cast<__m128i>(v)); } };
-    template<> struct StaticCastHelper<unsigned int  , double        > { static _M256D  cast(const _M256I  v) { return _mm256_cvtepi32_pd(avx_cast<__m128i>(v)); } };
-    template<> struct StaticCastHelper<int           , short         > { static __m128i cast(const _M256I  v) { return _mm_packs_epi32(lo128(v), hi128(v)); } };
-    template<> struct StaticCastHelper<float         , short         > { static __m128i cast(const _M256   v) { return StaticCastHelper<int, short>::cast(StaticCastHelper<float, int>::cast(v)); } };
-    template<> struct StaticCastHelper<short         , short         > { static __m128i cast(const __m128i v) { return v; } };
-    template<> struct StaticCastHelper<unsigned short, short         > { static __m128i cast(const __m128i v) { return v; } };
-    template<> struct StaticCastHelper<unsigned int  , unsigned short> { static __m128i cast(const _M256I  v) { return _mm_packus_epi32(lo128(v), hi128(v)); } };
-    template<> struct StaticCastHelper<float         , unsigned short> { static __m128i cast(const _M256   v) { return StaticCastHelper<unsigned int, unsigned short>::cast(StaticCastHelper<float, unsigned int>::cast(v)); } };
-    template<> struct StaticCastHelper<short         , unsigned short> { static __m128i cast(const __m128i v) { return v; } };
-    template<> struct StaticCastHelper<unsigned short, unsigned short> { static __m128i cast(const __m128i v) { return v; } };
-    template<> struct StaticCastHelper<sfloat        , short         > { static __m128i cast(const _M256   v) { return StaticCastHelper<int, short>::cast(StaticCastHelper<float, int>::cast(v)); } };
-    template<> struct StaticCastHelper<sfloat        , unsigned short> { static __m128i cast(const _M256   v) { return StaticCastHelper<unsigned int, unsigned short>::cast(StaticCastHelper<float, unsigned int>::cast(v)); } };
-    template<> struct StaticCastHelper<short         , sfloat        > { static _M256   cast(const __m128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<short, int>::cast(v)); } };
-    template<> struct StaticCastHelper<unsigned short, sfloat        > { static _M256   cast(const __m128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<unsigned short, unsigned int>::cast(v)); } };
+    template<> struct StaticCastHelper<short         , float         > { static Vc_ALWAYS_INLINE Vc_CONST m256  cast(param128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<short, int>::cast(v)); } };
+    template<> struct StaticCastHelper<unsigned short, float         > { static Vc_ALWAYS_INLINE Vc_CONST m256  cast(param128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<unsigned short, unsigned int>::cast(v)); } };
+    template<> struct StaticCastHelper<float         , double        > { static Vc_ALWAYS_INLINE Vc_CONST m256d cast(param256  v) { return _mm256_cvtps_pd(avx_cast<m128>(v)); } };
+    template<> struct StaticCastHelper<double        , double        > { static Vc_ALWAYS_INLINE Vc_CONST m256d cast(param256d v) { return v; } };
+    template<> struct StaticCastHelper<int           , double        > { static Vc_ALWAYS_INLINE Vc_CONST m256d cast(param256i v) { return _mm256_cvtepi32_pd(avx_cast<m128i>(v)); } };
+    template<> struct StaticCastHelper<unsigned int  , double        > { static Vc_ALWAYS_INLINE Vc_CONST m256d cast(param256i v) { return _mm256_cvtepi32_pd(avx_cast<m128i>(v)); } };
+    template<> struct StaticCastHelper<int           , short         > { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param256i v) { return _mm_packs_epi32(lo128(v), hi128(v)); } };
+    template<> struct StaticCastHelper<float         , short         > { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param256  v) { return StaticCastHelper<int, short>::cast(StaticCastHelper<float, int>::cast(v)); } };
+    template<> struct StaticCastHelper<short         , short         > { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param128i v) { return v; } };
+    template<> struct StaticCastHelper<unsigned short, short         > { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param128i v) { return v; } };
+    template<> struct StaticCastHelper<unsigned int  , unsigned short> { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param256i v) { return _mm_packus_epi32(lo128(v), hi128(v)); } };
+    template<> struct StaticCastHelper<float         , unsigned short> { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param256  v) { return StaticCastHelper<unsigned int, unsigned short>::cast(StaticCastHelper<float, unsigned int>::cast(v)); } };
+    template<> struct StaticCastHelper<short         , unsigned short> { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param128i v) { return v; } };
+    template<> struct StaticCastHelper<unsigned short, unsigned short> { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param128i v) { return v; } };
+    template<> struct StaticCastHelper<sfloat        , short         > { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param256  v) { return StaticCastHelper<int, short>::cast(StaticCastHelper<float, int>::cast(v)); } };
+    template<> struct StaticCastHelper<sfloat        , unsigned short> { static Vc_ALWAYS_INLINE Vc_CONST m128i cast(param256  v) { return StaticCastHelper<unsigned int, unsigned short>::cast(StaticCastHelper<float, unsigned int>::cast(v)); } };
+    template<> struct StaticCastHelper<short         , sfloat        > { static Vc_ALWAYS_INLINE Vc_CONST m256  cast(param128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<short, int>::cast(v)); } };
+    template<> struct StaticCastHelper<unsigned short, sfloat        > { static Vc_ALWAYS_INLINE Vc_CONST m256  cast(param128i v) { return _mm256_cvtepi32_ps(StaticCastHelper<unsigned short, unsigned int>::cast(v)); } };
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
+
+#include "undomacros.h"
 
 #endif // AVX_CASTS_H
index 2850865..d1eeab4 100644 (file)
@@ -24,6 +24,7 @@
 #include "const_data.h"
 #include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -32,82 +33,79 @@ namespace AVX
 
     template<typename T> struct IndexesFromZeroData;
     template<> struct IndexesFromZeroData<int> {
-        static const int *address() { return reinterpret_cast<const int *>(&_IndexesFromZero32[0]); }
+        static Vc_ALWAYS_INLINE Vc_CONST const int *address() { return reinterpret_cast<const int *>(&_IndexesFromZero32[0]); }
     };
     template<> struct IndexesFromZeroData<unsigned int> {
-        static const unsigned int *address() { return &_IndexesFromZero32[0]; }
+        static Vc_ALWAYS_INLINE Vc_CONST const unsigned int *address() { return &_IndexesFromZero32[0]; }
     };
     template<> struct IndexesFromZeroData<short> {
-        static const short *address() { return reinterpret_cast<const short *>(&_IndexesFromZero16[0]); }
+        static Vc_ALWAYS_INLINE Vc_CONST const short *address() { return reinterpret_cast<const short *>(&_IndexesFromZero16[0]); }
     };
     template<> struct IndexesFromZeroData<unsigned short> {
-        static const unsigned short *address() { return &_IndexesFromZero16[0]; }
+        static Vc_ALWAYS_INLINE Vc_CONST const unsigned short *address() { return &_IndexesFromZero16[0]; }
     };
     template<> struct IndexesFromZeroData<signed char> {
-        static const signed char *address() { return reinterpret_cast<const signed char *>(&_IndexesFromZero8[0]); }
+        static Vc_ALWAYS_INLINE Vc_CONST const signed char *address() { return reinterpret_cast<const signed char *>(&_IndexesFromZero8[0]); }
     };
     template<> struct IndexesFromZeroData<char> {
-        static const char *address() { return reinterpret_cast<const char *>(&_IndexesFromZero8[0]); }
+        static Vc_ALWAYS_INLINE Vc_CONST const char *address() { return reinterpret_cast<const char *>(&_IndexesFromZero8[0]); }
     };
     template<> struct IndexesFromZeroData<unsigned char> {
-        static const unsigned char *address() { return &_IndexesFromZero8[0]; }
+        static Vc_ALWAYS_INLINE Vc_CONST const unsigned char *address() { return &_IndexesFromZero8[0]; }
     };
 
-    template<typename T> struct Const
+    template<typename _T> struct Const
     {
-        typedef Vector<T> V;
+        typedef Vector<_T> V;
+        typedef typename V::EntryType T;
         typedef typename V::Mask M;
 
-        static inline V CONST_L _1_2pi()  CONST_R { return V(c_sin<T>::data[0]); }
-        static inline V CONST_L _2pi()    CONST_R { return V(c_sin<T>::data[1]); }
-        static inline V CONST_L _pi_2()   CONST_R { return V(c_sin<T>::data[2]); }
-        static inline V CONST_L _pi()     CONST_R { return V(c_sin<T>::data[3]); }
-        static inline V CONST_L _1_3fac() CONST_R { return V(c_sin<T>::data[4]); }
-        static inline V CONST_L _1_5fac() CONST_R { return V(c_sin<T>::data[5]); }
-        static inline V CONST_L _1_7fac() CONST_R { return V(c_sin<T>::data[6]); }
-        static inline V CONST_L _1_9fac() CONST_R { return V(c_sin<T>::data[7]); }
-
-        static inline M CONST_L exponentMask() CONST_R { return M(V(c_log<T>::d(1)).data()); }
-        static inline V CONST_L _1_2()         CONST_R { return V(c_log<T>::d(18)); }
-        static inline V CONST_L _1_sqrt2()     CONST_R { return V(c_log<T>::d(15)); }
-        static inline V CONST_L P(int i)       CONST_R { return V(c_log<T>::d(2 + i)); }
-        static inline V CONST_L Q(int i)       CONST_R { return V(c_log<T>::d(8 + i)); }
-        static inline V CONST_L min()          CONST_R { return V(c_log<T>::d(14)); }
-        static inline V CONST_L ln2_small()    CONST_R { return V(c_log<T>::d(17)); }
-        static inline V CONST_L ln2_large()    CONST_R { return V(c_log<T>::d(16)); }
-        static inline V CONST_L neginf()       CONST_R { return V(c_log<T>::d(13)); }
-        static inline V CONST_L log10_e()      CONST_R { return V(c_log<T>::d(19)); }
-        static inline V CONST_L log2_e()       CONST_R { return V(c_log<T>::d(20)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi_4()        { return V(c_trig<T>::data[0]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi_4_hi()     { return V(c_trig<T>::data[1]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi_4_rem1()   { return V(c_trig<T>::data[2]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi_4_rem2()   { return V(c_trig<T>::data[3]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _1_16()        { return V(c_trig<T>::data[4]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _16()          { return V(c_trig<T>::data[5]); }
+
+        static Vc_ALWAYS_INLINE Vc_CONST V cosCoeff(int i)   { return V(c_trig<T>::data[( 8 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V sinCoeff(int i)   { return V(c_trig<T>::data[(14 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V atanP(int i)      { return V(c_trig<T>::data[(24 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V atanQ(int i)      { return V(c_trig<T>::data[(29 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V atanThrsHi()      { return V(c_trig<T>::data[34]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V atanThrsLo()      { return V(c_trig<T>::data[35]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi_2_rem()       { return V(c_trig<T>::data[36]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V lossThreshold()   { return V(c_trig<T>::data[20]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _4_pi()           { return V(c_trig<T>::data[21]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi_2()           { return V(c_trig<T>::data[22]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _pi()             { return V(c_trig<T>::data[23]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V asinCoeff0(int i) { return V(c_trig<T>::data[(40 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V asinCoeff1(int i) { return V(c_trig<T>::data[(45 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V asinCoeff2(int i) { return V(c_trig<T>::data[(49 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V asinCoeff3(int i) { return V(c_trig<T>::data[(55 + i)]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V smallAsinInput()  { return V(c_trig<T>::data[37]); }
+        static Vc_ALWAYS_INLINE Vc_CONST V largeAsinInput()  { return V(c_trig<T>::data[38]); }
+
+        static Vc_ALWAYS_INLINE Vc_CONST M exponentMask() { return M(V(c_log<T>::d(1)).data()); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _1_2()         { return V(c_log<T>::d(18)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V _1_sqrt2()     { return V(c_log<T>::d(15)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V P(int i)       { return V(c_log<T>::d(2 + i)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V Q(int i)       { return V(c_log<T>::d(8 + i)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V min()          { return V(c_log<T>::d(14)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V ln2_small()    { return V(c_log<T>::d(17)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V ln2_large()    { return V(c_log<T>::d(16)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V neginf()       { return V(c_log<T>::d(13)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V log10_e()      { return V(c_log<T>::d(19)); }
+        static Vc_ALWAYS_INLINE Vc_CONST V log2_e()       { return V(c_log<T>::d(20)); }
+
+        static Vc_ALWAYS_INLINE_L Vc_CONST_L V highMask() Vc_ALWAYS_INLINE_R Vc_CONST_R;
     };
 
-    template<> struct Const<sfloat>
-    {
-        typedef sfloat_v V;
-        typedef V::Mask M;
-
-        static inline V CONST_L _1_2pi()  CONST_R { return V(c_sin<float>::data[0]); }
-        static inline V CONST_L _2pi()    CONST_R { return V(c_sin<float>::data[1]); }
-        static inline V CONST_L _pi_2()   CONST_R { return V(c_sin<float>::data[2]); }
-        static inline V CONST_L _pi()     CONST_R { return V(c_sin<float>::data[3]); }
-        static inline V CONST_L _1_3fac() CONST_R { return V(c_sin<float>::data[4]); }
-        static inline V CONST_L _1_5fac() CONST_R { return V(c_sin<float>::data[5]); }
-        static inline V CONST_L _1_7fac() CONST_R { return V(c_sin<float>::data[6]); }
-        static inline V CONST_L _1_9fac() CONST_R { return V(c_sin<float>::data[7]); }
-
-        static inline M CONST_L exponentMask() CONST_R { return M(V(c_log<float>::d(1)).data()); }
-        static inline V CONST_L _1_2()         CONST_R { return V(c_log<float>::d(18)); }
-        static inline V CONST_L _1_sqrt2()     CONST_R { return V(c_log<float>::d(15)); }
-        static inline V CONST_L P(int i)       CONST_R { return V(c_log<float>::d(2 + i)); }
-        static inline V CONST_L Q(int i)       CONST_R { return V(c_log<float>::d(8 + i)); }
-        static inline V CONST_L min()          CONST_R { return V(c_log<float>::d(14)); }
-        static inline V CONST_L ln2_small()    CONST_R { return V(c_log<float>::d(17)); }
-        static inline V CONST_L ln2_large()    CONST_R { return V(c_log<float>::d(16)); }
-        static inline V CONST_L neginf()       CONST_R { return V(c_log<float>::d(13)); }
-        static inline V CONST_L log10_e()      CONST_R { return V(c_log<float>::d(19)); }
-        static inline V CONST_L log2_e()       CONST_R { return V(c_log<float>::d(20)); }
-    };
+    template<> Vc_ALWAYS_INLINE Vc_CONST Vector<float>  Const<float>::highMask() { return _mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::highMaskFloat)); }
+    template<> Vc_ALWAYS_INLINE Vc_CONST Vector<double> Const<double>::highMask() { return _mm256_broadcast_sd(reinterpret_cast<const double *>(&c_general::highMaskDouble)); }
+    template<> Vc_ALWAYS_INLINE Vc_CONST Vector<sfloat> Const<sfloat>::highMask() { return _mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::highMaskFloat)); }
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #include "undomacros.h"
 
index dadc89b..12c6463 100644 (file)
@@ -21,6 +21,7 @@
 #define VC_AVX_CONST_DATA_H
 
 #include "macros.h"
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -35,35 +36,38 @@ struct STRUCT_ALIGN1(64) c_general
     static const float oneFloat;
     static const unsigned int absMaskFloat[2];
     static const unsigned int signMaskFloat[2];
+    static const unsigned int highMaskFloat;
     static const unsigned short minShort[2];
     static const unsigned short one16[2];
     static const float _2power31;
     static const double oneDouble;
     static const unsigned long long frexpMask;
+    static const unsigned long long highMaskDouble;
 } STRUCT_ALIGN2(64);
 
-template<typename T> struct c_sin
+template<typename T> struct c_trig
 {
     ALIGN(64) static const T data[];
 };
 
 template<typename T> struct c_log
 {
-    typedef float floatAlias MAY_ALIAS;
-    static inline float d(int i) { return *reinterpret_cast<const floatAlias *>(&data[i]); }
+    typedef float floatAlias Vc_MAY_ALIAS;
+    static Vc_ALWAYS_INLINE float d(int i) { return *reinterpret_cast<const floatAlias *>(&data[i]); }
     ALIGN(64) static const unsigned int data[];
 };
 
 template<> struct c_log<double>
 {
     enum VectorSize { Size = 16 / sizeof(double) };
-    typedef double doubleAlias MAY_ALIAS;
-    static inline double d(int i) { return *reinterpret_cast<const doubleAlias *>(&data[i]); }
+    typedef double doubleAlias Vc_MAY_ALIAS;
+    static Vc_ALWAYS_INLINE double d(int i) { return *reinterpret_cast<const doubleAlias *>(&data[i]); }
     ALIGN(64) static const unsigned long long data[];
 };
 
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #include "undomacros.h"
 
index a71c127..6e86fa6 100644 (file)
@@ -26,6 +26,7 @@
 #include <iomanip>
 #endif
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -92,9 +93,10 @@ class DebugStream
 };
 #endif
 
-#define VC_DEBUG ::Vc::AVX::DebugStream(__PRETTY_FUNCTION__, __FILE__, __LINE__)
+#define VC_DEBUG ::AliRoot::Vc::AVX::DebugStream(__PRETTY_FUNCTION__, __FILE__, __LINE__)
 
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #endif // VC_AVX_DEBUG_H
index dd92605..698c59e 100644 (file)
@@ -17,8 +17,7 @@
 
 */
 
-#include "macros.h"
-
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -26,9 +25,9 @@ namespace AVX
 
 inline void deinterleave(double_v &VC_RESTRICT a, double_v &VC_RESTRICT b, double_v &VC_RESTRICT c)
 {   // estimated latency (AVX): 4.5 cycles
-    const __m256d tmp0 = Mem::shuffle128<X0, Y1>(a.data(), b.data());
-    const __m256d tmp1 = Mem::shuffle128<X1, Y0>(a.data(), c.data());
-    const __m256d tmp2 = Mem::shuffle128<X0, Y1>(b.data(), c.data());
+    const m256d tmp0 = Mem::shuffle128<X0, Y1>(a.data(), b.data());
+    const m256d tmp1 = Mem::shuffle128<X1, Y0>(a.data(), c.data());
+    const m256d tmp2 = Mem::shuffle128<X0, Y1>(b.data(), c.data());
     a.data() = Mem::shuffle<X0, Y1, X2, Y3>(tmp0, tmp1);
     b.data() = Mem::shuffle<X1, Y0, X3, Y2>(tmp0, tmp2);
     c.data() = Mem::shuffle<X0, Y1, X2, Y3>(tmp1, tmp2);
@@ -40,14 +39,14 @@ inline void deinterleave(float_v &VC_RESTRICT a, float_v &VC_RESTRICT b, float_v
     // a = [a0 b0 c0 a1 b1 c1 a2 b2] 332 = 211+121
     // b = [c2 a3 b3 c3 a4 b4 c4 a5] 323 = 112+211
     // c = [b5 c5 a6 b6 c6 a7 b7 c7] 233 = 121+112
-    const __m256 ac0 = Mem::shuffle128<X0, Y0>(a.data(), c.data()); // a0 b0 c0 a1 b5 c5 a6 b6
-    const __m256 ac1 = Mem::shuffle128<X1, Y1>(a.data(), c.data()); // b1 c1 a2 b2 c6 a7 b7 c7
+    const m256 ac0 = Mem::shuffle128<X0, Y0>(a.data(), c.data()); // a0 b0 c0 a1 b5 c5 a6 b6
+    const m256 ac1 = Mem::shuffle128<X1, Y1>(a.data(), c.data()); // b1 c1 a2 b2 c6 a7 b7 c7
 
-    __m256 tmp0 = Mem::blend<X0, Y1, X2, X3, Y4, X5, X6, Y7>( ac0, b.data());
+    m256 tmp0 = Mem::blend<X0, Y1, X2, X3, Y4, X5, X6, Y7>( ac0, b.data());
            tmp0 = Mem::blend<X0, X1, Y2, X3, X4, Y5, X6, X7>(tmp0,      ac1); // a0 a3 a2 a1 a4 a7 a6 a5
-    __m256 tmp1 = Mem::blend<X0, X1, Y2, X3, X4, Y5, X6, X7>( ac0, b.data());
+    m256 tmp1 = Mem::blend<X0, X1, Y2, X3, X4, Y5, X6, X7>( ac0, b.data());
            tmp1 = Mem::blend<Y0, X1, X2, Y3, X4, X5, Y6, X7>(tmp1,      ac1); // b1 b0 b3 b2 b5 b4 b7 b6
-    __m256 tmp2 = Mem::blend<Y0, X1, X2, Y3, X4, X5, Y6, X7>( ac0, b.data());
+    m256 tmp2 = Mem::blend<Y0, X1, X2, Y3, X4, X5, Y6, X7>( ac0, b.data());
            tmp2 = Mem::blend<X0, Y1, X2, X3, Y4, X5, X6, Y7>(tmp2,      ac1); // c2 c1 c0 c3 c6 c5 c4 c7
 
     a.data() = Mem::permute<X0, X3, X2, X1>(tmp0);
@@ -74,14 +73,14 @@ inline void deinterleave(Vector<short> &VC_RESTRICT a, Vector<short> &VC_RESTRIC
     // a = [a0 b0 c0 a1 b1 c1 a2 b2] 332 = 211+121
     // b = [c2 a3 b3 c3 a4 b4 c4 a5] 323 = 112+211
     // c = [b5 c5 a6 b6 c6 a7 b7 c7] 233 = 121+112
-    __m128i ac0 = _mm_unpacklo_epi64(a.data(), c.data()); // a0 b0 c0 a1 b5 c5 a6 b6
-    __m128i ac1 = _mm_unpackhi_epi64(a.data(), c.data()); // b1 c1 a2 b2 c6 a7 b7 c7
+    m128i ac0 = _mm_unpacklo_epi64(a.data(), c.data()); // a0 b0 c0 a1 b5 c5 a6 b6
+    m128i ac1 = _mm_unpackhi_epi64(a.data(), c.data()); // b1 c1 a2 b2 c6 a7 b7 c7
 
-    __m128i tmp0 = Mem::blend<X0, Y1, X2, X3, Y4, X5, X6, Y7>( ac0, b.data());
+    m128i tmp0 = Mem::blend<X0, Y1, X2, X3, Y4, X5, X6, Y7>( ac0, b.data());
             tmp0 = Mem::blend<X0, X1, Y2, X3, X4, Y5, X6, X7>(tmp0,      ac1); // a0 a3 a2 a1 a4 a7 a6 a5
-    __m128i tmp1 = Mem::blend<X0, X1, Y2, X3, X4, Y5, X6, X7>( ac0, b.data());
+    m128i tmp1 = Mem::blend<X0, X1, Y2, X3, X4, Y5, X6, X7>( ac0, b.data());
             tmp1 = Mem::blend<Y0, X1, X2, Y3, X4, X5, Y6, X7>(tmp1,      ac1); // b1 b0 b3 b2 b5 b4 b7 b6
-    __m128i tmp2 = Mem::blend<Y0, X1, X2, Y3, X4, X5, Y6, X7>( ac0, b.data());
+    m128i tmp2 = Mem::blend<Y0, X1, X2, Y3, X4, X5, Y6, X7>( ac0, b.data());
             tmp2 = Mem::blend<X0, Y1, X2, X3, Y4, X5, X6, Y7>(tmp2,      ac1); // c2 c1 c0 c3 c6 c5 c4 c7
 
     a.data() = Mem::permuteHi<X4, X7, X6, X5>(Mem::permuteLo<X0, X3, X2, X1>(tmp0));
@@ -100,11 +99,11 @@ inline void deinterleave(Vector<float> &a, Vector<float> &b)
 {
     // a7 a6 a5 a4 a3 a2 a1 a0
     // b7 b6 b5 b4 b3 b2 b1 b0
-    const _M256 tmp0 = Reg::permute128<Y0, X0>(a.data(), b.data()); // b3 b2 b1 b0 a3 a2 a1 a0
-    const _M256 tmp1 = Reg::permute128<Y1, X1>(a.data(), b.data()); // b7 b6 b5 b4 a7 a6 a5 a4
+    const m256 tmp0 = Reg::permute128<Y0, X0>(a.data(), b.data()); // b3 b2 b1 b0 a3 a2 a1 a0
+    const m256 tmp1 = Reg::permute128<Y1, X1>(a.data(), b.data()); // b7 b6 b5 b4 a7 a6 a5 a4
 
-    const _M256 tmp2 = _mm256_unpacklo_ps(tmp0, tmp1); // b5 b1 b4 b0 a5 a1 a4 a0
-    const _M256 tmp3 = _mm256_unpackhi_ps(tmp0, tmp1); // b7 b3 b6 b2 a7 a3 a6 a2
+    const m256 tmp2 = _mm256_unpacklo_ps(tmp0, tmp1); // b5 b1 b4 b0 a5 a1 a4 a0
+    const m256 tmp3 = _mm256_unpackhi_ps(tmp0, tmp1); // b7 b3 b6 b2 a7 a3 a6 a2
 
     a.data() = _mm256_unpacklo_ps(tmp2, tmp3); // b6 b4 b2 b0 a6 a4 a2 a0
     b.data() = _mm256_unpackhi_ps(tmp2, tmp3); // b7 b5 b3 b1 a7 a5 a3 a1
@@ -112,20 +111,20 @@ inline void deinterleave(Vector<float> &a, Vector<float> &b)
 
 inline void deinterleave(Vector<short> &a, Vector<short> &b)
 {
-    __m128i tmp0 = _mm_unpacklo_epi16(a.data(), b.data()); // a0 a4 b0 b4 a1 a5 b1 b5
-    __m128i tmp1 = _mm_unpackhi_epi16(a.data(), b.data()); // a2 a6 b2 b6 a3 a7 b3 b7
-    __m128i tmp2 = _mm_unpacklo_epi16(tmp0, tmp1); // a0 a2 a4 a6 b0 b2 b4 b6
-    __m128i tmp3 = _mm_unpackhi_epi16(tmp0, tmp1); // a1 a3 a5 a7 b1 b3 b5 b7
+    m128i tmp0 = _mm_unpacklo_epi16(a.data(), b.data()); // a0 a4 b0 b4 a1 a5 b1 b5
+    m128i tmp1 = _mm_unpackhi_epi16(a.data(), b.data()); // a2 a6 b2 b6 a3 a7 b3 b7
+    m128i tmp2 = _mm_unpacklo_epi16(tmp0, tmp1); // a0 a2 a4 a6 b0 b2 b4 b6
+    m128i tmp3 = _mm_unpackhi_epi16(tmp0, tmp1); // a1 a3 a5 a7 b1 b3 b5 b7
     a.data() = _mm_unpacklo_epi16(tmp2, tmp3);
     b.data() = _mm_unpackhi_epi16(tmp2, tmp3);
 }
 
 inline void deinterleave(Vector<unsigned short> &a, Vector<unsigned short> &b)
 {
-    __m128i tmp0 = _mm_unpacklo_epi16(a.data(), b.data()); // a0 a4 b0 b4 a1 a5 b1 b5
-    __m128i tmp1 = _mm_unpackhi_epi16(a.data(), b.data()); // a2 a6 b2 b6 a3 a7 b3 b7
-    __m128i tmp2 = _mm_unpacklo_epi16(tmp0, tmp1); // a0 a2 a4 a6 b0 b2 b4 b6
-    __m128i tmp3 = _mm_unpackhi_epi16(tmp0, tmp1); // a1 a3 a5 a7 b1 b3 b5 b7
+    m128i tmp0 = _mm_unpacklo_epi16(a.data(), b.data()); // a0 a4 b0 b4 a1 a5 b1 b5
+    m128i tmp1 = _mm_unpackhi_epi16(a.data(), b.data()); // a2 a6 b2 b6 a3 a7 b3 b7
+    m128i tmp2 = _mm_unpacklo_epi16(tmp0, tmp1); // a0 a2 a4 a6 b0 b2 b4 b6
+    m128i tmp3 = _mm_unpackhi_epi16(tmp0, tmp1); // a1 a3 a5 a7 b1 b3 b5 b7
     a.data() = _mm_unpacklo_epi16(tmp2, tmp3);
     b.data() = _mm_unpackhi_epi16(tmp2, tmp3);
 }
@@ -147,7 +146,8 @@ template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
 template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
         float_v &a, float_v &b, const short *m, A align)
 {
-    const __m256i tmp = Vc::AVX::VectorHelper<__m256i>::load(m, align);
+    using Vc::AVX::m256i;
+    const m256i tmp = Vc::AVX::VectorHelper<m256i>::load(m, align);
     a.data() = _mm256_cvtepi32_ps(Vc::AVX::concat(
                 _mm_srai_epi32(_mm_slli_epi32(AVX::lo128(tmp), 16), 16),
                 _mm_srai_epi32(_mm_slli_epi32(AVX::hi128(tmp), 16), 16)));
@@ -159,7 +159,8 @@ template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
 template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
         float_v &a, float_v &b, const unsigned short *m, A align)
 {
-    const __m256i tmp = Vc::AVX::VectorHelper<__m256i>::load(m, align);
+    using Vc::AVX::m256i;
+    const m256i tmp = Vc::AVX::VectorHelper<m256i>::load(m, align);
     a.data() = _mm256_cvtepi32_ps(Vc::AVX::concat(
                 _mm_blend_epi16(AVX::lo128(tmp), _mm_setzero_si128(), 0xaa),
                 _mm_blend_epi16(AVX::hi128(tmp), _mm_setzero_si128(), 0xaa)));
@@ -182,8 +183,8 @@ template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
     a.load(m, align);
     b.load(m + double_v::Size, align);
 
-    __m256d tmp0 = Mem::shuffle128<Vc::X0, Vc::Y0>(a.data(), b.data()); // b1 b0 a1 a0
-    __m256d tmp1 = Mem::shuffle128<Vc::X1, Vc::Y1>(a.data(), b.data()); // b3 b2 a3 a2
+    m256d tmp0 = Mem::shuffle128<Vc::X0, Vc::Y0>(a.data(), b.data()); // b1 b0 a1 a0
+    m256d tmp1 = Mem::shuffle128<Vc::X1, Vc::Y1>(a.data(), b.data()); // b3 b2 a3 a2
 
     a.data() = _mm256_unpacklo_pd(tmp0, tmp1); // b2 b0 a2 a0
     b.data() = _mm256_unpackhi_pd(tmp0, tmp1); // b3 b1 a3 a1
@@ -192,23 +193,25 @@ template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
 template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
         int_v &a, int_v &b, const int *m, A align)
 {
+    using Vc::AVX::m256;
     a.load(m, align);
     b.load(m + int_v::Size, align);
 
-    const __m256 tmp0 = AVX::avx_cast<__m256>(Mem::shuffle128<Vc::X0, Vc::Y0>(a.data(), b.data()));
-    const __m256 tmp1 = AVX::avx_cast<__m256>(Mem::shuffle128<Vc::X1, Vc::Y1>(a.data(), b.data()));
+    const m256 tmp0 = AVX::avx_cast<m256>(Mem::shuffle128<Vc::X0, Vc::Y0>(a.data(), b.data()));
+    const m256 tmp1 = AVX::avx_cast<m256>(Mem::shuffle128<Vc::X1, Vc::Y1>(a.data(), b.data()));
 
-    const __m256 tmp2 = _mm256_unpacklo_ps(tmp0, tmp1); // b5 b1 b4 b0 a5 a1 a4 a0
-    const __m256 tmp3 = _mm256_unpackhi_ps(tmp0, tmp1); // b7 b3 b6 b2 a7 a3 a6 a2
+    const m256 tmp2 = _mm256_unpacklo_ps(tmp0, tmp1); // b5 b1 b4 b0 a5 a1 a4 a0
+    const m256 tmp3 = _mm256_unpackhi_ps(tmp0, tmp1); // b7 b3 b6 b2 a7 a3 a6 a2
 
-    a.data() = AVX::avx_cast<__m256i>(_mm256_unpacklo_ps(tmp2, tmp3)); // b6 b4 b2 b0 a6 a4 a2 a0
-    b.data() = AVX::avx_cast<__m256i>(_mm256_unpackhi_ps(tmp2, tmp3)); // b7 b5 b3 b1 a7 a5 a3 a1
+    a.data() = AVX::avx_cast<m256i>(_mm256_unpacklo_ps(tmp2, tmp3)); // b6 b4 b2 b0 a6 a4 a2 a0
+    b.data() = AVX::avx_cast<m256i>(_mm256_unpackhi_ps(tmp2, tmp3)); // b7 b5 b3 b1 a7 a5 a3 a1
 }
 
 template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
         int_v &a, int_v &b, const short *m, A align)
 {
-    const __m256i tmp = Vc::AVX::VectorHelper<__m256i>::load(m, align);
+    using Vc::AVX::m256i;
+    const m256i tmp = Vc::AVX::VectorHelper<m256i>::load(m, align);
     a.data() = Vc::AVX::concat(
                 _mm_srai_epi32(_mm_slli_epi32(AVX::lo128(tmp), 16), 16),
                 _mm_srai_epi32(_mm_slli_epi32(AVX::hi128(tmp), 16), 16));
@@ -220,23 +223,25 @@ template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
 template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
         uint_v &a, uint_v &b, const unsigned int *m, A align)
 {
+    using Vc::AVX::m256;
     a.load(m, align);
     b.load(m + uint_v::Size, align);
 
-    const __m256 tmp0 = AVX::avx_cast<__m256>(Mem::shuffle128<Vc::X0, Vc::Y0>(a.data(), b.data()));
-    const __m256 tmp1 = AVX::avx_cast<__m256>(Mem::shuffle128<Vc::X1, Vc::Y1>(a.data(), b.data()));
+    const m256 tmp0 = AVX::avx_cast<m256>(Mem::shuffle128<Vc::X0, Vc::Y0>(a.data(), b.data()));
+    const m256 tmp1 = AVX::avx_cast<m256>(Mem::shuffle128<Vc::X1, Vc::Y1>(a.data(), b.data()));
 
-    const __m256 tmp2 = _mm256_unpacklo_ps(tmp0, tmp1); // b5 b1 b4 b0 a5 a1 a4 a0
-    const __m256 tmp3 = _mm256_unpackhi_ps(tmp0, tmp1); // b7 b3 b6 b2 a7 a3 a6 a2
+    const m256 tmp2 = _mm256_unpacklo_ps(tmp0, tmp1); // b5 b1 b4 b0 a5 a1 a4 a0
+    const m256 tmp3 = _mm256_unpackhi_ps(tmp0, tmp1); // b7 b3 b6 b2 a7 a3 a6 a2
 
-    a.data() = AVX::avx_cast<__m256i>(_mm256_unpacklo_ps(tmp2, tmp3)); // b6 b4 b2 b0 a6 a4 a2 a0
-    b.data() = AVX::avx_cast<__m256i>(_mm256_unpackhi_ps(tmp2, tmp3)); // b7 b5 b3 b1 a7 a5 a3 a1
+    a.data() = AVX::avx_cast<m256i>(_mm256_unpacklo_ps(tmp2, tmp3)); // b6 b4 b2 b0 a6 a4 a2 a0
+    b.data() = AVX::avx_cast<m256i>(_mm256_unpackhi_ps(tmp2, tmp3)); // b7 b5 b3 b1 a7 a5 a3 a1
 }
 
 template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
         uint_v &a, uint_v &b, const unsigned short *m, A align)
 {
-    const __m256i tmp = Vc::AVX::VectorHelper<__m256i>::load(m, align);
+    using Vc::AVX::m256i;
+    const m256i tmp = Vc::AVX::VectorHelper<m256i>::load(m, align);
     a.data() = Vc::AVX::concat(
                 _mm_srli_epi32(_mm_slli_epi32(AVX::lo128(tmp), 16), 16),
                 _mm_srli_epi32(_mm_slli_epi32(AVX::hi128(tmp), 16), 16));
@@ -263,7 +268,7 @@ template<typename A> inline void HelperImpl<Vc::AVXImpl>::deinterleave(
 
 // only support M == V::EntryType -> no specialization
 template<typename V, typename M, typename A>
-inline void HelperImpl<Vc::AVXImpl>::deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
+inline Vc_FLATTEN void HelperImpl<Vc::AVXImpl>::deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
         V &VC_RESTRICT c, const M *VC_RESTRICT memory, A align)
 {
     a.load(&memory[0 * V::Size], align);
@@ -274,3 +279,4 @@ inline void HelperImpl<Vc::AVXImpl>::deinterleave(V &VC_RESTRICT a, V &VC_RESTRI
 
 } // namespace Internal
 } // namespace Vc
+} // namespace AliRoot
index 583209c..7906a27 100644 (file)
 #ifdef __GNUC__
 template<typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x1.data()));
 }
 template<typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x1.data()));
 }
 template<typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x2.data()), "x"(x1.data()));
 }
 template<typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x2.data()), "+x"(x1.data()));
 }
 template<typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x3.data()), "x"(x2.data()), "x"(x1.data()));
 }
 template<typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x3.data()), "+x"(x2.data()), "+x"(x1.data()));
 }
 template<typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x4.data()), "x"(x3.data()), "x"(x2.data()), "x"(x1.data()));
 }
 template<typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x4.data()), "+x"(x3.data()), "+x"(x2.data()), "+x"(x1.data()));
 }
 template<typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x5.data()), "x"(x4.data()), "x"(x3.data()), "x"(x2.data()), "x"(x1.data()));
 }
 template<typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x5.data()), "+x"(x4.data()), "+x"(x3.data()), "+x"(x2.data()), "+x"(x1.data()));
 }
 template<typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T6> &x6, const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T6> &x6, const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x6.data()), "x"(x5.data()), "x"(x4.data()), "x"(x3.data()), "x"(x2.data()), "x"(x1.data()));
 }
 template<typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T6> &x6, Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T6> &x6, Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x6.data()), "+x"(x5.data()), "+x"(x4.data()), "+x"(x3.data()), "+x"(x2.data()), "+x"(x1.data()));
 }
 template<typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T7> &x7, const Vector<T6> &x6, const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T7> &x7, const Vector<T6> &x6, const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x7.data()), "x"(x6.data()), "x"(x5.data()), "x"(x4.data()), "x"(x3.data()), "x"(x2.data()), "x"(x1.data()));
 }
 template<typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T7> &x7, Vector<T6> &x6, Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T7> &x7, Vector<T6> &x6, Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x7.data()), "+x"(x6.data()), "+x"(x5.data()), "+x"(x4.data()), "+x"(x3.data()), "+x"(x2.data()), "+x"(x1.data()));
 }
 template<typename T8, typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T8> &x8, const Vector<T7> &x7, const Vector<T6> &x6, const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T8> &x8, const Vector<T7> &x7, const Vector<T6> &x6, const Vector<T5> &x5, const Vector<T4> &x4, const Vector<T3> &x3, const Vector<T2> &x2, const Vector<T1> &x1) {
   __asm__ __volatile__(""::"x"(x8.data()), "x"(x7.data()), "x"(x6.data()), "x"(x5.data()), "x"(x4.data()), "x"(x3.data()), "x"(x2.data()), "x"(x1.data()));
 }
 template<typename T8, typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T8> &x8, Vector<T7> &x7, Vector<T6> &x6, Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T8> &x8, Vector<T7> &x7, Vector<T6> &x6, Vector<T5> &x5, Vector<T4> &x4, Vector<T3> &x3, Vector<T2> &x2, Vector<T1> &x1) {
   __asm__ __volatile__("":"+x"(x8.data()), "+x"(x7.data()), "+x"(x6.data()), "+x"(x5.data()), "+x"(x4.data()), "+x"(x3.data()), "+x"(x2.data()), "+x"(x1.data()));
 }
 #elif defined(VC_MSVC)
 #pragma optimize("g", off)
 template<typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T6> &/*x6*/, const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T6> &/*x6*/, const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T6> &/*x6*/, Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T6> &/*x6*/, Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T7> &/*x7*/, const Vector<T6> &/*x6*/, const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T7> &/*x7*/, const Vector<T6> &/*x6*/, const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T7> &/*x7*/, Vector<T6> &/*x6*/, Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T7> &/*x7*/, Vector<T6> &/*x6*/, Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #pragma optimize("g", off)
 template<typename T8, typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegisters(const Vector<T8> &/*x8*/, const Vector<T7> &/*x7*/, const Vector<T6> &/*x6*/, const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegisters(const Vector<T8> &/*x8*/, const Vector<T7> &/*x7*/, const Vector<T6> &/*x6*/, const Vector<T5> &/*x5*/, const Vector<T4> &/*x4*/, const Vector<T3> &/*x3*/, const Vector<T2> &/*x2*/, const Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", off)
 template<typename T8, typename T7, typename T6, typename T5, typename T4, typename T3, typename T2, typename T1>
-static inline void ALWAYS_INLINE forceToRegistersDirty(Vector<T8> &/*x8*/, Vector<T7> &/*x7*/, Vector<T6> &/*x6*/, Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
+static Vc_ALWAYS_INLINE void forceToRegistersDirty(Vector<T8> &/*x8*/, Vector<T7> &/*x7*/, Vector<T6> &/*x6*/, Vector<T5> &/*x5*/, Vector<T4> &/*x4*/, Vector<T3> &/*x3*/, Vector<T2> &/*x2*/, Vector<T1> &/*x1*/) {
 }
 #pragma optimize("g", on)
 #else
index d665cb5..c20d65d 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace Internal
@@ -56,47 +57,48 @@ template<> struct HelperImpl<Vc::AVXImpl>
     template<typename A> static void deinterleave(ushort_v &, ushort_v &, const unsigned short *, A);
 
     template<typename V, typename M, typename A>
-        static inline void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
-                V &VC_RESTRICT c, const M *VC_RESTRICT memory, A align);
+        static Vc_ALWAYS_INLINE_L void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
+                V &VC_RESTRICT c, const M *VC_RESTRICT memory, A align) Vc_ALWAYS_INLINE_R;
 
     template<typename V, typename M, typename A>
-        static inline void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
+        static Vc_ALWAYS_INLINE_L void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
                 V &VC_RESTRICT c, V &VC_RESTRICT d,
-                const M *VC_RESTRICT memory, A align);
+                const M *VC_RESTRICT memory, A align) Vc_ALWAYS_INLINE_R;
 
     template<typename V, typename M, typename A>
-        static inline void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
+        static Vc_ALWAYS_INLINE_L void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
                 V &VC_RESTRICT c, V &VC_RESTRICT d, V &VC_RESTRICT e,
-                const M *VC_RESTRICT memory, A align);
+                const M *VC_RESTRICT memory, A align) Vc_ALWAYS_INLINE_R;
 
     template<typename V, typename M, typename A>
-        static inline void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
+        static Vc_ALWAYS_INLINE_L void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
                 V &VC_RESTRICT c, V &VC_RESTRICT d, V &VC_RESTRICT e,
-                V &VC_RESTRICT f, const M *VC_RESTRICT memory, A align);
+                V &VC_RESTRICT f, const M *VC_RESTRICT memory, A align) Vc_ALWAYS_INLINE_R;
 
     template<typename V, typename M, typename A>
-        static inline void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
+        static Vc_ALWAYS_INLINE_L void deinterleave(V &VC_RESTRICT a, V &VC_RESTRICT b,
                 V &VC_RESTRICT c, V &VC_RESTRICT d, V &VC_RESTRICT e,
                 V &VC_RESTRICT f, V &VC_RESTRICT g, V &VC_RESTRICT h,
-                const M *VC_RESTRICT memory, A align);
+                const M *VC_RESTRICT memory, A align) Vc_ALWAYS_INLINE_R;
 
-    static inline void ALWAYS_INLINE_L prefetchForOneRead(const void *addr) ALWAYS_INLINE_R;
-    static inline void ALWAYS_INLINE_L prefetchForModify(const void *addr) ALWAYS_INLINE_R;
-    static inline void ALWAYS_INLINE_L prefetchClose(const void *addr) ALWAYS_INLINE_R;
-    static inline void ALWAYS_INLINE_L prefetchMid(const void *addr) ALWAYS_INLINE_R;
-    static inline void ALWAYS_INLINE_L prefetchFar(const void *addr) ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void prefetchForOneRead(const void *addr) Vc_ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void prefetchForModify(const void *addr) Vc_ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void prefetchClose(const void *addr) Vc_ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void prefetchMid(const void *addr) Vc_ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void prefetchFar(const void *addr) Vc_ALWAYS_INLINE_R;
 
     template<Vc::MallocAlignment A>
-    static inline ALWAYS_INLINE_L void *malloc(size_t n) ALWAYS_INLINE_R;
-    static inline ALWAYS_INLINE_L void free(void *p) ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void *malloc(size_t n) Vc_ALWAYS_INLINE_R;
+    static Vc_ALWAYS_INLINE_L void free(void *p) Vc_ALWAYS_INLINE_R;
 };
 
 } // namespace Internal
 } // namespace Vc
+} // namespace AliRoot
 
-#include "undomacros.h"
 #include "deinterleave.tcc"
 #include "prefetches.tcc"
 #include "helperimpl.tcc"
+#include "undomacros.h"
 
 #endif // VC_AVX_HELPERIMPL_H
index 2ca8eb4..b6150cb 100644 (file)
 #ifndef VC_AVX_HELPERIMPL_TCC
 #define VC_AVX_HELPERIMPL_TCC
 
+namespace AliRoot {
 namespace Vc
 {
 namespace Internal
 {
 
 template<size_t X>
-static inline size_t nextMultipleOf(size_t value)
+static _VC_CONSTEXPR size_t nextMultipleOf(size_t value)
 {
-    const size_t offset = value % X;
-    if ( offset > 0 ) {
-        return value + X - offset;
-    }
-    return value;
+    return (value % X) > 0 ? value + X - (value % X) : value;
 }
 
 template<Vc::MallocAlignment A>
-inline ALWAYS_INLINE void *HelperImpl<AVXImpl>::malloc(size_t n)
+Vc_ALWAYS_INLINE void *HelperImpl<AVXImpl>::malloc(size_t n)
 {
     switch (A) {
         case Vc::AlignOnVector:
@@ -55,12 +52,13 @@ inline ALWAYS_INLINE void *HelperImpl<AVXImpl>::malloc(size_t n)
     }
 }
 
-inline ALWAYS_INLINE void HelperImpl<AVXImpl>::free(void *p)
+Vc_ALWAYS_INLINE void HelperImpl<AVXImpl>::free(void *p)
 {
     _mm_free(p);
 }
 
 } // namespace Internal
 } // namespace Vc
+} // namespace AliRoot
 
 #endif // VC_AVX_HELPERIMPL_TCC
diff --git a/Vc/include/Vc/avx/interleavedmemory.tcc b/Vc/include/Vc/avx/interleavedmemory.tcc
new file mode 100644 (file)
index 0000000..23a2c40
--- /dev/null
@@ -0,0 +1,890 @@
+/*  This file is part of the Vc library. {{{
+
+    Copyright (C) 2012 Matthias Kretz <kretz@kde.org>
+
+    Vc is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser General Public License as
+    published by the Free Software Foundation, either version 3 of
+    the License, or (at your option) any later version.
+
+    Vc is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with Vc.  If not, see <http://www.gnu.org/licenses/>.
+
+}}}*/
+
+#ifndef VC_AVX_INTERLEAVEDMEMORY_TCC
+#define VC_AVX_INTERLEAVEDMEMORY_TCC
+
+#include "macros.h"
+
+namespace AliRoot {
+namespace Vc
+{
+namespace Common
+{
+
+namespace
+{
+template<typename V, int Size, size_t VSize> struct InterleaveImpl;
+template<typename V> struct InterleaveImpl<V, 8, 16> {
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1)
+    {
+        const m128i tmp0 = _mm_unpacklo_epi16(v0.data(), v1.data());
+        const m128i tmp1 = _mm_unpackhi_epi16(v0.data(), v1.data());
+#ifdef __x86_64__
+        const long long tmp00 = _mm_cvtsi128_si64(tmp0);
+        const long long tmp01 = _mm_cvtsi128_si64(_mm_unpackhi_epi64(tmp0, tmp0));
+        const long long tmp10 = _mm_cvtsi128_si64(tmp1);
+        const long long tmp11 = _mm_cvtsi128_si64(_mm_unpackhi_epi64(tmp1, tmp1));
+        *reinterpret_cast<int *>(&data[i[0]]) = tmp00;
+        *reinterpret_cast<int *>(&data[i[1]]) = tmp00 >> 32;
+        *reinterpret_cast<int *>(&data[i[2]]) = tmp01;
+        *reinterpret_cast<int *>(&data[i[3]]) = tmp01 >> 32;
+        *reinterpret_cast<int *>(&data[i[4]]) = tmp10;
+        *reinterpret_cast<int *>(&data[i[5]]) = tmp10 >> 32;
+        *reinterpret_cast<int *>(&data[i[6]]) = tmp11;
+        *reinterpret_cast<int *>(&data[i[7]]) = tmp11 >> 32;
+#else
+        *reinterpret_cast<int *>(&data[i[0]]) = _mm_cvtsi128_si32(tmp0);
+        *reinterpret_cast<int *>(&data[i[1]]) = _mm_extract_epi32(tmp0, 1);
+        *reinterpret_cast<int *>(&data[i[2]]) = _mm_extract_epi32(tmp0, 2);
+        *reinterpret_cast<int *>(&data[i[3]]) = _mm_extract_epi32(tmp0, 3);
+        *reinterpret_cast<int *>(&data[i[4]]) = _mm_cvtsi128_si32(tmp1);
+        *reinterpret_cast<int *>(&data[i[5]]) = _mm_extract_epi32(tmp1, 1);
+        *reinterpret_cast<int *>(&data[i[6]]) = _mm_extract_epi32(tmp1, 2);
+        *reinterpret_cast<int *>(&data[i[7]]) = _mm_extract_epi32(tmp1, 3);
+#endif
+    }/*}}}*/
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1, const typename V::AsArg v2)
+    {
+#ifdef VC_USE_MASKMOV_SCATTER
+        const m128i maskLo = _mm_set_epi16(0, 0, 0, 0, 0, -1, -1, -1);
+        const m128i maskHi = _mm_set_epi16(0, -1, -1, -1, 0, 0, 0, 0);
+        typename V::EntryType *const dataHi = data - 4;
+        const m128i tmp0 = _mm_unpacklo_epi16(v0.data(), v2.data());
+        const m128i tmp1 = _mm_unpackhi_epi16(v0.data(), v2.data());
+        const m128i tmp2 = _mm_unpacklo_epi16(v1.data(), v1.data());
+        const m128i tmp3 = _mm_unpackhi_epi16(v1.data(), v1.data());
+
+        const m128i tmp4 = _mm_unpacklo_epi16(tmp0, tmp2);
+        const m128i tmp5 = _mm_unpackhi_epi16(tmp0, tmp2);
+        const m128i tmp6 = _mm_unpacklo_epi16(tmp1, tmp3);
+        const m128i tmp7 = _mm_unpackhi_epi16(tmp1, tmp3);
+        _mm_maskmoveu_si128(tmp4, maskLo, reinterpret_cast<char *>(&data[i[0]]));
+        _mm_maskmoveu_si128(tmp4, maskHi, reinterpret_cast<char *>(&dataHi[i[1]]));
+        _mm_maskmoveu_si128(tmp5, maskLo, reinterpret_cast<char *>(&data[i[2]]));
+        _mm_maskmoveu_si128(tmp5, maskHi, reinterpret_cast<char *>(&dataHi[i[3]]));
+        _mm_maskmoveu_si128(tmp6, maskLo, reinterpret_cast<char *>(&data[i[4]]));
+        _mm_maskmoveu_si128(tmp6, maskHi, reinterpret_cast<char *>(&dataHi[i[5]]));
+        _mm_maskmoveu_si128(tmp7, maskLo, reinterpret_cast<char *>(&data[i[6]]));
+        _mm_maskmoveu_si128(tmp7, maskHi, reinterpret_cast<char *>(&dataHi[i[7]]));
+#else
+        interleave(data, i, v0, v1);
+        v2.scatter(data + 2, i);
+#endif
+    }/*}}}*/
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1,
+            const typename V::AsArg v2, const typename V::AsArg v3)
+    {
+        const m128i tmp0 = _mm_unpacklo_epi16(v0.data(), v2.data());
+        const m128i tmp1 = _mm_unpackhi_epi16(v0.data(), v2.data());
+        const m128i tmp2 = _mm_unpacklo_epi16(v1.data(), v3.data());
+        const m128i tmp3 = _mm_unpackhi_epi16(v1.data(), v3.data());
+
+        const m128i tmp4 = _mm_unpacklo_epi16(tmp0, tmp2);
+        const m128i tmp5 = _mm_unpackhi_epi16(tmp0, tmp2);
+        const m128i tmp6 = _mm_unpacklo_epi16(tmp1, tmp3);
+        const m128i tmp7 = _mm_unpackhi_epi16(tmp1, tmp3);
+
+        _mm_storel_epi64(reinterpret_cast<__m128i *>(&data[i[0]]), tmp4);
+        _mm_storel_epi64(reinterpret_cast<__m128i *>(&data[i[2]]), tmp5);
+        _mm_storel_epi64(reinterpret_cast<__m128i *>(&data[i[4]]), tmp6);
+        _mm_storel_epi64(reinterpret_cast<__m128i *>(&data[i[6]]), tmp7);
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[1]]), _mm_castsi128_ps(tmp4));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[3]]), _mm_castsi128_ps(tmp5));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[5]]), _mm_castsi128_ps(tmp6));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[7]]), _mm_castsi128_ps(tmp7));
+    }/*}}}*/
+};
+template<typename V> struct InterleaveImpl<V, 8, 32> {
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1)
+    {
+        using namespace Vc::AVX;
+        // [0a 1a 0b 1b 0e 1e 0f 1f]:
+        const m256 tmp0 = _mm256_unpacklo_ps(AVX::avx_cast<m256>(v0.data()), AVX::avx_cast<m256>(v1.data()));
+        // [0c 1c 0d 1d 0g 1g 0h 1h]:
+        const m256 tmp1 = _mm256_unpackhi_ps(AVX::avx_cast<m256>(v0.data()), AVX::avx_cast<m256>(v1.data()));
+        _mm_storel_pi(reinterpret_cast<__m64 *>(&data[i[0]]), lo128(tmp0));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[1]]), lo128(tmp0));
+        _mm_storel_pi(reinterpret_cast<__m64 *>(&data[i[2]]), lo128(tmp1));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[3]]), lo128(tmp1));
+        _mm_storel_pi(reinterpret_cast<__m64 *>(&data[i[4]]), hi128(tmp0));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[5]]), hi128(tmp0));
+        _mm_storel_pi(reinterpret_cast<__m64 *>(&data[i[6]]), hi128(tmp1));
+        _mm_storeh_pi(reinterpret_cast<__m64 *>(&data[i[7]]), hi128(tmp1));
+    }/*}}}*/
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1, const typename V::AsArg v2)
+    {
+        using namespace Vc::AVX;
+#ifdef VC_USE_MASKMOV_SCATTER
+        // [0a 2a 0b 2b 0e 2e 0f 2f]:
+        const m256 tmp0 = _mm256_unpacklo_ps(AVX::avx_cast<m256>(v0.data()), AVX::avx_cast<m256>(v2.data()));
+        // [0c 2c 0d 2d 0g 2g 0h 2h]:
+        const m256 tmp1 = _mm256_unpackhi_ps(AVX::avx_cast<m256>(v0.data()), AVX::avx_cast<m256>(v2.data()));
+        // [1a __ 1b __ 1e __ 1f __]:
+        const m256 tmp2 = _mm256_unpacklo_ps(AVX::avx_cast<m256>(v1.data()), AVX::avx_cast<m256>(v1.data()));
+        // [1c __ 1d __ 1g __ 1h __]:
+        const m256 tmp3 = _mm256_unpackhi_ps(AVX::avx_cast<m256>(v1.data()), AVX::avx_cast<m256>(v1.data()));
+        const m256 tmp4 = _mm256_unpacklo_ps(tmp0, tmp2);
+        const m256 tmp5 = _mm256_unpackhi_ps(tmp0, tmp2);
+        const m256 tmp6 = _mm256_unpacklo_ps(tmp1, tmp3);
+        const m256 tmp7 = _mm256_unpackhi_ps(tmp1, tmp3);
+        const m128i mask = _mm_set_epi32(0, -1, -1, -1);
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[0]]), mask, lo128(tmp4));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[1]]), mask, lo128(tmp5));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[2]]), mask, lo128(tmp6));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[3]]), mask, lo128(tmp7));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[4]]), mask, hi128(tmp4));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[5]]), mask, hi128(tmp5));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[6]]), mask, hi128(tmp6));
+        _mm_maskstore_ps(reinterpret_cast<float *>(&data[i[7]]), mask, hi128(tmp7));
+#else
+        interleave(data, i, v0, v1);
+        v2.scatter(data + 2, i);
+#endif
+    }/*}}}*/
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1,
+            const typename V::AsArg v2, const typename V::AsArg v3)
+    {
+        using namespace Vc::AVX;
+        const m256 tmp0 = _mm256_unpacklo_ps(AVX::avx_cast<m256>(v0.data()), AVX::avx_cast<m256>(v2.data()));
+        const m256 tmp1 = _mm256_unpackhi_ps(AVX::avx_cast<m256>(v0.data()), AVX::avx_cast<m256>(v2.data()));
+        const m256 tmp2 = _mm256_unpacklo_ps(AVX::avx_cast<m256>(v1.data()), AVX::avx_cast<m256>(v3.data()));
+        const m256 tmp3 = _mm256_unpackhi_ps(AVX::avx_cast<m256>(v1.data()), AVX::avx_cast<m256>(v3.data()));
+        const m256 tmp4 = _mm256_unpacklo_ps(tmp0, tmp2);
+        const m256 tmp5 = _mm256_unpackhi_ps(tmp0, tmp2);
+        const m256 tmp6 = _mm256_unpacklo_ps(tmp1, tmp3);
+        const m256 tmp7 = _mm256_unpackhi_ps(tmp1, tmp3);
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[0]]), lo128(tmp4));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[1]]), lo128(tmp5));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[2]]), lo128(tmp6));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[3]]), lo128(tmp7));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[4]]), hi128(tmp4));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[5]]), hi128(tmp5));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[6]]), hi128(tmp6));
+        _mm_storeu_ps(reinterpret_cast<float *>(&data[i[7]]), hi128(tmp7));
+    }/*}}}*/
+};
+template<typename V> struct InterleaveImpl<V, 4, 32> {
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1)
+    {
+        using namespace Vc::AVX;
+        const m256d tmp0 = _mm256_unpacklo_pd(v0.data(), v1.data());
+        const m256d tmp1 = _mm256_unpackhi_pd(v0.data(), v1.data());
+        _mm_storeu_pd(&data[i[0]], lo128(tmp0));
+        _mm_storeu_pd(&data[i[1]], lo128(tmp1));
+        _mm_storeu_pd(&data[i[2]], hi128(tmp0));
+        _mm_storeu_pd(&data[i[3]], hi128(tmp1));
+    }/*}}}*/
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1, const typename V::AsArg v2)
+    {
+        using namespace Vc::AVX;
+#ifdef VC_USE_MASKMOV_SCATTER
+        const m256d tmp0 = _mm256_unpacklo_pd(v0.data(), v1.data());
+        const m256d tmp1 = _mm256_unpackhi_pd(v0.data(), v1.data());
+        const m256d tmp2 = _mm256_unpacklo_pd(v2.data(), v2.data());
+        const m256d tmp3 = _mm256_unpackhi_pd(v2.data(), v2.data());
+
+#if defined(VC_MSVC) && (VC_MSVC < 170000000 || !defined(_WIN64))
+        // MSVC needs to be at Version 2012 before _mm256_set_epi64x works
+        const m256i mask = AVX::concat(_mm_setallone_si128(), _mm_set_epi32(0, 0, -1, -1));
+#else
+        const m256i mask = _mm256_set_epi64x(0, -1, -1, -1);
+#endif
+        _mm256_maskstore_pd(&data[i[0]], mask, Mem::shuffle128<X0, Y0>(tmp0, tmp2));
+        _mm256_maskstore_pd(&data[i[1]], mask, Mem::shuffle128<X0, Y0>(tmp1, tmp3));
+        _mm256_maskstore_pd(&data[i[2]], mask, Mem::shuffle128<X1, Y1>(tmp0, tmp2));
+        _mm256_maskstore_pd(&data[i[3]], mask, Mem::shuffle128<X1, Y1>(tmp1, tmp3));
+#else
+        interleave(data, i, v0, v1);
+        v2.scatter(data + 2, i);
+#endif
+    }/*}}}*/
+    static inline void interleave(typename V::EntryType *const data, const typename V::IndexType &i,/*{{{*/
+            const typename V::AsArg v0, const typename V::AsArg v1,
+            const typename V::AsArg v2, const typename V::AsArg v3)
+    {
+        using namespace Vc::AVX;
+        // 0a 1a 0c 1c:
+        const m256d tmp0 = _mm256_unpacklo_pd(v0.data(), v1.data());
+        // 0b 1b 0b 1b:
+        const m256d tmp1 = _mm256_unpackhi_pd(v0.data(), v1.data());
+        // 2a 3a 2c 3c:
+        const m256d tmp2 = _mm256_unpacklo_pd(v2.data(), v3.data());
+        // 2b 3b 2b 3b:
+        const m256d tmp3 = _mm256_unpackhi_pd(v2.data(), v3.data());
+        _mm256_storeu_pd(&data[i[0]], Mem::shuffle128<X0, Y0>(tmp0, tmp2));
+        _mm256_storeu_pd(&data[i[1]], Mem::shuffle128<X0, Y0>(tmp1, tmp3));
+        _mm256_storeu_pd(&data[i[2]], Mem::shuffle128<X1, Y1>(tmp0, tmp2));
+        _mm256_storeu_pd(&data[i[3]], Mem::shuffle128<X1, Y1>(tmp1, tmp3));
+    }/*}}}*/
+};
+} // anonymous namespace
+
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data, m_indexes, v0, v1);
+}/*}}}*/
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1, const typename V::AsArg v2)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data, m_indexes, v0, v1, v2);
+}/*}}}*/
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1, const typename V::AsArg v2, const typename V::AsArg v3)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data, m_indexes, v0, v1, v2, v3);
+}/*}}}*/
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1, const typename V::AsArg v2, const typename V::AsArg v3, const typename V::AsArg v4)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data, m_indexes, v0, v1, v2, v3);
+    v4.scatter(m_data + 4, m_indexes);
+}/*}}}*/
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1, const typename V::AsArg v2, const typename V::AsArg v3, const typename V::AsArg v4,
+        const typename V::AsArg v5)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data    , m_indexes, v0, v1, v2, v3);
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data + 4, m_indexes, v4, v5);
+}/*}}}*/
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1, const typename V::AsArg v2, const typename V::AsArg v3, const typename V::AsArg v4,
+        const typename V::AsArg v5, const typename V::AsArg v6)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data + 0, m_indexes, v0, v1, v2, v3);
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data + 4, m_indexes, v4, v5, v6);
+}/*}}}*/
+template<typename V> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::interleave(const typename V::AsArg v0,/*{{{*/
+        const typename V::AsArg v1, const typename V::AsArg v2, const typename V::AsArg v3, const typename V::AsArg v4,
+        const typename V::AsArg v5, const typename V::AsArg v6, const typename V::AsArg v7)
+{
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data + 0, m_indexes, v0, v1, v2, v3);
+    InterleaveImpl<V, V::Size, sizeof(V)>::interleave(m_data + 4, m_indexes, v4, v5, v6, v7);
+}/*}}}*/
+
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1) const/*{{{*/
+{
+    const m128  il0 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[0]])); // a0 b0
+    const m128  il2 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[2]])); // a2 b2
+    const m128  il4 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[4]])); // a4 b4
+    const m128  il6 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[6]])); // a6 b6
+    const m128 il01 = _mm_loadh_pi(             il0, reinterpret_cast<__m64 const *>(&m_data[m_indexes[1]])); // a0 b0 a1 b1
+    const m128 il23 = _mm_loadh_pi(             il2, reinterpret_cast<__m64 const *>(&m_data[m_indexes[3]])); // a2 b2 a3 b3
+    const m128 il45 = _mm_loadh_pi(             il4, reinterpret_cast<__m64 const *>(&m_data[m_indexes[5]])); // a4 b4 a5 b5
+    const m128 il67 = _mm_loadh_pi(             il6, reinterpret_cast<__m64 const *>(&m_data[m_indexes[7]])); // a6 b6 a7 b7
+
+    const m256 tmp2 = AVX::concat(il01, il45);
+    const m256 tmp3 = AVX::concat(il23, il67);
+
+    const m256 tmp0 = _mm256_unpacklo_ps(tmp2, tmp3);
+    const m256 tmp1 = _mm256_unpackhi_ps(tmp2, tmp3);
+
+    v0.data() = _mm256_unpacklo_ps(tmp0, tmp1);
+    v1.data() = _mm256_unpackhi_ps(tmp0, tmp1);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1, float_v &v2) const/*{{{*/
+{
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0]]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1]]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2]]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3]]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4]]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5]]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6]]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7]]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v0.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v1.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v2.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1, float_v &v2, float_v &v3) const/*{{{*/
+{
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0]]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1]]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2]]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3]]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4]]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5]]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6]]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7]]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v0.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v1.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v2.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+    v3.data() = _mm256_unpackhi_ps(cd0246, cd1357);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1, float_v &v2, float_v &v3, float_v &v4) const/*{{{*/
+{
+    v4.gather(m_data, m_indexes + I(4));
+    deinterleave(v0, v1, v2, v3);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1, float_v &v2, float_v &v3, float_v &v4, float_v &v5) const/*{{{*/
+{
+    deinterleave(v0, v1, v2, v3);
+    const m128  il0 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[0] + 4])); // a0 b0
+    const m128  il2 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[2] + 4])); // a2 b2
+    const m128  il4 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[4] + 4])); // a4 b4
+    const m128  il6 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[6] + 4])); // a6 b6
+    const m128 il01 = _mm_loadh_pi(             il0, reinterpret_cast<__m64 const *>(&m_data[m_indexes[1] + 4])); // a0 b0 a1 b1
+    const m128 il23 = _mm_loadh_pi(             il2, reinterpret_cast<__m64 const *>(&m_data[m_indexes[3] + 4])); // a2 b2 a3 b3
+    const m128 il45 = _mm_loadh_pi(             il4, reinterpret_cast<__m64 const *>(&m_data[m_indexes[5] + 4])); // a4 b4 a5 b5
+    const m128 il67 = _mm_loadh_pi(             il6, reinterpret_cast<__m64 const *>(&m_data[m_indexes[7] + 4])); // a6 b6 a7 b7
+
+    const m256 tmp2 = AVX::concat(il01, il45);
+    const m256 tmp3 = AVX::concat(il23, il67);
+
+    const m256 tmp0 = _mm256_unpacklo_ps(tmp2, tmp3);
+    const m256 tmp1 = _mm256_unpackhi_ps(tmp2, tmp3);
+
+    v4.data() = _mm256_unpacklo_ps(tmp0, tmp1);
+    v5.data() = _mm256_unpackhi_ps(tmp0, tmp1);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1, float_v &v2, float_v &v3, float_v &v4, float_v &v5, float_v &v6) const/*{{{*/
+{
+    deinterleave(v0, v1, v2, v3);
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0] + 4]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1] + 4]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2] + 4]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3] + 4]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4] + 4]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5] + 4]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6] + 4]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7] + 4]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v4.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v5.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v6.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<float_v>::deinterleave(float_v &v0, float_v &v1, float_v &v2, float_v &v3, float_v &v4, float_v &v5, float_v &v6, float_v &v7) const/*{{{*/
+{
+    deinterleave(v0, v1, v2, v3);
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0] + 4]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1] + 4]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2] + 4]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3] + 4]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4] + 4]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5] + 4]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6] + 4]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7] + 4]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v4.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v5.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v6.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+    v7.data() = _mm256_unpackhi_ps(cd0246, cd1357);
+}/*}}}*/
+
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1) const/*{{{*/
+{
+    const m128  il0 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[0]])); // a0 b0
+    const m128  il2 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[2]])); // a2 b2
+    const m128  il4 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[4]])); // a4 b4
+    const m128  il6 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[6]])); // a6 b6
+    const m128 il01 = _mm_loadh_pi(             il0, reinterpret_cast<__m64 const *>(&m_data[m_indexes[1]])); // a0 b0 a1 b1
+    const m128 il23 = _mm_loadh_pi(             il2, reinterpret_cast<__m64 const *>(&m_data[m_indexes[3]])); // a2 b2 a3 b3
+    const m128 il45 = _mm_loadh_pi(             il4, reinterpret_cast<__m64 const *>(&m_data[m_indexes[5]])); // a4 b4 a5 b5
+    const m128 il67 = _mm_loadh_pi(             il6, reinterpret_cast<__m64 const *>(&m_data[m_indexes[7]])); // a6 b6 a7 b7
+
+    const m256 tmp2 = AVX::concat(il01, il45);
+    const m256 tmp3 = AVX::concat(il23, il67);
+
+    const m256 tmp0 = _mm256_unpacklo_ps(tmp2, tmp3);
+    const m256 tmp1 = _mm256_unpackhi_ps(tmp2, tmp3);
+
+    v0.data() = _mm256_unpacklo_ps(tmp0, tmp1);
+    v1.data() = _mm256_unpackhi_ps(tmp0, tmp1);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1, sfloat_v &v2) const/*{{{*/
+{
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0]]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1]]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2]]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3]]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4]]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5]]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6]]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7]]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v0.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v1.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v2.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1, sfloat_v &v2, sfloat_v &v3) const/*{{{*/
+{
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0]]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1]]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2]]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3]]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4]]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5]]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6]]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7]]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v0.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v1.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v2.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+    v3.data() = _mm256_unpackhi_ps(cd0246, cd1357);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1, sfloat_v &v2, sfloat_v &v3, sfloat_v &v4) const/*{{{*/
+{
+    v4.gather(m_data, m_indexes + I(4));
+    deinterleave(v0, v1, v2, v3);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1, sfloat_v &v2, sfloat_v &v3, sfloat_v &v4, sfloat_v &v5) const/*{{{*/
+{
+    deinterleave(v0, v1, v2, v3);
+    const m128  il0 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[0] + 4])); // a0 b0
+    const m128  il2 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[2] + 4])); // a2 b2
+    const m128  il4 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[4] + 4])); // a4 b4
+    const m128  il6 = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64 const *>(&m_data[m_indexes[6] + 4])); // a6 b6
+    const m128 il01 = _mm_loadh_pi(             il0, reinterpret_cast<__m64 const *>(&m_data[m_indexes[1] + 4])); // a0 b0 a1 b1
+    const m128 il23 = _mm_loadh_pi(             il2, reinterpret_cast<__m64 const *>(&m_data[m_indexes[3] + 4])); // a2 b2 a3 b3
+    const m128 il45 = _mm_loadh_pi(             il4, reinterpret_cast<__m64 const *>(&m_data[m_indexes[5] + 4])); // a4 b4 a5 b5
+    const m128 il67 = _mm_loadh_pi(             il6, reinterpret_cast<__m64 const *>(&m_data[m_indexes[7] + 4])); // a6 b6 a7 b7
+
+    const m256 tmp2 = AVX::concat(il01, il45);
+    const m256 tmp3 = AVX::concat(il23, il67);
+
+    const m256 tmp0 = _mm256_unpacklo_ps(tmp2, tmp3);
+    const m256 tmp1 = _mm256_unpackhi_ps(tmp2, tmp3);
+
+    v4.data() = _mm256_unpacklo_ps(tmp0, tmp1);
+    v5.data() = _mm256_unpackhi_ps(tmp0, tmp1);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1, sfloat_v &v2, sfloat_v &v3, sfloat_v &v4, sfloat_v &v5, sfloat_v &v6) const/*{{{*/
+{
+    deinterleave(v0, v1, v2, v3);
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0] + 4]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1] + 4]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2] + 4]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3] + 4]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4] + 4]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5] + 4]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6] + 4]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7] + 4]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v4.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v5.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v6.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<sfloat_v>::deinterleave(sfloat_v &v0, sfloat_v &v1, sfloat_v &v2, sfloat_v &v3, sfloat_v &v4, sfloat_v &v5, sfloat_v &v6, sfloat_v &v7) const/*{{{*/
+{
+    deinterleave(v0, v1, v2, v3);
+    const m128  il0 = _mm_loadu_ps(&m_data[m_indexes[0] + 4]); // a0 b0 c0 d0
+    const m128  il1 = _mm_loadu_ps(&m_data[m_indexes[1] + 4]); // a1 b1 c1 d1
+    const m128  il2 = _mm_loadu_ps(&m_data[m_indexes[2] + 4]); // a2 b2 c2 d2
+    const m128  il3 = _mm_loadu_ps(&m_data[m_indexes[3] + 4]); // a3 b3 c3 d3
+    const m128  il4 = _mm_loadu_ps(&m_data[m_indexes[4] + 4]); // a4 b4 c4 d4
+    const m128  il5 = _mm_loadu_ps(&m_data[m_indexes[5] + 4]); // a5 b5 c5 d5
+    const m128  il6 = _mm_loadu_ps(&m_data[m_indexes[6] + 4]); // a6 b6 c6 d6
+    const m128  il7 = _mm_loadu_ps(&m_data[m_indexes[7] + 4]); // a7 b7 c7 d7
+
+    const m256 il04 = AVX::concat(il0, il4);
+    const m256 il15 = AVX::concat(il1, il5);
+    const m256 il26 = AVX::concat(il2, il6);
+    const m256 il37 = AVX::concat(il3, il7);
+    const m256 ab0246 = _mm256_unpacklo_ps(il04, il26);
+    const m256 ab1357 = _mm256_unpacklo_ps(il15, il37);
+    const m256 cd0246 = _mm256_unpackhi_ps(il04, il26);
+    const m256 cd1357 = _mm256_unpackhi_ps(il15, il37);
+    v4.data() = _mm256_unpacklo_ps(ab0246, ab1357);
+    v5.data() = _mm256_unpackhi_ps(ab0246, ab1357);
+    v6.data() = _mm256_unpacklo_ps(cd0246, cd1357);
+    v7.data() = _mm256_unpackhi_ps(cd0246, cd1357);
+}/*}}}*/
+
+static Vc_ALWAYS_INLINE void _avx_deinterleave_double(const double *VC_RESTRICT data, const uint_v &indexes, double_v &v0, double_v &v1)/*{{{*/
+{
+    const m256d ab02 = AVX::concat(_mm_loadu_pd(&data[indexes[0]]), _mm_loadu_pd(&data[indexes[2]]));
+    const m256d ab13 = AVX::concat(_mm_loadu_pd(&data[indexes[1]]), _mm_loadu_pd(&data[indexes[3]]));
+
+    v0.data() = _mm256_unpacklo_pd(ab02, ab13);
+    v1.data() = _mm256_unpackhi_pd(ab02, ab13);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1, double_v &v2) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+    v2.gather(m_data + 2, m_indexes);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1, double_v &v2, double_v &v3) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+    _avx_deinterleave_double(m_data + 2, m_indexes, v2, v3);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1, double_v &v2, double_v &v3, double_v &v4) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+    _avx_deinterleave_double(m_data + 2, m_indexes, v2, v3);
+    v4.gather(m_data + 4, m_indexes);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1, double_v &v2, double_v &v3, double_v &v4, double_v &v5) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+    _avx_deinterleave_double(m_data + 2, m_indexes, v2, v3);
+    _avx_deinterleave_double(m_data + 4, m_indexes, v4, v5);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1, double_v &v2, double_v &v3, double_v &v4, double_v &v5, double_v &v6) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+    _avx_deinterleave_double(m_data + 2, m_indexes, v2, v3);
+    _avx_deinterleave_double(m_data + 4, m_indexes, v4, v5);
+    v6.gather(m_data + 6, m_indexes);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<double_v>::deinterleave(double_v &v0, double_v &v1, double_v &v2, double_v &v3, double_v &v4, double_v &v5, double_v &v6, double_v &v7) const/*{{{*/
+{
+    _avx_deinterleave_double(m_data    , m_indexes, v0, v1);
+    _avx_deinterleave_double(m_data + 2, m_indexes, v2, v3);
+    _avx_deinterleave_double(m_data + 4, m_indexes, v4, v5);
+    _avx_deinterleave_double(m_data + 6, m_indexes, v6, v7);
+}/*}}}*/
+
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1) const {/*{{{*/
+    const m128i a = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_cvtsi32_si128(*reinterpret_cast<const int *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+}
+/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1,/*{{{*/
+        short_v &v2) const {
+    const m128i a = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+    const m128i tmp6  = _mm_unpackhi_epi16(tmp2, tmp3); // c0 c2 c4 c6 d0 d2 d4 d6
+    const m128i tmp7  = _mm_unpackhi_epi16(tmp4, tmp5); // c1 c3 c5 c7 d1 d3 d5 d7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+    v2.data() = _mm_unpacklo_epi16(tmp6, tmp7);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1,/*{{{*/
+        short_v &v2, short_v &v3) const {
+    const m128i a = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+    const m128i tmp6  = _mm_unpackhi_epi16(tmp2, tmp3); // c0 c2 c4 c6 d0 d2 d4 d6
+    const m128i tmp7  = _mm_unpackhi_epi16(tmp4, tmp5); // c1 c3 c5 c7 d1 d3 d5 d7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+    v2.data() = _mm_unpacklo_epi16(tmp6, tmp7);
+    v3.data() = _mm_unpackhi_epi16(tmp6, tmp7);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1,/*{{{*/
+        short_v &v2, short_v &v3, short_v &v4) const {
+    const m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+    const m128i tmp10 = _mm_unpackhi_epi16(a, e); // e0 e4 f0 f4 g0 g4 h0 h4
+    const m128i tmp11 = _mm_unpackhi_epi16(c, g); // e1 e5 f1 f5 g1 g5 h1 h5
+    const m128i tmp12 = _mm_unpackhi_epi16(b, f); // e2 e6 f2 f6 g2 g6 h2 h6
+    const m128i tmp13 = _mm_unpackhi_epi16(d, h); // e3 e7 f3 f7 g3 g7 h3 h7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+    const m128i tmp6  = _mm_unpackhi_epi16(tmp2, tmp3); // c0 c2 c4 c6 d0 d2 d4 d6
+    const m128i tmp7  = _mm_unpackhi_epi16(tmp4, tmp5); // c1 c3 c5 c7 d1 d3 d5 d7
+    const m128i tmp8  = _mm_unpacklo_epi16(tmp10, tmp11); // e0 e2 e4 e6 f0 f2 f4 f6
+    const m128i tmp9  = _mm_unpacklo_epi16(tmp12, tmp13); // e1 e3 e5 e7 f1 f3 f5 f7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+    v2.data() = _mm_unpacklo_epi16(tmp6, tmp7);
+    v3.data() = _mm_unpackhi_epi16(tmp6, tmp7);
+    v4.data() = _mm_unpacklo_epi16(tmp8, tmp9);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1,/*{{{*/
+        short_v &v2, short_v &v3, short_v &v4, short_v &v5) const {
+    const m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+    const m128i tmp10 = _mm_unpackhi_epi16(a, e); // e0 e4 f0 f4 g0 g4 h0 h4
+    const m128i tmp11 = _mm_unpackhi_epi16(c, g); // e1 e5 f1 f5 g1 g5 h1 h5
+    const m128i tmp12 = _mm_unpackhi_epi16(b, f); // e2 e6 f2 f6 g2 g6 h2 h6
+    const m128i tmp13 = _mm_unpackhi_epi16(d, h); // e3 e7 f3 f7 g3 g7 h3 h7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+    const m128i tmp6  = _mm_unpackhi_epi16(tmp2, tmp3); // c0 c2 c4 c6 d0 d2 d4 d6
+    const m128i tmp7  = _mm_unpackhi_epi16(tmp4, tmp5); // c1 c3 c5 c7 d1 d3 d5 d7
+    const m128i tmp8  = _mm_unpacklo_epi16(tmp10, tmp11); // e0 e2 e4 e6 f0 f2 f4 f6
+    const m128i tmp9  = _mm_unpacklo_epi16(tmp12, tmp13); // e1 e3 e5 e7 f1 f3 f5 f7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+    v2.data() = _mm_unpacklo_epi16(tmp6, tmp7);
+    v3.data() = _mm_unpackhi_epi16(tmp6, tmp7);
+    v4.data() = _mm_unpacklo_epi16(tmp8, tmp9);
+    v5.data() = _mm_unpackhi_epi16(tmp8, tmp9);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1,/*{{{*/
+        short_v &v2, short_v &v3, short_v &v4, short_v &v5, short_v &v6) const {
+    const m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+    const m128i tmp10 = _mm_unpackhi_epi16(a, e); // e0 e4 f0 f4 g0 g4 h0 h4
+    const m128i tmp11 = _mm_unpackhi_epi16(c, g); // e1 e5 f1 f5 g1 g5 h1 h5
+    const m128i tmp12 = _mm_unpackhi_epi16(b, f); // e2 e6 f2 f6 g2 g6 h2 h6
+    const m128i tmp13 = _mm_unpackhi_epi16(d, h); // e3 e7 f3 f7 g3 g7 h3 h7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+    const m128i tmp6  = _mm_unpackhi_epi16(tmp2, tmp3); // c0 c2 c4 c6 d0 d2 d4 d6
+    const m128i tmp7  = _mm_unpackhi_epi16(tmp4, tmp5); // c1 c3 c5 c7 d1 d3 d5 d7
+    const m128i tmp8  = _mm_unpacklo_epi16(tmp10, tmp11); // e0 e2 e4 e6 f0 f2 f4 f6
+    const m128i tmp9  = _mm_unpacklo_epi16(tmp12, tmp13); // e1 e3 e5 e7 f1 f3 f5 f7
+    const m128i tmp14 = _mm_unpackhi_epi16(tmp10, tmp11); // g0 g2 g4 g6 h0 h2 h4 h6
+    const m128i tmp15 = _mm_unpackhi_epi16(tmp12, tmp13); // g1 g3 g5 g7 h1 h3 h5 h7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+    v2.data() = _mm_unpacklo_epi16(tmp6, tmp7);
+    v3.data() = _mm_unpackhi_epi16(tmp6, tmp7);
+    v4.data() = _mm_unpacklo_epi16(tmp8, tmp9);
+    v5.data() = _mm_unpackhi_epi16(tmp8, tmp9);
+    v6.data() = _mm_unpacklo_epi16(tmp14, tmp15);
+}/*}}}*/
+template<> inline void InterleavedMemoryAccessBase<short_v>::deinterleave(short_v &v0, short_v &v1,/*{{{*/
+        short_v &v2, short_v &v3, short_v &v4, short_v &v5, short_v &v6, short_v &v7) const {
+    const m128i a = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[0]]));
+    const m128i b = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[1]]));
+    const m128i c = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[2]]));
+    const m128i d = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[3]]));
+    const m128i e = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[4]]));
+    const m128i f = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[5]]));
+    const m128i g = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[6]]));
+    const m128i h = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&m_data[m_indexes[7]]));
+
+    const m128i tmp2  = _mm_unpacklo_epi16(a, e); // a0 a4 b0 b4 c0 c4 d0 d4
+    const m128i tmp4  = _mm_unpacklo_epi16(b, f); // a1 a5 b1 b5 c1 c5 d1 d5
+    const m128i tmp3  = _mm_unpacklo_epi16(c, g); // a2 a6 b2 b6 c2 c6 d2 d6
+    const m128i tmp5  = _mm_unpacklo_epi16(d, h); // a3 a7 b3 b7 c3 c7 d3 d7
+    const m128i tmp10 = _mm_unpackhi_epi16(a, e); // e0 e4 f0 f4 g0 g4 h0 h4
+    const m128i tmp11 = _mm_unpackhi_epi16(c, g); // e1 e5 f1 f5 g1 g5 h1 h5
+    const m128i tmp12 = _mm_unpackhi_epi16(b, f); // e2 e6 f2 f6 g2 g6 h2 h6
+    const m128i tmp13 = _mm_unpackhi_epi16(d, h); // e3 e7 f3 f7 g3 g7 h3 h7
+
+    const m128i tmp0  = _mm_unpacklo_epi16(tmp2, tmp3); // a0 a2 a4 a6 b0 b2 b4 b6
+    const m128i tmp1  = _mm_unpacklo_epi16(tmp4, tmp5); // a1 a3 a5 a7 b1 b3 b5 b7
+    const m128i tmp6  = _mm_unpackhi_epi16(tmp2, tmp3); // c0 c2 c4 c6 d0 d2 d4 d6
+    const m128i tmp7  = _mm_unpackhi_epi16(tmp4, tmp5); // c1 c3 c5 c7 d1 d3 d5 d7
+    const m128i tmp8  = _mm_unpacklo_epi16(tmp10, tmp11); // e0 e2 e4 e6 f0 f2 f4 f6
+    const m128i tmp9  = _mm_unpacklo_epi16(tmp12, tmp13); // e1 e3 e5 e7 f1 f3 f5 f7
+    const m128i tmp14 = _mm_unpackhi_epi16(tmp10, tmp11); // g0 g2 g4 g6 h0 h2 h4 h6
+    const m128i tmp15 = _mm_unpackhi_epi16(tmp12, tmp13); // g1 g3 g5 g7 h1 h3 h5 h7
+
+    v0.data() = _mm_unpacklo_epi16(tmp0, tmp1);
+    v1.data() = _mm_unpackhi_epi16(tmp0, tmp1);
+    v2.data() = _mm_unpacklo_epi16(tmp6, tmp7);
+    v3.data() = _mm_unpackhi_epi16(tmp6, tmp7);
+    v4.data() = _mm_unpacklo_epi16(tmp8, tmp9);
+    v5.data() = _mm_unpackhi_epi16(tmp8, tmp9);
+    v6.data() = _mm_unpacklo_epi16(tmp14, tmp15);
+    v7.data() = _mm_unpackhi_epi16(tmp14, tmp15);
+}/*}}}*/
+
+// forward types of equal size - ugly, but it works/*{{{*/
+#define _forward(V, V2) \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1)); \
+} \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1, V &v2) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1), \
+            reinterpret_cast<V2 &>(v2)); \
+} \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1, V &v2, V &v3) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1), \
+            reinterpret_cast<V2 &>(v2), reinterpret_cast<V2 &>(v3)); \
+} \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1, V &v2, V &v3, \
+        V &v4) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1), \
+            reinterpret_cast<V2 &>(v2), reinterpret_cast<V2 &>(v3), reinterpret_cast<V2 &>(v4)); \
+} \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1, V &v2, V &v3, \
+        V &v4, V &v5) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1), \
+            reinterpret_cast<V2 &>(v2), reinterpret_cast<V2 &>(v3), reinterpret_cast<V2 &>(v4), \
+            reinterpret_cast<V2 &>(v5)); \
+} \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1, V &v2, V &v3, \
+        V &v4, V &v5, V &v6) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1), \
+            reinterpret_cast<V2 &>(v2), reinterpret_cast<V2 &>(v3), reinterpret_cast<V2 &>(v4), \
+            reinterpret_cast<V2 &>(v5), reinterpret_cast<V2 &>(v6)); \
+} \
+template<> Vc_ALWAYS_INLINE void InterleavedMemoryAccessBase<V>::deinterleave(V &v0, V &v1, V &v2, V &v3, \
+        V &v4, V &v5, V &v6, V &v7) const { \
+    reinterpret_cast<const InterleavedMemoryAccessBase<V2> *>(this)->deinterleave(reinterpret_cast<V2 &>(v0), reinterpret_cast<V2 &>(v1), \
+            reinterpret_cast<V2 &>(v2), reinterpret_cast<V2 &>(v3), reinterpret_cast<V2 &>(v4), \
+            reinterpret_cast<V2 &>(v5), reinterpret_cast<V2 &>(v6), reinterpret_cast<V2 &>(v7)); \
+}
+_forward( int_v, float_v)
+_forward(uint_v, float_v)
+_forward(ushort_v, short_v)
+#undef _forward/*}}}*/
+
+} // namespace Common
+} // namespace Vc
+} // namespace AliRoot
+
+#include "undomacros.h"
+
+#endif // VC_AVX_INTERLEAVEDMEMORY_TCC
+
+// vim: foldmethod=marker
index 4bb3661..709cbc9 100644 (file)
 
 #include "../common/windows_fix_intrin.h"
 
+#include <Vc/global.h>
+
+// see comment in sse/intrinsics.h
+extern "C" {
 // AVX
 #include <immintrin.h>
 
+#if (defined(VC_IMPL_XOP) || defined(VC_IMPL_FMA4)) && !defined(VC_MSVC)
+#include <x86intrin.h>
+#endif
+}
+
+#include "../common/fix_clang_emmintrin.h"
+
 #if defined(VC_CLANG) && VC_CLANG < 0x30100
 // _mm_permute_ps is broken: http://llvm.org/bugs/show_bug.cgi?id=12401
 #undef _mm_permute_ps
 #define _mm_permute_ps(A, C) __extension__ ({ \
-  __m128 __A = (A); \
-  (__m128)__builtin_shufflevector((__v4sf)__A, (__v4sf) _mm_setzero_ps(), \
+  m128 __A = (A); \
+  (m128)__builtin_shufflevector((__v4sf)__A, (__v4sf) _mm_setzero_ps(), \
                                    (C) & 0x3, ((C) & 0xc) >> 2, \
                                    ((C) & 0x30) >> 4, ((C) & 0xc0) >> 6); })
 #endif
 
-#include <Vc/global.h>
 #include "const_data.h"
 #include "macros.h"
 #include <cstdlib>
 #if defined(VC_CLANG) && VC_CLANG <= 0x30000
 // _mm_alignr_epi8 doesn't specify its return type, thus breaking overload resolution
 #undef _mm_alignr_epi8
-#define _mm_alignr_epi8(a, b, n) ((__m128i)__builtin_ia32_palignr128((a), (b), (n)))
+#define _mm_alignr_epi8(a, b, n) ((m128i)__builtin_ia32_palignr128((a), (b), (n)))
 #endif
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
 {
+    /* super evil hacking around C++ features:
+     * consider
+     * void fun(int);
+     * namespace X { void fun(int); }
+     * namespace X { void bar() { fun(0); } } // this will be a call to X::fun(int)
+     *
+     * void fun(m256);
+     * namespace X { void fun(m256); }
+     * namespace X { void bar() { fun(0); } } // this will be ambiguous because m256 is a
+     *                                           non-fundamental type in the global namespace, thus
+     *                                           adding ::fun(m256) to the candidates
+     *
+     * To make my own overloads of the intrinsics distinct I have to use a type that is inside the
+     * Vc::AVX namespace. To reduce porting effort and increase generality I want to use the same
+     * function names as used in the global namespace. The type name may not be the same, though
+     * because identifiers starting with two underscores are reserved by the standard. Thus using
+     * those would mean to depend on undefined behavior.
+     * Sadly a typedef is not enough.
+     * Public inheritance also does not work, because at least ICC considers the __m??? types to be
+     * some sort of fundamental types.
+     * Thus composition is the only solution.
+     */
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+    template<typename T> struct Alias
+    {
+        typedef T Base;
+        T _d;
+        Vc_ALWAYS_INLINE operator T &() { return _d; }
+        Vc_ALWAYS_INLINE operator const T &() const { return _d; }
+        Vc_ALWAYS_INLINE Alias() {}
+        Vc_ALWAYS_INLINE Alias(T x) : _d(x) {}
+        Vc_ALWAYS_INLINE Alias(const Alias &x) : _d(x._d) {}
+        Vc_ALWAYS_INLINE Alias &operator=(T x) { _d = x; return *this; }
+        Vc_ALWAYS_INLINE Alias &operator=(const Alias &x) { _d = x._d; return *this; }
+    };
+    typedef Alias<__m128 > m128 ;
+    typedef Alias<__m128d> m128d;
+    typedef Alias<__m128i> m128i;
+    typedef Alias<__m256 > m256 ;
+    typedef Alias<__m256d> m256d;
+    typedef Alias<__m256i> m256i;
+#else
+    typedef __m128  m128 ;
+    typedef __m128d m128d;
+    typedef __m128i m128i;
+    typedef __m256  m256 ;
+    typedef __m256d m256d;
+    typedef __m256i m256i;
+#endif
+#if defined(VC_UNCONDITIONAL_AVX2_INTRINSICS) && defined(VC_PASSING_VECTOR_BY_VALUE_IS_BROKEN)
+    typedef const m128  & param128 ;
+    typedef const m128d & param128d;
+    typedef const m128i & param128i;
+    typedef const m256  & param256 ;
+    typedef const m256d & param256d;
+    typedef const m256i & param256i;
+#else
+    typedef const m128  param128 ;
+    typedef const m128d param128d;
+    typedef const m128i param128i;
+    typedef const m256  param256 ;
+    typedef const m256d param256d;
+    typedef const m256i param256i;
+#endif
+
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+    // Make use of cast intrinsics easier. But if param256 == const __m256 then these would lead to
+    // ambiguities.
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_castps_si256(param256  a) { return ::_mm256_castps_si256(a); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_castps_pd   (param256  a) { return ::_mm256_castps_pd   (a); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_castpd_si256(param256d a) { return ::_mm256_castpd_si256(a); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_castpd_ps   (param256d a) { return ::_mm256_castpd_ps   (a); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_castsi256_ps(param256i a) { return ::_mm256_castsi256_ps(a); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_castsi256_pd(param256i a) { return ::_mm256_castsi256_pd(a); }
+#endif
+
+#ifdef VC_GCC
+    // Redefine the mul/add/sub intrinsics to use GCC-specific operators instead of builtin
+    // functions. This way the fp-contraction optimization step kicks in and creates FMAs! :)
+    static Vc_INTRINSIC Vc_CONST m256d _mm256_mul_pd(m256d a, m256d b) { return static_cast<m256d>(static_cast<__v4df>(a) * static_cast<__v4df>(b)); }
+    static Vc_INTRINSIC Vc_CONST m256d _mm256_add_pd(m256d a, m256d b) { return static_cast<m256d>(static_cast<__v4df>(a) + static_cast<__v4df>(b)); }
+    static Vc_INTRINSIC Vc_CONST m256d _mm256_sub_pd(m256d a, m256d b) { return static_cast<m256d>(static_cast<__v4df>(a) - static_cast<__v4df>(b)); }
+    static Vc_INTRINSIC Vc_CONST m256 _mm256_mul_ps(m256 a, m256 b) { return static_cast<m256>(static_cast<__v8sf>(a) * static_cast<__v8sf>(b)); }
+    static Vc_INTRINSIC Vc_CONST m256 _mm256_add_ps(m256 a, m256 b) { return static_cast<m256>(static_cast<__v8sf>(a) + static_cast<__v8sf>(b)); }
+    static Vc_INTRINSIC Vc_CONST m256 _mm256_sub_ps(m256 a, m256 b) { return static_cast<m256>(static_cast<__v8sf>(a) - static_cast<__v8sf>(b)); }
+#endif
+
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_set1_ps   (float  a) { return ::_mm256_set1_ps   (a); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_set1_pd   (double a) { return ::_mm256_set1_pd   (a); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_set1_epi32(int    a) { return ::_mm256_set1_epi32(a); }
+    //static Vc_INTRINSIC m256i Vc_CONST _mm256_set1_epu32(unsigned int a) { return ::_mm256_set1_epu32(a); }
+
 #if defined(VC_GNU_ASM) && !defined(NVALGRIND)
-    static inline __m128i CONST _mm_setallone() { __m128i r; __asm__("pcmpeqb %0,%0":"=x"(r)); return r; }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setallone() { m128i r; __asm__("pcmpeqb %0,%0":"=x"(r)); return r; }
 #else
-    static inline __m128i CONST _mm_setallone() { __m128i r = _mm_setzero_si128(); return _mm_cmpeq_epi8(r, r); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setallone() { m128i r = _mm_setzero_si128(); return _mm_cmpeq_epi8(r, r); }
 #endif
-    static inline __m128i CONST _mm_setallone_si128() { return _mm_setallone(); }
-    static inline __m128d CONST _mm_setallone_pd() { return _mm_castsi128_pd(_mm_setallone()); }
-    static inline __m128  CONST _mm_setallone_ps() { return _mm_castsi128_ps(_mm_setallone()); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setallone_si128() { return _mm_setallone(); }
+    static Vc_INTRINSIC m128d Vc_CONST _mm_setallone_pd() { return _mm_castsi128_pd(_mm_setallone()); }
+    static Vc_INTRINSIC m128  Vc_CONST _mm_setallone_ps() { return _mm_castsi128_ps(_mm_setallone()); }
 
-    static inline __m128i CONST _mm_setone_epi8 ()  { return _mm_set1_epi8(1); }
-    static inline __m128i CONST _mm_setone_epu8 ()  { return _mm_setone_epi8(); }
-    static inline __m128i CONST _mm_setone_epi16()  { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(c_general::one16))); }
-    static inline __m128i CONST _mm_setone_epu16()  { return _mm_setone_epi16(); }
-    static inline __m128i CONST _mm_setone_epi32()  { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(&_IndexesFromZero32[1]))); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setone_epi8 ()  { return _mm_set1_epi8(1); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setone_epu8 ()  { return _mm_setone_epi8(); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setone_epi16()  { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(c_general::one16))); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setone_epu16()  { return _mm_setone_epi16(); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setone_epi32()  { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(&_IndexesFromZero32[1]))); }
 
 #if defined(VC_GNU_ASM) && !defined(NVALGRIND)
-    static inline __m256 CONST _mm256_setallone() { __m256 r; __asm__("vcmpps $8,%0,%0,%0":"=x"(r)); return r; }
+    static Vc_INTRINSIC m256 Vc_CONST _mm256_setallone() { __m256 r; __asm__("vcmpps $8,%0,%0,%0":"=x"(r)); return r; }
+#elif defined(VC_MSVC)
+    // MSVC puts temporaries of this value on the stack, but sometimes at misaligned addresses, try
+    // some other generator instead...
+    static Vc_INTRINSIC m256 Vc_CONST _mm256_setallone() { return _mm256_castsi256_ps(_mm256_set1_epi32(-1)); }
 #else
-    static inline __m256 CONST _mm256_setallone() { __m256 r = _mm256_setzero_ps(); return _mm256_cmp_ps(r, r, _CMP_EQ_UQ); }
+    static Vc_INTRINSIC m256 Vc_CONST _mm256_setallone() { m256 r = _mm256_setzero_ps(); return _mm256_cmp_ps(r, r, _CMP_EQ_UQ); }
 #endif
-    static inline __m256i CONST _mm256_setallone_si256() { return _mm256_castps_si256(_mm256_setallone()); }
-    static inline __m256d CONST _mm256_setallone_pd() { return _mm256_castps_pd(_mm256_setallone()); }
-    static inline __m256  CONST _mm256_setallone_ps() { return _mm256_setallone(); }
-
-    static inline __m256i CONST _mm256_setone_epi8 ()  { return _mm256_set1_epi8(1); }
-    static inline __m256i CONST _mm256_setone_epu8 ()  { return _mm256_setone_epi8(); }
-    static inline __m256i CONST _mm256_setone_epi16()  { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(c_general::one16))); }
-    static inline __m256i CONST _mm256_setone_epu16()  { return _mm256_setone_epi16(); }
-    static inline __m256i CONST _mm256_setone_epi32()  { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(&_IndexesFromZero32[1]))); }
-    static inline __m256i CONST _mm256_setone_epu32()  { return _mm256_setone_epi32(); }
-
-    static inline __m256  CONST _mm256_setone_ps()     { return _mm256_broadcast_ss(&c_general::oneFloat); }
-    static inline __m256d CONST _mm256_setone_pd()     { return _mm256_broadcast_sd(&c_general::oneDouble); }
-
-    static inline __m256d CONST _mm256_setabsmask_pd() { return _mm256_broadcast_sd(reinterpret_cast<const double *>(&c_general::absMaskFloat[0])); }
-    static inline __m256  CONST _mm256_setabsmask_ps() { return _mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::absMaskFloat[1])); }
-    static inline __m256d CONST _mm256_setsignmask_pd(){ return _mm256_broadcast_sd(reinterpret_cast<const double *>(&c_general::signMaskFloat[0])); }
-    static inline __m256  CONST _mm256_setsignmask_ps(){ return _mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1])); }
-
-    static inline __m256  CONST _mm256_set2power31_ps()    { return _mm256_broadcast_ss(&c_general::_2power31); }
-    static inline __m256i CONST _mm256_set2power31_epu32() { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1]))); }
-
-    //X         static inline __m256i CONST _mm256_setmin_epi8 () { return _mm256_slli_epi8 (_mm256_setallone_si256(),  7); }
-    static inline __m128i CONST _mm_setmin_epi16() { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(c_general::minShort))); }
-    static inline __m128i CONST _mm_setmin_epi32() { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1]))); }
-    static inline __m256i CONST _mm256_setmin_epi16() { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(c_general::minShort))); }
-    static inline __m256i CONST _mm256_setmin_epi32() { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1]))); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setallone_si256() { return _mm256_castps_si256(_mm256_setallone()); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_setallone_pd() { return _mm256_castps_pd(_mm256_setallone()); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_setallone_ps() { return _mm256_setallone(); }
+
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setone_epi8 ()  { return _mm256_set1_epi8(1); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setone_epu8 ()  { return _mm256_setone_epi8(); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setone_epi16()  { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(c_general::one16))); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setone_epu16()  { return _mm256_setone_epi16(); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setone_epi32()  { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(&_IndexesFromZero32[1]))); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setone_epu32()  { return _mm256_setone_epi32(); }
+
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_setone_ps()     { return _mm256_broadcast_ss(&c_general::oneFloat); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_setone_pd()     { return _mm256_broadcast_sd(&c_general::oneDouble); }
+
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_setabsmask_pd() { return _mm256_broadcast_sd(reinterpret_cast<const double *>(&c_general::absMaskFloat[0])); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_setabsmask_ps() { return _mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::absMaskFloat[1])); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_setsignmask_pd(){ return _mm256_broadcast_sd(reinterpret_cast<const double *>(&c_general::signMaskFloat[0])); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_setsignmask_ps(){ return _mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1])); }
+
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_set2power31_ps()    { return _mm256_broadcast_ss(&c_general::_2power31); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_set2power31_epu32() { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1]))); }
+
+    //X         static Vc_INTRINSIC m256i Vc_CONST _mm256_setmin_epi8 () { return _mm256_slli_epi8 (_mm256_setallone_si256(),  7); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setmin_epi16() { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(c_general::minShort))); }
+    static Vc_INTRINSIC m128i Vc_CONST _mm_setmin_epi32() { return _mm_castps_si128(_mm_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1]))); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setmin_epi16() { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(c_general::minShort))); }
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_setmin_epi32() { return _mm256_castps_si256(_mm256_broadcast_ss(reinterpret_cast<const float *>(&c_general::signMaskFloat[1]))); }
 
 #ifdef VC_REQUIRES_MACRO_FOR_IMMEDIATE_ARGUMENT
 #define _mm_extract_epu8 _mm_extract_epi8
 #define _mm_extract_epu16 _mm_extract_epi16
 #define _mm_extract_epu32 _mm_extract_epi32
 #else
-    static inline unsigned char INTRINSIC CONST _mm_extract_epu8(__m128i x, const int i) { return _mm_extract_epi8(x, i); }
-    static inline unsigned short INTRINSIC CONST _mm_extract_epu16(__m128i x, const int i) { return _mm_extract_epi16(x, i); }
-    static inline unsigned int INTRINSIC CONST _mm_extract_epu32(__m128i x, const int i) { return _mm_extract_epi32(x, i); }
+    static Vc_INTRINSIC unsigned char Vc_CONST _mm_extract_epu8(param128i x, const int i) { return _mm_extract_epi8(x, i); }
+    static Vc_INTRINSIC unsigned short Vc_CONST _mm_extract_epu16(param128i x, const int i) { return _mm_extract_epi16(x, i); }
+    static Vc_INTRINSIC unsigned int Vc_CONST _mm_extract_epu32(param128i x, const int i) { return _mm_extract_epi32(x, i); }
 #endif
 
     /////////////////////// COMPARE OPS ///////////////////////
-    static inline __m256d INTRINSIC CONST _mm256_cmpeq_pd   (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); }
-    static inline __m256d INTRINSIC CONST _mm256_cmpneq_pd  (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); }
-    static inline __m256d INTRINSIC CONST _mm256_cmplt_pd   (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_LT_OS); }
-    static inline __m256d INTRINSIC CONST _mm256_cmpnlt_pd  (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_NLT_US); }
-    static inline __m256d INTRINSIC CONST _mm256_cmple_pd   (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_LE_OS); }
-    static inline __m256d INTRINSIC CONST _mm256_cmpnle_pd  (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_NLE_US); }
-    static inline __m256d INTRINSIC CONST _mm256_cmpord_pd  (__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_ORD_Q); }
-    static inline __m256d INTRINSIC CONST _mm256_cmpunord_pd(__m256d a, __m256d b) { return _mm256_cmp_pd(a, b, _CMP_UNORD_Q); }
-
-    static inline __m256  INTRINSIC CONST _mm256_cmpeq_ps   (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpneq_ps  (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); }
-    static inline __m256  INTRINSIC CONST _mm256_cmplt_ps   (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpnlt_ps  (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpge_ps   (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
-    static inline __m256  INTRINSIC CONST _mm256_cmple_ps   (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpnle_ps  (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpgt_ps   (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpord_ps  (__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_ORD_Q); }
-    static inline __m256  INTRINSIC CONST _mm256_cmpunord_ps(__m256  a, __m256  b) { return _mm256_cmp_ps(a, b, _CMP_UNORD_Q); }
-
-    static inline __m128i _mm_cmplt_epu16(__m128i a, __m128i b) {
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmpeq_pd   (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_EQ_OQ); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmpneq_pd  (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_NEQ_UQ); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmplt_pd   (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_LT_OS); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmpnlt_pd  (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_NLT_US); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmple_pd   (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_LE_OS); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmpnle_pd  (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_NLE_US); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmpord_pd  (param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_ORD_Q); }
+    static Vc_INTRINSIC m256d Vc_CONST _mm256_cmpunord_pd(param256d a, param256d b) { return _mm256_cmp_pd(a, b, _CMP_UNORD_Q); }
+
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpeq_ps   (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_EQ_OQ); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpneq_ps  (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_NEQ_UQ); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmplt_ps   (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_LT_OS); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpnlt_ps  (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpge_ps   (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_NLT_US); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmple_ps   (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_LE_OS); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpnle_ps  (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpgt_ps   (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_NLE_US); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpord_ps  (param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_ORD_Q); }
+    static Vc_INTRINSIC m256  Vc_CONST _mm256_cmpunord_ps(param256  a, param256  b) { return _mm256_cmp_ps(a, b, _CMP_UNORD_Q); }
+
+    static Vc_INTRINSIC m128i _mm_cmplt_epu16(param128i a, param128i b) {
         return _mm_cmplt_epi16(_mm_xor_si128(a, _mm_setmin_epi16()), _mm_xor_si128(b, _mm_setmin_epi16()));
     }
-    static inline __m128i _mm_cmpgt_epu16(__m128i a, __m128i b) {
+    static Vc_INTRINSIC m128i _mm_cmpgt_epu16(param128i a, param128i b) {
         return _mm_cmpgt_epi16(_mm_xor_si128(a, _mm_setmin_epi16()), _mm_xor_si128(b, _mm_setmin_epi16()));
     }
 
     /////////////////////// INTEGER OPS ///////////////////////
 #define AVX_TO_SSE_2(name) \
-    static inline __m256i INTRINSIC CONST _mm256_##name(__m256i a0, __m256i b0) { \
-        __m128i a1 = _mm256_extractf128_si256(a0, 1); \
-        __m128i b1 = _mm256_extractf128_si256(b0, 1); \
-        __m128i r0 = _mm_##name(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0)); \
-        __m128i r1 = _mm_##name(a1, b1); \
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_##name(param256i a0, param256i b0) { \
+        m128i a1 = _mm256_extractf128_si256(a0, 1); \
+        m128i b1 = _mm256_extractf128_si256(b0, 1); \
+        m128i r0 = _mm_##name(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0)); \
+        m128i r1 = _mm_##name(a1, b1); \
         return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1); \
     }
 #define AVX_TO_SSE_2_si128_si256(name) \
-    static inline __m256i INTRINSIC CONST _mm256_##name##_si256(__m256i a0, __m256i b0) { \
-        __m128i a1 = _mm256_extractf128_si256(a0, 1); \
-        __m128i b1 = _mm256_extractf128_si256(b0, 1); \
-        __m128i r0 = _mm_##name##_si128(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0)); \
-        __m128i r1 = _mm_##name##_si128(a1, b1); \
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_##name##_si256(param256i a0, param256i b0) { \
+        m128i a1 = _mm256_extractf128_si256(a0, 1); \
+        m128i b1 = _mm256_extractf128_si256(b0, 1); \
+        m128i r0 = _mm_##name##_si128(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0)); \
+        m128i r1 = _mm_##name##_si128(a1, b1); \
         return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1); \
     }
 #define AVX_TO_SSE_1(name) \
-    static inline __m256i INTRINSIC CONST _mm256_##name(__m256i a0) { \
-        __m128i a1 = _mm256_extractf128_si256(a0, 1); \
-        __m128i r0 = _mm_##name(_mm256_castsi256_si128(a0)); \
-        __m128i r1 = _mm_##name(a1); \
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_##name(param256i a0) { \
+        m128i a1 = _mm256_extractf128_si256(a0, 1); \
+        m128i r0 = _mm_##name(_mm256_castsi256_si128(a0)); \
+        m128i r1 = _mm_##name(a1); \
         return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1); \
     }
 #define AVX_TO_SSE_1i(name) \
-    static inline __m256i INTRINSIC CONST _mm256_##name(__m256i a0, const int i) { \
-        __m128i a1 = _mm256_extractf128_si256(a0, 1); \
-        __m128i r0 = _mm_##name(_mm256_castsi256_si128(a0), i); \
-        __m128i r1 = _mm_##name(a1, i); \
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_##name(param256i a0, const int i) { \
+        m128i a1 = _mm256_extractf128_si256(a0, 1); \
+        m128i r0 = _mm_##name(_mm256_castsi256_si128(a0), i); \
+        m128i r1 = _mm_##name(a1, i); \
         return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1); \
     }
 
-    AVX_TO_SSE_2(cmpeq_epi8)
-    AVX_TO_SSE_2(cmpeq_epi16)
-    AVX_TO_SSE_2(cmpeq_epi32)
     AVX_TO_SSE_2(cmplt_epi8)
     AVX_TO_SSE_2(cmplt_epi16)
     AVX_TO_SSE_2(cmplt_epi32)
+    AVX_TO_SSE_2(cmpeq_epi8)
+    AVX_TO_SSE_2(cmpeq_epi16)
+    AVX_TO_SSE_2(cmpeq_epi32)
     AVX_TO_SSE_2(cmpgt_epi8)
     AVX_TO_SSE_2(cmpgt_epi16)
     AVX_TO_SSE_2(cmpgt_epi32)
 
-#ifndef VC_ICC
-    // ICC ships the Integer intrinsics inside the AVX1 header these days.
-
-#ifdef VC_REQUIRES_MACRO_FOR_IMMEDIATE_ARGUMENT
-#   define _mm256_srli_si256(a, i) \
-        _mm256_insertf128_si256( \
-                _mm256_castsi128_si256(_mm_srli_si128(_mm256_castsi256_si128((a)), i)), \
-                _mm_srli_si128(_mm256_extractf128_si256((a), 1), i), 1);
-#   define _mm256_slli_si256(a, i) \
-        _mm256_insertf128_si256( \
-                _mm256_castsi128_si256( _mm_slli_si128(_mm256_castsi256_si128((a)), i)), \
-                _mm_slli_si128(_mm256_extractf128_si256((a), 1), i), 1);
-#else
-    static inline __m256i INTRINSIC CONST _mm256_srli_si256(__m256i a0, const int i) {
-        const __m128i r0 = _mm_srli_si128(_mm256_castsi256_si128(a0), i);
-        const __m128i r1 = _mm_srli_si128(_mm256_extractf128_si256(a0, 1), i);
-        return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1);
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_srli_si256(param256i a0, const int i) {
+        const m128i vLo = _mm256_castsi256_si128(a0);
+        const m128i vHi = _mm256_extractf128_si256(a0, 1);
+        switch (i) {
+        case  0: return a0;
+        case  1: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  1)), _mm_srli_si128(vHi,  1), 1);
+        case  2: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  2)), _mm_srli_si128(vHi,  2), 1);
+        case  3: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  3)), _mm_srli_si128(vHi,  3), 1);
+        case  4: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  4)), _mm_srli_si128(vHi,  4), 1);
+        case  5: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  5)), _mm_srli_si128(vHi,  5), 1);
+        case  6: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  6)), _mm_srli_si128(vHi,  6), 1);
+        case  7: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  7)), _mm_srli_si128(vHi,  7), 1);
+        case  8: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  8)), _mm_srli_si128(vHi,  8), 1);
+        case  9: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo,  9)), _mm_srli_si128(vHi,  9), 1);
+        case 10: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo, 10)), _mm_srli_si128(vHi, 10), 1);
+        case 11: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo, 11)), _mm_srli_si128(vHi, 11), 1);
+        case 12: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo, 12)), _mm_srli_si128(vHi, 12), 1);
+        case 13: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo, 13)), _mm_srli_si128(vHi, 13), 1);
+        case 14: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo, 14)), _mm_srli_si128(vHi, 14), 1);
+        case 15: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_alignr_epi8(vHi, vLo, 15)), _mm_srli_si128(vHi, 15), 1);
+        case 16: return _mm256_permute2f128_si256(a0, a0, 0x81);
+        case 17: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  1)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  1)), 0x80);
+        case 18: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  2)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  2)), 0x80);
+        case 19: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  3)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  3)), 0x80);
+        case 20: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  4)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  4)), 0x80);
+        case 21: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  5)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  5)), 0x80);
+        case 22: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  6)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  6)), 0x80);
+        case 23: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  7)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  7)), 0x80);
+        case 24: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  8)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  8)), 0x80);
+        case 25: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi,  9)), _mm256_castsi128_si256(_mm_srli_si128(vHi,  9)), 0x80);
+        case 26: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi, 10)), _mm256_castsi128_si256(_mm_srli_si128(vHi, 10)), 0x80);
+        case 27: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi, 11)), _mm256_castsi128_si256(_mm_srli_si128(vHi, 11)), 0x80);
+        case 28: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi, 12)), _mm256_castsi128_si256(_mm_srli_si128(vHi, 12)), 0x80);
+        case 29: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi, 13)), _mm256_castsi128_si256(_mm_srli_si128(vHi, 13)), 0x80);
+        case 30: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi, 14)), _mm256_castsi128_si256(_mm_srli_si128(vHi, 14)), 0x80);
+        case 31: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_srli_si128(vHi, 15)), _mm256_castsi128_si256(_mm_srli_si128(vHi, 15)), 0x80);
+        }
+        return _mm256_setzero_si256();
     }
-    static inline __m256i INTRINSIC CONST _mm256_slli_si256(__m256i a0, const int i) {
-        const __m128i r0 = _mm_slli_si128(_mm256_castsi256_si128(a0), i);
-        const __m128i r1 = _mm_slli_si128(_mm256_extractf128_si256(a0, 1), i);
-        return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1);
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_slli_si256(param256i a0, const int i) {
+        const m128i vLo = _mm256_castsi256_si128(a0);
+        const m128i vHi = _mm256_extractf128_si256(a0, 1);
+        switch (i) {
+        case  0: return a0;
+        case  1: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  1)), _mm_alignr_epi8(vHi, vLo, 15), 1);
+        case  2: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  2)), _mm_alignr_epi8(vHi, vLo, 14), 1);
+        case  3: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  3)), _mm_alignr_epi8(vHi, vLo, 13), 1);
+        case  4: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  4)), _mm_alignr_epi8(vHi, vLo, 12), 1);
+        case  5: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  5)), _mm_alignr_epi8(vHi, vLo, 11), 1);
+        case  6: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  6)), _mm_alignr_epi8(vHi, vLo, 10), 1);
+        case  7: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  7)), _mm_alignr_epi8(vHi, vLo,  9), 1);
+        case  8: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  8)), _mm_alignr_epi8(vHi, vLo,  8), 1);
+        case  9: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  9)), _mm_alignr_epi8(vHi, vLo,  7), 1);
+        case 10: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 10)), _mm_alignr_epi8(vHi, vLo,  6), 1);
+        case 11: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 11)), _mm_alignr_epi8(vHi, vLo,  5), 1);
+        case 12: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 12)), _mm_alignr_epi8(vHi, vLo,  4), 1);
+        case 13: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 13)), _mm_alignr_epi8(vHi, vLo,  3), 1);
+        case 14: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 14)), _mm_alignr_epi8(vHi, vLo,  2), 1);
+        case 15: return _mm256_insertf128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 15)), _mm_alignr_epi8(vHi, vLo,  1), 1);
+        case 16: return _mm256_permute2f128_si256(a0, a0, 0x8);
+        case 17: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  1)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  1)), 0x8);
+        case 18: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  2)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  2)), 0x8);
+        case 19: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  3)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  3)), 0x8);
+        case 20: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  4)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  4)), 0x8);
+        case 21: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  5)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  5)), 0x8);
+        case 22: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  6)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  6)), 0x8);
+        case 23: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  7)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  7)), 0x8);
+        case 24: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  8)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  8)), 0x8);
+        case 25: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo,  9)), _mm256_castsi128_si256(_mm_slli_si128(vLo,  9)), 0x8);
+        case 26: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 10)), _mm256_castsi128_si256(_mm_slli_si128(vLo, 10)), 0x8);
+        case 27: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 11)), _mm256_castsi128_si256(_mm_slli_si128(vLo, 11)), 0x8);
+        case 28: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 12)), _mm256_castsi128_si256(_mm_slli_si128(vLo, 12)), 0x8);
+        case 29: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 13)), _mm256_castsi128_si256(_mm_slli_si128(vLo, 13)), 0x8);
+        case 30: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 14)), _mm256_castsi128_si256(_mm_slli_si128(vLo, 14)), 0x8);
+        case 31: return _mm256_permute2f128_si256(_mm256_castsi128_si256(_mm_slli_si128(vLo, 15)), _mm256_castsi128_si256(_mm_slli_si128(vLo, 15)), 0x8);
+        }
+        return _mm256_setzero_si256();
     }
-#endif
 
-    static inline __m256i INTRINSIC CONST _mm256_and_si256(__m256i x, __m256i y) {
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_and_si256(param256i x, param256i y) {
         return _mm256_castps_si256(_mm256_and_ps(_mm256_castsi256_ps(x), _mm256_castsi256_ps(y)));
     }
-    static inline __m256i INTRINSIC CONST _mm256_andnot_si256(__m256i x, __m256i y) {
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_andnot_si256(param256i x, param256i y) {
         return _mm256_castps_si256(_mm256_andnot_ps(_mm256_castsi256_ps(x), _mm256_castsi256_ps(y)));
     }
-    static inline __m256i INTRINSIC CONST _mm256_or_si256(__m256i x, __m256i y) {
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_or_si256(param256i x, param256i y) {
         return _mm256_castps_si256(_mm256_or_ps(_mm256_castsi256_ps(x), _mm256_castsi256_ps(y)));
     }
-    static inline __m256i INTRINSIC CONST _mm256_xor_si256(__m256i x, __m256i y) {
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_xor_si256(param256i x, param256i y) {
         return _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(x), _mm256_castsi256_ps(y)));
     }
 
@@ -271,21 +432,21 @@ namespace AVX
     AVX_TO_SSE_2(max_epu8)
     AVX_TO_SSE_2(min_epi16)
     AVX_TO_SSE_2(min_epu8)
-    inline int INTRINSIC CONST _mm256_movemask_epi8(__m256i a0)
+    Vc_INTRINSIC int Vc_CONST _mm256_movemask_epi8(param256i a0)
     {
-        __m128i a1 = _mm256_extractf128_si256(a0, 1);
+        m128i a1 = _mm256_extractf128_si256(a0, 1);
         return (_mm_movemask_epi8(a1) << 16) | _mm_movemask_epi8(_mm256_castsi256_si128(a0));
     }
     AVX_TO_SSE_2(mulhi_epu16)
     // shufflehi_epi16
-    // shufflelo_epi16 (__m128i __A, const int __mask)
-    // shuffle_epi32 (__m128i __A, const int __mask)
-    // maskmoveu_si128 (__m128i __A, __m128i __B, char *__C)
+    // shufflelo_epi16 (param128i __A, const int __mask)
+    // shuffle_epi32 (param128i __A, const int __mask)
+    // maskmoveu_si128 (param128i __A, param128i __B, char *__C)
     AVX_TO_SSE_2(avg_epu8)
     AVX_TO_SSE_2(avg_epu16)
     AVX_TO_SSE_2(sad_epu8)
     // stream_si32 (int *__A, int __B)
-    // stream_si128 (__m128i *__A, __m128i __B)
+    // stream_si128 (param128i *__A, param128i __B)
     // cvtsi32_si128 (int __A)
     // cvtsi64_si128 (long long __A)
     // cvtsi64x_si128 (long long __A)
@@ -301,16 +462,16 @@ namespace AVX
     AVX_TO_SSE_2(sign_epi8)
     AVX_TO_SSE_2(sign_epi16)
     AVX_TO_SSE_2(sign_epi32)
-    // alignr_epi8(__m128i __X, __m128i __Y, const int __N)
+    // alignr_epi8(param128i __X, param128i __Y, const int __N)
     AVX_TO_SSE_1(abs_epi8)
     AVX_TO_SSE_1(abs_epi16)
     AVX_TO_SSE_1(abs_epi32)
 #if !defined(VC_REQUIRES_MACRO_FOR_IMMEDIATE_ARGUMENT)
-    __m256i inline INTRINSIC CONST _mm256_blend_epi16(__m256i a0, __m256i b0, const int m) {
-        __m128i a1 = _mm256_extractf128_si256(a0, 1);
-        __m128i b1 = _mm256_extractf128_si256(b0, 1);
-        __m128i r0 = _mm_blend_epi16(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0), m & 0xff);
-        __m128i r1 = _mm_blend_epi16(a1, b1, m >> 8);
+    m256i Vc_INTRINSIC Vc_CONST _mm256_blend_epi16(param256i a0, param256i b0, const int m) {
+        m128i a1 = _mm256_extractf128_si256(a0, 1);
+        m128i b1 = _mm256_extractf128_si256(b0, 1);
+        m128i r0 = _mm_blend_epi16(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0), m & 0xff);
+        m128i r1 = _mm_blend_epi16(a1, b1, m >> 8);
         return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1);
     }
 #else
@@ -321,12 +482,12 @@ namespace AVX
                     _mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0), m & 0xff)), \
             _mm_blend_epi16(_mm256_extractf128_si256(a0, 1), _mm256_extractf128_si256(b0, 1), m >> 8);, 1)
 #endif
-    inline __m256i INTRINSIC CONST _mm256_blendv_epi8(__m256i a0, __m256i b0, __m256i m0) {
-        __m128i a1 = _mm256_extractf128_si256(a0, 1);
-        __m128i b1 = _mm256_extractf128_si256(b0, 1);
-        __m128i m1 = _mm256_extractf128_si256(m0, 1);
-        __m128i r0 = _mm_blendv_epi8(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0), _mm256_castsi256_si128(m0));
-        __m128i r1 = _mm_blendv_epi8(a1, b1, m1);
+    Vc_INTRINSIC m256i Vc_CONST _mm256_blendv_epi8(param256i a0, param256i b0, param256i m0) {
+        m128i a1 = _mm256_extractf128_si256(a0, 1);
+        m128i b1 = _mm256_extractf128_si256(b0, 1);
+        m128i m1 = _mm256_extractf128_si256(m0, 1);
+        m128i r0 = _mm_blendv_epi8(_mm256_castsi256_si128(a0), _mm256_castsi256_si128(b0), _mm256_castsi256_si128(m0));
+        m128i r1 = _mm_blendv_epi8(a1, b1, m1);
         return _mm256_insertf128_si256(_mm256_castsi128_si256(r0), r1, 1);
     }
     AVX_TO_SSE_2(cmpeq_epi64)
@@ -358,56 +519,82 @@ namespace AVX
     AVX_TO_SSE_1(cvtepu16_epi64)
     AVX_TO_SSE_1(cvtepu8_epi16)
     AVX_TO_SSE_2(packus_epi32)
-    // mpsadbw_epu8 (__m128i __X, __m128i __Y, const int __M)
-    // stream_load_si128 (__m128i *__X)
+    // mpsadbw_epu8 (param128i __X, param128i __Y, const int __M)
+    // stream_load_si128 (param128i *__X)
     AVX_TO_SSE_2(cmpgt_epi64)
-#endif
 
-//X     static inline __m256i _mm256_cmplt_epu8 (__m256i a, __m256i b) { return _mm256_cmplt_epi8 (
+//X     static Vc_INTRINSIC m256i _mm256_cmplt_epu8 (param256i a, param256i b) { return _mm256_cmplt_epi8 (
 //X             _mm256_xor_si256(a, _mm256_setmin_epi8 ()), _mm256_xor_si256(b, _mm256_setmin_epi8 ())); }
-//X     static inline __m256i _mm256_cmpgt_epu8 (__m256i a, __m256i b) { return _mm256_cmpgt_epi8 (
+//X     static Vc_INTRINSIC m256i _mm256_cmpgt_epu8 (param256i a, param256i b) { return _mm256_cmpgt_epi8 (
 //X             _mm256_xor_si256(a, _mm256_setmin_epi8 ()), _mm256_xor_si256(b, _mm256_setmin_epi8 ())); }
-    static inline __m256i CONST _mm256_cmplt_epu32(__m256i a, __m256i b) {
-        a = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(_mm256_setmin_epi32())));
-        b = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(b), _mm256_castsi256_ps(_mm256_setmin_epi32())));
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_cmplt_epu32(param256i _a, param256i _b) {
+        m256i a = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(_a), _mm256_castsi256_ps(_mm256_setmin_epi32())));
+        m256i b = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(_b), _mm256_castsi256_ps(_mm256_setmin_epi32())));
         return _mm256_insertf128_si256(_mm256_castsi128_si256(
                     _mm_cmplt_epi32(_mm256_castsi256_si128(a), _mm256_castsi256_si128(b))),
                 _mm_cmplt_epi32(_mm256_extractf128_si256(a, 1), _mm256_extractf128_si256(b, 1)), 1);
     }
-    static inline __m256i CONST _mm256_cmpgt_epu32(__m256i a, __m256i b) {
-        a = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(a), _mm256_castsi256_ps(_mm256_setmin_epi32())));
-        b = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(b), _mm256_castsi256_ps(_mm256_setmin_epi32())));
+    static Vc_INTRINSIC m256i Vc_CONST _mm256_cmpgt_epu32(param256i _a, param256i _b) {
+        m256i a = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(_a), _mm256_castsi256_ps(_mm256_setmin_epi32())));
+        m256i b = _mm256_castps_si256(_mm256_xor_ps(_mm256_castsi256_ps(_b), _mm256_castsi256_ps(_mm256_setmin_epi32())));
         return _mm256_insertf128_si256(_mm256_castsi128_si256(
                     _mm_cmpgt_epi32(_mm256_castsi256_si128(a), _mm256_castsi256_si128(b))),
                 _mm_cmpgt_epi32(_mm256_extractf128_si256(a, 1), _mm256_extractf128_si256(b, 1)), 1);
     }
 
-        static inline void INTRINSIC _mm256_maskstore(float *mem, const __m256 mask, const __m256 v) {
+        static Vc_INTRINSIC void _mm256_maskstore(float *mem, const param256 mask, const param256 v) {
 #ifndef VC_MM256_MASKSTORE_WRONG_MASK_TYPE
             _mm256_maskstore_ps(mem, _mm256_castps_si256(mask), v);
 #else
             _mm256_maskstore_ps(mem, mask, v);
 #endif
         }
-        static inline void INTRINSIC _mm256_maskstore(double *mem, const __m256d mask, const __m256d v) {
+        static Vc_INTRINSIC void _mm256_maskstore(double *mem, const param256d mask, const param256d v) {
 #ifndef VC_MM256_MASKSTORE_WRONG_MASK_TYPE
             _mm256_maskstore_pd(mem, _mm256_castpd_si256(mask), v);
 #else
             _mm256_maskstore_pd(mem, mask, v);
 #endif
         }
-        static inline void INTRINSIC _mm256_maskstore(int *mem, const __m256i mask, const __m256i v) {
+        static Vc_INTRINSIC void _mm256_maskstore(int *mem, const param256i mask, const param256i v) {
 #ifndef VC_MM256_MASKSTORE_WRONG_MASK_TYPE
             _mm256_maskstore_ps(reinterpret_cast<float *>(mem), mask, _mm256_castsi256_ps(v));
 #else
             _mm256_maskstore_ps(reinterpret_cast<float *>(mem), _mm256_castsi256_ps(mask), _mm256_castsi256_ps(v));
 #endif
         }
-        static inline void INTRINSIC _mm256_maskstore(unsigned int *mem, const __m256i mask, const __m256i v) {
+        static Vc_INTRINSIC void _mm256_maskstore(unsigned int *mem, const param256i mask, const param256i v) {
             _mm256_maskstore(reinterpret_cast<int *>(mem), mask, v);
         }
+
+#if defined(VC_IMPL_FMA4) && defined(VC_CLANG) && VC_CLANG < 0x30300
+        // clang miscompiles _mm256_macc_ps: http://llvm.org/bugs/show_bug.cgi?id=15040
+        static Vc_INTRINSIC __m256 my256_macc_ps(__m256 a, __m256 b, __m256 c) {
+            __m256 r;
+            // avoid loading c from memory as that would trigger the bug
+            asm("vfmaddps %[c], %[b], %[a], %[r]" : [r]"=x"(r) : [a]"x"(a), [b]"x"(b), [c]"x"(c));
+            return r;
+        }
+#ifdef _mm256_macc_ps
+#undef _mm256_macc_ps
+#endif
+#define _mm256_macc_ps(a, b, c) Vc::AVX::my256_macc_ps(a, b, c)
+
+        static Vc_INTRINSIC __m256d my256_macc_pd(__m256d a, __m256d b, __m256d c) {
+            __m256d r;
+            // avoid loading c from memory as that would trigger the bug
+            asm("vfmaddpd %[c], %[b], %[a], %[r]" : [r]"=x"(r) : [a]"x"(a), [b]"x"(b), [c]"x"(c));
+            return r;
+        }
+#ifdef _mm256_macc_pd
+#undef _mm256_macc_pd
+#endif
+#define _mm256_macc_pd(a, b, c) Vc::AVX::my256_macc_pd(a, b, c)
+#endif
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
+#include "undomacros.h"
 
 #include "shuffle.h"
 
index 80722da..109d614 100644 (file)
 namespace std
 {
 #define _VC_NUM_LIM(T, _max, _min) \
-template<> struct numeric_limits<Vc::AVX::Vector<T> > : public numeric_limits<T> \
+template<> struct numeric_limits< ::AliRoot::Vc::AVX::Vector<T> > : public numeric_limits<T> \
 { \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> max()           _VC_NOEXCEPT { return _max; } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> min()           _VC_NOEXCEPT { return _min; } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> lowest()        _VC_NOEXCEPT { return min(); } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> epsilon()       _VC_NOEXCEPT { return Vc::AVX::Vector<T>::Zero(); } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> round_error()   _VC_NOEXCEPT { return Vc::AVX::Vector<T>::Zero(); } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> infinity()      _VC_NOEXCEPT { return Vc::AVX::Vector<T>::Zero(); } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> quiet_NaN()     _VC_NOEXCEPT { return Vc::AVX::Vector<T>::Zero(); } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> signaling_NaN() _VC_NOEXCEPT { return Vc::AVX::Vector<T>::Zero(); } \
-    static inline INTRINSIC CONST Vc::AVX::Vector<T> denorm_min()    _VC_NOEXCEPT { return Vc::AVX::Vector<T>::Zero(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> max()           _VC_NOEXCEPT { return _max; } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> min()           _VC_NOEXCEPT { return _min; } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> lowest()        _VC_NOEXCEPT { return min(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> epsilon()       _VC_NOEXCEPT { return ::AliRoot::Vc::AVX::Vector<T>::Zero(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> round_error()   _VC_NOEXCEPT { return ::AliRoot::Vc::AVX::Vector<T>::Zero(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> infinity()      _VC_NOEXCEPT { return ::AliRoot::Vc::AVX::Vector<T>::Zero(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> quiet_NaN()     _VC_NOEXCEPT { return ::AliRoot::Vc::AVX::Vector<T>::Zero(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> signaling_NaN() _VC_NOEXCEPT { return ::AliRoot::Vc::AVX::Vector<T>::Zero(); } \
+    static Vc_INTRINSIC Vc_CONST ::AliRoot::Vc::AVX::Vector<T> denorm_min()    _VC_NOEXCEPT { return ::AliRoot::Vc::AVX::Vector<T>::Zero(); } \
 }
-_VC_NUM_LIM(unsigned short, Vc::AVX::_mm_setallone_si128(), _mm_setzero_si128());
-_VC_NUM_LIM(         short, _mm_srli_epi16(Vc::AVX::_mm_setallone_si128(), 1), Vc::AVX::_mm_setmin_epi16());
-_VC_NUM_LIM(  unsigned int, Vc::AVX::_mm256_setallone_si256(), _mm256_setzero_si256());
-_VC_NUM_LIM(           int, Vc::AVX::_mm256_srli_epi32(Vc::AVX::_mm256_setallone_si256(), 1), Vc::AVX::_mm256_setmin_epi32());
+
+#ifndef VC_IMPL_AVX2
+namespace {
+    using ::AliRoot::Vc::AVX::_mm256_srli_epi32;
+}
+#endif
+_VC_NUM_LIM(unsigned short, ::AliRoot::Vc::AVX::_mm_setallone_si128(), _mm_setzero_si128());
+_VC_NUM_LIM(         short, _mm_srli_epi16(::AliRoot::Vc::AVX::_mm_setallone_si128(), 1), ::AliRoot::Vc::AVX::_mm_setmin_epi16());
+_VC_NUM_LIM(  unsigned int, ::AliRoot::Vc::AVX::_mm256_setallone_si256(), _mm256_setzero_si256());
+_VC_NUM_LIM(           int, _mm256_srli_epi32(::AliRoot::Vc::AVX::_mm256_setallone_si256(), 1), ::AliRoot::Vc::AVX::_mm256_setmin_epi32());
 #undef _VC_NUM_LIM
 
 } // namespace std
index 17d10f6..3a75543 100644 (file)
 #define VC_AVX_MACROS_H
 #undef VC_AVX_UNDOMACROS_H
 
-#ifndef _M256
-# define _M256 __m256
-#endif
-
-#ifndef _M256I
-# define _M256I __m256i
-#endif
-
-#ifndef _M256D
-# define _M256D __m256d
-#endif
-
 #endif // VC_AVX_MACROS_H
index 4d678ea..aaaffe2 100644 (file)
@@ -22,7 +22,9 @@
 
 #include "intrinsics.h"
 #include "../common/bitscanintrinsics.h"
+#include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -44,57 +46,61 @@ template<unsigned int VectorSize> class Mask<VectorSize, 32u>
         typedef Mask<VectorSize, 32u> AsArg;
 #endif
 
-        inline Mask() {}
-        inline Mask(const __m256  &x) : k(x) {}
-        inline Mask(const __m256d &x) : k(_mm256_castpd_ps(x)) {}
-        inline Mask(const __m256i &x) : k(_mm256_castsi256_ps(x)) {}
-        inline explicit Mask(VectorSpecialInitializerZero::ZEnum) : k(_mm256_setzero_ps()) {}
-        inline explicit Mask(VectorSpecialInitializerOne::OEnum) : k(_mm256_setallone_ps()) {}
-        inline explicit Mask(bool b) : k(b ? _mm256_setallone_ps() : _mm256_setzero_ps()) {}
-        inline Mask(const Mask &rhs) : k(rhs.k) {}
-        inline Mask(const Mask<VectorSize, 16u> &rhs) : k(avx_cast<__m256>(concat(
+        Vc_ALWAYS_INLINE Mask() {}
+        Vc_ALWAYS_INLINE Mask(param256  x) : k(x) {}
+        Vc_ALWAYS_INLINE Mask(param256d x) : k(_mm256_castpd_ps(x)) {}
+        Vc_ALWAYS_INLINE Mask(param256i x) : k(_mm256_castsi256_ps(x)) {}
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+        Vc_ALWAYS_INLINE Mask(__m256  x) : k(x) {}
+        Vc_ALWAYS_INLINE Mask(__m256d x) : k(_mm256_castpd_ps(x)) {}
+        Vc_ALWAYS_INLINE Mask(__m256i x) : k(_mm256_castsi256_ps(x)) {}
+#endif
+        Vc_ALWAYS_INLINE explicit Mask(VectorSpecialInitializerZero::ZEnum) : k(_mm256_setzero_ps()) {}
+        Vc_ALWAYS_INLINE explicit Mask(VectorSpecialInitializerOne::OEnum) : k(_mm256_setallone_ps()) {}
+        Vc_ALWAYS_INLINE explicit Mask(bool b) : k(b ? _mm256_setallone_ps() : m256(_mm256_setzero_ps())) {}
+        Vc_ALWAYS_INLINE Mask(const Mask &rhs) : k(rhs.k) {}
+        Vc_ALWAYS_INLINE Mask(const Mask<VectorSize, 16u> &rhs) : k(avx_cast<m256>(concat(
                         _mm_unpacklo_epi16(rhs.dataI(), rhs.dataI()),
                         _mm_unpackhi_epi16(rhs.dataI(), rhs.dataI())))) {}
-        inline Mask(const Mask<VectorSize * 2, 32u> &m);
-        inline Mask(const Mask<VectorSize / 2, 32u> &m);
+        Vc_ALWAYS_INLINE_L Mask(const Mask<VectorSize * 2, 32u> &m) Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L Mask(const Mask<VectorSize / 2, 32u> &m) Vc_ALWAYS_INLINE_R;
 
-        inline bool operator==(const Mask &rhs) const { return 0 != _mm256_testc_ps(k, rhs.k); }
-        inline bool operator!=(const Mask &rhs) const { return 0 == _mm256_testc_ps(k, rhs.k); }
+        Vc_ALWAYS_INLINE bool operator==(const Mask &rhs) const { return 0 != _mm256_testc_ps(k, rhs.k); }
+        Vc_ALWAYS_INLINE bool operator!=(const Mask &rhs) const { return 0 == _mm256_testc_ps(k, rhs.k); }
 
-        inline Mask operator&&(const Mask &rhs) const { return _mm256_and_ps(k, rhs.k); }
-        inline Mask operator& (const Mask &rhs) const { return _mm256_and_ps(k, rhs.k); }
-        inline Mask operator||(const Mask &rhs) const { return _mm256_or_ps (k, rhs.k); }
-        inline Mask operator| (const Mask &rhs) const { return _mm256_or_ps (k, rhs.k); }
-        inline Mask operator^ (const Mask &rhs) const { return _mm256_xor_ps(k, rhs.k); }
-        inline Mask operator!() const { return _mm256_andnot_ps(data(), _mm256_setallone_ps()); }
+        Vc_ALWAYS_INLINE Mask operator!() const { return _mm256_andnot_ps(data(), _mm256_setallone_ps()); }
 
-        inline Mask &operator&=(const Mask &rhs) { k = _mm256_and_ps(k, rhs.k); return *this; }
-        inline Mask &operator|=(const Mask &rhs) { k = _mm256_or_ps (k, rhs.k); return *this; }
+        Vc_ALWAYS_INLINE Mask &operator&=(const Mask &rhs) { k = _mm256_and_ps(k, rhs.k); return *this; }
+        Vc_ALWAYS_INLINE Mask &operator|=(const Mask &rhs) { k = _mm256_or_ps (k, rhs.k); return *this; }
+        Vc_ALWAYS_INLINE Mask &operator^=(const Mask &rhs) { k = _mm256_xor_ps(k, rhs.k); return *this; }
 
         // no need for expression template optimizations because cmp(n)eq for floats are not bitwise
         // compares
-        inline bool isFull () const { return 0 != _mm256_testc_ps(k, _mm256_setallone_ps()); }
-        inline bool isEmpty() const { return 0 != _mm256_testz_ps(k, k); }
-        inline bool isMix  () const { return 0 != _mm256_testnzc_ps(k, _mm256_setallone_ps()); }
+        Vc_ALWAYS_INLINE bool isFull () const { return 0 != _mm256_testc_ps(k, _mm256_setallone_ps()); }
+        Vc_ALWAYS_INLINE bool isEmpty() const { return 0 != _mm256_testz_ps(k, k); }
+        Vc_ALWAYS_INLINE bool isMix  () const { return 0 != _mm256_testnzc_ps(k, _mm256_setallone_ps()); }
 
 #ifndef VC_NO_AUTOMATIC_BOOL_FROM_MASK
-        inline operator bool() const { return isFull(); }
+        Vc_ALWAYS_INLINE operator bool() const { return isFull(); }
 #endif
 
-        inline int CONST_L shiftMask() const CONST_R;
-        int CONST_L toInt() const CONST_R;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int shiftMask() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int toInt() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 
-        inline _M256  data () const { return k; }
-        inline _M256I dataI() const { return _mm256_castps_si256(k); }
-        inline _M256D dataD() const { return _mm256_castps_pd(k); }
+        Vc_ALWAYS_INLINE m256  data () const { return k; }
+        Vc_ALWAYS_INLINE m256i dataI() const { return _mm256_castps_si256(k); }
+        Vc_ALWAYS_INLINE m256d dataD() const { return _mm256_castps_pd(k); }
 
-        bool operator[](int index) const;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L bool operator[](int index) const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 
-        int count() const;
-        int firstOne() const;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int count() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int firstOne() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 
     private:
-        _M256 k;
+#ifdef VC_COMPILE_BENCHMARKS
+    public:
+#endif
+        m256 k;
 };
 
 template<unsigned int VectorSize> class Mask<VectorSize, 16u>
@@ -113,69 +119,79 @@ template<unsigned int VectorSize> class Mask<VectorSize, 16u>
         typedef Mask<VectorSize, 16u> AsArg;
 #endif
 
-        inline Mask() {}
-        inline Mask(const __m128  &x) : k(x) {}
-        inline Mask(const __m128d &x) : k(_mm_castpd_ps(x)) {}
-        inline Mask(const __m128i &x) : k(_mm_castsi128_ps(x)) {}
-        inline explicit Mask(VectorSpecialInitializerZero::ZEnum) : k(_mm_setzero_ps()) {}
-        inline explicit Mask(VectorSpecialInitializerOne::OEnum) : k(_mm_setallone_ps()) {}
-        inline explicit Mask(bool b) : k(b ? _mm_setallone_ps() : _mm_setzero_ps()) {}
-        inline Mask(const Mask &rhs) : k(rhs.k) {}
-        inline Mask(const Mask<VectorSize, 32u> &rhs) : k(avx_cast<__m128>(
-                _mm_packs_epi32(avx_cast<__m128i>(rhs.data()), _mm256_extractf128_si256(rhs.dataI(), 1)))) {}
-        inline Mask(const Mask<VectorSize / 2, 16u> *a) : k(avx_cast<__m128>(
+        Vc_ALWAYS_INLINE Mask() {}
+        Vc_ALWAYS_INLINE Mask(param128  x) : k(x) {}
+        Vc_ALWAYS_INLINE Mask(param128d x) : k(_mm_castpd_ps(x)) {}
+        Vc_ALWAYS_INLINE Mask(param128i x) : k(_mm_castsi128_ps(x)) {}
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+        Vc_ALWAYS_INLINE Mask(__m128  x) : k(x) {}
+        Vc_ALWAYS_INLINE Mask(__m128d x) : k(_mm_castpd_ps(x)) {}
+        Vc_ALWAYS_INLINE Mask(__m128i x) : k(_mm_castsi128_ps(x)) {}
+#endif
+        Vc_ALWAYS_INLINE explicit Mask(VectorSpecialInitializerZero::ZEnum) : k(_mm_setzero_ps()) {}
+        Vc_ALWAYS_INLINE explicit Mask(VectorSpecialInitializerOne::OEnum) : k(_mm_setallone_ps()) {}
+        Vc_ALWAYS_INLINE explicit Mask(bool b) : k(b ? _mm_setallone_ps() : m128(_mm_setzero_ps())) {}
+        Vc_ALWAYS_INLINE Mask(const Mask &rhs) : k(rhs.k) {}
+        Vc_ALWAYS_INLINE Mask(const Mask<VectorSize, 32u> &rhs) : k(avx_cast<m128>(
+                _mm_packs_epi32(avx_cast<m128i>(rhs.data()), _mm256_extractf128_si256(rhs.dataI(), 1)))) {}
+        Vc_ALWAYS_INLINE Mask(const Mask<VectorSize / 2, 16u> *a) : k(avx_cast<m128>(
                 _mm_packs_epi16(a[0].dataI(), a[1].dataI()))) {}
 
-        inline bool operator==(const Mask &rhs) const { return 0 != _mm_testc_si128(dataI(), rhs.dataI()); }
-        inline bool operator!=(const Mask &rhs) const { return 0 == _mm_testc_si128(dataI(), rhs.dataI()); }
+        Vc_ALWAYS_INLINE bool operator==(const Mask &rhs) const { return 0 != _mm_testc_si128(dataI(), rhs.dataI()); }
+        Vc_ALWAYS_INLINE bool operator!=(const Mask &rhs) const { return 0 == _mm_testc_si128(dataI(), rhs.dataI()); }
 
-        inline Mask operator&&(const Mask &rhs) const { return _mm_and_ps(k, rhs.k); }
-        inline Mask operator& (const Mask &rhs) const { return _mm_and_ps(k, rhs.k); }
-        inline Mask operator||(const Mask &rhs) const { return _mm_or_ps (k, rhs.k); }
-        inline Mask operator| (const Mask &rhs) const { return _mm_or_ps (k, rhs.k); }
-        inline Mask operator^ (const Mask &rhs) const { return _mm_xor_ps(k, rhs.k); }
-        inline Mask operator!() const { return _mm_andnot_ps(data(), _mm_setallone_ps()); }
+        Vc_ALWAYS_INLINE Mask operator!() const { return _mm_andnot_ps(data(), _mm_setallone_ps()); }
 
-        inline Mask &operator&=(const Mask &rhs) { k = _mm_and_ps(k, rhs.k); return *this; }
-        inline Mask &operator|=(const Mask &rhs) { k = _mm_or_ps (k, rhs.k); return *this; }
+        Vc_ALWAYS_INLINE Mask &operator&=(const Mask &rhs) { k = _mm_and_ps(k, rhs.k); return *this; }
+        Vc_ALWAYS_INLINE Mask &operator|=(const Mask &rhs) { k = _mm_or_ps (k, rhs.k); return *this; }
+        Vc_ALWAYS_INLINE Mask &operator^=(const Mask &rhs) { k = _mm_xor_ps(k, rhs.k); return *this; }
 
         // TODO: use expression templates to optimize (v1 == v2).isFull() and friends
-        inline bool isFull () const { return 0 != _mm_testc_si128(dataI(), _mm_setallone_si128()); }
-        inline bool isEmpty() const { return 0 != _mm_testz_si128(dataI(), dataI()); }
-        inline bool isMix  () const { return 0 != _mm_testnzc_si128(dataI(), _mm_setallone_si128()); }
+        Vc_ALWAYS_INLINE bool isFull () const { return 0 != _mm_testc_si128(dataI(), _mm_setallone_si128()); }
+        Vc_ALWAYS_INLINE bool isEmpty() const { return 0 != _mm_testz_si128(dataI(), dataI()); }
+        Vc_ALWAYS_INLINE bool isMix  () const { return 0 != _mm_testnzc_si128(dataI(), _mm_setallone_si128()); }
 
 #ifndef VC_NO_AUTOMATIC_BOOL_FROM_MASK
-        inline operator bool() const { return isFull(); }
+        Vc_ALWAYS_INLINE operator bool() const { return isFull(); }
 #endif
 
-        inline int CONST_L shiftMask() const CONST_R;
-        int CONST_L toInt() const CONST_R;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int shiftMask() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int toInt() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 
-        inline __m128  data () const { return k; }
-        inline __m128i dataI() const { return avx_cast<__m128i>(k); }
-        inline __m128d dataD() const { return avx_cast<__m128d>(k); }
+        Vc_ALWAYS_INLINE m128  data () const { return k; }
+        Vc_ALWAYS_INLINE m128i dataI() const { return avx_cast<m128i>(k); }
+        Vc_ALWAYS_INLINE m128d dataD() const { return avx_cast<m128d>(k); }
 
-        bool operator[](int index) const;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L bool operator[](int index) const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 
-        int count() const;
-        int firstOne() const;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int count() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
+        Vc_ALWAYS_INLINE_L Vc_PURE_L int firstOne() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 
     private:
-        __m128 k;
+#ifdef VC_COMPILE_BENCHMARKS
+    public:
+#endif
+        m128 k;
 };
 
 struct ForeachHelper
 {
     size_t mask;
     bool brk;
-    inline ForeachHelper(size_t _mask) : mask(_mask), brk(false) {}
-    inline bool outer() const { return mask != 0; }
-    inline bool inner() { return (brk = !brk); }
-    inline size_t next() {
+    bool outerBreak;
+    Vc_ALWAYS_INLINE ForeachHelper(size_t _mask) : mask(_mask), brk(false), outerBreak(false) {}
+    Vc_ALWAYS_INLINE bool outer() const { return mask != 0 && !outerBreak; }
+    Vc_ALWAYS_INLINE bool inner() { return (brk = !brk); }
+    Vc_ALWAYS_INLINE void noBreak() { outerBreak = false; }
+    Vc_ALWAYS_INLINE size_t next() {
+        outerBreak = true;
 #ifdef VC_GNU_ASM
         const size_t bit = __builtin_ctzl(mask);
         __asm__("btr %1,%0" : "+r"(mask) : "r"(bit));
 #else
+#ifdef VC_MSVC
+#pragma warning(suppress : 4267) // conversion from 'size_t' to 'unsigned long', possible loss of data
+#endif
         const size_t bit = _bit_scan_forward(mask);
         mask &= ~(1 << bit);
 #endif
@@ -184,12 +200,47 @@ struct ForeachHelper
 };
 
 #define Vc_foreach_bit(_it_, _mask_) \
-    for (Vc::AVX::ForeachHelper _Vc_foreach_bit_helper((_mask_).toInt()); _Vc_foreach_bit_helper.outer(); ) \
-        for (_it_ = _Vc_foreach_bit_helper.next(); _Vc_foreach_bit_helper.inner(); )
+    for (Vc::AVX::ForeachHelper Vc__make_unique(foreach_bit_obj)((_mask_).toInt()); Vc__make_unique(foreach_bit_obj).outer(); ) \
+        for (_it_ = Vc__make_unique(foreach_bit_obj).next(); Vc__make_unique(foreach_bit_obj).inner(); Vc__make_unique(foreach_bit_obj).noBreak())
+
+// Operators
+namespace Intrinsics
+{
+    static Vc_ALWAYS_INLINE Vc_PURE m256 and_(param256 a, param256 b) { return _mm256_and_ps(a, b); }
+    static Vc_ALWAYS_INLINE Vc_PURE m256  or_(param256 a, param256 b) { return _mm256_or_ps(a, b); }
+    static Vc_ALWAYS_INLINE Vc_PURE m256 xor_(param256 a, param256 b) { return _mm256_xor_ps(a, b); }
+
+    static Vc_ALWAYS_INLINE Vc_PURE m128 and_(param128 a, param128 b) { return _mm_and_ps(a, b); }
+    static Vc_ALWAYS_INLINE Vc_PURE m128  or_(param128 a, param128 b) { return _mm_or_ps(a, b); }
+    static Vc_ALWAYS_INLINE Vc_PURE m128 xor_(param128 a, param128 b) { return _mm_xor_ps(a, b); }
+} // namespace Intrinsics
+
+// binary and/or/xor cannot work with one operand larger than the other
+template<unsigned int LSize, unsigned int RSize, size_t LWidth, size_t RWidth> void operator&(const Mask<LSize, LWidth> &l, const Mask<RSize, RWidth> &r);
+template<unsigned int LSize, unsigned int RSize, size_t LWidth, size_t RWidth> void operator|(const Mask<LSize, LWidth> &l, const Mask<RSize, RWidth> &r);
+template<unsigned int LSize, unsigned int RSize, size_t LWidth, size_t RWidth> void operator^(const Mask<LSize, LWidth> &l, const Mask<RSize, RWidth> &r);
+
+// let binary and/or/xor work for any combination of masks (as long as they have the same sizeof)
+template<unsigned int LSize, unsigned int RSize, size_t Width> Vc_ALWAYS_INLINE Vc_PURE Mask<LSize, Width> operator&(const Mask<LSize, Width> &l, const Mask<RSize, Width> &r) { return Intrinsics::and_(l.data(), r.data()); }
+template<unsigned int LSize, unsigned int RSize, size_t Width> Vc_ALWAYS_INLINE Vc_PURE Mask<LSize, Width> operator|(const Mask<LSize, Width> &l, const Mask<RSize, Width> &r) { return Intrinsics:: or_(l.data(), r.data()); }
+template<unsigned int LSize, unsigned int RSize, size_t Width> Vc_ALWAYS_INLINE Vc_PURE Mask<LSize, Width> operator^(const Mask<LSize, Width> &l, const Mask<RSize, Width> &r) { return Intrinsics::xor_(l.data(), r.data()); }
+
+// disable logical and/or for incompatible masks
+template<unsigned int LSize, unsigned int RSize, size_t LWidth, size_t RWidth> void operator&&(const Mask<LSize, LWidth> &lhs, const Mask<RSize, RWidth> &rhs);
+template<unsigned int LSize, unsigned int RSize, size_t LWidth, size_t RWidth> void operator||(const Mask<LSize, LWidth> &lhs, const Mask<RSize, RWidth> &rhs);
+
+// logical and/or for compatible masks
+template<unsigned int Size, size_t LWidth, size_t RWidth> Vc_ALWAYS_INLINE Vc_PURE Mask<Size, LWidth> operator&&(const Mask<Size, LWidth> &lhs, const Mask<Size, RWidth> &rhs) { return lhs && static_cast<Mask<Size, LWidth> >(rhs); }
+template<unsigned int Size, size_t LWidth, size_t RWidth> Vc_ALWAYS_INLINE Vc_PURE Mask<Size, LWidth> operator||(const Mask<Size, LWidth> &lhs, const Mask<Size, RWidth> &rhs) { return lhs || static_cast<Mask<Size, LWidth> >(rhs); }
+
+template<unsigned int Size, size_t Width> Vc_ALWAYS_INLINE Vc_PURE Mask<Size, Width> operator&&(const Mask<Size, Width> &lhs, const Mask<Size, Width> &rhs) { return Intrinsics::and_(lhs.data(), rhs.data()); }
+template<unsigned int Size, size_t Width> Vc_ALWAYS_INLINE Vc_PURE Mask<Size, Width> operator||(const Mask<Size, Width> &lhs, const Mask<Size, Width> &rhs) { return Intrinsics::or_ (lhs.data(), rhs.data()); }
 
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #include "mask.tcc"
+#include "undomacros.h"
 
 #endif // VC_AVX_MASK_H
index ce09174..99bc0ff 100644 (file)
 
 */
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
 {
 
-template<> inline Mask<4, 32>::Mask(const Mask<8, 32> &m)
+template<> Vc_ALWAYS_INLINE Mask<4, 32>::Mask(const Mask<8, 32> &m)
     : k(concat(_mm_unpacklo_ps(lo128(m.data()), lo128(m.data())),
                 _mm_unpackhi_ps(lo128(m.data()), lo128(m.data()))))
 {
 }
 
-template<> inline Mask<8, 32>::Mask(const Mask<4, 32> &m)
+template<> Vc_ALWAYS_INLINE Mask<8, 32>::Mask(const Mask<4, 32> &m)
     // aabb ccdd -> abcd 0000
     : k(concat(Mem::shuffle<X0, X2, Y0, Y2>(lo128(m.data()), hi128(m.data())),
                 _mm_setzero_ps()))
 {
 }
 
-template<unsigned int Size> inline int Mask<Size, 32u>::shiftMask() const
+template<unsigned int Size> Vc_ALWAYS_INLINE Vc_PURE int Mask<Size, 32u>::shiftMask() const
 {
     return _mm256_movemask_epi8(dataI());
 }
-template<unsigned int Size> inline int Mask<Size, 16u>::shiftMask() const
+template<unsigned int Size> Vc_ALWAYS_INLINE Vc_PURE int Mask<Size, 16u>::shiftMask() const
 {
     return _mm_movemask_epi8(dataI());
 }
 
-template<> inline int Mask< 4, 32>::toInt() const { return _mm256_movemask_pd(dataD()); }
-template<> inline int Mask< 8, 32>::toInt() const { return _mm256_movemask_ps(data ()); }
-template<> inline int Mask< 8, 16>::toInt() const { return _mm_movemask_epi8(_mm_packs_epi16(dataI(), _mm_setzero_si128())); }
-template<> inline int Mask<16, 16>::toInt() const { return _mm_movemask_epi8(dataI()); }
+template<> Vc_ALWAYS_INLINE Vc_PURE int Mask< 4, 32>::toInt() const { return _mm256_movemask_pd(dataD()); }
+template<> Vc_ALWAYS_INLINE Vc_PURE int Mask< 8, 32>::toInt() const { return _mm256_movemask_ps(data ()); }
+template<> Vc_ALWAYS_INLINE Vc_PURE int Mask< 8, 16>::toInt() const { return _mm_movemask_epi8(_mm_packs_epi16(dataI(), _mm_setzero_si128())); }
+template<> Vc_ALWAYS_INLINE Vc_PURE int Mask<16, 16>::toInt() const { return _mm_movemask_epi8(dataI()); }
 
-template<> inline bool Mask< 4, 32>::operator[](int index) const { return toInt() & (1 << index); }
-template<> inline bool Mask< 8, 32>::operator[](int index) const { return toInt() & (1 << index); }
-template<> inline bool Mask< 8, 16>::operator[](int index) const { return shiftMask() & (1 << 2 * index); }
-template<> inline bool Mask<16, 16>::operator[](int index) const { return toInt() & (1 << index); }
+template<> Vc_ALWAYS_INLINE Vc_PURE bool Mask< 4, 32>::operator[](int index) const { return toInt() & (1 << index); }
+template<> Vc_ALWAYS_INLINE Vc_PURE bool Mask< 8, 32>::operator[](int index) const { return toInt() & (1 << index); }
+template<> Vc_ALWAYS_INLINE Vc_PURE bool Mask< 8, 16>::operator[](int index) const { return shiftMask() & (1 << 2 * index); }
+template<> Vc_ALWAYS_INLINE Vc_PURE bool Mask<16, 16>::operator[](int index) const { return toInt() & (1 << index); }
 
-template<unsigned int Size> inline int Mask<Size, 32u>::count() const { return _mm_popcnt_u32(toInt()); }
-template<unsigned int Size> inline int Mask<Size, 16u>::count() const { return _mm_popcnt_u32(toInt()); }
-template<unsigned int Size> inline int Mask<Size, 32u>::firstOne() const { return _bit_scan_forward(toInt()); }
-template<unsigned int Size> inline int Mask<Size, 16u>::firstOne() const { return _bit_scan_forward(toInt()); }
+#ifndef VC_IMPL_POPCNT
+static Vc_ALWAYS_INLINE Vc_CONST unsigned int _mm_popcnt_u32(unsigned int n) {
+    n = (n & 0x55555555U) + ((n >> 1) & 0x55555555U);
+    n = (n & 0x33333333U) + ((n >> 2) & 0x33333333U);
+    n = (n & 0x0f0f0f0fU) + ((n >> 4) & 0x0f0f0f0fU);
+    //n = (n & 0x00ff00ffU) + ((n >> 8) & 0x00ff00ffU);
+    //n = (n & 0x0000ffffU) + ((n >>16) & 0x0000ffffU);
+    return n;
+}
+#endif
+template<unsigned int Size> Vc_ALWAYS_INLINE Vc_PURE int Mask<Size, 32u>::count() const { return _mm_popcnt_u32(toInt()); }
+template<unsigned int Size> Vc_ALWAYS_INLINE Vc_PURE int Mask<Size, 16u>::count() const { return _mm_popcnt_u32(toInt()); }
+template<unsigned int Size> Vc_ALWAYS_INLINE Vc_PURE int Mask<Size, 32u>::firstOne() const { return _bit_scan_forward(toInt()); }
+template<unsigned int Size> Vc_ALWAYS_INLINE Vc_PURE int Mask<Size, 16u>::firstOne() const { return _bit_scan_forward(toInt()); }
 
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
index be7d1ba..38da5ec 100644 (file)
@@ -24,6 +24,7 @@
 #include "limits.h"
 #include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -35,10 +36,10 @@ namespace AVX
      * The \p e value will be an integer defining the power-of-two exponent
      */
     inline double_v frexp(double_v::AsArg v, int_v *e) {
-        const __m256d exponentBits = Const<double>::exponentMask().dataD();
-        const __m256d exponentPart = _mm256_and_pd(v.data(), exponentBits);
-        e->data() = _mm256_sub_epi32(_mm256_srli_epi64(avx_cast<__m256i>(exponentPart), 52), _mm256_set1_epi32(0x3fe));
-        const __m256d exponentMaximized = _mm256_or_pd(v.data(), exponentBits);
+        const m256d exponentBits = Const<double>::exponentMask().dataD();
+        const m256d exponentPart = _mm256_and_pd(v.data(), exponentBits);
+        e->data() = _mm256_sub_epi32(_mm256_srli_epi64(avx_cast<m256i>(exponentPart), 52), _mm256_set1_epi32(0x3fe));
+        const m256d exponentMaximized = _mm256_or_pd(v.data(), exponentBits);
         double_v ret = _mm256_and_pd(exponentMaximized, _mm256_broadcast_sd(reinterpret_cast<const double *>(&c_general::frexpMask)));
         double_m zeroMask = v == double_v::Zero();
         ret(isnan(v) || !isfinite(v) || zeroMask) = v;
@@ -46,22 +47,22 @@ namespace AVX
         return ret;
     }
     inline float_v frexp(float_v::AsArg v, int_v *e) {
-        const __m256 exponentBits = Const<float>::exponentMask().data();
-        const __m256 exponentPart = _mm256_and_ps(v.data(), exponentBits);
-        e->data() = _mm256_sub_epi32(_mm256_srli_epi32(avx_cast<__m256i>(exponentPart), 23), _mm256_set1_epi32(0x7e));
-        const __m256 exponentMaximized = _mm256_or_ps(v.data(), exponentBits);
-        float_v ret = _mm256_and_ps(exponentMaximized, avx_cast<__m256>(_mm256_set1_epi32(0xbf7fffffu)));
+        const m256 exponentBits = Const<float>::exponentMask().data();
+        const m256 exponentPart = _mm256_and_ps(v.data(), exponentBits);
+        e->data() = _mm256_sub_epi32(_mm256_srli_epi32(avx_cast<m256i>(exponentPart), 23), _mm256_set1_epi32(0x7e));
+        const m256 exponentMaximized = _mm256_or_ps(v.data(), exponentBits);
+        float_v ret = _mm256_and_ps(exponentMaximized, avx_cast<m256>(_mm256_set1_epi32(0xbf7fffffu)));
         ret(isnan(v) || !isfinite(v) || v == float_v::Zero()) = v;
         e->setZero(v == float_v::Zero());
         return ret;
     }
     inline sfloat_v frexp(sfloat_v::AsArg v, short_v *e) {
-        const __m256 exponentBits = Const<float>::exponentMask().data();
-        const __m256 exponentPart = _mm256_and_ps(v.data(), exponentBits);
-        e->data() = _mm_sub_epi16(_mm_packs_epi32(_mm_srli_epi32(avx_cast<__m128i>(exponentPart), 23),
-                    _mm_srli_epi32(avx_cast<__m128i>(hi128(exponentPart)), 23)), _mm_set1_epi16(0x7e));
-        const __m256 exponentMaximized = _mm256_or_ps(v.data(), exponentBits);
-        sfloat_v ret = _mm256_and_ps(exponentMaximized, avx_cast<__m256>(_mm256_set1_epi32(0xbf7fffffu)));
+        const m256 exponentBits = Const<float>::exponentMask().data();
+        const m256 exponentPart = _mm256_and_ps(v.data(), exponentBits);
+        e->data() = _mm_sub_epi16(_mm_packs_epi32(_mm_srli_epi32(avx_cast<m128i>(exponentPart), 23),
+                    _mm_srli_epi32(avx_cast<m128i>(hi128(exponentPart)), 23)), _mm_set1_epi16(0x7e));
+        const m256 exponentMaximized = _mm256_or_ps(v.data(), exponentBits);
+        sfloat_v ret = _mm256_and_ps(exponentMaximized, avx_cast<m256>(_mm256_set1_epi32(0xbf7fffffu)));
         ret(isnan(v) || !isfinite(v) || v == sfloat_v::Zero()) = v;
         e->setZero(v == sfloat_v::Zero());
         return ret;
@@ -74,8 +75,8 @@ namespace AVX
     inline double_v ldexp(double_v::AsArg v, int_v::AsArg _e) {
         int_v e = _e;
         e.setZero((v == double_v::Zero()).dataI());
-        const __m256i exponentBits = _mm256_slli_epi64(e.data(), 52);
-        return avx_cast<__m256d>(_mm256_add_epi64(avx_cast<__m256i>(v.data()), exponentBits));
+        const m256i exponentBits = _mm256_slli_epi64(e.data(), 52);
+        return avx_cast<m256d>(_mm256_add_epi64(avx_cast<m256i>(v.data()), exponentBits));
     }
     inline float_v ldexp(float_v::AsArg v, int_v::AsArg _e) {
         int_v e = _e;
@@ -86,20 +87,25 @@ namespace AVX
         short_v e = _e;
         e.setZero(static_cast<short_m>(v == sfloat_v::Zero()));
         e = e << (23 - 16);
-        const __m256i exponentBits = concat(_mm_unpacklo_epi16(_mm_setzero_si128(), e.data()),
+        const m256i exponentBits = concat(_mm_unpacklo_epi16(_mm_setzero_si128(), e.data()),
                 _mm_unpackhi_epi16(_mm_setzero_si128(), e.data()));
         return (v.reinterpretCast<int_v>() + int_v(exponentBits)).reinterpretCast<sfloat_v>();
     }
 
-    static inline float_v floor(float_v::AsArg v) { return _mm256_floor_ps(v.data()); }
-    static inline sfloat_v floor(sfloat_v::AsArg v) { return _mm256_floor_ps(v.data()); }
-    static inline double_v floor(double_v::AsArg v) { return _mm256_floor_pd(v.data()); }
+    static Vc_ALWAYS_INLINE  float_v trunc( float_v::AsArg v) { return _mm256_round_ps(v.data(), 0x3); }
+    static Vc_ALWAYS_INLINE sfloat_v trunc(sfloat_v::AsArg v) { return _mm256_round_ps(v.data(), 0x3); }
+    static Vc_ALWAYS_INLINE double_v trunc(double_v::AsArg v) { return _mm256_round_pd(v.data(), 0x3); }
 
-    static inline float_v ceil(float_v::AsArg v) { return _mm256_ceil_ps(v.data()); }
-    static inline sfloat_v ceil(sfloat_v::AsArg v) { return _mm256_ceil_ps(v.data()); }
-    static inline double_v ceil(double_v::AsArg v) { return _mm256_ceil_pd(v.data()); }
+    static Vc_ALWAYS_INLINE float_v floor(float_v::AsArg v) { return _mm256_floor_ps(v.data()); }
+    static Vc_ALWAYS_INLINE sfloat_v floor(sfloat_v::AsArg v) { return _mm256_floor_ps(v.data()); }
+    static Vc_ALWAYS_INLINE double_v floor(double_v::AsArg v) { return _mm256_floor_pd(v.data()); }
+
+    static Vc_ALWAYS_INLINE float_v ceil(float_v::AsArg v) { return _mm256_ceil_ps(v.data()); }
+    static Vc_ALWAYS_INLINE sfloat_v ceil(sfloat_v::AsArg v) { return _mm256_ceil_ps(v.data()); }
+    static Vc_ALWAYS_INLINE double_v ceil(double_v::AsArg v) { return _mm256_ceil_pd(v.data()); }
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #include "undomacros.h"
 #define VC__USE_NAMESPACE AVX
index 3a178a8..e614608 100644 (file)
 #ifndef VC_AVX_PREFETCHES_TCC
 #define VC_AVX_PREFETCHES_TCC
 
+namespace AliRoot {
 namespace Vc
 {
 namespace Internal
 {
 
-inline ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchForOneRead(const void *addr)
+Vc_ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchForOneRead(const void *addr)
 {
     _mm_prefetch(static_cast<char *>(const_cast<void *>(addr)), _MM_HINT_NTA);
 }
-inline ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchClose(const void *addr)
+Vc_ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchClose(const void *addr)
 {
     _mm_prefetch(static_cast<char *>(const_cast<void *>(addr)), _MM_HINT_T0);
 }
-inline ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchMid(const void *addr)
+Vc_ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchMid(const void *addr)
 {
     _mm_prefetch(static_cast<char *>(const_cast<void *>(addr)), _MM_HINT_T1);
 }
-inline ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchFar(const void *addr)
+Vc_ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchFar(const void *addr)
 {
     _mm_prefetch(static_cast<char *>(const_cast<void *>(addr)), _MM_HINT_T2);
 }
-inline ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchForModify(const void *addr)
+Vc_ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchForModify(const void *addr)
 {
 #ifdef __3dNOW__
     _m_prefetchw(const_cast<void *>(addr));
@@ -52,5 +53,6 @@ inline ALWAYS_INLINE void HelperImpl<Vc::AVXImpl>::prefetchForModify(const void
 
 } // namespace Internal
 } // namespace Vc
+} // namespace AliRoot
 
 #endif // VC_AVX_PREFETCHES_TCC
index b7e8287..9bc56b5 100644 (file)
 #define VC_AVX_SHUFFLE_H
 
 #include "../sse/shuffle.h"
+#include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
+        using AVX::m128;
+        using AVX::m128d;
+        using AVX::m128i;
+        using AVX::m256;
+        using AVX::m256d;
+        using AVX::m256i;
+        using AVX::param128;
+        using AVX::param128d;
+        using AVX::param128i;
+        using AVX::param256;
+        using AVX::param256d;
+        using AVX::param256i;
     namespace Mem
     {
-        template<VecPos L, VecPos H> static inline __m256 ALWAYS_INLINE CONST shuffle128(__m256 x, __m256 y) {
+        template<VecPos L, VecPos H> static Vc_ALWAYS_INLINE m256 Vc_CONST permute128(param256 x) {
+            VC_STATIC_ASSERT(L >= X0 && L <= X1, Incorrect_Range);
+            VC_STATIC_ASSERT(H >= X0 && H <= X1, Incorrect_Range);
+            return _mm256_permute2f128_ps(x, x, L + H * (1 << 4));
+        }
+        template<VecPos L, VecPos H> static Vc_ALWAYS_INLINE m256d Vc_CONST permute128(param256d x) {
+            VC_STATIC_ASSERT(L >= X0 && L <= X1, Incorrect_Range);
+            VC_STATIC_ASSERT(H >= X0 && H <= X1, Incorrect_Range);
+            return _mm256_permute2f128_pd(x, x, L + H * (1 << 4));
+        }
+        template<VecPos L, VecPos H> static Vc_ALWAYS_INLINE m256i Vc_CONST permute128(param256i x) {
+            VC_STATIC_ASSERT(L >= X0 && L <= X1, Incorrect_Range);
+            VC_STATIC_ASSERT(H >= X0 && H <= X1, Incorrect_Range);
+            return _mm256_permute2f128_si256(x, x, L + H * (1 << 4));
+        }
+        template<VecPos L, VecPos H> static Vc_ALWAYS_INLINE m256 Vc_CONST shuffle128(param256 x, param256 y) {
             VC_STATIC_ASSERT(L >= X0 && H >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(L <= Y1 && H <= Y1, Incorrect_Range);
             return _mm256_permute2f128_ps(x, y, (L < Y0 ? L : L - Y0 + 2) + (H < Y0 ? H : H - Y0 + 2) * (1 << 4));
         }
-        template<VecPos L, VecPos H> static inline __m256i ALWAYS_INLINE CONST shuffle128(__m256i x, __m256i y) {
+        template<VecPos L, VecPos H> static Vc_ALWAYS_INLINE m256i Vc_CONST shuffle128(param256i x, param256i y) {
             VC_STATIC_ASSERT(L >= X0 && H >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(L <= Y1 && H <= Y1, Incorrect_Range);
             return _mm256_permute2f128_si256(x, y, (L < Y0 ? L : L - Y0 + 2) + (H < Y0 ? H : H - Y0 + 2) * (1 << 4));
         }
-        template<VecPos L, VecPos H> static inline __m256d ALWAYS_INLINE CONST shuffle128(__m256d x, __m256d y) {
+        template<VecPos L, VecPos H> static Vc_ALWAYS_INLINE m256d Vc_CONST shuffle128(param256d x, param256d y) {
             VC_STATIC_ASSERT(L >= X0 && H >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(L <= Y1 && H <= Y1, Incorrect_Range);
             return _mm256_permute2f128_pd(x, y, (L < Y0 ? L : L - Y0 + 2) + (H < Y0 ? H : H - Y0 + 2) * (1 << 4));
         }
-        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static inline __m256d ALWAYS_INLINE CONST permute(__m256d x) {
+        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static Vc_ALWAYS_INLINE m256d Vc_CONST permute(param256d x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= X2 && Dst3 >= X2, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X1 && Dst1 <= X1 && Dst2 <= X3 && Dst3 <= X3, Incorrect_Range);
             return _mm256_permute_pd(x, Dst0 + Dst1 * 2 + (Dst2 - X2) * 4 + (Dst3 - X2) * 8);
         }
-        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static inline __m256 ALWAYS_INLINE CONST permute(__m256 x) {
+        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static Vc_ALWAYS_INLINE m256 Vc_CONST permute(param256 x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= X0 && Dst3 >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X3 && Dst1 <= X3 && Dst2 <= X3 && Dst3 <= X3, Incorrect_Range);
             return _mm256_permute_ps(x, Dst0 + Dst1 * 4 + Dst2 * 16 + Dst3 * 64);
         }
-        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static inline __m256i ALWAYS_INLINE CONST permute(__m256i x) {
+        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static Vc_ALWAYS_INLINE m256i Vc_CONST permute(param256i x) {
             return _mm256_castps_si256(permute<Dst0, Dst1, Dst2, Dst3>(_mm256_castsi256_ps(x)));
         }
-        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static inline __m256d ALWAYS_INLINE CONST shuffle(__m256d x, __m256d y) {
+        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static Vc_ALWAYS_INLINE m256d Vc_CONST shuffle(param256d x, param256d y) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= Y0 && Dst2 >= X2 && Dst3 >= Y2, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X1 && Dst1 <= Y1 && Dst2 <= X3 && Dst3 <= Y3, Incorrect_Range);
             return _mm256_shuffle_pd(x, y, Dst0 + (Dst1 - Y0) * 2 + (Dst2 - X2) * 4 + (Dst3 - Y2) * 8);
         }
-        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static inline __m256 ALWAYS_INLINE CONST shuffle(__m256 x, __m256 y) {
+        template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3> static Vc_ALWAYS_INLINE m256 Vc_CONST shuffle(param256 x, param256 y) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= Y0 && Dst3 >= Y0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X3 && Dst1 <= X3 && Dst2 <= Y3 && Dst3 <= Y3, Incorrect_Range);
             return _mm256_shuffle_ps(x, y, Dst0 + Dst1 * 4 + (Dst2 - Y0) * 16 + (Dst3 - Y0) * 64);
         }
         template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3, VecPos Dst4, VecPos Dst5, VecPos Dst6, VecPos Dst7>
-        static inline __m256 ALWAYS_INLINE CONST blend(__m256 x, __m256 y) {
+        static Vc_ALWAYS_INLINE m256 Vc_CONST blend(param256 x, param256 y) {
             VC_STATIC_ASSERT(Dst0 == X0 || Dst0 == Y0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst1 == X1 || Dst1 == Y1, Incorrect_Range);
             VC_STATIC_ASSERT(Dst2 == X2 || Dst2 == Y2, Incorrect_Range);
@@ -82,12 +111,12 @@ namespace Vc
                     );
         }
         template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3, VecPos Dst4, VecPos Dst5, VecPos Dst6, VecPos Dst7>
-        static inline __m256i ALWAYS_INLINE CONST blend(__m256i x, __m256i y) {
+        static Vc_ALWAYS_INLINE m256i Vc_CONST blend(param256i x, param256i y) {
             return _mm256_castps_si256(blend<Dst0, Dst1, Dst2, Dst3, Dst4, Dst5, Dst6, Dst7>(_mm256_castsi256_ps(x), _mm256_castsi256_ps(y)));
         }
         template<VecPos Dst> struct ScaleForBlend { enum { Value = Dst >= X4 ? Dst - X4 + Y0 : Dst }; };
         template<VecPos Dst0, VecPos Dst1, VecPos Dst2, VecPos Dst3, VecPos Dst4, VecPos Dst5, VecPos Dst6, VecPos Dst7>
-        static inline __m256 ALWAYS_INLINE CONST permute(__m256 x) {
+        static Vc_ALWAYS_INLINE m256 Vc_CONST permute(param256 x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst0 <= X7, Incorrect_Range);
             VC_STATIC_ASSERT(Dst1 >= X0 && Dst1 <= X7, Incorrect_Range);
             VC_STATIC_ASSERT(Dst2 >= X0 && Dst2 <= X7, Incorrect_Range);
@@ -99,9 +128,9 @@ namespace Vc
             if (Dst0 + X4 == Dst4 && Dst1 + X4 == Dst5 && Dst2 + X4 == Dst6 && Dst3 + X4 == Dst7) {
                 return permute<Dst0, Dst1, Dst2, Dst3>(x);
             }
-            const __m128 loIn = _mm256_castps256_ps128(x);
-            const __m128 hiIn = _mm256_extractf128_ps(x, 1);
-            __m128 lo, hi;
+            const m128 loIn = _mm256_castps256_ps128(x);
+            const m128 hiIn = _mm256_extractf128_ps(x, 1);
+            m128 lo, hi;
 
             if (Dst0 < X4 && Dst1 < X4 && Dst2 < X4 && Dst3 < X4) {
                 lo = _mm_permute_ps(loIn, Dst0 + Dst1 * 4 + Dst2 * 16 + Dst3 * 64);
@@ -157,52 +186,54 @@ namespace Vc
     // The shuffles and permutes above use memory ordering. The ones below use register ordering:
     namespace Reg
     {
-        template<VecPos H, VecPos L> static inline __m256 ALWAYS_INLINE CONST permute128(__m256 x, __m256 y) {
+        template<VecPos H, VecPos L> static Vc_ALWAYS_INLINE m256 Vc_CONST permute128(param256 x, param256 y) {
             VC_STATIC_ASSERT(L >= X0 && H >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(L <= Y1 && H <= Y1, Incorrect_Range);
             return _mm256_permute2f128_ps(x, y, (L < Y0 ? L : L - Y0 + 2) + (H < Y0 ? H : H - Y0 + 2) * (1 << 4));
         }
-        template<VecPos H, VecPos L> static inline __m256i ALWAYS_INLINE CONST permute128(__m256i x, __m256i y) {
+        template<VecPos H, VecPos L> static Vc_ALWAYS_INLINE m256i Vc_CONST permute128(param256i x, param256i y) {
             VC_STATIC_ASSERT(L >= X0 && H >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(L <= Y1 && H <= Y1, Incorrect_Range);
             return _mm256_permute2f128_si256(x, y, (L < Y0 ? L : L - Y0 + 2) + (H < Y0 ? H : H - Y0 + 2) * (1 << 4));
         }
-        template<VecPos H, VecPos L> static inline __m256d ALWAYS_INLINE CONST permute128(__m256d x, __m256d y) {
+        template<VecPos H, VecPos L> static Vc_ALWAYS_INLINE m256d Vc_CONST permute128(param256d x, param256d y) {
             VC_STATIC_ASSERT(L >= X0 && H >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(L <= Y1 && H <= Y1, Incorrect_Range);
             return _mm256_permute2f128_pd(x, y, (L < Y0 ? L : L - Y0 + 2) + (H < Y0 ? H : H - Y0 + 2) * (1 << 4));
         }
-        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static inline __m256d ALWAYS_INLINE CONST permute(__m256d x) {
+        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static Vc_ALWAYS_INLINE m256d Vc_CONST permute(param256d x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= X2 && Dst3 >= X2, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X1 && Dst1 <= X1 && Dst2 <= X3 && Dst3 <= X3, Incorrect_Range);
             return _mm256_permute_pd(x, Dst0 + Dst1 * 2 + (Dst2 - X2) * 4 + (Dst3 - X2) * 8);
         }
-        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static inline __m256 ALWAYS_INLINE CONST permute(__m256 x) {
+        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static Vc_ALWAYS_INLINE m256 Vc_CONST permute(param256 x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= X0 && Dst3 >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X3 && Dst1 <= X3 && Dst2 <= X3 && Dst3 <= X3, Incorrect_Range);
             return _mm256_permute_ps(x, Dst0 + Dst1 * 4 + Dst2 * 16 + Dst3 * 64);
         }
-        template<VecPos Dst1, VecPos Dst0> static inline __m128d ALWAYS_INLINE CONST permute(__m128d x) {
+        template<VecPos Dst1, VecPos Dst0> static Vc_ALWAYS_INLINE m128d Vc_CONST permute(param128d x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X1 && Dst1 <= X1, Incorrect_Range);
             return _mm_permute_pd(x, Dst0 + Dst1 * 2);
         }
-        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static inline __m128 ALWAYS_INLINE CONST permute(__m128 x) {
+        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static Vc_ALWAYS_INLINE m128 Vc_CONST permute(param128 x) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= X0 && Dst3 >= X0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X3 && Dst1 <= X3 && Dst2 <= X3 && Dst3 <= X3, Incorrect_Range);
             return _mm_permute_ps(x, Dst0 + Dst1 * 4 + Dst2 * 16 + Dst3 * 64);
         }
-        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static inline __m256d ALWAYS_INLINE CONST shuffle(__m256d x, __m256d y) {
+        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static Vc_ALWAYS_INLINE m256d Vc_CONST shuffle(param256d x, param256d y) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= Y0 && Dst2 >= X2 && Dst3 >= Y2, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X1 && Dst1 <= Y1 && Dst2 <= X3 && Dst3 <= Y3, Incorrect_Range);
             return _mm256_shuffle_pd(x, y, Dst0 + (Dst1 - Y0) * 2 + (Dst2 - X2) * 4 + (Dst3 - Y2) * 8);
         }
-        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static inline __m256 ALWAYS_INLINE CONST shuffle(__m256 x, __m256 y) {
+        template<VecPos Dst3, VecPos Dst2, VecPos Dst1, VecPos Dst0> static Vc_ALWAYS_INLINE m256 Vc_CONST shuffle(param256 x, param256 y) {
             VC_STATIC_ASSERT(Dst0 >= X0 && Dst1 >= X0 && Dst2 >= Y0 && Dst3 >= Y0, Incorrect_Range);
             VC_STATIC_ASSERT(Dst0 <= X3 && Dst1 <= X3 && Dst2 <= Y3 && Dst3 <= Y3, Incorrect_Range);
             return _mm256_shuffle_ps(x, y, Dst0 + Dst1 * 4 + (Dst2 - Y0) * 16 + (Dst3 - Y0) * 64);
         }
     } // namespace Reg
 } // namespace Vc
+} // namespace AliRoot
+#include "undomacros.h"
 
 #endif // VC_AVX_SHUFFLE_H
index 9544f1f..ff085e2 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "types.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -29,10 +30,16 @@ namespace AVX
 template<typename T> struct SortHelper
 {
     typedef typename VectorTypeHelper<T>::Type VectorType;
-    static VectorType sort(VectorType);
+#ifdef VC_PASSING_VECTOR_BY_VALUE_IS_BROKEN
+    typedef const VectorType & VTArg;
+#else
+    typedef const VectorType VTArg;
+#endif
+    static VectorType sort(VTArg);
     static void sort(VectorType &, VectorType &);
 };
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #endif // VC_AVX_SORTHELPER_H
index cca7290..76a2297 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "../common/types.h"
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -58,15 +59,23 @@ namespace AVX
     template<> struct IndexTypeHelper<        double> { typedef unsigned int   Type; }; // _M128I based int32 would be nice
 
     template<typename T> struct VectorTypeHelper;
-    template<> struct VectorTypeHelper<         char > { typedef __m128i Type; };
-    template<> struct VectorTypeHelper<unsigned char > { typedef __m128i Type; };
-    template<> struct VectorTypeHelper<         short> { typedef __m128i Type; };
-    template<> struct VectorTypeHelper<unsigned short> { typedef __m128i Type; };
-    template<> struct VectorTypeHelper<         int  > { typedef _M256I Type; };
-    template<> struct VectorTypeHelper<unsigned int  > { typedef _M256I Type; };
-    template<> struct VectorTypeHelper<         float> { typedef _M256  Type; };
-    template<> struct VectorTypeHelper<        sfloat> { typedef _M256  Type; };
-    template<> struct VectorTypeHelper<        double> { typedef _M256D Type; };
+    template<> struct VectorTypeHelper<         char > { typedef m128i Type; };
+    template<> struct VectorTypeHelper<unsigned char > { typedef m128i Type; };
+    template<> struct VectorTypeHelper<         short> { typedef m128i Type; };
+    template<> struct VectorTypeHelper<unsigned short> { typedef m128i Type; };
+    template<> struct VectorTypeHelper<         int  > { typedef m256i Type; };
+    template<> struct VectorTypeHelper<unsigned int  > { typedef m256i Type; };
+    template<> struct VectorTypeHelper<         float> { typedef m256  Type; };
+    template<> struct VectorTypeHelper<        sfloat> { typedef m256  Type; };
+    template<> struct VectorTypeHelper<        double> { typedef m256d Type; };
+
+    template<typename T> struct SseVectorType;
+    template<> struct SseVectorType<m256 > { typedef m128  Type; };
+    template<> struct SseVectorType<m256i> { typedef m128i Type; };
+    template<> struct SseVectorType<m256d> { typedef m128d Type; };
+    template<> struct SseVectorType<m128 > { typedef m128  Type; };
+    template<> struct SseVectorType<m128i> { typedef m128i Type; };
+    template<> struct SseVectorType<m128d> { typedef m128d Type; };
 
     template<typename T> struct HasVectorDivisionHelper { enum { Value = 1 }; };
     //template<> struct HasVectorDivisionHelper<unsigned int> { enum { Value = 0 }; };
@@ -96,5 +105,7 @@ namespace AVX
 #endif
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
+#include "undomacros.h"
 
 #endif // AVX_TYPES_H
index a32b20e..4fcb903 100644 (file)
@@ -38,6 +38,7 @@
 #undef isnan
 #endif
 
+namespace AliRoot {
 namespace Vc
 {
 namespace AVX
@@ -61,8 +62,10 @@ template<typename T> class Vector
         typedef Vc::Memory<Vector<T>, Size> Memory;
 #ifdef VC_PASSING_VECTOR_BY_VALUE_IS_BROKEN
         typedef const Vector<T> &AsArg;
+        typedef const VectorType &VectorTypeArg;
 #else
         typedef Vector<T> AsArg;
+        typedef VectorType VectorTypeArg;
 #endif
 
     protected:
@@ -73,72 +76,79 @@ template<typename T> class Vector
         typedef VectorHelper<T> HT;
 
         // cast any m256/m128 to VectorType
-        static inline VectorType INTRINSIC _cast(__m128  v) { return avx_cast<VectorType>(v); }
-        static inline VectorType INTRINSIC _cast(__m128i v) { return avx_cast<VectorType>(v); }
-        static inline VectorType INTRINSIC _cast(__m128d v) { return avx_cast<VectorType>(v); }
-        static inline VectorType INTRINSIC _cast(__m256  v) { return avx_cast<VectorType>(v); }
-        static inline VectorType INTRINSIC _cast(__m256i v) { return avx_cast<VectorType>(v); }
-        static inline VectorType INTRINSIC _cast(__m256d v) { return avx_cast<VectorType>(v); }
-
+        static Vc_INTRINSIC VectorType _cast(param128  v) { return avx_cast<VectorType>(v); }
+        static Vc_INTRINSIC VectorType _cast(param128i v) { return avx_cast<VectorType>(v); }
+        static Vc_INTRINSIC VectorType _cast(param128d v) { return avx_cast<VectorType>(v); }
+        static Vc_INTRINSIC VectorType _cast(param256  v) { return avx_cast<VectorType>(v); }
+        static Vc_INTRINSIC VectorType _cast(param256i v) { return avx_cast<VectorType>(v); }
+        static Vc_INTRINSIC VectorType _cast(param256d v) { return avx_cast<VectorType>(v); }
+
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+        typedef Common::VectorMemoryUnion<VectorType, EntryType, typename VectorType::Base> StorageType;
+#else
         typedef Common::VectorMemoryUnion<VectorType, EntryType> StorageType;
+#endif
         StorageType d;
 
     public:
         ///////////////////////////////////////////////////////////////////////////////////////////
         // uninitialized
-        inline Vector() {}
+        Vc_ALWAYS_INLINE Vector() {}
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // constants
-        explicit Vector(VectorSpecialInitializerZero::ZEnum);
-        explicit Vector(VectorSpecialInitializerOne::OEnum);
-        explicit Vector(VectorSpecialInitializerIndexesFromZero::IEnum);
-        static Vector Zero();
-        static Vector One();
-        static Vector IndexesFromZero();
-        static Vector Random();
+        explicit Vc_ALWAYS_INLINE_L Vector(VectorSpecialInitializerZero::ZEnum) Vc_ALWAYS_INLINE_R;
+        explicit Vc_ALWAYS_INLINE_L Vector(VectorSpecialInitializerOne::OEnum) Vc_ALWAYS_INLINE_R;
+        explicit Vc_ALWAYS_INLINE_L Vector(VectorSpecialInitializerIndexesFromZero::IEnum) Vc_ALWAYS_INLINE_R;
+        static Vc_INTRINSIC_L Vc_CONST_L Vector Zero() Vc_INTRINSIC_R Vc_CONST_R;
+        static Vc_INTRINSIC_L Vc_CONST_L Vector One() Vc_INTRINSIC_R Vc_CONST_R;
+        static Vc_INTRINSIC_L Vc_CONST_L Vector IndexesFromZero() Vc_INTRINSIC_R Vc_CONST_R;
+        static Vc_ALWAYS_INLINE_L Vector Random() Vc_ALWAYS_INLINE_R;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // internal: required to enable returning objects of VectorType
-        inline Vector(const VectorType &x) : d(x) {}
+        Vc_ALWAYS_INLINE Vector(VectorTypeArg x) : d(x) {}
+#ifdef VC_UNCONDITIONAL_AVX2_INTRINSICS
+        Vc_ALWAYS_INLINE Vector(typename VectorType::Base x) : d(x) {}
+#endif
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // static_cast / copy ctor
-        template<typename T2> explicit Vector(Vector<T2> x);
+        template<typename T2> explicit Vector(VC_ALIGNED_PARAMETER(Vector<T2>) x);
 
         // implicit cast
-        template<typename OtherT> inline INTRINSIC_L Vector &operator=(const Vector<OtherT> &x) INTRINSIC_R;
+        template<typename OtherT> Vc_INTRINSIC_L Vector &operator=(const Vector<OtherT> &x) Vc_INTRINSIC_R;
 
         // copy assignment
-        inline Vector &operator=(AsArg v) { d.v() = v.d.v(); return *this; }
+        Vc_ALWAYS_INLINE Vector &operator=(AsArg v) { d.v() = v.d.v(); return *this; }
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // broadcast
-        explicit Vector(EntryType a);
-        template<typename TT> inline INTRINSIC Vector(TT x, VC_EXACT_TYPE(TT, EntryType, void *) = 0) : d(HT::set(x)) {}
-        inline Vector &operator=(EntryType a) { d.v() = HT::set(a); return *this; }
+        explicit Vc_ALWAYS_INLINE_L Vector(EntryType a) Vc_ALWAYS_INLINE_R;
+        template<typename TT> Vc_INTRINSIC Vector(TT x, VC_EXACT_TYPE(TT, EntryType, void *) = 0) : d(HT::set(x)) {}
+        Vc_ALWAYS_INLINE Vector &operator=(EntryType a) { d.v() = HT::set(a); return *this; }
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // load ctors
-        explicit inline INTRINSIC_L
-            Vector(const EntryType *x) INTRINSIC_R;
-        template<typename Alignment> inline INTRINSIC_L
-            Vector(const EntryType *x, Alignment align) INTRINSIC_R;
-        template<typename OtherT> explicit inline INTRINSIC_L
-            Vector(const OtherT    *x) INTRINSIC_R;
-        template<typename OtherT, typename Alignment> inline INTRINSIC_L
-            Vector(const OtherT    *x, Alignment align) INTRINSIC_R;
+        explicit Vc_INTRINSIC_L
+            Vector(const EntryType *x) Vc_INTRINSIC_R;
+        template<typename Alignment> Vc_INTRINSIC_L
+            Vector(const EntryType *x, Alignment align) Vc_INTRINSIC_R;
+        template<typename OtherT> explicit Vc_INTRINSIC_L
+            Vector(const OtherT    *x) Vc_INTRINSIC_R;
+        template<typename OtherT, typename Alignment> Vc_INTRINSIC_L
+            Vector(const OtherT    *x, Alignment align) Vc_INTRINSIC_R;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // load member functions
-        inline INTRINSIC_L
-            void load(const EntryType *mem) INTRINSIC_R;
-        template<typename Alignment> inline INTRINSIC_L
-            void load(const EntryType *mem, Alignment align) INTRINSIC_R;
-        template<typename OtherT> inline INTRINSIC_L
-            void load(const OtherT    *mem) INTRINSIC_R;
-        template<typename OtherT, typename Alignment> inline INTRINSIC_L
-            void load(const OtherT    *mem, Alignment align) INTRINSIC_R;
+        Vc_INTRINSIC_L
+            void load(const EntryType *mem) Vc_INTRINSIC_R;
+        template<typename Alignment> Vc_INTRINSIC_L
+            void load(const EntryType *mem, Alignment align) Vc_INTRINSIC_R;
+        template<typename OtherT> Vc_INTRINSIC_L
+            void load(const OtherT    *mem) Vc_INTRINSIC_R;
+        template<typename OtherT, typename Alignment> Vc_INTRINSIC_L
+            void load(const OtherT    *mem, Alignment align) Vc_INTRINSIC_R;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // expand/merge 1 float_v <=> 2 double_v          XXX rationale? remove it for release? XXX
@@ -147,132 +157,135 @@ template<typename T> class Vector
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // zeroing
-        inline void setZero();
-        inline void setZero(const Mask &k);
+        Vc_INTRINSIC_L void setZero() Vc_INTRINSIC_R;
+        Vc_INTRINSIC_L void setZero(const Mask &k) Vc_INTRINSIC_R;
 
-        void setQnan();
-        void setQnan(MaskArg k);
+        Vc_INTRINSIC_L void setQnan() Vc_INTRINSIC_R;
+        Vc_INTRINSIC_L void setQnan(MaskArg k) Vc_INTRINSIC_R;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // stores
-        inline void store(EntryType *mem) const;
-        inline void store(EntryType *mem, const Mask &mask) const;
-        template<typename A> inline void store(EntryType *mem, A align) const;
-        template<typename A> inline void store(EntryType *mem, const Mask &mask, A align) const;
+        Vc_INTRINSIC_L void store(EntryType *mem) const Vc_INTRINSIC_R;
+        Vc_INTRINSIC_L void store(EntryType *mem, const Mask &mask) const Vc_INTRINSIC_R;
+        template<typename A> Vc_INTRINSIC_L void store(EntryType *mem, A align) const Vc_INTRINSIC_R;
+        template<typename A> Vc_INTRINSIC_L void store(EntryType *mem, const Mask &mask, A align) const Vc_INTRINSIC_R;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // swizzles
-        inline const Vector<T> INTRINSIC_L CONST_L &abcd() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  cdab() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  badc() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  aaaa() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  bbbb() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  cccc() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  dddd() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  bcad() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  bcda() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  dabc() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  acbd() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  dbca() const INTRINSIC_R CONST_R;
-        inline const Vector<T> INTRINSIC_L CONST_L  dcba() const INTRINSIC_R CONST_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T> &abcd() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  cdab() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  badc() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  aaaa() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  bbbb() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  cccc() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  dddd() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  bcad() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  bcda() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  dabc() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  acbd() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  dbca() const Vc_INTRINSIC_R Vc_PURE_R;
+        Vc_INTRINSIC_L Vc_PURE_L const Vector<T>  dcba() const Vc_INTRINSIC_R Vc_PURE_R;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // gathers
         template<typename IndexT> Vector(const EntryType *mem, const IndexT *indexes);
-        template<typename IndexT> Vector(const EntryType *mem, Vector<IndexT> indexes);
+        template<typename IndexT> Vector(const EntryType *mem, VC_ALIGNED_PARAMETER(Vector<IndexT>) indexes);
         template<typename IndexT> Vector(const EntryType *mem, const IndexT *indexes, MaskArg mask);
-        template<typename IndexT> Vector(const EntryType *mem, Vector<IndexT> indexes, MaskArg mask);
-        template<typename S1, typename IT> Vector(const S1 *array, const EntryType S1::* member1, IT indexes);
-        template<typename S1, typename IT> Vector(const S1 *array, const EntryType S1::* member1, IT indexes, MaskArg mask);
-        template<typename S1, typename S2, typename IT> Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes);
-        template<typename S1, typename S2, typename IT> Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes, MaskArg mask);
-        template<typename S1, typename IT1, typename IT2> Vector(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes);
-        template<typename S1, typename IT1, typename IT2> Vector(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes, MaskArg mask);
-        template<typename Index> void gather(const EntryType *mem, Index indexes);
-        template<typename Index> void gather(const EntryType *mem, Index indexes, MaskArg mask);
+        template<typename IndexT> Vector(const EntryType *mem, VC_ALIGNED_PARAMETER(Vector<IndexT>) indexes, MaskArg mask);
+        template<typename S1, typename IT> Vector(const S1 *array, const EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes);
+        template<typename S1, typename IT> Vector(const S1 *array, const EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask);
+        template<typename S1, typename S2, typename IT> Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes);
+        template<typename S1, typename S2, typename IT> Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask);
+        template<typename S1, typename IT1, typename IT2> Vector(const S1 *array, const EntryType *const S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes);
+        template<typename S1, typename IT1, typename IT2> Vector(const S1 *array, const EntryType *const S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes, MaskArg mask);
+        template<typename Index> void gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes);
+        template<typename Index> void gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes, MaskArg mask);
 #ifdef VC_USE_SET_GATHERS
-        template<typename IT> void gather(const EntryType *mem, Vector<IT> indexes, MaskArg mask);
+        template<typename IT> void gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Vector<IT>) indexes, MaskArg mask);
 #endif
-        template<typename S1, typename IT> void gather(const S1 *array, const EntryType S1::* member1, IT indexes);
-        template<typename S1, typename IT> void gather(const S1 *array, const EntryType S1::* member1, IT indexes, MaskArg mask);
-        template<typename S1, typename S2, typename IT> void gather(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes);
-        template<typename S1, typename S2, typename IT> void gather(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes, MaskArg mask);
-        template<typename S1, typename IT1, typename IT2> void gather(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes);
-        template<typename S1, typename IT1, typename IT2> void gather(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes, MaskArg mask);
+        template<typename S1, typename IT> void gather(const S1 *array, const EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes);
+        template<typename S1, typename IT> void gather(const S1 *array, const EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask);
+        template<typename S1, typename S2, typename IT> void gather(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes);
+        template<typename S1, typename S2, typename IT> void gather(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask);
+        template<typename S1, typename IT1, typename IT2> void gather(const S1 *array, const EntryType *const S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes);
+        template<typename S1, typename IT1, typename IT2> void gather(const S1 *array, const EntryType *const S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes, MaskArg mask);
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         // scatters
-        template<typename Index> void scatter(EntryType *mem, Index indexes) const;
-        template<typename Index> void scatter(EntryType *mem, Index indexes, MaskArg mask) const;
-        template<typename S1, typename IT> void scatter(S1 *array, EntryType S1::* member1, IT indexes) const;
-        template<typename S1, typename IT> void scatter(S1 *array, EntryType S1::* member1, IT indexes, MaskArg mask) const;
-        template<typename S1, typename S2, typename IT> void scatter(S1 *array, S2 S1::* member1, EntryType S2::* member2, IT indexes) const;
-        template<typename S1, typename S2, typename IT> void scatter(S1 *array, S2 S1::* member1, EntryType S2::* member2, IT indexes, MaskArg mask) const;
-        template<typename S1, typename IT1, typename IT2> void scatter(S1 *array, EntryType *S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes) const;
-        template<typename S1, typename IT1, typename IT2> void scatter(S1 *array, EntryType *S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes, MaskArg mask) const;
+        template<typename Index> void scatter(EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes) const;
+        template<typename Index> void scatter(EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes, MaskArg mask) const;
+        template<typename S1, typename IT> void scatter(S1 *array, EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes) const;
+        template<typename S1, typename IT> void scatter(S1 *array, EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask) const;
+        template<typename S1, typename S2, typename IT> void scatter(S1 *array, S2 S1::* member1, EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes) const;
+        template<typename S1, typename S2, typename IT> void scatter(S1 *array, S2 S1::* member1, EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask) const;
+        template<typename S1, typename IT1, typename IT2> void scatter(S1 *array, EntryType *S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes) const;
+        template<typename S1, typename IT1, typename IT2> void scatter(S1 *array, EntryType *S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes, MaskArg mask) const;
 
         ///////////////////////////////////////////////////////////////////////////////////////////
         //prefix
-        inline Vector ALWAYS_INLINE &operator++() { data() = VectorHelper<T>::add(data(), VectorHelper<T>::one()); return *this; }
+        Vc_ALWAYS_INLINE Vector &operator++() { data() = VectorHelper<T>::add(data(), VectorHelper<T>::one()); return *this; }
+        Vc_ALWAYS_INLINE Vector &operator--() { data() = VectorHelper<T>::sub(data(), VectorHelper<T>::one()); return *this; }
         //postfix
-        inline Vector ALWAYS_INLINE operator++(int) { const Vector<T> r = *this; data() = VectorHelper<T>::add(data(), VectorHelper<T>::one()); return r; }
+        Vc_ALWAYS_INLINE Vector operator++(int) { const Vector<T> r = *this; data() = VectorHelper<T>::add(data(), VectorHelper<T>::one()); return r; }
+        Vc_ALWAYS_INLINE Vector operator--(int) { const Vector<T> r = *this; data() = VectorHelper<T>::sub(data(), VectorHelper<T>::one()); return r; }
 
-        inline Common::AliasingEntryHelper<StorageType> INTRINSIC operator[](int index) {
+        Vc_INTRINSIC Common::AliasingEntryHelper<StorageType> operator[](size_t index) {
 #if defined(VC_GCC) && VC_GCC >= 0x40300 && VC_GCC < 0x40400
-            ::Vc::Warnings::_operator_bracket_warning();
+            ::AliRoot::Vc::Warnings::_operator_bracket_warning();
 #endif
             return d.m(index);
         }
-        inline EntryType ALWAYS_INLINE operator[](int index) const {
+        Vc_ALWAYS_INLINE EntryType operator[](size_t index) const {
             return d.m(index);
         }
 
-        inline Vector ALWAYS_INLINE operator~() const { return VectorHelper<VectorType>::andnot_(data(), VectorHelper<VectorType>::allone()); }
-        inline Vector<typename NegateTypeHelper<T>::Type> operator-() const;
+        Vc_ALWAYS_INLINE Vector operator~() const { return VectorHelper<VectorType>::andnot_(data(), VectorHelper<VectorType>::allone()); }
+        Vc_ALWAYS_INLINE_L Vc_PURE_L Vector<typename NegateTypeHelper<T>::Type> operator-() const Vc_ALWAYS_INLINE_R Vc_PURE_R;
+        Vc_INTRINSIC Vc_PURE Vector operator+() const { return *this; }
 
 #define OP1(fun) \
-        inline Vector fun() const { return Vector<T>(VectorHelper<T>::fun(data())); } \
-        inline Vector &fun##_eq() { data() = VectorHelper<T>::fun(data()); return *this; }
+        Vc_ALWAYS_INLINE Vector fun() const { return Vector<T>(VectorHelper<T>::fun(data())); } \
+        Vc_ALWAYS_INLINE Vector &fun##_eq() { data() = VectorHelper<T>::fun(data()); return *this; }
         OP1(sqrt)
         OP1(abs)
 #undef OP1
 
 #define OP(symbol, fun) \
-        inline Vector ALWAYS_INLINE &operator symbol##=(const Vector<T> &x) { data() = VectorHelper<T>::fun(data(), x.data()); return *this; } \
-        inline Vector ALWAYS_INLINE &operator symbol##=(EntryType x) { return operator symbol##=(Vector(x)); } \
-        inline Vector ALWAYS_INLINE operator symbol(const Vector<T> &x) const { return Vector<T>(VectorHelper<T>::fun(data(), x.data())); } \
-        template<typename TT> inline VC_EXACT_TYPE(TT, EntryType, Vector) ALWAYS_INLINE operator symbol(TT x) const { return operator symbol(Vector(x)); }
+        Vc_ALWAYS_INLINE Vector &operator symbol##=(const Vector<T> &x) { data() = VectorHelper<T>::fun(data(), x.data()); return *this; } \
+        Vc_ALWAYS_INLINE Vector &operator symbol##=(EntryType x) { return operator symbol##=(Vector(x)); } \
+        Vc_ALWAYS_INLINE Vector operator symbol(const Vector<T> &x) const { return Vector<T>(VectorHelper<T>::fun(data(), x.data())); } \
+        template<typename TT> Vc_ALWAYS_INLINE VC_EXACT_TYPE(TT, EntryType, Vector) operator symbol(TT x) const { return operator symbol(Vector(x)); }
 
         OP(+, add)
         OP(-, sub)
         OP(*, mul)
 #undef OP
         inline Vector &operator/=(EntryType x);
-        template<typename TT> inline PURE_L VC_EXACT_TYPE(TT, EntryType, Vector) operator/(TT x) const PURE_R;
+        template<typename TT> inline Vc_PURE_L VC_EXACT_TYPE(TT, EntryType, Vector) operator/(TT x) const Vc_PURE_R;
         inline Vector &operator/=(const Vector<T> &x);
-        inline Vector  operator/ (const Vector<T> &x) const;
+        inline Vc_PURE_L Vector  operator/ (const Vector<T> &x) const Vc_PURE_R;
 
         // bitwise ops
 #define OP_VEC(op) \
-        inline Vector<T> ALWAYS_INLINE_L &operator op##=(AsArg x) ALWAYS_INLINE_R; \
-        inline Vector<T> ALWAYS_INLINE_L  operator op   (AsArg x) const ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L Vector<T> &operator op##=(AsArg x) Vc_ALWAYS_INLINE_R; \
+        Vc_ALWAYS_INLINE_L Vc_PURE_L Vector<T>  operator op   (AsArg x) const Vc_ALWAYS_INLINE_R Vc_PURE_R;
 #define OP_ENTRY(op) \
-        inline ALWAYS_INLINE Vector<T> &operator op##=(EntryType x) { return operator op##=(Vector(x)); } \
-        template<typename TT> inline ALWAYS_INLINE VC_EXACT_TYPE(TT, EntryType, Vector) operator op(TT x) const { return operator op(Vector(x)); }
+        Vc_ALWAYS_INLINE Vector<T> &operator op##=(EntryType x) { return operator op##=(Vector(x)); } \
+        template<typename TT> Vc_ALWAYS_INLINE Vc_PURE VC_EXACT_TYPE(TT, EntryType, Vector) operator op(TT x) const { return operator op(Vector(x)); }
         VC_ALL_BINARY(OP_VEC)
         VC_ALL_BINARY(OP_ENTRY)
         VC_ALL_SHIFTS(OP_VEC)
 #undef OP_VEC
 #undef OP_ENTRY
 
-        inline Vector<T> ALWAYS_INLINE_L &operator>>=(int x) ALWAYS_INLINE_R;
-        inline Vector<T> ALWAYS_INLINE_L &operator<<=(int x) ALWAYS_INLINE_R;
-        inline Vector<T> ALWAYS_INLINE_L operator>>(int x) const ALWAYS_INLINE_R;
-        inline Vector<T> ALWAYS_INLINE_L operator<<(int x) const ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L Vector<T> &operator>>=(int x) Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L Vector<T> &operator<<=(int x) Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L Vector<T> operator>>(int x) const Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L Vector<T> operator<<(int x) const Vc_ALWAYS_INLINE_R;
 
 #define OPcmp(symbol, fun) \
-        inline Mask ALWAYS_INLINE operator symbol(AsArg x) const { return VectorHelper<T>::fun(data(), x.data()); } \
-        template<typename TT> inline VC_EXACT_TYPE(TT, EntryType, Mask) ALWAYS_INLINE operator symbol(TT x) const { return operator symbol(Vector(x)); }
+        Vc_ALWAYS_INLINE Mask operator symbol(AsArg x) const { return VectorHelper<T>::fun(data(), x.data()); } \
+        template<typename TT> Vc_ALWAYS_INLINE VC_EXACT_TYPE(TT, EntryType, Mask) operator symbol(TT x) const { return operator symbol(Vector(x)); }
 
         OPcmp(==, cmpeq)
         OPcmp(!=, cmpneq)
@@ -281,20 +294,21 @@ template<typename T> class Vector
         OPcmp(<, cmplt)
         OPcmp(<=, cmple)
 #undef OPcmp
+        Vc_INTRINSIC_L Vc_PURE_L Mask isNegative() const Vc_PURE_R Vc_INTRINSIC_R;
 
-        inline void multiplyAndAdd(const Vector<T> &factor, const Vector<T> &summand) {
-            VectorHelper<T>::multiplyAndAdd(data(), factor, summand);
+        Vc_ALWAYS_INLINE void fusedMultiplyAdd(const Vector<T> &factor, const Vector<T> &summand) {
+            VectorHelper<T>::fma(data(), factor.data(), summand.data());
         }
 
-        inline void assign( const Vector<T> &v, const Mask &mask ) {
+        Vc_ALWAYS_INLINE void assign( const Vector<T> &v, const Mask &mask ) {
             const VectorType k = avx_cast<VectorType>(mask.data());
             data() = VectorHelper<VectorType>::blend(data(), v.data(), k);
         }
 
-        template<typename V2> inline V2 staticCast() const { return V2(*this); }
-        template<typename V2> inline V2 reinterpretCast() const { return avx_cast<typename V2::VectorType>(data()); }
+        template<typename V2> Vc_ALWAYS_INLINE V2 staticCast() const { return V2(*this); }
+        template<typename V2> Vc_ALWAYS_INLINE V2 reinterpretCast() const { return avx_cast<typename V2::VectorType>(data()); }
 
-        inline WriteMaskedVector<T> ALWAYS_INLINE operator()(const Mask &k) { return WriteMaskedVector<T>(this, k); }
+        Vc_ALWAYS_INLINE WriteMaskedVector<T> operator()(const Mask &k) { return WriteMaskedVector<T>(this, k); }
 
         /**
          * \return \p true  This vector was completely filled. m2 might be 0 or != 0. You still have
@@ -305,19 +319,21 @@ template<typename T> class Vector
             //return VectorHelper<T>::pack(data(), m1.data, v2.data(), m2.data);
         //}
 
-        inline VectorType &data() { return d.v(); }
-        inline const VectorType &data() const { return d.v(); }
+        Vc_ALWAYS_INLINE VectorType &data() { return d.v(); }
+        Vc_ALWAYS_INLINE const VectorType data() const { return d.v(); }
 
-        inline EntryType min() const { return VectorHelper<T>::min(data()); }
-        inline EntryType max() const { return VectorHelper<T>::max(data()); }
-        inline EntryType product() const { return VectorHelper<T>::mul(data()); }
-        inline EntryType sum() const { return VectorHelper<T>::add(data()); }
-        inline EntryType min(MaskArg m) const;
-        inline EntryType max(MaskArg m) const;
-        inline EntryType product(MaskArg m) const;
-        inline EntryType sum(MaskArg m) const;
+        Vc_ALWAYS_INLINE EntryType min() const { return VectorHelper<T>::min(data()); }
+        Vc_ALWAYS_INLINE EntryType max() const { return VectorHelper<T>::max(data()); }
+        Vc_ALWAYS_INLINE EntryType product() const { return VectorHelper<T>::mul(data()); }
+        Vc_ALWAYS_INLINE EntryType sum() const { return VectorHelper<T>::add(data()); }
+        Vc_ALWAYS_INLINE_L EntryType min(MaskArg m) const Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L EntryType max(MaskArg m) const Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L EntryType product(MaskArg m) const Vc_ALWAYS_INLINE_R;
+        Vc_ALWAYS_INLINE_L EntryType sum(MaskArg m) const Vc_ALWAYS_INLINE_R;
 
-        inline Vector sorted() const { return SortHelper<T>::sort(data()); }
+        Vc_INTRINSIC_L Vector shifted(int amount) const Vc_INTRINSIC_R;
+        Vc_INTRINSIC_L Vector rotated(int amount) const Vc_INTRINSIC_R;
+        Vc_ALWAYS_INLINE Vector sorted() const { return SortHelper<T>::sort(data()); }
 
         template<typename F> void callWithValuesSorted(F &f) {
             EntryType value = d.m(0);
@@ -330,36 +346,36 @@ template<typename T> class Vector
             }
         }
 
-        template<typename F> inline void INTRINSIC call(const F &f) const {
+        template<typename F> Vc_INTRINSIC void call(const F &f) const {
             for_all_vector_entries(i,
                     f(EntryType(d.m(i)));
                     );
         }
-        template<typename F> inline void INTRINSIC call(F &f) const {
+        template<typename F> Vc_INTRINSIC void call(F &f) const {
             for_all_vector_entries(i,
                     f(EntryType(d.m(i)));
                     );
         }
 
-        template<typename F> inline void INTRINSIC call(const F &f, const Mask &mask) const {
+        template<typename F> Vc_INTRINSIC void call(const F &f, const Mask &mask) const {
             Vc_foreach_bit(size_t i, mask) {
                 f(EntryType(d.m(i)));
             }
         }
-        template<typename F> inline void INTRINSIC call(F &f, const Mask &mask) const {
+        template<typename F> Vc_INTRINSIC void call(F &f, const Mask &mask) const {
             Vc_foreach_bit(size_t i, mask) {
                 f(EntryType(d.m(i)));
             }
         }
 
-        template<typename F> inline Vector<T> INTRINSIC apply(const F &f) const {
+        template<typename F> Vc_INTRINSIC Vector<T> apply(const F &f) const {
             Vector<T> r;
             for_all_vector_entries(i,
                     r.d.m(i) = f(EntryType(d.m(i)));
                     );
             return r;
         }
-        template<typename F> inline Vector<T> INTRINSIC apply(F &f) const {
+        template<typename F> Vc_INTRINSIC Vector<T> apply(F &f) const {
             Vector<T> r;
             for_all_vector_entries(i,
                     r.d.m(i) = f(EntryType(d.m(i)));
@@ -367,14 +383,14 @@ template<typename T> class Vector
             return r;
         }
 
-        template<typename F> inline Vector<T> INTRINSIC apply(const F &f, const Mask &mask) const {
+        template<typename F> Vc_INTRINSIC Vector<T> apply(const F &f, const Mask &mask) const {
             Vector<T> r(*this);
             Vc_foreach_bit (size_t i, mask) {
                 r.d.m(i) = f(EntryType(r.d.m(i)));
             }
             return r;
         }
-        template<typename F> inline Vector<T> INTRINSIC apply(F &f, const Mask &mask) const {
+        template<typename F> Vc_INTRINSIC Vector<T> apply(F &f, const Mask &mask) const {
             Vector<T> r(*this);
             Vc_foreach_bit (size_t i, mask) {
                 r.d.m(i) = f(EntryType(r.d.m(i)));
@@ -382,19 +398,19 @@ template<typename T> class Vector
             return r;
         }
 
-        template<typename IndexT> inline void INTRINSIC fill(EntryType (&f)(IndexT)) {
+        template<typename IndexT> Vc_INTRINSIC void fill(EntryType (&f)(IndexT)) {
             for_all_vector_entries(i,
                     d.m(i) = f(i);
                     );
         }
-        inline void INTRINSIC fill(EntryType (&f)()) {
+        Vc_INTRINSIC void fill(EntryType (&f)()) {
             for_all_vector_entries(i,
                     d.m(i) = f();
                     );
         }
 
-        inline INTRINSIC_L Vector copySign(AsArg reference) const INTRINSIC_R;
-        inline INTRINSIC_L Vector exponent() const INTRINSIC_R;
+        Vc_INTRINSIC_L Vector copySign(AsArg reference) const Vc_INTRINSIC_R;
+        Vc_INTRINSIC_L Vector exponent() const Vc_INTRINSIC_R;
 };
 
 typedef Vector<double>         double_v;
@@ -414,33 +430,34 @@ typedef ushort_v::Mask ushort_m;
 
 template<typename T> class SwizzledVector : public Vector<T> {};
 
-static inline int_v    min(const int_v    &x, const int_v    &y) { return _mm256_min_epi32(x.data(), y.data()); }
-static inline uint_v   min(const uint_v   &x, const uint_v   &y) { return _mm256_min_epu32(x.data(), y.data()); }
-static inline short_v  min(const short_v  &x, const short_v  &y) { return _mm_min_epi16(x.data(), y.data()); }
-static inline ushort_v min(const ushort_v &x, const ushort_v &y) { return _mm_min_epu16(x.data(), y.data()); }
-static inline float_v  min(const float_v  &x, const float_v  &y) { return _mm256_min_ps(x.data(), y.data()); }
-static inline sfloat_v min(const sfloat_v &x, const sfloat_v &y) { return _mm256_min_ps(x.data(), y.data()); }
-static inline double_v min(const double_v &x, const double_v &y) { return _mm256_min_pd(x.data(), y.data()); }
-static inline int_v    max(const int_v    &x, const int_v    &y) { return _mm256_max_epi32(x.data(), y.data()); }
-static inline uint_v   max(const uint_v   &x, const uint_v   &y) { return _mm256_max_epu32(x.data(), y.data()); }
-static inline short_v  max(const short_v  &x, const short_v  &y) { return _mm_max_epi16(x.data(), y.data()); }
-static inline ushort_v max(const ushort_v &x, const ushort_v &y) { return _mm_max_epu16(x.data(), y.data()); }
-static inline float_v  max(const float_v  &x, const float_v  &y) { return _mm256_max_ps(x.data(), y.data()); }
-static inline sfloat_v max(const sfloat_v &x, const sfloat_v &y) { return _mm256_max_ps(x.data(), y.data()); }
-static inline double_v max(const double_v &x, const double_v &y) { return _mm256_max_pd(x.data(), y.data()); }
-
-  template<typename T> static inline Vector<T> sqrt (const Vector<T> &x) { return VectorHelper<T>::sqrt(x.data()); }
-  template<typename T> static inline Vector<T> rsqrt(const Vector<T> &x) { return VectorHelper<T>::rsqrt(x.data()); }
-  template<typename T> static inline Vector<T> abs  (const Vector<T> &x) { return VectorHelper<T>::abs(x.data()); }
-  template<typename T> static inline Vector<T> reciprocal(const Vector<T> &x) { return VectorHelper<T>::reciprocal(x.data()); }
-  template<typename T> static inline Vector<T> round(const Vector<T> &x) { return VectorHelper<T>::round(x.data()); }
-
-  template<typename T> static inline typename Vector<T>::Mask isfinite(const Vector<T> &x) { return VectorHelper<T>::isFinite(x.data()); }
-  template<typename T> static inline typename Vector<T>::Mask isnan(const Vector<T> &x) { return VectorHelper<T>::isNaN(x.data()); }
+static Vc_ALWAYS_INLINE int_v    min(const int_v    &x, const int_v    &y) { return _mm256_min_epi32(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE uint_v   min(const uint_v   &x, const uint_v   &y) { return _mm256_min_epu32(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE short_v  min(const short_v  &x, const short_v  &y) { return _mm_min_epi16(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE ushort_v min(const ushort_v &x, const ushort_v &y) { return _mm_min_epu16(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE float_v  min(const float_v  &x, const float_v  &y) { return _mm256_min_ps(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE sfloat_v min(const sfloat_v &x, const sfloat_v &y) { return _mm256_min_ps(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE double_v min(const double_v &x, const double_v &y) { return _mm256_min_pd(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE int_v    max(const int_v    &x, const int_v    &y) { return _mm256_max_epi32(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE uint_v   max(const uint_v   &x, const uint_v   &y) { return _mm256_max_epu32(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE short_v  max(const short_v  &x, const short_v  &y) { return _mm_max_epi16(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE ushort_v max(const ushort_v &x, const ushort_v &y) { return _mm_max_epu16(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE float_v  max(const float_v  &x, const float_v  &y) { return _mm256_max_ps(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE sfloat_v max(const sfloat_v &x, const sfloat_v &y) { return _mm256_max_ps(x.data(), y.data()); }
+static Vc_ALWAYS_INLINE double_v max(const double_v &x, const double_v &y) { return _mm256_max_pd(x.data(), y.data()); }
+
+  template<typename T> static Vc_ALWAYS_INLINE Vector<T> sqrt (const Vector<T> &x) { return VectorHelper<T>::sqrt(x.data()); }
+  template<typename T> static Vc_ALWAYS_INLINE Vector<T> rsqrt(const Vector<T> &x) { return VectorHelper<T>::rsqrt(x.data()); }
+  template<typename T> static Vc_ALWAYS_INLINE Vector<T> abs  (const Vector<T> &x) { return VectorHelper<T>::abs(x.data()); }
+  template<typename T> static Vc_ALWAYS_INLINE Vector<T> reciprocal(const Vector<T> &x) { return VectorHelper<T>::reciprocal(x.data()); }
+  template<typename T> static Vc_ALWAYS_INLINE Vector<T> round(const Vector<T> &x) { return VectorHelper<T>::round(x.data()); }
+
+  template<typename T> static Vc_ALWAYS_INLINE typename Vector<T>::Mask isfinite(const Vector<T> &x) { return VectorHelper<T>::isFinite(x.data()); }
+  template<typename T> static Vc_ALWAYS_INLINE typename Vector<T>::Mask isnan(const Vector<T> &x) { return VectorHelper<T>::isNaN(x.data()); }
 
 #include "forceToRegisters.tcc"
 } // namespace AVX
 } // namespace Vc
+} // namespace AliRoot
 
 #include "vector.tcc"
 #include "math.h"
index f7a1f11..a58e748 100644 (file)
@@ -21,6 +21,7 @@
 #include "const.h"
 #include "macros.h"
 
+namespace AliRoot {
 namespace Vc
 {
 ALIGN(64) extern unsigned int RandomState[16];
@@ -30,42 +31,42 @@ namespace AVX
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // constants {{{1
-template<typename T> inline ALWAYS_INLINE Vector<T>::Vector(VectorSpecialInitializerZero::ZEnum) : d(HT::zero()) {}
-template<typename T> inline ALWAYS_INLINE Vector<T>::Vector(VectorSpecialInitializerOne::OEnum) : d(HT::one()) {}
-template<typename T> inline ALWAYS_INLINE Vector<T>::Vector(VectorSpecialInitializerIndexesFromZero::IEnum)
+template<typename T> Vc_ALWAYS_INLINE Vector<T>::Vector(VectorSpecialInitializerZero::ZEnum) : d(HT::zero()) {}
+template<typename T> Vc_ALWAYS_INLINE Vector<T>::Vector(VectorSpecialInitializerOne::OEnum) : d(HT::one()) {}
+template<typename T> Vc_ALWAYS_INLINE Vector<T>::Vector(VectorSpecialInitializerIndexesFromZero::IEnum)
     : d(HV::load(IndexesFromZeroData<T>::address(), Aligned)) {}
 
-template<typename T> inline Vector<T> INTRINSIC CONST Vector<T>::Zero() { return HT::zero(); }
-template<typename T> inline Vector<T> INTRINSIC CONST Vector<T>::One() { return HT::one(); }
-template<typename T> inline Vector<T> INTRINSIC CONST Vector<T>::IndexesFromZero() { return HV::load(IndexesFromZeroData<T>::address(), Aligned); }
+template<typename T> Vc_INTRINSIC Vector<T> Vc_CONST Vector<T>::Zero() { return HT::zero(); }
+template<typename T> Vc_INTRINSIC Vector<T> Vc_CONST Vector<T>::One() { return HT::one(); }
+template<typename T> Vc_INTRINSIC Vector<T> Vc_CONST Vector<T>::IndexesFromZero() { return HV::load(IndexesFromZeroData<T>::address(), Aligned); }
 
-template<typename T> template<typename T2> inline ALWAYS_INLINE Vector<T>::Vector(Vector<T2> x)
+template<typename T> template<typename T2> Vc_ALWAYS_INLINE Vector<T>::Vector(VC_ALIGNED_PARAMETER(Vector<T2>) x)
     : d(StaticCastHelper<T2, T>::cast(x.data())) {}
 
-template<typename T> inline ALWAYS_INLINE Vector<T>::Vector(EntryType x) : d(HT::set(x)) {}
-template<> inline ALWAYS_INLINE Vector<double>::Vector(EntryType x) : d(_mm256_set1_pd(x)) {}
+template<typename T> Vc_ALWAYS_INLINE Vector<T>::Vector(EntryType x) : d(HT::set(x)) {}
+template<> Vc_ALWAYS_INLINE Vector<double>::Vector(EntryType x) : d(_mm256_set1_pd(x)) {}
 
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // load ctors {{{1
-template<typename T> inline ALWAYS_INLINE Vector<T>::Vector(const EntryType *x) { load(x); }
-template<typename T> template<typename A> inline ALWAYS_INLINE Vector<T>::Vector(const EntryType *x, A a) { load(x, a); }
-template<typename T> template<typename OtherT> inline ALWAYS_INLINE Vector<T>::Vector(const OtherT *x) { load(x); }
-template<typename T> template<typename OtherT, typename A> inline ALWAYS_INLINE Vector<T>::Vector(const OtherT *x, A a) { load(x, a); }
+template<typename T> Vc_ALWAYS_INLINE Vector<T>::Vector(const EntryType *x) { load(x); }
+template<typename T> template<typename A> Vc_ALWAYS_INLINE Vector<T>::Vector(const EntryType *x, A a) { load(x, a); }
+template<typename T> template<typename OtherT> Vc_ALWAYS_INLINE Vector<T>::Vector(const OtherT *x) { load(x); }
+template<typename T> template<typename OtherT, typename A> Vc_ALWAYS_INLINE Vector<T>::Vector(const OtherT *x, A a) { load(x, a); }
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // load member functions {{{1
-template<typename T> inline void INTRINSIC Vector<T>::load(const EntryType *mem)
+template<typename T> Vc_INTRINSIC void Vector<T>::load(const EntryType *mem)
 {
     load(mem, Aligned);
 }
 
-template<typename T> template<typename A> inline void INTRINSIC Vector<T>::load(const EntryType *mem, A align)
+template<typename T> template<typename A> Vc_INTRINSIC void Vector<T>::load(const EntryType *mem, A align)
 {
     d.v() = HV::load(mem, align);
 }
 
-template<typename T> template<typename OtherT> inline void INTRINSIC Vector<T>::load(const OtherT *mem)
+template<typename T> template<typename OtherT> Vc_INTRINSIC void Vector<T>::load(const OtherT *mem)
 {
     load(mem, Aligned);
 }
@@ -75,44 +76,44 @@ template<typename DstT, typename SrcT, typename Flags> struct LoadHelper;
 
 // float {{{2
 template<typename Flags> struct LoadHelper<float, double, Flags> {
-    static __m256 load(const double *mem, Flags f)
+    static m256 load(const double *mem, Flags f)
     {
-        return concat(_mm256_cvtpd_ps(VectorHelper<__m256d>::load(&mem[0], f)),
-                      _mm256_cvtpd_ps(VectorHelper<__m256d>::load(&mem[4], f)));
+        return concat(_mm256_cvtpd_ps(VectorHelper<m256d>::load(&mem[0], f)),
+                      _mm256_cvtpd_ps(VectorHelper<m256d>::load(&mem[4], f)));
     }
 };
 template<typename Flags> struct LoadHelper<float, unsigned int, Flags> {
-    static __m256 load(const unsigned int *mem, Flags f)
+    static m256 load(const unsigned int *mem, Flags f)
     {
-        return StaticCastHelper<unsigned int, float>::cast(VectorHelper<__m256i>::load(mem, f));
+        return StaticCastHelper<unsigned int, float>::cast(VectorHelper<m256i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<float, int, Flags> {
-    static __m256 load(const int *mem, Flags f)
+    static m256 load(const int *mem, Flags f)
     {
-        return StaticCastHelper<int, float>::cast(VectorHelper<__m256i>::load(mem, f));
+        return StaticCastHelper<int, float>::cast(VectorHelper<m256i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<float, unsigned short, Flags> {
-    static __m256 load(const unsigned short *mem, Flags f)
+    static m256 load(const unsigned short *mem, Flags f)
     {
-        return StaticCastHelper<unsigned short, float>::cast(VectorHelper<__m128i>::load(mem, f));
+        return StaticCastHelper<unsigned short, float>::cast(VectorHelper<m128i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<float, short, Flags> {
-    static __m256 load(const short *mem, Flags f)
+    static m256 load(const short *mem, Flags f)
     {
-        return StaticCastHelper<short, float>::cast(VectorHelper<__m128i>::load(mem, f));
+        return StaticCastHelper<short, float>::cast(VectorHelper<m128i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<float, unsigned char, Flags> {
-    static __m256 load(const unsigned char *mem, Flags f)
+    static m256 load(const unsigned char *mem, Flags f)
     {
         return StaticCastHelper<unsigned int, float>::cast(LoadHelper<unsigned int, unsigned char, Flags>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<float, signed char, Flags> {
-    static __m256 load(const signed char *mem, Flags f)
+    static m256 load(const signed char *mem, Flags f)
     {
         return StaticCastHelper<int, float>::cast(LoadHelper<int, signed char, Flags>::load(mem, f));
     }
@@ -122,193 +123,193 @@ template<typename SrcT, typename Flags> struct LoadHelper<sfloat, SrcT, Flags> :
 
 // int {{{2
 template<typename Flags> struct LoadHelper<int, unsigned int, Flags> {
-    static __m256i load(const unsigned int *mem, Flags f)
+    static m256i load(const unsigned int *mem, Flags f)
     {
-        return VectorHelper<__m256i>::load(mem, f);
+        return VectorHelper<m256i>::load(mem, f);
     }
 };
 template<typename Flags> struct LoadHelper<int, unsigned short, Flags> {
-    static __m256i load(const unsigned short *mem, Flags f)
+    static m256i load(const unsigned short *mem, Flags f)
     {
-        return StaticCastHelper<unsigned short, unsigned int>::cast(VectorHelper<__m128i>::load(mem, f));
+        return StaticCastHelper<unsigned short, unsigned int>::cast(VectorHelper<m128i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<int, short, Flags> {
-    static __m256i load(const short *mem, Flags f)
+    static m256i load(const short *mem, Flags f)
     {
-        return StaticCastHelper<short, int>::cast(VectorHelper<__m128i>::load(mem, f));
+        return StaticCastHelper<short, int>::cast(VectorHelper<m128i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<int, unsigned char, Flags> {
-    static __m256i load(const unsigned char *mem, Flags)
+    static m256i load(const unsigned char *mem, Flags)
     {
         // the only available streaming load loads 16 bytes - twice as much as we need => can't use
         // it, or we risk an out-of-bounds read and an unaligned load exception
-        const __m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
-        const __m128i epu16 = _mm_cvtepu8_epi16(epu8);
+        const m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
+        const m128i epu16 = _mm_cvtepu8_epi16(epu8);
         return StaticCastHelper<unsigned short, unsigned int>::cast(epu16);
     }
 };
 template<typename Flags> struct LoadHelper<int, signed char, Flags> {
-    static __m256i load(const signed char *mem, Flags)
+    static m256i load(const signed char *mem, Flags)
     {
         // the only available streaming load loads 16 bytes - twice as much as we need => can't use
         // it, or we risk an out-of-bounds read and an unaligned load exception
-        const __m128i epi8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
-        const __m128i epi16 = _mm_cvtepi8_epi16(epi8);
+        const m128i epi8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
+        const m128i epi16 = _mm_cvtepi8_epi16(epi8);
         return StaticCastHelper<short, int>::cast(epi16);
     }
 };
 
 // unsigned int {{{2
 template<typename Flags> struct LoadHelper<unsigned int, unsigned short, Flags> {
-    static __m256i load(const unsigned short *mem, Flags f)
+    static m256i load(const unsigned short *mem, Flags f)
     {
-        return StaticCastHelper<unsigned short, unsigned int>::cast(VectorHelper<__m128i>::load(mem, f));
+        return StaticCastHelper<unsigned short, unsigned int>::cast(VectorHelper<m128i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<unsigned int, unsigned char, Flags> {
-    static __m256i load(const unsigned char *mem, Flags)
+    static m256i load(const unsigned char *mem, Flags)
     {
         // the only available streaming load loads 16 bytes - twice as much as we need => can't use
         // it, or we risk an out-of-bounds read and an unaligned load exception
-        const __m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
-        const __m128i epu16 = _mm_cvtepu8_epi16(epu8);
+        const m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
+        const m128i epu16 = _mm_cvtepu8_epi16(epu8);
         return StaticCastHelper<unsigned short, unsigned int>::cast(epu16);
     }
 };
 
 // short {{{2
 template<typename Flags> struct LoadHelper<short, unsigned short, Flags> {
-    static __m128i load(const unsigned short *mem, Flags f)
+    static m128i load(const unsigned short *mem, Flags f)
     {
-        return StaticCastHelper<unsigned short, short>::cast(VectorHelper<__m128i>::load(mem, f));
+        return StaticCastHelper<unsigned short, short>::cast(VectorHelper<m128i>::load(mem, f));
     }
 };
 template<typename Flags> struct LoadHelper<short, unsigned char, Flags> {
-    static __m128i load(const unsigned char *mem, Flags)
+    static m128i load(const unsigned char *mem, Flags)
     {
         // the only available streaming load loads 16 bytes - twice as much as we need => can't use
         // it, or we risk an out-of-bounds read and an unaligned load exception
-        const __m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
+        const m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
         return _mm_cvtepu8_epi16(epu8);
     }
 };
 template<typename Flags> struct LoadHelper<short, signed char, Flags> {
-    static __m128i load(const signed char *mem, Flags)
+    static m128i load(const signed char *mem, Flags)
     {
         // the only available streaming load loads 16 bytes - twice as much as we need => can't use
         // it, or we risk an out-of-bounds read and an unaligned load exception
-        const __m128i epi8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
+        const m128i epi8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
         return _mm_cvtepi8_epi16(epi8);
     }
 };
 
 // unsigned short {{{2
 template<typename Flags> struct LoadHelper<unsigned short, unsigned char, Flags> {
-    static __m128i load(const unsigned char *mem, Flags)
+    static m128i load(const unsigned char *mem, Flags)
     {
         // the only available streaming load loads 16 bytes - twice as much as we need => can't use
         // it, or we risk an out-of-bounds read and an unaligned load exception
-        const __m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
+        const m128i epu8 = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(mem));
         return _mm_cvtepu8_epi16(epu8);
     }
 };
 
 // general load, implemented via LoadHelper {{{2
-template<typename DstT> template<typename SrcT, typename Flags> inline void INTRINSIC Vector<DstT>::load(const SrcT *x, Flags f)
+template<typename DstT> template<typename SrcT, typename Flags> Vc_INTRINSIC void Vector<DstT>::load(const SrcT *x, Flags f)
 {
     d.v() = LoadHelper<DstT, SrcT, Flags>::load(x, f);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // zeroing {{{1
-template<typename T> inline void INTRINSIC Vector<T>::setZero()
+template<typename T> Vc_INTRINSIC void Vector<T>::setZero()
 {
     data() = HV::zero();
 }
-template<typename T> inline void INTRINSIC Vector<T>::setZero(const Mask &k)
+template<typename T> Vc_INTRINSIC void Vector<T>::setZero(const Mask &k)
 {
     data() = HV::andnot_(avx_cast<VectorType>(k.data()), data());
 }
 
-template<> inline void INTRINSIC Vector<double>::setQnan()
+template<> Vc_INTRINSIC void Vector<double>::setQnan()
 {
     data() = _mm256_setallone_pd();
 }
-template<> inline void INTRINSIC Vector<double>::setQnan(MaskArg k)
+template<> Vc_INTRINSIC void Vector<double>::setQnan(MaskArg k)
 {
     data() = _mm256_or_pd(data(), k.dataD());
 }
-template<> inline void INTRINSIC Vector<float>::setQnan()
+template<> Vc_INTRINSIC void Vector<float>::setQnan()
 {
     data() = _mm256_setallone_ps();
 }
-template<> inline void INTRINSIC Vector<float>::setQnan(MaskArg k)
+template<> Vc_INTRINSIC void Vector<float>::setQnan(MaskArg k)
 {
     data() = _mm256_or_ps(data(), k.data());
 }
-template<> inline void INTRINSIC Vector<sfloat>::setQnan()
+template<> Vc_INTRINSIC void Vector<sfloat>::setQnan()
 {
     data() = _mm256_setallone_ps();
 }
-template<> inline void INTRINSIC Vector<sfloat>::setQnan(MaskArg k)
+template<> Vc_INTRINSIC void Vector<sfloat>::setQnan(MaskArg k)
 {
     data() = _mm256_or_ps(data(), k.data());
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // stores {{{1
-template<typename T> inline void INTRINSIC Vector<T>::store(EntryType *mem) const
+template<typename T> Vc_INTRINSIC void Vector<T>::store(EntryType *mem) const
 {
     HV::store(mem, data(), Aligned);
 }
-template<typename T> inline void INTRINSIC Vector<T>::store(EntryType *mem, const Mask &mask) const
+template<typename T> Vc_INTRINSIC void Vector<T>::store(EntryType *mem, const Mask &mask) const
 {
     HV::store(mem, data(), avx_cast<VectorType>(mask.data()), Aligned);
 }
-template<typename T> template<typename A> inline void INTRINSIC Vector<T>::store(EntryType *mem, A align) const
+template<typename T> template<typename A> Vc_INTRINSIC void Vector<T>::store(EntryType *mem, A align) const
 {
     HV::store(mem, data(), align);
 }
-template<typename T> template<typename A> inline void INTRINSIC Vector<T>::store(EntryType *mem, const Mask &mask, A align) const
+template<typename T> template<typename A> Vc_INTRINSIC void Vector<T>::store(EntryType *mem, const Mask &mask, A align) const
 {
     HV::store(mem, data(), avx_cast<VectorType>(mask.data()), align);
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // expand/merge 1 float_v <=> 2 double_v          XXX rationale? remove it for release? XXX {{{1
-template<typename T> inline ALWAYS_INLINE FLATTEN Vector<T>::Vector(const Vector<typename HT::ConcatType> *a)
+template<typename T> Vc_ALWAYS_INLINE Vc_FLATTEN Vector<T>::Vector(const Vector<typename HT::ConcatType> *a)
     : d(a[0])
 {
 }
-template<> inline ALWAYS_INLINE FLATTEN Vector<float>::Vector(const Vector<HT::ConcatType> *a)
+template<> Vc_ALWAYS_INLINE Vc_FLATTEN Vector<float>::Vector(const Vector<HT::ConcatType> *a)
     : d(concat(_mm256_cvtpd_ps(a[0].data()), _mm256_cvtpd_ps(a[1].data())))
 {
 }
-template<> inline ALWAYS_INLINE FLATTEN Vector<short>::Vector(const Vector<HT::ConcatType> *a)
+template<> Vc_ALWAYS_INLINE Vc_FLATTEN Vector<short>::Vector(const Vector<HT::ConcatType> *a)
     : d(_mm_packs_epi32(lo128(a->data()), hi128(a->data())))
 {
 }
-template<> inline ALWAYS_INLINE FLATTEN Vector<unsigned short>::Vector(const Vector<HT::ConcatType> *a)
+template<> Vc_ALWAYS_INLINE Vc_FLATTEN Vector<unsigned short>::Vector(const Vector<HT::ConcatType> *a)
     : d(_mm_packus_epi32(lo128(a->data()), hi128(a->data())))
 {
 }
-template<typename T> inline void ALWAYS_INLINE FLATTEN Vector<T>::expand(Vector<typename HT::ConcatType> *x) const
+template<typename T> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<T>::expand(Vector<typename HT::ConcatType> *x) const
 {
     x[0] = *this;
 }
-template<> inline void ALWAYS_INLINE FLATTEN Vector<float>::expand(Vector<HT::ConcatType> *x) const
+template<> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<float>::expand(Vector<HT::ConcatType> *x) const
 {
     x[0].data() = _mm256_cvtps_pd(lo128(d.v()));
     x[1].data() = _mm256_cvtps_pd(hi128(d.v()));
 }
-template<> inline void ALWAYS_INLINE FLATTEN Vector<short>::expand(Vector<HT::ConcatType> *x) const
+template<> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<short>::expand(Vector<HT::ConcatType> *x) const
 {
     x[0].data() = concat(_mm_cvtepi16_epi32(d.v()),
             _mm_cvtepi16_epi32(_mm_unpackhi_epi64(d.v(), d.v())));
 }
-template<> inline void ALWAYS_INLINE FLATTEN Vector<unsigned short>::expand(Vector<HT::ConcatType> *x) const
+template<> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<unsigned short>::expand(Vector<HT::ConcatType> *x) const
 {
     x[0].data() = concat(_mm_cvtepu16_epi32(d.v()),
             _mm_cvtepu16_epi32(_mm_unpackhi_epi64(d.v(), d.v())));
@@ -316,46 +317,46 @@ template<> inline void ALWAYS_INLINE FLATTEN Vector<unsigned short>::expand(Vect
 
 ///////////////////////////////////////////////////////////////////////////////////////////
 // swizzles {{{1
-template<typename T> inline const Vector<T> INTRINSIC CONST &Vector<T>::abcd() const { return *this; }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::cdab() const { return Mem::permute<X2, X3, X0, X1>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::badc() const { return Mem::permute<X1, X0, X3, X2>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::aaaa() const { return Mem::permute<X0, X0, X0, X0>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::bbbb() const { return Mem::permute<X1, X1, X1, X1>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::cccc() const { return Mem::permute<X2, X2, X2, X2>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::dddd() const { return Mem::permute<X3, X3, X3, X3>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::bcad() const { return Mem::permute<X1, X2, X0, X3>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::bcda() const { return Mem::permute<X1, X2, X3, X0>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::dabc() const { return Mem::permute<X3, X0, X1, X2>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::acbd() const { return Mem::permute<X0, X2, X1, X3>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::dbca() const { return Mem::permute<X3, X1, X2, X0>(data()); }
-template<typename T> inline const Vector<T> INTRINSIC CONST  Vector<T>::dcba() const { return Mem::permute<X3, X2, X1, X0>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE &Vector<T>::abcd() const { return *this; }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::cdab() const { return Mem::permute<X2, X3, X0, X1>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::badc() const { return Mem::permute<X1, X0, X3, X2>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::aaaa() const { return Mem::permute<X0, X0, X0, X0>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::bbbb() const { return Mem::permute<X1, X1, X1, X1>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::cccc() const { return Mem::permute<X2, X2, X2, X2>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::dddd() const { return Mem::permute<X3, X3, X3, X3>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::bcad() const { return Mem::permute<X1, X2, X0, X3>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::bcda() const { return Mem::permute<X1, X2, X3, X0>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::dabc() const { return Mem::permute<X3, X0, X1, X2>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::acbd() const { return Mem::permute<X0, X2, X1, X3>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::dbca() const { return Mem::permute<X3, X1, X2, X0>(data()); }
+template<typename T> Vc_INTRINSIC const Vector<T> Vc_PURE  Vector<T>::dcba() const { return Mem::permute<X3, X2, X1, X0>(data()); }
 
-template<> inline const double_v INTRINSIC CONST Vector<double>::cdab() const { return Mem::shuffle128<X1, X0>(data(), data()); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::badc() const { return Mem::permute<X1, X0, X3, X2>(data()); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::aaaa() const { const double &tmp = d.m(0); return _mm256_broadcast_sd(&tmp); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::bbbb() const { const double &tmp = d.m(1); return _mm256_broadcast_sd(&tmp); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::cccc() const { const double &tmp = d.m(2); return _mm256_broadcast_sd(&tmp); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::dddd() const { const double &tmp = d.m(3); return _mm256_broadcast_sd(&tmp); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::bcad() const { return Mem::shuffle<X1, Y0, X2, Y3>(Mem::shuffle128<X0, X0>(data(), data()), Mem::shuffle128<X1, X1>(data(), data())); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::bcda() const { return Mem::shuffle<X1, Y0, X3, Y2>(data(), Mem::shuffle128<X1, X0>(data(), data())); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::dabc() const { return Mem::shuffle<X1, Y0, X3, Y2>(Mem::shuffle128<X1, X0>(data(), data()), data()); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::acbd() const { return Mem::shuffle<X0, Y0, X3, Y3>(Mem::shuffle128<X0, X0>(data(), data()), Mem::shuffle128<X1, X1>(data(), data())); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::dbca() const { return Mem::shuffle<X1, Y1, X2, Y2>(Mem::shuffle128<X1, X1>(data(), data()), Mem::shuffle128<X0, X0>(data(), data())); }
-template<> inline const double_v INTRINSIC CONST Vector<double>::dcba() const { return cdab().badc(); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::cdab() const { return Mem::shuffle128<X1, X0>(data(), data()); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::badc() const { return Mem::permute<X1, X0, X3, X2>(data()); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::aaaa() const { const double &tmp = d.m(0); return _mm256_broadcast_sd(&tmp); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::bbbb() const { const double &tmp = d.m(1); return _mm256_broadcast_sd(&tmp); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::cccc() const { const double &tmp = d.m(2); return _mm256_broadcast_sd(&tmp); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::dddd() const { const double &tmp = d.m(3); return _mm256_broadcast_sd(&tmp); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::bcad() const { return Mem::shuffle<X1, Y0, X2, Y3>(Mem::shuffle128<X0, X0>(data(), data()), Mem::shuffle128<X1, X1>(data(), data())); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::bcda() const { return Mem::shuffle<X1, Y0, X3, Y2>(data(), Mem::shuffle128<X1, X0>(data(), data())); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::dabc() const { return Mem::shuffle<X1, Y0, X3, Y2>(Mem::shuffle128<X1, X0>(data(), data()), data()); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::acbd() const { return Mem::shuffle<X0, Y0, X3, Y3>(Mem::shuffle128<X0, X0>(data(), data()), Mem::shuffle128<X1, X1>(data(), data())); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::dbca() const { return Mem::shuffle<X1, Y1, X2, Y2>(Mem::shuffle128<X1, X1>(data(), data()), Mem::shuffle128<X0, X0>(data(), data())); }
+template<> Vc_INTRINSIC const double_v Vc_PURE Vector<double>::dcba() const { return cdab().badc(); }
 
 #define VC_SWIZZLES_16BIT_IMPL(T) \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::cdab() const { return Mem::permute<X2, X3, X0, X1, X6, X7, X4, X5>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::badc() const { return Mem::permute<X1, X0, X3, X2, X5, X4, X7, X6>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::aaaa() const { return Mem::permute<X0, X0, X0, X0, X4, X4, X4, X4>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::bbbb() const { return Mem::permute<X1, X1, X1, X1, X5, X5, X5, X5>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::cccc() const { return Mem::permute<X2, X2, X2, X2, X6, X6, X6, X6>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::dddd() const { return Mem::permute<X3, X3, X3, X3, X7, X7, X7, X7>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::bcad() const { return Mem::permute<X1, X2, X0, X3, X5, X6, X4, X7>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::bcda() const { return Mem::permute<X1, X2, X3, X0, X5, X6, X7, X4>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::dabc() const { return Mem::permute<X3, X0, X1, X2, X7, X4, X5, X6>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::acbd() const { return Mem::permute<X0, X2, X1, X3, X4, X6, X5, X7>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::dbca() const { return Mem::permute<X3, X1, X2, X0, X7, X5, X6, X4>(data()); } \
-template<> inline const Vector<T> INTRINSIC CONST Vector<T>::dcba() const { return Mem::permute<X3, X2, X1, X0, X7, X6, X5, X4>(data()); }
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::cdab() const { return Mem::permute<X2, X3, X0, X1, X6, X7, X4, X5>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::badc() const { return Mem::permute<X1, X0, X3, X2, X5, X4, X7, X6>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::aaaa() const { return Mem::permute<X0, X0, X0, X0, X4, X4, X4, X4>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::bbbb() const { return Mem::permute<X1, X1, X1, X1, X5, X5, X5, X5>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::cccc() const { return Mem::permute<X2, X2, X2, X2, X6, X6, X6, X6>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::dddd() const { return Mem::permute<X3, X3, X3, X3, X7, X7, X7, X7>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::bcad() const { return Mem::permute<X1, X2, X0, X3, X5, X6, X4, X7>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::bcda() const { return Mem::permute<X1, X2, X3, X0, X5, X6, X7, X4>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::dabc() const { return Mem::permute<X3, X0, X1, X2, X7, X4, X5, X6>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::acbd() const { return Mem::permute<X0, X2, X1, X3, X4, X6, X5, X7>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::dbca() const { return Mem::permute<X3, X1, X2, X0, X7, X5, X6, X4>(data()); } \
+template<> Vc_INTRINSIC const Vector<T> Vc_PURE Vector<T>::dcba() const { return Mem::permute<X3, X2, X1, X0, X7, X6, X5, X4>(data()); }
 VC_SWIZZLES_16BIT_IMPL(short)
 VC_SWIZZLES_16BIT_IMPL(unsigned short)
 #undef VC_SWIZZLES_16BIT_IMPL
@@ -372,7 +373,7 @@ template<typename T> inline Vector<T> &Vector<T>::operator/=(EntryType x)
             );
     return *this;
 }
-template<typename T> template<typename TT> inline PURE VC_EXACT_TYPE(TT, typename DetermineEntryType<T>::Type, Vector<T>) Vector<T>::operator/(TT x) const
+template<typename T> template<typename TT> inline Vc_PURE VC_EXACT_TYPE(TT, typename DetermineEntryType<T>::Type, Vector<T>) Vector<T>::operator/(TT x) const
 {
     if (HasVectorDivision) {
         return operator/(Vector<T>(x));
@@ -392,7 +393,7 @@ template<typename T> inline Vector<T> &Vector<T>::operator/=(const Vector<T> &x)
     return *this;
 }
 
-template<typename T> inline Vector<T> PURE Vector<T>::operator/(const Vector<T> &x) const
+template<typename T> inline Vector<T> Vc_PURE Vector<T>::operator/(const Vector<T> &x) const
 {
     Vector<T> r;
     for_all_vector_entries(i,
@@ -401,11 +402,11 @@ template<typename T> inline Vector<T> PURE Vector<T>::operator/(const Vector<T>
     return r;
 }
 // specialize division on type
-static inline __m256i INTRINSIC CONST divInt(__m256i a, __m256i b) {
-    const __m256d lo1 = _mm256_cvtepi32_pd(lo128(a));
-    const __m256d lo2 = _mm256_cvtepi32_pd(lo128(b));
-    const __m256d hi1 = _mm256_cvtepi32_pd(hi128(a));
-    const __m256d hi2 = _mm256_cvtepi32_pd(hi128(b));
+static Vc_INTRINSIC m256i Vc_CONST divInt(param256i a, param256i b) {
+    const m256d lo1 = _mm256_cvtepi32_pd(lo128(a));
+    const m256d lo2 = _mm256_cvtepi32_pd(lo128(b));
+    const m256d hi1 = _mm256_cvtepi32_pd(hi128(a));
+    const m256d hi2 = _mm256_cvtepi32_pd(hi128(b));
     return concat(
             _mm256_cvttpd_epi32(_mm256_div_pd(lo1, lo2)),
             _mm256_cvttpd_epi32(_mm256_div_pd(hi1, hi2))
@@ -416,15 +417,15 @@ template<> inline Vector<int> &Vector<int>::operator/=(const Vector<int> &x)
     d.v() = divInt(d.v(), x.d.v());
     return *this;
 }
-template<> inline Vector<int> PURE Vector<int>::operator/(const Vector<int> &x) const
+template<> inline Vector<int> Vc_PURE Vector<int>::operator/(const Vector<int> &x) const
 {
     return divInt(d.v(), x.d.v());
 }
-static inline __m256i CONST divUInt(__m256i a, __m256i b) {
-    __m256d loa = _mm256_cvtepi32_pd(lo128(a));
-    __m256d hia = _mm256_cvtepi32_pd(hi128(a));
-    __m256d lob = _mm256_cvtepi32_pd(lo128(b));
-    __m256d hib = _mm256_cvtepi32_pd(hi128(b));
+static inline m256i Vc_CONST divUInt(param256i a, param256i b) {
+    m256d loa = _mm256_cvtepi32_pd(lo128(a));
+    m256d hia = _mm256_cvtepi32_pd(hi128(a));
+    m256d lob = _mm256_cvtepi32_pd(lo128(b));
+    m256d hib = _mm256_cvtepi32_pd(hi128(b));
     // if a >= 2^31 then after conversion to double it will contain a negative number (i.e. a-2^32)
     // to get the right number back we have to add 2^32 where a >= 2^31
     loa = _mm256_add_pd(loa, _mm256_and_pd(_mm256_cmp_pd(loa, _mm256_setzero_pd(), _CMP_LT_OS), _mm256_set1_pd(4294967296.)));
@@ -434,61 +435,70 @@ static inline __m256i CONST divUInt(__m256i a, __m256i b) {
     //
     // there is one remaining problem: a >= 2^31 and b == 1
     // in that case the return value would be 2^31
-    return avx_cast<__m256i>(_mm256_blendv_ps(avx_cast<__m256>(concat(
+    return avx_cast<m256i>(_mm256_blendv_ps(avx_cast<m256>(concat(
                         _mm256_cvttpd_epi32(_mm256_div_pd(loa, lob)),
                         _mm256_cvttpd_epi32(_mm256_div_pd(hia, hib))
-                        )), avx_cast<__m256>(a), avx_cast<__m256>(concat(
+                        )), avx_cast<m256>(a), avx_cast<m256>(concat(
                             _mm_cmpeq_epi32(lo128(b), _mm_setone_epi32()),
                             _mm_cmpeq_epi32(hi128(b), _mm_setone_epi32())))));
 }
-template<> inline Vector<unsigned int> ALWAYS_INLINE &Vector<unsigned int>::operator/=(const Vector<unsigned int> &x)
+template<> Vc_ALWAYS_INLINE Vector<unsigned int> &Vector<unsigned int>::operator/=(const Vector<unsigned int> &x)
 {
     d.v() = divUInt(d.v(), x.d.v());
     return *this;
 }
-template<> inline Vector<unsigned int> ALWAYS_INLINE PURE Vector<unsigned int>::operator/(const Vector<unsigned int> &x) const
+template<> Vc_ALWAYS_INLINE Vector<unsigned int> Vc_PURE Vector<unsigned int>::operator/(const Vector<unsigned int> &x) const
 {
     return divUInt(d.v(), x.d.v());
 }
-template<typename T> static inline __m128i CONST divShort(__m128i a, __m128i b)
+template<typename T> static inline m128i Vc_CONST divShort(param128i a, param128i b)
 {
-    const __m256 r = _mm256_div_ps(StaticCastHelper<T, float>::cast(a),
+    const m256 r = _mm256_div_ps(StaticCastHelper<T, float>::cast(a),
             StaticCastHelper<T, float>::cast(b));
     return StaticCastHelper<float, T>::cast(r);
 }
-template<> inline Vector<short> ALWAYS_INLINE &Vector<short>::operator/=(const Vector<short> &x)
+template<> Vc_ALWAYS_INLINE Vector<short> &Vector<short>::operator/=(const Vector<short> &x)
 {
     d.v() = divShort<short>(d.v(), x.d.v());
     return *this;
 }
-template<> inline Vector<short> ALWAYS_INLINE PURE Vector<short>::operator/(const Vector<short> &x) const
+template<> Vc_ALWAYS_INLINE Vector<short> Vc_PURE Vector<short>::operator/(const Vector<short> &x) const
 {
     return divShort<short>(d.v(), x.d.v());
 }
-template<> inline Vector<unsigned short> ALWAYS_INLINE &Vector<unsigned short>::operator/=(const Vector<unsigned short> &x)
+template<> Vc_ALWAYS_INLINE Vector<unsigned short> &Vector<unsigned short>::operator/=(const Vector<unsigned short> &x)
 {
     d.v() = divShort<unsigned short>(d.v(), x.d.v());
     return *this;
 }
-template<> inline Vector<unsigned short> ALWAYS_INLINE PURE Vector<unsigned short>::operator/(const Vector<unsigned short> &x) const
+template<> Vc_ALWAYS_INLINE Vector<unsigned short> Vc_PURE Vector<unsigned short>::operator/(const Vector<unsigned short> &x) const
 {
     return divShort<unsigned short>(d.v(), x.d.v());
 }
-template<> inline Vector<float> INTRINSIC &Vector<float>::operator/=(const Vector<float> &x)
+template<> Vc_INTRINSIC float_v &float_v::operator/=(const float_v &x)
 {
     d.v() = _mm256_div_ps(d.v(), x.d.v());
     return *this;
 }
-template<> inline Vector<float> INTRINSIC PURE Vector<float>::operator/(const Vector<float> &x) const
+template<> Vc_INTRINSIC float_v Vc_PURE float_v::operator/(const float_v &x) const
 {
     return _mm256_div_ps(d.v(), x.d.v());
 }
-template<> inline Vector<double> INTRINSIC &Vector<double>::operator/=(const Vector<double> &x)
+template<> Vc_INTRINSIC sfloat_v &sfloat_v::operator/=(const sfloat_v &x)
+{
+    d.v() = _mm256_div_ps(d.v(), x.d.v());
+    return *this;
+}
+template<> Vc_INTRINSIC sfloat_v Vc_PURE sfloat_v::operator/(const sfloat_v &x) const
+{
+    return _mm256_div_ps(d.v(), x.d.v());
+}
+template<> Vc_INTRINSIC double_v &double_v::operator/=(const double_v &x)
 {
     d.v() = _mm256_div_pd(d.v(), x.d.v());
     return *this;
 }
-template<> inline Vector<double> INTRINSIC PURE Vector<double>::operator/(const Vector<double> &x) const
+template<> Vc_INTRINSIC double_v Vc_PURE double_v::operator/(const double_v &x) const
 {
     return _mm256_div_pd(d.v(), x.d.v());
 }
@@ -496,12 +506,12 @@ template<> inline Vector<double> INTRINSIC PURE Vector<double>::operator/(const
 ///////////////////////////////////////////////////////////////////////////////////////////
 // integer ops {{{1
 #define OP_IMPL(T, symbol) \
-template<> inline Vector<T> &Vector<T>::operator symbol##=(AsArg x) \
+template<> Vc_ALWAYS_INLINE Vector<T> &Vector<T>::operator symbol##=(AsArg x) \
 { \
     for_all_vector_entries(i, d.m(i) symbol##= x.d.m(i); ); \
     return *this; \
 } \
-template<> inline Vector<T>  Vector<T>::operator symbol(AsArg x) const \
+template<> Vc_ALWAYS_INLINE Vc_PURE Vector<T>  Vector<T>::operator symbol(AsArg x) const \
 { \
     Vector<T> r; \
     for_all_vector_entries(i, r.d.m(i) = d.m(i) symbol x.d.m(i); ); \
@@ -517,24 +527,24 @@ OP_IMPL(unsigned short, <<)
 OP_IMPL(unsigned short, >>)
 #undef OP_IMPL
 
-template<typename T> inline Vector<T> &Vector<T>::operator>>=(int shift) {
+template<typename T> Vc_ALWAYS_INLINE Vector<T> &Vector<T>::operator>>=(int shift) {
     d.v() = VectorHelper<T>::shiftRight(d.v(), shift);
     return *static_cast<Vector<T> *>(this);
 }
-template<typename T> inline Vector<T> Vector<T>::operator>>(int shift) const {
+template<typename T> Vc_ALWAYS_INLINE Vc_PURE Vector<T> Vector<T>::operator>>(int shift) const {
     return VectorHelper<T>::shiftRight(d.v(), shift);
 }
-template<typename T> inline Vector<T> &Vector<T>::operator<<=(int shift) {
+template<typename T> Vc_ALWAYS_INLINE Vector<T> &Vector<T>::operator<<=(int shift) {
     d.v() = VectorHelper<T>::shiftLeft(d.v(), shift);
     return *static_cast<Vector<T> *>(this);
 }
-template<typename T> inline Vector<T> Vector<T>::operator<<(int shift) const {
+template<typename T> Vc_ALWAYS_INLINE Vc_PURE Vector<T> Vector<T>::operator<<(int shift) const {
     return VectorHelper<T>::shiftLeft(d.v(), shift);
 }
 
 #define OP_IMPL(T, symbol, fun) \
-  template<> inline Vector<T> &Vector<T>::operator symbol##=(AsArg x) { d.v() = HV::fun(d.v(), x.d.v()); return *this; } \
-  template<> inline Vector<T>  Vector<T>::operator symbol(AsArg x) const { return Vector<T>(HV::fun(d.v(), x.d.v())); }
+  template<> Vc_ALWAYS_INLINE Vector<T> &Vector<T>::operator symbol##=(AsArg x) { d.v() = HV::fun(d.v(), x.d.v()); return *this; } \
+  template<> Vc_ALWAYS_INLINE Vc_PURE Vector<T>  Vector<T>::operator symbol(AsArg x) const { return Vector<T>(HV::fun(d.v(), x.d.v())); }
   OP_IMPL(int, &, and_)
   OP_IMPL(int, |, or_)
   OP_IMPL(int, ^, xor_)
@@ -560,6 +570,21 @@ template<typename T> inline Vector<T> Vector<T>::operator<<(int shift) const {
 
 // operators {{{1
 #include "../common/operators.h"
+// isNegative {{{1
+template<> Vc_INTRINSIC Vc_PURE float_m float_v::isNegative() const
+{
+    return avx_cast<m256>(_mm256_srai_epi32(avx_cast<m256i>(_mm256_and_ps(_mm256_setsignmask_ps(), d.v())), 31));
+}
+template<> Vc_INTRINSIC Vc_PURE sfloat_m sfloat_v::isNegative() const
+{
+    return avx_cast<m256>(_mm256_srai_epi32(avx_cast<m256i>(_mm256_and_ps(_mm256_setsignmask_ps(), d.v())), 31));
+}
+template<> Vc_INTRINSIC Vc_PURE double_m double_v::isNegative() const
+{
+    return Mem::permute<X1, X1, X3, X3>(avx_cast<m256>(
+                _mm256_srai_epi32(avx_cast<m256i>(_mm256_and_pd(_mm256_setsignmask_pd(), d.v())), 31)
+                ));
+}
 // gathers {{{1
 // Better implementation (hopefully) with _mm256_set_
 //X template<typename T> template<typename Index> Vector<T>::Vector(const EntryType *mem, const Index *indexes)
@@ -568,50 +593,50 @@ template<typename T> inline Vector<T> Vector<T>::operator<<(int shift) const {
 //X             d.m(i) = mem[indexes[i]];
 //X             );
 //X }
-template<typename T> template<typename IndexT> inline ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, const IndexT *indexes)
+template<typename T> template<typename IndexT> Vc_ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, const IndexT *indexes)
 {
     gather(mem, indexes);
 }
-template<typename T> template<typename IndexT> inline ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, Vector<IndexT> indexes)
+template<typename T> template<typename IndexT> Vc_ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, VC_ALIGNED_PARAMETER(Vector<IndexT>) indexes)
 {
     gather(mem, indexes);
 }
 
-template<typename T> template<typename IndexT> inline ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, const IndexT *indexes, MaskArg mask)
+template<typename T> template<typename IndexT> Vc_ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, const IndexT *indexes, MaskArg mask)
     : d(HT::zero())
 {
     gather(mem, indexes, mask);
 }
 
-template<typename T> template<typename IndexT> inline ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, Vector<IndexT> indexes, MaskArg mask)
+template<typename T> template<typename IndexT> Vc_ALWAYS_INLINE Vector<T>::Vector(const EntryType *mem, VC_ALIGNED_PARAMETER(Vector<IndexT>) indexes, MaskArg mask)
     : d(HT::zero())
 {
     gather(mem, indexes, mask);
 }
 
-template<typename T> template<typename S1, typename IT> inline ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType S1::* member1, IT indexes)
+template<typename T> template<typename S1, typename IT> Vc_ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes)
 {
     gather(array, member1, indexes);
 }
-template<typename T> template<typename S1, typename IT> inline ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType S1::* member1, IT indexes, MaskArg mask)
+template<typename T> template<typename S1, typename IT> Vc_ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType S1::* member1, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask)
     : d(HT::zero())
 {
     gather(array, member1, indexes, mask);
 }
-template<typename T> template<typename S1, typename S2, typename IT> inline ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes)
+template<typename T> template<typename S1, typename S2, typename IT> Vc_ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes)
 {
     gather(array, member1, member2, indexes);
 }
-template<typename T> template<typename S1, typename S2, typename IT> inline ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, IT indexes, MaskArg mask)
+template<typename T> template<typename S1, typename S2, typename IT> Vc_ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const S2 S1::* member1, const EntryType S2::* member2, VC_ALIGNED_PARAMETER(IT) indexes, MaskArg mask)
     : d(HT::zero())
 {
     gather(array, member1, member2, indexes, mask);
 }
-template<typename T> template<typename S1, typename IT1, typename IT2> inline ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes)
+template<typename T> template<typename S1, typename IT1, typename IT2> Vc_ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType *const S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes)
 {
     gather(array, ptrMember1, outerIndexes, innerIndexes);
 }
-template<typename T> template<typename S1, typename IT1, typename IT2> inline ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType *const S1::* ptrMember1, IT1 outerIndexes, IT2 innerIndexes, MaskArg mask)
+template<typename T> template<typename S1, typename IT1, typename IT2> Vc_ALWAYS_INLINE Vector<T>::Vector(const S1 *array, const EntryType *const S1::* ptrMember1, VC_ALIGNED_PARAMETER(IT1) outerIndexes, VC_ALIGNED_PARAMETER(IT2) innerIndexes, MaskArg mask)
     : d(HT::zero())
 {
     gather(array, ptrMember1, outerIndexes, innerIndexes, mask);
@@ -624,42 +649,42 @@ template<typename T, size_t Size> struct IndexSizeChecker<Vector<T>, Size>
         VC_STATIC_ASSERT(Vector<T>::Size >= Size, IndexVector_must_have_greater_or_equal_number_of_entries);
     }
 };
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<double>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<double>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm256_setr_pd(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]]);
 }
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<float>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<float>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm256_setr_ps(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]],
             mem[indexes[4]], mem[indexes[5]], mem[indexes[6]], mem[indexes[7]]);
 }
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<sfloat>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<sfloat>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm256_setr_ps(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]],
             mem[indexes[4]], mem[indexes[5]], mem[indexes[6]], mem[indexes[7]]);
 }
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<int>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<int>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm256_setr_epi32(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]],
             mem[indexes[4]], mem[indexes[5]], mem[indexes[6]], mem[indexes[7]]);
 }
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<unsigned int>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<unsigned int>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm256_setr_epi32(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]],
             mem[indexes[4]], mem[indexes[5]], mem[indexes[6]], mem[indexes[7]]);
 }
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<short>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<short>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm_setr_epi16(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]],
             mem[indexes[4]], mem[indexes[5]], mem[indexes[6]], mem[indexes[7]]);
 }
-template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<unsigned short>::gather(const EntryType *mem, Index indexes)
+template<> template<typename Index> Vc_ALWAYS_INLINE void Vc_FLATTEN Vector<unsigned short>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes)
 {
     IndexSizeChecker<Index, Size>::check();
     d.v() = _mm_setr_epi16(mem[indexes[0]], mem[indexes[1]], mem[indexes[2]], mem[indexes[3]],
@@ -667,11 +692,12 @@ template<> template<typename Index> inline void ALWAYS_INLINE FLATTEN Vector<uns
 }
 
 #ifdef VC_USE_SET_GATHERS
-template<typename T> template<typename IT> inline void ALWAYS_INLINE Vector<T>::gather(const EntryType *mem, Vector<IT> indexes, MaskArg mask)
+template<typename T> template<typename IT> Vc_ALWAYS_INLINE void Vector<T>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Vector<IT>) indexes, MaskArg mask)
 {
     IndexSizeChecker<Vector<IT>, Size>::check();
-    indexes.setZero(!mask);
-    (*this)(mask) = Vector<T>(mem, indexes);
+    Vector<IT> indexesTmp = indexes;
+    indexesTmp.setZero(!mask);
+    (*this)(mask) = Vector<T>(mem, indexesTmp);
 }
 #endif
 
@@ -732,7 +758,7 @@ template<typename T> template<typename IT> inline void ALWAYS_INLINE Vector<T>::
 #endif
 
 template<typename T> template<typename Index>
-inline void INTRINSIC Vector<T>::gather(const EntryType *mem, Index indexes, MaskArg mask)
+Vc_INTRINSIC void Vector<T>::gather(const EntryType *mem, VC_ALIGNED_PARAMETER(Index) indexes, MaskArg mask)
 {
     IndexSizeChecker<Index, Size>::check();
 #define ith_value(_i_) (mem[indexes[_i_]])</