integral_conversions.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  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. * Copyright (c) 2018 Andrey Semashev
  7. */
  8. /*!
  9. * \file atomic/detail/integral_conversions.hpp
  10. *
  11. * This header defines sign/zero extension and truncation utilities for Boost.Atomic. The tools assume two's complement signed integer representation.
  12. */
  13. #ifndef BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_
  14. #define BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_
  15. #include <boost/atomic/detail/config.hpp>
  16. #include <boost/atomic/detail/bitwise_cast.hpp>
  17. #include <boost/atomic/detail/type_traits/integral_constant.hpp>
  18. #include <boost/atomic/detail/type_traits/is_signed.hpp>
  19. #include <boost/atomic/detail/type_traits/make_signed.hpp>
  20. #include <boost/atomic/detail/type_traits/make_unsigned.hpp>
  21. #include <boost/atomic/detail/header.hpp>
  22. #ifdef BOOST_HAS_PRAGMA_ONCE
  23. #pragma once
  24. #endif
  25. namespace boost {
  26. namespace atomics {
  27. namespace detail {
  28. template< typename Output, typename Input >
  29. BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
  30. {
  31. // Note: If we are casting with truncation or to the same-sized output, don't cause signed integer overflow by this chain of conversions
  32. return atomics::detail::bitwise_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Output >::type >(
  33. static_cast< typename atomics::detail::make_unsigned< Input >::type >(input)));
  34. }
  35. template< typename Output, typename Input >
  36. BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
  37. {
  38. return static_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Input >::type >(input));
  39. }
  40. //! Zero-extends or truncates (wraps) input operand to fit in the output type
  41. template< typename Output, typename Input >
  42. BOOST_FORCEINLINE Output zero_extend(Input input) BOOST_NOEXCEPT
  43. {
  44. return atomics::detail::zero_extend_impl< Output >(input, atomics::detail::integral_constant< bool, atomics::detail::is_signed< Output >::value >());
  45. }
  46. //! Truncates (wraps) input operand to fit in the output type
  47. template< typename Output, typename Input >
  48. BOOST_FORCEINLINE Output integral_truncate(Input input) BOOST_NOEXCEPT
  49. {
  50. // zero_extend does the truncation
  51. return atomics::detail::zero_extend< Output >(input);
  52. }
  53. template< typename Output, typename Input >
  54. BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
  55. {
  56. return atomics::detail::integral_truncate< Output >(input);
  57. }
  58. template< typename Output, typename Input >
  59. BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
  60. {
  61. return static_cast< Output >(atomics::detail::bitwise_cast< typename atomics::detail::make_signed< Input >::type >(input));
  62. }
  63. //! Sign-extends or truncates (wraps) input operand to fit in the output type
  64. template< typename Output, typename Input >
  65. BOOST_FORCEINLINE Output sign_extend(Input input) BOOST_NOEXCEPT
  66. {
  67. return atomics::detail::sign_extend_impl< Output >(input, atomics::detail::integral_constant< bool, sizeof(Output) <= sizeof(Input) >());
  68. }
  69. //! Sign-extends or truncates (wraps) input operand to fit in the output type
  70. template< typename Output, typename Input >
  71. BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
  72. {
  73. return atomics::detail::sign_extend< Output >(input);
  74. }
  75. //! Zero-extends or truncates (wraps) input operand to fit in the output type
  76. template< typename Output, typename Input >
  77. BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
  78. {
  79. return atomics::detail::zero_extend< Output >(input);
  80. }
  81. //! Sign- or zero-extends or truncates (wraps) input operand to fit in the output type
  82. template< bool Signed, typename Output, typename Input >
  83. BOOST_FORCEINLINE Output integral_extend(Input input) BOOST_NOEXCEPT
  84. {
  85. return atomics::detail::integral_extend< Output >(input, atomics::detail::integral_constant< bool, Signed >());
  86. }
  87. } // namespace detail
  88. } // namespace atomics
  89. } // namespace boost
  90. #include <boost/atomic/detail/footer.hpp>
  91. #endif // BOOST_ATOMIC_DETAIL_INTEGRAL_CONVERSIONS_HPP_INCLUDED_