split.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /* Copyright (C) 2011-2014 Povilas Kanapickas <[email protected]>
  2. Distributed under the Boost Software License, Version 1.0.
  3. (See accompanying file LICENSE_1_0.txt or copy at
  4. http://www.boost.org/LICENSE_1_0.txt)
  5. */
  6. #ifndef LIBSIMDPP_SIMDPP_CORE_SPLIT_H
  7. #define LIBSIMDPP_SIMDPP_CORE_SPLIT_H
  8. #ifndef LIBSIMDPP_SIMD_H
  9. #error "This file must be included through simd.h"
  10. #endif
  11. #include <simdpp/types.h>
  12. #include <simdpp/detail/insn/split.h>
  13. namespace simdpp {
  14. namespace SIMDPP_ARCH_NAMESPACE {
  15. namespace detail {
  16. template<class A, class R> SIMDPP_INL
  17. void v256_split(A a, R& r1, R& r2)
  18. {
  19. #if SIMDPP_USE_AVX2
  20. r1 = _mm256_extracti128_si256(a.native(), 0);
  21. r2 = _mm256_extracti128_si256(a.native(), 1);
  22. #else
  23. r1 = a[0];
  24. r2 = a[1];
  25. #endif
  26. }
  27. } // namespcae detail
  28. /** Splits a vector into two vectors half as wide. This function is useful when
  29. the ISA supports multiple vector sizes and the user does some operations
  30. with vectors that are narrower than the widest native vector.
  31. For example, on AVX, a __m256 vector can be split into two __m128 vectors.
  32. @code
  33. [ r1, r2 ] = a
  34. @endcode
  35. @icost{AVX2, 1}
  36. @icost{SSE2-AVX, NEON, ALTIVEC, 0}
  37. */
  38. template<unsigned N> SIMDPP_INL
  39. void split(const uint8<N>& a, uint8<N/2>& r1, uint8<N/2>& r2)
  40. {
  41. detail::insn::i_split(a, r1, r2);
  42. }
  43. template<unsigned N> SIMDPP_INL
  44. void split(const uint16<N>& a, uint16<N/2>& r1, uint16<N/2>& r2)
  45. {
  46. detail::insn::i_split(a, r1, r2);
  47. }
  48. template<unsigned N> SIMDPP_INL
  49. void split(const uint32<N>& a, uint32<N/2>& r1, uint32<N/2>& r2)
  50. {
  51. detail::insn::i_split(a, r1, r2);
  52. }
  53. template<unsigned N> SIMDPP_INL
  54. void split(const uint64<N>& a, uint64<N/2>& r1, uint64<N/2>& r2)
  55. {
  56. detail::insn::i_split(a, r1, r2);
  57. }
  58. template<unsigned N> SIMDPP_INL
  59. void split(const int8<N>& a, int8<N/2>& r1, int8<N/2>& r2)
  60. {
  61. uint8<N/2> q1, q2; q1 = r1; q2 = r2;
  62. detail::insn::i_split(uint8<N>(a), q1, q2);
  63. r1 = q1; r2 = q2;
  64. }
  65. template<unsigned N> SIMDPP_INL
  66. void split(const int16<N>& a, int16<N/2>& r1, int16<N/2>& r2)
  67. {
  68. uint16<N/2> q1, q2; q1 = r1; q2 = r2;
  69. detail::insn::i_split(uint16<N>(a), q1, q2);
  70. r1 = q1; r2 = q2;
  71. }
  72. template<unsigned N> SIMDPP_INL
  73. void split(const int32<N>& a, int32<N/2>& r1, int32<N/2>& r2)
  74. {
  75. uint32<N/2> q1, q2; q1 = r1; q2 = r2;
  76. detail::insn::i_split(uint32<N>(a), q1, q2);
  77. r1 = q1; r2 = q2;
  78. }
  79. template<unsigned N> SIMDPP_INL
  80. void split(const int64<N>& a, int64<N/2>& r1, int64<N/2>& r2)
  81. {
  82. uint64<N/2> q1, q2; q1 = r1; q2 = r2;
  83. detail::insn::i_split(uint64<N>(a), q1, q2);
  84. r1 = q1; r2 = q2;
  85. }
  86. template<unsigned N> SIMDPP_INL
  87. void split(const float32<N>& a, float32<N/2>& r1, float32<N/2>& r2)
  88. {
  89. detail::insn::i_split(a, r1, r2);
  90. }
  91. template<unsigned N> SIMDPP_INL
  92. void split(const float64<N>& a, float64<N/2>& r1, float64<N/2>& r2)
  93. {
  94. detail::insn::i_split(a, r1, r2);
  95. }
  96. } // namespace SIMDPP_ARCH_NAMESPACE
  97. } // namespace simdpp
  98. #endif