blob: dea48ac6fe4e52192cd92cde39e9c90093aff582 [file] [log] [blame]
Brian Silverman7e171022018-08-05 00:17:49 -07001/*
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
28namespace boost {
29namespace atomics {
30namespace detail {
31
32template< typename Output, typename Input >
33BOOST_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
40template< typename Output, typename Input >
41BOOST_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
47template< typename Output, typename Input >
48BOOST_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
54template< typename Output, typename Input >
55BOOST_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
61template< typename Output, typename Input >
62BOOST_FORCEINLINE Output sign_extend_impl(Input input, atomics::detail::true_type) BOOST_NOEXCEPT
63{
64 return atomics::detail::integral_truncate< Output >(input);
65}
66
67template< typename Output, typename Input >
68BOOST_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
74template< typename Output, typename Input >
75BOOST_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
81template< typename Output, typename Input >
82BOOST_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
88template< typename Output, typename Input >
89BOOST_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
95template< bool Signed, typename Output, typename Input >
96BOOST_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_