From e4afccd20e8a9762da182e2f9d34dfa56a458a30 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 25 Jun 2025 23:44:08 +0200 Subject: [PATCH 1/4] P3008R6 Atomic floating-point min/max --- source/numerics.tex | 5 ++ source/support.tex | 2 +- source/threads.tex | 131 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 135 insertions(+), 3 deletions(-) diff --git a/source/numerics.tex b/source/numerics.tex index 529ed10969..5194f4c655 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -9649,6 +9649,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 95d674aafb..43c189bd99 100644 --- a/source/support.tex +++ b/source/support.tex @@ -578,7 +578,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 313a925e70..cb7dfb882a 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,7 +3805,15 @@ \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}>}% @@ -3830,6 +3851,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 +5021,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 +5074,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}% @@ -5035,6 +5123,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 539b7c79e2365ad445df23096607283e8b726110 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 26 Jun 2025 13:14:05 +0200 Subject: [PATCH 2/4] fixup: indexing --- source/threads.tex | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/source/threads.tex b/source/threads.tex index cb7dfb882a..e3a7f70f0e 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -3817,6 +3817,12 @@ \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; @@ -5090,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; From 2fdfad1bd72b560ceaf175a40c9dd1510f293f18 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 26 Jun 2025 14:47:16 +0200 Subject: [PATCH 3/4] fixup markup --- source/threads.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/threads.tex b/source/threads.tex index e3a7f70f0e..97cadca996 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -5145,7 +5145,7 @@ 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}, +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 From 53ec473bca9ff2b63459703ea38a7a278c32aebf Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Thu, 26 Jun 2025 13:18:12 +0200 Subject: [PATCH 4/4] [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 97cadca996..e25de0d4d9 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;