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