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
14 #ifndef BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
15 #define BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
16
17 #include <boost/atomic/detail/config.hpp>
18 #include <boost/atomic/detail/bitwise_cast.hpp>
19 #include <boost/atomic/detail/type_traits/integral_constant.hpp>
20 #include <boost/atomic/detail/type_traits/is_signed.hpp>
21 #include <boost/atomic/detail/type_traits/make_signed.hpp>
22 #include <boost/atomic/detail/type_traits/make_unsigned.hpp>
23
24 #ifdef BOOST_HAS_PRAGMA_ONCE
25 #pragma once
26 #endif
27
28 namespace boost {
29 namespace atomics {
30 namespace detail {
31
32 template< typename Output, typename Input >
zero_extend_impl(Input input,atomics::detail::true_type)33 BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
34 {
35 // Note: If we are casting with truncation or to the same-sized output, don't cause signed integer overflow by this chain of conversions
36 return atomics::detail::bitwise_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Output >::type >(
37 static_cast< typename atomics::detail::make_unsigned< Input >::type >(input)));
38 }
39
40 template< typename Output, typename Input >
zero_extend_impl(Input input,atomics::detail::false_type)41 BOOST_FORCEINLINE Output zero_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
42 {
43 return static_cast< Output >(static_cast< typename atomics::detail::make_unsigned< Input >::type >(input));
44 }
45
46 //! Zero-extends or truncates (wraps) input operand to fit in the output type
47 template< typename Output, typename Input >
zero_extend(Input input)48 BOOST_FORCEINLINE Output zero_extend(Input input) BOOST_NOEXCEPT
49 {
50 return atomics::detail::zero_extend_impl< Output >(input, atomics::detail::integral_constant< bool, atomics::detail::is_signed< Output >::value >());
51 }
52
53 //! Truncates (wraps) input operand to fit in the output type
54 template< typename Output, typename Input >
integral_truncate(Input input)55 BOOST_FORCEINLINE Output integral_truncate(Input input) BOOST_NOEXCEPT
56 {
57 // zero_extend does the truncation
58 return atomics::detail::zero_extend< Output >(input);
59 }
60
61 template< typename Output, typename Input >
sign_extend_impl(Input input,atomics::detail::true_type)62 BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
63 {
64 return atomics::detail::integral_truncate< Output >(input);
65 }
66
67 template< typename Output, typename Input >
sign_extend_impl(Input input,atomics::detail::false_type)68 BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
69 {
70 return static_cast< Output >(atomics::detail::bitwise_cast< typename atomics::detail::make_signed< Input >::type >(input));
71 }
72
73 //! Sign-extends or truncates (wraps) input operand to fit in the output type
74 template< typename Output, typename Input >
sign_extend(Input input)75 BOOST_FORCEINLINE Output sign_extend(Input input) BOOST_NOEXCEPT
76 {
77 return atomics::detail::sign_extend_impl< Output >(input, atomics::detail::integral_constant< bool, sizeof(Output) <= sizeof(Input) >());
78 }
79
80 //! Sign-extends or truncates (wraps) input operand to fit in the output type
81 template< typename Output, typename Input >
integral_extend(Input input,atomics::detail::true_type)82 BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
83 {
84 return atomics::detail::sign_extend< Output >(input);
85 }
86
87 //! Zero-extends or truncates (wraps) input operand to fit in the output type
88 template< typename Output, typename Input >
integral_extend(Input input,atomics::detail::false_type)89 BOOST_FORCEINLINE Output integral_extend(Input input, atomics::detail::false_type) BOOST_NOEXCEPT
90 {
91 return atomics::detail::zero_extend< Output >(input);
92 }
93
94 //! Sign- or zero-extends or truncates (wraps) input operand to fit in the output type
95 template< bool Signed, typename Output, typename Input >
integral_extend(Input input)96 BOOST_FORCEINLINE Output integral_extend(Input input) BOOST_NOEXCEPT
97 {
98 return atomics::detail::integral_extend< Output >(input, atomics::detail::integral_constant< bool, Signed >());
99 }
100
101 } // namespace detail
102 } // namespace atomics
103 } // namespace boost
104
105 #endif // BOOST_ATOMIC_DETAIL_INTEGRAL_EXTEND_HPP_INCLUDED_
106