[atomics.types.float]

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

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

### 32.5.8 Class template atomic [[atomics.types.generic]](atomics.types.generic#atomics.types.float)

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

[1](#1)

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

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

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

namespace std {template<> struct atomic<*floating-point-type*> {using value_type = *floating-point-type*; using difference_type = value_type; static constexpr bool is_always_lock_free = *implementation-defined*; bool is_lock_free() const volatile noexcept; bool is_lock_free() const noexcept; constexpr atomic() noexcept; constexpr atomic(*floating-point-type*) noexcept;
 atomic(const atomic&) = delete;
 atomic& operator=(const atomic&) = delete;
 atomic& operator=(const atomic&) volatile = delete; void store(*floating-point-type*, memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store(*floating-point-type*, memory_order = memory_order::seq_cst) noexcept; *floating-point-type* operator=(*floating-point-type*) volatile noexcept; constexpr *floating-point-type* operator=(*floating-point-type*) noexcept; *floating-point-type* load(memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* load(memory_order = memory_order::seq_cst) noexcept; operator *floating-point-type*() volatile noexcept; constexpr operator *floating-point-type*() noexcept; *floating-point-type* exchange(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* exchange(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*,
 memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*,
 memory_order, memory_order) noexcept; bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*,
 memory_order, memory_order) volatile noexcept; constexpr bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*,
 memory_order, memory_order) noexcept; bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_weak(*floating-point-type*&, *floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr bool compare_exchange_strong(*floating-point-type*&, *floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_add(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_add(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_sub(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_sub(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_max(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_max(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_min(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-poin-type*t fetch_min(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fmaximum(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fmaximum(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fminimum(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fminimum(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fmaximum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fmaximum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* fetch_fminimum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr *floating-point-type* fetch_fminimum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_add(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_add(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_sub(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_sub(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_max(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_max(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_min(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_min(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_fmaximum(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fmaximum(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_fminimum(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fminimum(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_fmaximum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fmaximum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; void store_fminimum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) volatile noexcept; constexpr void store_fminimum_num(*floating-point-type*,
 memory_order = memory_order::seq_cst) noexcept; *floating-point-type* operator+=(*floating-point-type*) volatile noexcept; constexpr *floating-point-type* operator+=(*floating-point-type*) noexcept; *floating-point-type* operator-=(*floating-point-type*) volatile noexcept; constexpr *floating-point-type* operator-=(*floating-point-type*) noexcept; void wait(*floating-point-type*, memory_order = memory_order::seq_cst) const volatile noexcept; constexpr void wait(*floating-point-type*,
 memory_order = memory_order::seq_cst) const noexcept; void notify_one() volatile noexcept; constexpr void notify_one() noexcept; void notify_all() volatile noexcept; constexpr void notify_all() noexcept; };}

[2](#2)

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

The atomic floating-point specializations
are standard-layout structs[.](#2.sentence-1)

They each have
a trivial destructor[.](#2.sentence-2)

[3](#3)

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

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#L5515)

The following operations perform arithmetic addition and subtraction 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:atomic_fetch_add)

`floating-point-type fetch_key(floating-point-type operand,
                               memory_order order = memory_order::seq_cst) volatile noexcept;
constexpr floating-point-type fetch_key(floating-point-type operand,
                                         memory_order order = memory_order::seq_cst) noexcept;
`

[5](#5)

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

*Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#5.sentence-1)

[6](#6)

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

*Effects*: Atomically replaces the value pointed to by this with the result of the computation applied to the value pointed
to by this 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.multithread]](intro.multithread "6.10.2 Multi-threaded executions and data races"))[.](#6.sentence-3)

[7](#7)

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

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

[8](#8)

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

*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<*floating-point-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#L5576)

- [(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 the value pointed to by this 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 the value pointed to by this 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 the value pointed to by this and the first parameter
as the arguments, except that:
  * [(9.3.1)](#9.3.1)

      If both arguments are NaN,
an unspecified NaN value replaces the value pointed to by this[.](#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
replaces the value pointed to by this; 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 replaces the value pointed to by this is unspecified[.](#9.3.3.sentence-1)

[10](#10)

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

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

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

`void store_key(floating-point-type operand,
  memory_order order = memory_order::seq_cst) volatile noexcept;
constexpr void store_key(floating-point-type operand,
  memory_order order = memory_order::seq_cst) noexcept;
`

[11](#11)

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

*Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#11.sentence-1)

[12](#12)

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

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

[13](#13)

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

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

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

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

[14](#14)

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

*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[.](#14.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"))[.](#14.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[.](#14.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[.](#14.sentence-4)

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

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

â *end note*]

[15](#15)

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

- [(15.1)](#15.1)

  For store_fmaximum and store_fminimum,
the maximum and minimum computation is performed
as if by fmaximum and fminimum, respectively,
with the value pointed to by this and
the first parameter as the arguments[.](#15.1.sentence-1)

- [(15.2)](#15.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 the value pointed to by this and
the first parameter as the arguments[.](#15.2.sentence-1)

- [(15.3)](#15.3)

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

      If both arguments are NaN,
an unspecified NaN value replaces the value pointed to by this[.](#15.3.1.sentence-1)

  * [(15.3.2)](#15.3.2)

      If exactly one argument is a NaN,
either the other argument or an unspecified NaN value replaces
the value pointed to by this;
it is unspecified which[.](#15.3.2.sentence-1)

  * [(15.3.3)](#15.3.3)

      If the arguments are differently signed zeros,
which of these values replaces the value pointed to by this is unspecified[.](#15.3.3.sentence-1)

[16](#16)

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

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

[ð](#lib:operator+=,atomic%3cT*%3e)

`floating-point-type operator op=(floating-point-type operand) volatile noexcept;
constexpr floating-point-type operator op=(floating-point-type operand) noexcept;
`

[17](#17)

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

*Constraints*: For the volatile overload of this function,is_always_lock_free is true[.](#17.sentence-1)

[18](#18)

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

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

[19](#19)

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

*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[.](#19.sentence-1)

Atomic arithmetic operations on *floating-point-type* should conform to the std​::​numeric_limits<*floating-point-type*> traits associated with the floating-point type ([[limits.syn]](limits.syn "17.3.3 Header <limits> synopsis"))[.](#19.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[.](#19.sentence-3)
