]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/atomic/detail/extra_fp_ops_generic.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / atomic / detail / extra_fp_ops_generic.hpp
CommitLineData
11fdf7f2
TL
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/extra_fp_ops_generic.hpp
10 *
11 * This header contains generic implementation of the extra floating point atomic operations.
12 */
13
14#ifndef BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_GENERIC_HPP_INCLUDED_
15#define BOOST_ATOMIC_DETAIL_EXTRA_FP_OPS_GENERIC_HPP_INCLUDED_
16
17#include <cstddef>
18#include <boost/memory_order.hpp>
19#include <boost/atomic/detail/config.hpp>
20#include <boost/atomic/detail/bitwise_fp_cast.hpp>
f67539c2 21#include <boost/atomic/detail/storage_traits.hpp>
11fdf7f2
TL
22#include <boost/atomic/detail/extra_fp_operations_fwd.hpp>
23#include <boost/atomic/detail/type_traits/is_iec559.hpp>
24#include <boost/atomic/detail/type_traits/is_integral.hpp>
20effc67 25#include <boost/atomic/detail/header.hpp>
11fdf7f2
TL
26
27#ifdef BOOST_HAS_PRAGMA_ONCE
28#pragma once
29#endif
30
20effc67 31#if defined(BOOST_GCC) && BOOST_GCC >= 60000
11fdf7f2
TL
32#pragma GCC diagnostic push
33// ignoring attributes on template argument X - this warning is because we need to pass storage_type as a template argument; no problem in this case
34#pragma GCC diagnostic ignored "-Wignored-attributes"
35#endif
36
37namespace boost {
38namespace atomics {
39namespace detail {
40
41//! Negate implementation
42template<
43 typename Base,
44 typename Value,
45 std::size_t Size
46#if defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH)
47 , bool = atomics::detail::is_iec559< Value >::value && atomics::detail::is_integral< typename Base::storage_type >::value
48#endif
49>
20effc67 50struct extra_fp_negate_generic :
11fdf7f2
TL
51 public Base
52{
53 typedef Base base_type;
54 typedef typename base_type::storage_type storage_type;
55 typedef Value value_type;
56
57 static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
58 {
59 storage_type old_storage, new_storage;
60 value_type old_val, new_val;
61 atomics::detail::non_atomic_load(storage, old_storage);
62 do
63 {
64 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
65 new_val = -old_val;
66 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
67 }
68 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
69 return old_val;
70 }
71
72 static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
73 {
74 storage_type old_storage, new_storage;
75 value_type old_val, new_val;
76 atomics::detail::non_atomic_load(storage, old_storage);
77 do
78 {
79 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
80 new_val = -old_val;
81 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
82 }
83 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
84 return new_val;
85 }
86
87 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
88 {
89 fetch_negate(storage, order);
90 }
91};
92
93#if defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH)
94
95//! Negate implementation for IEEE 754 / IEC 559 floating point types. We leverage the fact that the sign bit is the most significant bit in the value.
96template< typename Base, typename Value, std::size_t Size >
20effc67 97struct extra_fp_negate_generic< Base, Value, Size, true > :
11fdf7f2
TL
98 public Base
99{
100 typedef Base base_type;
101 typedef typename base_type::storage_type storage_type;
102 typedef Value value_type;
103
104 //! The mask with only one sign bit set to 1
105 static BOOST_CONSTEXPR_OR_CONST storage_type sign_mask = static_cast< storage_type >(1u) << (atomics::detail::value_sizeof< value_type >::value * 8u - 1u);
106
107 static BOOST_FORCEINLINE value_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
108 {
109 return atomics::detail::bitwise_fp_cast< value_type >(base_type::fetch_xor(storage, sign_mask, order));
110 }
111
112 static BOOST_FORCEINLINE value_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
113 {
114 return atomics::detail::bitwise_fp_cast< value_type >(base_type::bitwise_xor(storage, sign_mask, order));
115 }
116
117 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
118 {
119 base_type::opaque_xor(storage, sign_mask, order);
120 }
121};
122
123#endif // defined(BOOST_ATOMIC_DETAIL_INT_FP_ENDIAN_MATCH)
124
125//! Generic implementation of floating point operations
126template< typename Base, typename Value, std::size_t Size >
20effc67
TL
127struct extra_fp_operations_generic :
128 public extra_fp_negate_generic< Base, Value, Size >
11fdf7f2 129{
20effc67 130 typedef extra_fp_negate_generic< Base, Value, Size > base_type;
11fdf7f2
TL
131 typedef typename base_type::storage_type storage_type;
132 typedef Value value_type;
133
134 static BOOST_FORCEINLINE value_type add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
135 {
136 storage_type old_storage, new_storage;
137 value_type old_val, new_val;
138 atomics::detail::non_atomic_load(storage, old_storage);
139 do
140 {
141 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
142 new_val = old_val + v;
143 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
144 }
145 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
146 return new_val;
147 }
148
149 static BOOST_FORCEINLINE value_type sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
150 {
151 storage_type old_storage, new_storage;
152 value_type old_val, new_val;
153 atomics::detail::non_atomic_load(storage, old_storage);
154 do
155 {
156 old_val = atomics::detail::bitwise_fp_cast< value_type >(old_storage);
157 new_val = old_val - v;
158 new_storage = atomics::detail::bitwise_fp_cast< storage_type >(new_val);
159 }
160 while (!base_type::compare_exchange_weak(storage, old_storage, new_storage, order, memory_order_relaxed));
161 return new_val;
162 }
163
164 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
165 {
166 base_type::fetch_add(storage, v, order);
167 }
168
169 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, value_type v, memory_order order) BOOST_NOEXCEPT
170 {
171 base_type::fetch_sub(storage, v, order);
172 }
173};
174
175// Default extra_fp_operations template definition will be used unless specialized for a specific platform
176template< typename Base, typename Value, std::size_t Size >
177struct extra_fp_operations< Base, Value, Size, true > :
20effc67 178 public extra_fp_operations_generic< Base, Value, Size >
11fdf7f2
TL
179{
180};
181
182} // namespace detail
183} // namespace atomics
184} // namespace boost
185
20effc67 186#if defined(BOOST_GCC) && BOOST_GCC >= 60000
11fdf7f2
TL
187#pragma GCC diagnostic pop
188#endif
189
20effc67
TL
190#include <boost/atomic/detail/footer.hpp>
191
11fdf7f2 192#endif // BOOST_ATOMIC_DETAIL_FP_OPS_GENERIC_HPP_INCLUDED_