cast.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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_CAST_H
  7. #define LIBSIMDPP_SIMDPP_CORE_CAST_H
  8. #ifndef LIBSIMDPP_SIMD_H
  9. #error "This file must be included through simd.h"
  10. #endif
  11. #include <simdpp/setup_arch.h>
  12. #include <simdpp/detail/cast.h>
  13. #include <simdpp/types/traits.h>
  14. namespace simdpp {
  15. namespace SIMDPP_ARCH_NAMESPACE {
  16. namespace detail {
  17. // on certain architectures mask-mask conversions may need unmasking or remasking
  18. template<class R, class T> struct cast_mask_override { static const unsigned value = CAST_MASK_MEMCPY; };
  19. #if SIMDPP_USE_NEON_NO_FLT_SP
  20. template<unsigned N>
  21. struct cast_mask_override<mask_float32<N>, mask_int32<N>> { static const unsigned value = CAST_MASK_UNMASK; };
  22. template<unsigned N>
  23. struct cast_mask_override<mask_int32<N>, mask_float32<N>> { static const unsigned value = CAST_MASK_REMASK; };
  24. #endif
  25. #if SIMDPP_USE_NEON && SIMDPP_32_BITS
  26. template<unsigned N>
  27. struct cast_mask_override<mask_int64<N>, mask_float64<N>> { static const unsigned value = CAST_MASK_UNMASK; };
  28. template<unsigned N>
  29. struct cast_mask_override<mask_float64<N>, mask_int64<N>> { static const unsigned value = CAST_MASK_REMASK; };
  30. #endif
  31. #if SIMDPP_USE_VSX_206 && !SIMDPP_USE_VSX_207
  32. template<unsigned N>
  33. struct cast_mask_override<mask_int64<N>, mask_float64<N>> { static const unsigned value = CAST_MASK_REMASK; };
  34. template<unsigned N>
  35. struct cast_mask_override<mask_float64<N>, mask_int64<N>> { static const unsigned value = CAST_MASK_UNMASK; };
  36. #endif
  37. template<class R, class T> SIMDPP_INL
  38. void bit_cast_impl(const T& t, R& r)
  39. {
  40. const bool is_vector_r = is_vector<R>::value;
  41. const bool is_vector_t = is_vector<T>::value;
  42. const bool is_mask_r = is_mask<R>::value;
  43. const bool is_mask_t = is_mask<T>::value;
  44. const unsigned mask_mask_cast_override = detail::cast_mask_override<R,T>::value;
  45. const unsigned cast_type =
  46. (!is_vector_t && !is_vector_r) ? CAST_TYPE_OTHER :
  47. (!is_mask_t && !is_mask_r) ? CAST_TYPE_VECTOR_TO_VECTOR :
  48. (is_mask_t && !is_mask_r) ? CAST_TYPE_MASK_TO_VECTOR :
  49. (!is_mask_t && is_mask_r) ? CAST_TYPE_VECTOR_TO_MASK :
  50. // remaining cases deal with is_mask_t && is_mask_r
  51. (mask_mask_cast_override == CAST_MASK_REMASK) ? CAST_TYPE_MASK_TO_MASK_REMASK :
  52. (mask_mask_cast_override == CAST_MASK_UNMASK) ? CAST_TYPE_MASK_TO_MASK_UNMASK :
  53. CAST_TYPE_MASK_TO_MASK_BITWISE;
  54. static_assert(is_vector_r == is_vector_t,
  55. "bit_cast can't convert between vector and non-vector types");
  56. detail::cast_wrapper<cast_type>::run(t, r);
  57. }
  58. template<class T> SIMDPP_INL
  59. void bit_cast_impl(const T& t, T& r)
  60. {
  61. // Simple implementation for the common case
  62. r = t;
  63. }
  64. } // namespace detail
  65. /** Casts between unrelated types. No changes to the stored values are
  66. performed.
  67. Conversions between vector and non-vector types are not allowed.
  68. Conversion from non-mask type to mask type is not allowed.
  69. Conversion from mask type to a non-mask type is not a costless operation
  70. because masks may have different logical and physical layout (e.g., in
  71. some implementations one bit represents entire element in a vector).
  72. Conversions between mask types is only allowed if the element size is the
  73. same.
  74. */
  75. template<class R, class T> SIMDPP_INL
  76. R bit_cast(const T& t)
  77. {
  78. R r;
  79. detail::bit_cast_impl(t, r);
  80. return r;
  81. }
  82. } // namespace SIMDPP_ARCH_NAMESPACE
  83. } // namespace simdpp
  84. #endif