[atomics.ref.float]

# 32 Concurrency support library [[thread]](./#thread)

## 32.5 Atomic operations [[atomics]](atomics#ref.float)

### 32.5.7 Class template atomic_ref [[atomics.ref.generic]](atomics.ref.generic#atomics.ref.float)

#### 32.5.7.4 Specializations for floating-point types [atomics.ref.float]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3884)

There are specializations of the atomic_ref class template
for all floating-point types[.](#1.sentence-1)

For each such type *floating-point-type*,
the specialization atomic_ref<*floating-point-type*> provides
additional atomic operations appropriate to floating-point types[.](#1.sentence-2)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3892)

The program is ill-formed
if is_always_lock_free is false andis_volatile_v<*floating-point-type*> is true[.](#2.sentence-1)

namespace std {template<> struct atomic_ref<*floating-point-type*> {private:*floating-point-type** ptr; // *exposition only*public:using value_type = remove_cv_t<*floating-point-type*>; using difference_type = value_type; static constexpr size_t required_alignment = *implementation-defined*; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const noexcept; constexpr explicit atomic_ref(*floating-point-type*&); constexpr atomic_ref(const atomic_ref&) noexcept;
 atomic_ref& operator=(const atomic_ref&) = delete; constexpr void store(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator=(value_type) const noexcept; constexpr value_type load(memory_order = memory_order::seq_cst) const noexcept; constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type,
 memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type,
 memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum_num(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum_num(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_add(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_max(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_min(value_type, memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fmaximum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fminimum(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fmaximum_num(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void store_fminimum_num(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; constexpr void wait(value_type,
 memory_order = memory_order::seq_cst) const noexcept; constexpr void notify_one() const noexcept; constexpr void notify_all() const noexcept; constexpr *floating-point-type** address() const noexcept; };}

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3975)

Descriptions are provided below only for members
that differ from the primary template[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L3979)

The following operations perform arithmetic computations[.](#4.sentence-1)

The correspondence among key, operator, and computation is specified
in Table [155](atomics.types.int#tab:atomic.types.int.comp "Table 155: Atomic arithmetic computations"),
except for the keysmax,min,fmaximum,fminimum,fmaximum_num, andfminimum_num,
which are specified below[.](#4.sentence-2)

[ð](#lib:fetch_add,atomic_ref%3cfloating-point-type%3e)

`constexpr value_type fetch_key(value_type operand,
                          memory_order order = memory_order::seq_cst) const noexcept;
`

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4006)

*Constraints*: is_const_v<*floating-point-type*> is false[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4010)

*Effects*: Atomically replaces the value referenced by *ptr with
the result of the computation applied to the value referenced by *ptr and the given operand[.](#6.sentence-1)

Memory is affected according to the value of order[.](#6.sentence-2)

These operations are atomic read-modify-write operations ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#6.sentence-3)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4018)

*Returns*: Atomically, the value referenced by *ptr immediately before the effects[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4023)

*Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")),
the result is unspecified,
but the operations otherwise have no undefined behavior[.](#8.sentence-1)

Atomic arithmetic operations on *floating-point-type* should conform to
the std​::​numeric_limits<value_type> traits
associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header <limits> synopsis"))[.](#8.sentence-2)

The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment"))
for atomic arithmetic operations on *floating-​point-type* may be different than the calling thread's floating-point environment[.](#8.sentence-3)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4035)

- [(9.1)](#9.1)

  For fetch_fmaximum and fetch_fminimum,
the maximum and minimum computation is performed
as if by fmaximum and fminimum, respectively,
with *ptr and the first parameter as the arguments[.](#9.1.sentence-1)

- [(9.2)](#9.2)

  For fetch_fmaximum_num and fetch_fminimum_num,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments[.](#9.2.sentence-1)

- [(9.3)](#9.3)

  For fetch_max and fetch_min,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments, except that:
  * [(9.3.1)](#9.3.1)

      If both arguments are NaN, an unspecified NaN value is stored at *ptr[.](#9.3.1.sentence-1)

  * [(9.3.2)](#9.3.2)

      If exactly one argument is a NaN,
either the other argument or an unspecified NaN value is stored at *ptr;
it is unspecified which[.](#9.3.2.sentence-1)

  * [(9.3.3)](#9.3.3)

      If the arguments are differently signed zeros,
which of these values is stored at *ptr is unspecified[.](#9.3.3.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4065)

*Recommended practice*: The implementation of fetch_max and fetch_min should treat negative zero as smaller than positive zero[.](#10.sentence-1)

[ð](#lib:store_add,atomic_ref%3cfloating-point-type%3e)

`constexpr void store_key(value_type operand,
                          memory_order order = memory_order::seq_cst) const noexcept;
`

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4085)

*Preconditions*: order is memory_order​::​relaxed,memory_order​::​release, ormemory_order​::​seq_cst[.](#11.sentence-1)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4091)

*Effects*: Atomically replaces the value referenced by *ptr with the result of the computation applied to
the value referenced by *ptr and the given operand[.](#12.sentence-1)

Memory is affected according to the value of order[.](#12.sentence-2)

These operations are atomic modify-write operations ([[atomics.order]](atomics.order "32.5.4 Order and consistency"))[.](#12.sentence-3)

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4099)

*Remarks*: If the result is not a representable value for its type ([[expr.pre]](expr.pre "7.1 Preamble")),
the result is unspecified,
but the operations otherwise have no undefined behavior[.](#13.sentence-1)

Atomic arithmetic operations on *floating-point-type* should conform to the numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header <limits> synopsis"))[.](#13.sentence-2)

The floating-point environment ([[cfenv]](cfenv "29.3 The floating-point environment"))
for atomic arithmetic operations on *floating-point-type* may be different than the calling thread's floating-point environment[.](#13.sentence-3)

The arithmetic rules of floating-point atomic modify-write operations
may be different from operations on floating-point types or
atomic floating-point types[.](#13.sentence-4)

[*Note [1](#note-1)*:

Tree reductions are permitted for atomic modify-write operations[.](#13.sentence-5)

â *end note*]

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4117)

- [(14.1)](#14.1)

  For store_fmaximum and store_fminimum,
the maximum and minimum computation is performed
as if by fmaximum and fminimum, respectively,
with *ptr and the first parameter as the arguments[.](#14.1.sentence-1)

- [(14.2)](#14.2)

  For store_fmaximum_num and store_fminimum_num,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments[.](#14.2.sentence-1)

- [(14.3)](#14.3)

  For store_max and store_min,
the maximum and minimum computation is performed
as if by fmaximum_num and fminimum_num, respectively,
with *ptr and the first parameter as the arguments, except that:
  * [(14.3.1)](#14.3.1)

      If both arguments are NaN, an unspecified NaN value is stored at *ptr[.](#14.3.1.sentence-1)

  * [(14.3.2)](#14.3.2)

      If exactly one argument is a NaN,
either the other argument or an unspecified NaN value is stored at *ptr,
it is unspecified which[.](#14.3.2.sentence-1)

  * [(14.3.3)](#14.3.3)

      If the arguments are differently signed zeros,
which of these values is stored at *ptr is unspecified[.](#14.3.3.sentence-1)

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4147)

*Recommended practice*: The implementation of store_max and store_min should treat negative zero as smaller than positive zero[.](#15.sentence-1)

[ð](#lib:operator+=,atomic_ref%3cfloating-point-type%3e)

`constexpr value_type operator op=(value_type operand) const noexcept;
`

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4160)

*Constraints*: is_const_v<*floating-point-type*> is false[.](#16.sentence-1)

[17](#17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L4164)

*Effects*: Equivalent to:return fetch_*key*(operand) *op* operand;
