From 90f0ac10a74b2d43b5a65aab4be40565e359be43 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 28 Sep 2021 23:31:35 +0000 Subject: Add fmaximum, fminimum functions C2X adds new functions for floating-point maximum and minimum, corresponding to the new operations that were added in IEEE 754-2019 because of concerns about the old operations not being associative in the presence of signaling NaNs. fmaximum and fminimum handle NaNs like most functions (any NaN argument means the result is a quiet NaN). fmaximum_num and fminimum_num handle both quiet and signaling NaNs the way fmax and fmin handle quiet NaNs (if one argument is a number and the other is a NaN, return the number), but still raise "invalid" for a signaling NaN argument, making them exceptions to the normal rule that a function with a floating-point result raising "invalid" also returns a quiet NaN. fmaximum_mag, fminimum_mag, fmaximum_mag_num and fminimum_mag_num are corresponding functions returning the argument with greatest or least absolute value. All these functions also treat +0 as greater than -0. There are also corresponding type-generic macros. Add these functions to glibc. The implementations use type-generic templates based on those for fmax, fmin, fmaxmag and fminmag, and test inputs are based on those for those functions with appropriate adjustments to the expected results. The RISC-V maintainers might wish to add optimized versions of fmaximum_num and fminimum_num (for float and double), since RISC-V (F extension version 2.2 and later) provides instructions corresponding to those functions - though it might be at least as useful to add architecture-independent built-in functions to GCC and teach the RISC-V back end to expand those functions inline, which is what you generally want for functions that can be implemented with a single instruction. Tested for x86_64 and x86, and with build-many-glibcs.py. --- manual/arith.texi | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 106 insertions(+), 4 deletions(-) (limited to 'manual/arith.texi') diff --git a/manual/arith.texi b/manual/arith.texi index 6a158e6..edb9cfd 100644 --- a/manual/arith.texi +++ b/manual/arith.texi @@ -2097,8 +2097,8 @@ and @var{y}. It is similar to the expression @end smallexample except that @var{x} and @var{y} are only evaluated once. -If an argument is NaN, the other argument is returned. If both arguments -are NaN, NaN is returned. +If an argument is a quiet NaN, the other argument is returned. If both arguments +are NaN, or either is a signaling NaN, NaN is returned. @end deftypefun @deftypefun double fmax (double @var{x}, double @var{y}) @@ -2113,8 +2113,58 @@ are NaN, NaN is returned. The @code{fmax} function returns the greater of the two values @var{x} and @var{y}. -If an argument is NaN, the other argument is returned. If both arguments -are NaN, NaN is returned. +If an argument is a quiet NaN, the other argument is returned. If both arguments +are NaN, or either is a signaling NaN, NaN is returned. +@end deftypefun + +@deftypefun double fminimum (double @var{x}, double @var{y}) +@deftypefunx float fminimumf (float @var{x}, float @var{y}) +@deftypefunx {long double} fminimuml (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fminimumfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fminimumfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +The @code{fminimum} function returns the lesser of the two values @var{x} +and @var{y}. Unlike @code{fmin}, if either argument is a NaN, NaN is returned. +Positive zero is treated as greater than negative zero. +@end deftypefun + +@deftypefun double fmaximum (double @var{x}, double @var{y}) +@deftypefunx float fmaximumf (float @var{x}, float @var{y}) +@deftypefunx {long double} fmaximuml (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fmaximumfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fmaximumfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +The @code{fmaximum} function returns the greater of the two values @var{x} +and @var{y}. Unlike @code{fmax}, if either argument is a NaN, NaN is returned. +Positive zero is treated as greater than negative zero. +@end deftypefun + +@deftypefun double fminimum_num (double @var{x}, double @var{y}) +@deftypefunx float fminimum_numf (float @var{x}, float @var{y}) +@deftypefunx {long double} fminimum_numl (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fminimum_numfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fminimum_numfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +The @code{fminimum_num} function returns the lesser of the two values +@var{x} and @var{y}. If one argument is a number and the other is a +NaN, even a signaling NaN, the number is returned. Positive zero is +treated as greater than negative zero. +@end deftypefun + +@deftypefun double fmaximum_num (double @var{x}, double @var{y}) +@deftypefunx float fmaximum_numf (float @var{x}, float @var{y}) +@deftypefunx {long double} fmaximum_numl (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fmaximum_numfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fmaximum_numfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +The @code{fmaximum_num} function returns the greater of the two values +@var{x} and @var{y}. If one argument is a number and the other is a +NaN, even a signaling NaN, the number is returned. Positive zero is +treated as greater than negative zero. @end deftypefun @deftypefun double fminmag (double @var{x}, double @var{y}) @@ -2147,6 +2197,58 @@ have the same absolute value, or either is NaN, they behave the same as the @code{fmax} functions. @end deftypefun +@deftypefun double fminimum_mag (double @var{x}, double @var{y}) +@deftypefunx float fminimum_magf (float @var{x}, float @var{y}) +@deftypefunx {long double} fminimum_magl (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fminimum_magfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fminimum_magfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +These functions return whichever of the two values @var{x} and @var{y} +has the smaller absolute value. If both have the same absolute value, +or either is NaN, they behave the same as the @code{fminimum} +functions. +@end deftypefun + +@deftypefun double fmaximum_mag (double @var{x}, double @var{y}) +@deftypefunx float fmaximum_magf (float @var{x}, float @var{y}) +@deftypefunx {long double} fmaximum_magl (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fmaximum_magfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fmaximum_magfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +These functions return whichever of the two values @var{x} and @var{y} +has the greater absolute value. If both have the same absolute value, +or either is NaN, they behave the same as the @code{fmaximum} +functions. +@end deftypefun + +@deftypefun double fminimum_mag_num (double @var{x}, double @var{y}) +@deftypefunx float fminimum_mag_numf (float @var{x}, float @var{y}) +@deftypefunx {long double} fminimum_mag_numl (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fminimum_mag_numfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fminimum_mag_numfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +These functions return whichever of the two values @var{x} and @var{y} +has the smaller absolute value. If both have the same absolute value, +or either is NaN, they behave the same as the @code{fminimum_num} +functions. +@end deftypefun + +@deftypefun double fmaximum_mag_num (double @var{x}, double @var{y}) +@deftypefunx float fmaximum_mag_numf (float @var{x}, float @var{y}) +@deftypefunx {long double} fmaximum_mag_numl (long double @var{x}, long double @var{y}) +@deftypefunx _FloatN fmaximum_mag_numfN (_Float@var{N} @var{x}, _Float@var{N} @var{y}) +@deftypefunx _FloatNx fmaximum_mag_numfNx (_Float@var{N}x @var{x}, _Float@var{N}x @var{y}) +@standards{C2X, math.h} +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +These functions return whichever of the two values @var{x} and @var{y} +has the greater absolute value. If both have the same absolute value, +or either is NaN, they behave the same as the @code{fmaximum_num} +functions. +@end deftypefun + @deftypefun double fdim (double @var{x}, double @var{y}) @deftypefunx float fdimf (float @var{x}, float @var{y}) @deftypefunx {long double} fdiml (long double @var{x}, long double @var{y}) -- cgit v1.1