integral_extend.hpp 4.1 KB

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