From f254d59663fd23c27192b07b8c051979561578cc Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 25 Jun 2025 23:44:08 +0200 Subject: [PATCH 1/3] P3008R6 Atomic floating-point min/max --- source/numerics.tex | 5 ++ source/support.tex | 2 +- source/threads.tex | 143 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 147 insertions(+), 3 deletions(-) diff --git a/source/numerics.tex b/source/numerics.tex index 59d0c30c13..b8eadeaaed 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -9664,6 +9664,11 @@ constexpr float fminf(float x, float y); constexpr long double fminl(long double x, long double y); + constexpr @\placeholdernc{floating-point-type}@ fmaximum(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr @\placeholdernc{floating-point-type}@ fmaximum_num(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr @\placeholdernc{floating-point-type}@ fminimum(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr @\placeholdernc{floating-point-type}@ fminimum_num(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y); + constexpr @\placeholdernc{floating-point-type}@ fma(@\placeholdernc{floating-point-type}@ x, @\placeholdernc{floating-point-type}@ y, @\placeholdernc{floating-point-type}@ z); constexpr float fmaf(float x, float y, float z); diff --git a/source/support.tex b/source/support.tex index 15422c73cb..091af12305 100644 --- a/source/support.tex +++ b/source/support.tex @@ -590,7 +590,7 @@ #define @\defnlibxname{cpp_lib_atomic_float}@ 201711L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_is_always_lock_free}@ 201603L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_lock_free_type_aliases}@ 201907L // also in \libheader{atomic} -#define @\defnlibxname{cpp_lib_atomic_min_max}@ 202403L // freestanding, also in \libheader{atomic} +#define @\defnlibxname{cpp_lib_atomic_min_max}@ 202506L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_ref}@ 202411L // freestanding, also in \libheader{atomic} #define @\defnlibxname{cpp_lib_atomic_shared_ptr}@ 201711L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_atomic_value_initialization}@ 201911L // freestanding, also in \libheader{atomic}, \libheader{memory} diff --git a/source/threads.tex b/source/threads.tex index 08a184c6c2..3135fe2ec4 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -3773,6 +3773,19 @@ constexpr value_type fetch_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum_num(@\placeholdernc{floating-point}@, + memory_order = memory_order::seq_cst) const noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum_num(@\placeholdernc{floating-point-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; @@ -3792,10 +3805,24 @@ \pnum The following operations perform arithmetic computations. The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. +in \tref{atomic.types.int.comp}, +except for the keys +\tcode{max}, +\tcode{min}, +\tcode{fmaximum}, +\tcode{fminimum}, +\tcode{fmaximum_num}, and +\tcode{fminimum_num}, +which are specified below. \indexlibrarymember{fetch_add}{atomic_ref<\placeholder{floating-point-type}>}% \indexlibrarymember{fetch_sub}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum_num}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum_num}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_max}{atomic_ref<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_min}{atomic_ref<\placeholder{floating-point-type}>}% \begin{itemdecl} constexpr value_type fetch_@\placeholdernc{key}@(value_type operand, memory_order order = memory_order::seq_cst) const noexcept; @@ -3830,6 +3857,41 @@ The floating-point environment\iref{cfenv} for atomic arithmetic operations on \tcode{\placeholder{floating-\newline point-type}} may be different than the calling thread's floating-point environment. + +\pnum +\begin{itemize} +\item +For \tcode{fetch_fmaximum} and \tcode{fetch_fminimum}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\item +For \tcode{fetch_fmaximum_num} and \tcode{fetch_fminimum_num}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with \tcode{*ptr} and the first parameter as the arguments. +\item +For \tcode{fetch_max} and \tcode{fetch_min}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with \tcode{*ptr} and the first parameter as the arguments, except that: +\begin{itemize} +\item +If both arguments are NaN, an unspecified NaN value is stored at \tcode{*ptr}. +\item +If exactly one argument is a NaN, +either the other argument or an unspecified NaN value is stored at \tcode{*ptr}; +it is unspecified which. +\item +If the arguments are differently signed zeros, +which of these values is stored at \tcode{*ptr} is unspecified. +\end{itemize} +\end{itemize} + +\pnum +\recommended +The implementation of \tcode{fetch_max} and \tcode{fetch_min} +should treat negative zero as smaller than positive zero. \end{itemdescr} \indexlibrarymember{operator+=}{atomic_ref<\placeholder{floating-point-type}>}% @@ -4965,6 +5027,30 @@ memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{floating-point-type}@ fetch_sub(@\placeholdernc{floating-point-type}@, memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_max(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-poin-type}@t fetch_min(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fmaximum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; + @\placeholdernc{floating-point-type}@ fetch_fminimum_num(@\placeholdernc{floating-point-type}@, + memory_order = memory_order::seq_cst) volatile noexcept; + constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum_num(f@\placeholdernc{loating-point-type}@, + memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) volatile noexcept; constexpr @\placeholdernc{floating-point-type}@ operator+=(@\placeholder{floating-point-type}@) noexcept; @@ -4994,7 +5080,15 @@ \pnum The following operations perform arithmetic addition and subtraction computations. The correspondence among key, operator, and computation is specified -in \tref{atomic.types.int.comp}. +in \tref{atomic.types.int.comp}, +except for the keys +\tcode{max}, +\tcode{min}, +\tcode{fmaximum}, +\tcode{fminimum}, +\tcode{fmaximum_num}, and +\tcode{fminimum_num}, +which are specified below. \indexlibraryglobal{atomic_fetch_add}% \indexlibraryglobal{atomic_fetch_sub}% @@ -5002,6 +5096,12 @@ \indexlibraryglobal{atomic_fetch_sub_explicit}% \indexlibrarymember{fetch_add}{atomic<\placeholder{floating-point-type}>}% \indexlibrarymember{fetch_sub}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fmaximum_num}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_fminimum_num}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_max}{atomic<\placeholder{floating-point-type}>}% +\indexlibrarymember{fetch_min}{atomic<\placeholder{floating-point-type}>}% \begin{itemdecl} T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) volatile noexcept; constexpr T fetch_@\placeholdernc{key}@(T operand, memory_order order = memory_order::seq_cst) noexcept; @@ -5035,6 +5135,45 @@ The floating-point environment\iref{cfenv} for atomic arithmetic operations on \tcode{\placeholder{floating-point-type}} may be different than the calling thread's floating-point environment. + +\pnum +\begin{itemize} +\item +For \tcode{fetch_fmaximum} and \tcode{fetch_fminimum}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum} and \tcode{fminimum}, respectively, +with the value pointed to by \tcode{this} and the first parameter +as the arguments. +\item +For \tcode{fetch_fmaximum_num} and \tcode{fetch_fminimum_num}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with the value pointed to by \tcode{this} and the first parameter +as the arguments. +\item +For \tcode{fetch_max} and \tcode{fetch_min}, +the maximum and minimum computation is performed +as if by \tcode{fmaximum_num} and \tcode{fminimum_num}, respectively, +with the value pointed to by \tcode{this} and the first parameter +as the arguments, except that: +\begin{itemize} +\item +If both arguments are NaN, +an unspecified NaN value replaces the value pointed to by \tcode{this}. +\item +If exactly one argument is a NaN, +either the other argument or an unspecified NaN value +replaces the value pointed to by \tcode{this}; it is unspecified which. +\item +If the arguments are differently signed zeros, +which of these values replaces the value pointed to by this is unspecified. +\end{itemize} +\end{itemize} + +\pnum +\recommended +The implementation of \tcode{fetch_max} and \tcode{fetch_min} +should treat negative zero as smaller than positive zero. \end{itemdescr} \indexlibrarymember{operator+=}{atomic}% From af0179c5093ee107c24ac8e841721802958e1964 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 26 Jun 2025 13:18:12 +0200 Subject: [PATCH 2/3] [atomics.ref.float] Apply design intent of P3323R1 to new functions --- source/threads.tex | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/source/threads.tex b/source/threads.tex index 3135fe2ec4..bc7a2db51b 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -3773,18 +3773,18 @@ constexpr value_type fetch_sub(value_type, memory_order = memory_order::seq_cst) const noexcept; - constexpr @\placeholdernc{floating-point-type}@ fetch_max(@\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; - constexpr @\placeholdernc{floating-point-type}@ fetch_min(@\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; - constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum(@\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; - constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum(@\placeholdernc{floating-point-type}@, - memory_order = memory_order::seq_cst) const noexcept; - constexpr @\placeholdernc{floating-point-type}@ fetch_fmaximum_num(@\placeholdernc{floating-point}@, - memory_order = memory_order::seq_cst) const noexcept; - constexpr @\placeholdernc{floating-point-type}@ fetch_fminimum_num(@\placeholdernc{floating-point-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 valu_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 value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; From 3add3e778f5db1d6ff183eb23e04622b540be2c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20K=C3=B6ppe?= Date: Wed, 16 Jul 2025 18:52:23 +0100 Subject: [PATCH 3/3] [atomics.ref.float] Fix indentations and whitespace --- source/threads.tex | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/source/threads.tex b/source/threads.tex index bc7a2db51b..4349f32e24 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -3758,33 +3758,33 @@ constexpr operator value_type() const noexcept; constexpr value_type exchange(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, - memory_order, memory_order) const noexcept; + memory_order, memory_order) const noexcept; constexpr bool compare_exchange_strong(value_type&, value_type, - memory_order, memory_order) const noexcept; + memory_order, memory_order) const noexcept; constexpr bool compare_exchange_weak(value_type&, value_type, - memory_order = memory_order::seq_cst) const noexcept; + 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; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_add(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_sub(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_max(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_min(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr valu_type fetch_fminimum(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fmaximum_num(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type fetch_fminimum_num(value_type, - memory_order = memory_order::seq_cst) const noexcept; + memory_order = memory_order::seq_cst) const noexcept; constexpr value_type operator+=(value_type) const noexcept; constexpr value_type operator-=(value_type) const noexcept; @@ -4793,13 +4793,13 @@ memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_xor(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral-type}@ fetch_max( @\placeholdernc{integral-type}@, + @\placeholdernc{integral-type}@ fetch_max(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; constexpr @\placeholdernc{integral-type}@ fetch_max( @\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; - @\placeholdernc{integral-type}@ fetch_min( @\placeholdernc{integral-type}@, + @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) volatile noexcept; - constexpr @\placeholdernc{integral-type}@ fetch_min( @\placeholdernc{integral-type}@, + constexpr @\placeholdernc{integral-type}@ fetch_min(@\placeholdernc{integral-type}@, memory_order = memory_order::seq_cst) noexcept; @\placeholdernc{integral-type}@ operator++(int) volatile noexcept;