lib/msun: fmaximum_mag_num family. Tests and man page

Added the fmaximum_mag_num{,f,l} and fminimum_mag_num{,f,l} functions.

PR:		294719
Reviewed by:	fuz, kargl
MFC after:	1 month
This commit is contained in:
Jesús Blázquez
2026-04-21 17:17:00 +00:00
committed by Robert Clausecker
parent f9590540c5
commit f62d826a6f
12 changed files with 677 additions and 19 deletions
+13 -5
View File
@@ -76,9 +76,11 @@ COMMON_SRCS= b_tgamma.c \
s_finite.c s_finitef.c \
s_floor.c s_floorf.c s_fma.c s_fmaf.c \
s_fmax.c s_fmaxf.c s_fmaximum.c s_fmaximumf.c \
s_fmaximum_mag.c s_fmaximum_magf.c s_fmaximum_num.c s_fmaximum_numf.c \
s_fmaximum_mag.c s_fmaximum_magf.c s_fmaximum_mag_num.c \
s_fmaximum_mag_numf.c s_fmaximum_num.c s_fmaximum_numf.c \
s_fmin.c s_fminf.c s_fminimum.c s_fminimumf.c \
s_fminimum_mag.c s_fminimum_magf.c s_fminimum_num.c s_fminimum_numf.c \
s_fminimum_mag.c s_fminimum_magf.c s_fminimum_mag_num.c \
s_fminimum_mag_numf.c s_fminimum_num.c s_fminimum_numf.c \
s_frexp.c s_frexpf.c s_ilogb.c s_ilogbf.c \
s_ilogbl.c s_isfinite.c s_isnan.c s_isnormal.c \
s_llrint.c s_llrintf.c s_llround.c s_llroundf.c s_llroundl.c \
@@ -135,8 +137,10 @@ COMMON_SRCS+= b_tgammal.c catrigl.c \
s_asinhl.c s_atanl.c s_cbrtl.c s_ceill.c s_cexpl.c \
s_clogl.c s_cosl.c s_cospil.c s_cprojl.c \
s_csqrtl.c s_erfl.c s_exp2l.c s_expl.c s_floorl.c s_fmal.c \
s_fmaxl.c s_fmaximuml.c s_fmaximum_magl.c s_fmaximum_numl.c \
s_fminl.c s_fminimuml.c s_fminimum_magl.c s_fminimum_numl.c \
s_fmaxl.c s_fmaximuml.c s_fmaximum_magl.c \
s_fmaximum_numl.c s_fmaximum_mag_numl.c \
s_fminl.c s_fminimuml.c s_fminimum_magl.c \
s_fminimum_numl.c s_fminimum_mag_numl.c \
s_frexpl.c s_logbl.c s_logl.c s_nanl.c \
s_nextafterl.c s_nexttoward.c s_remquol.c s_rintl.c s_roundl.c \
s_scalbnl.c s_sinl.c s_sincosl.c s_sinpil.c \
@@ -182,7 +186,8 @@ MAN= acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 \
exp.3 fabs.3 fdim.3 \
feclearexcept.3 feenableexcept.3 fegetenv.3 \
fegetround.3 fenv.3 floor.3 fma.3 \
fmax.3 fmaximum.3 fmaximum_mag.3 fmaximum_num.3 fmod.3 \
fmax.3 fmaximum.3 fmaximum_mag.3 \
fmaximum_mag_num.3 fmaximum_num.3 fmod.3 \
hypot.3 ieee.3 ieee_test.3 ilogb.3 j0.3 \
lgamma.3 log.3 lrint.3 lround.3 math.3 nan.3 \
nextafter.3 remainder.3 rint.3 \
@@ -242,6 +247,9 @@ MLINKS+=fmaximum.3 fmaximumf.3 fmaximum.3 fmaximuml.3 \
MLINKS+=fmaximum_mag.3 fmaximum_magf.3 fmaximum_mag.3 fmaximum_magl.3 \
fmaximum_mag.3 fminimum_mag.3 fmaximum_mag.3 fminimum_magf.3 \
fmaximum_mag.3 fminimum_magl.3
MLINKS+=fmaximum_mag_num.3 fmaximum_mag_numf.3 fmaximum_mag_num.3 fmaximum_mag_numl.3 \
fmaximum_mag_num.3 fminimum_mag_num.3 fmaximum_mag_num.3 fminimum_mag_numf.3 \
fmaximum_mag_num.3 fminimum_mag_numl.3
MLINKS+=fmaximum_num.3 fmaximum_numf.3 fmaximum_num.3 fmaximum_numl.3 \
fmaximum_num.3 fminimum_num.3 fmaximum_num.3 fminimum_numf.3 \
fmaximum_num.3 fminimum_numl.3
+12 -6
View File
@@ -323,19 +323,25 @@ FBSD_1.9 {
fmaximum;
fmaximumf;
fmaximuml;
fminimum;
fminimumf;
fminimuml;
fmaximum_mag;
fmaximum_magf;
fmaximum_magl;
fminimum_mag;
fminimum_magf;
fminimum_magl;
fmaximum_mag_num;
fmaximum_mag_numf;
fmaximum_mag_numl;
fmaximum_num;
fmaximum_numf;
fmaximum_numl;
fminimum;
fminimumf;
fminimuml;
fminimum_mag;
fminimum_magf;
fminimum_magl;
fminimum_num;
fminimum_numf;
fminimum_numl;
fminimum_mag_num;
fminimum_mag_numf;
fminimum_mag_numl;
};
+1 -1
View File
@@ -84,7 +84,7 @@ These routines do not raise any floating-point exceptions.
.Sh SEE ALSO
.Xr fmax 3 ,
.Xr fmaximum 3 ,
.Xr fmaximum_num 3 ,
.Xr fmaximum_mag_num 3 ,
.Xr math 3
.Sh STANDARDS
The
+109
View File
@@ -0,0 +1,109 @@
.\" Copyright (c) 2004 David Schultz <das@FreeBSD.org>
.\" Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.Dd April 3, 2026
.Dt FMAXIMUM_MAG_NUM 3
.Os
.Sh NAME
.Nm fmaximum_mag_num ,
.Nm fmaximum_mag_numf ,
.Nm fmaximum_mag_numl ,
.Nm fminimum_mag_num ,
.Nm fminimum_mag_numf ,
.Nm fminimum_mag_numl
.Nd floating-point maximum and minimum magnitude number functions
.Sh LIBRARY
.Lb libm
.Sh SYNOPSIS
.In math.h
.Ft double
.Fn fmaximum_mag_num "double x" "double y"
.Ft float
.Fn fmaximum_mag_numf "float x" "float y"
.Ft "long double"
.Fn fmaximum_mag_numl "long double x" "long double y"
.Ft double
.Fn fminimum_mag_num "double x" "double y"
.Ft float
.Fn fminimum_mag_numf "float x" "float y"
.Ft "long double"
.Fn fminimum_mag_numl "long double x" "long double y"
.Sh DESCRIPTION
The
.Fn fmaximum_mag_num ,
.Fn fmaximum_mag_numf ,
and
.Fn fmaximum_mag_numl
functions determine the larger of the absolute values of
.Fa x
and
.Fa y ,
and return the argument with the larger absolute value,
preferring a numeric value over an \*(Na.
If one argument is a numeric value and the other is an \*(Na,
the numeric value is returned.
If the absolute values are equal, the behavior is equivalent to calling the corresponding
.Fn fmaximum_num
function on the arguments.
.Pp
Likewise, the
.Fn fminimum_mag_num ,
.Fn fminimum_mag_numf ,
and
.Fn fminimum_mag_numl
functions determine the smaller of the absolute values of
.Fa x
and
.Fa y ,
and return the argument with the smaller absolute value,
preferring a numeric value over an \*(Na.
If one argument is a numeric value and the other is an \*(Na,
the numeric value is returned.
If the absolute values are equal, the behavior is equivalent to calling the corresponding
.Fn fminimum_num
function on the arguments.
.Pp
If both arguments are \*(Nas, a quiet \*(Na is returned.
If either argument is a signaling \*(Na, an invalid exception is raised.
Otherwise, these routines do not raise any floating-point exceptions.
.Sh SEE ALSO
.Xr fmax 3 ,
.Xr fmaximum 3 ,
.Xr fmaximum_mag 3 ,
.Xr fmaximum_num 3 ,
.Xr math 3
.Sh STANDARDS
The
.Fn fmaximum_mag_num ,
.Fn fmaximum_mag_numf ,
.Fn fmaximum_mag_numl ,
.Fn fminimum_mag_num ,
.Fn fminimum_mag_numf ,
and
.Fn fminimum_mag_numl
functions conform to
.St -isoC-2023 .
.Sh HISTORY
These routines first appeared in
.Fx 16.0 ..\"
+12 -6
View File
@@ -523,18 +523,24 @@ long double tanpil(long double);
double fmaximum(double, double);
float fmaximumf(float, float);
long double fmaximuml(long double, long double);
double fminimum(double, double);
float fminimumf(float, float);
long double fminimuml(long double, long double);
double fmaximum_mag(double, double);
float fmaximum_magf(float, float);
long double fmaximum_magl(long double, long double);
double fminimum_mag(double, double);
float fminimum_magf(float, float);
long double fminimum_magl(long double, long double);
double fmaximum_mag_num(double, double);
float fmaximum_mag_numf(float, float);
long double fmaximum_mag_numl(long double, long double);
double fmaximum_num(double, double);
float fmaximum_numf(float, float);
long double fmaximum_numl(long double, long double);
double fminimum(double, double);
float fminimumf(float, float);
long double fminimuml(long double, long double);
double fminimum_mag(double, double);
float fminimum_magf(float, float);
long double fminimum_magl(long double, long double);
double fminimum_mag_num(double, double);
float fminimum_mag_numf(float, float);
long double fminimum_mag_numl(long double, long double);
double fminimum_num(double, double);
float fminimum_numf(float, float);
long double fminimum_numl(long double, long double);
+88
View File
@@ -0,0 +1,88 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include "fpmath.h"
#ifdef USE_BUILTIN_FMAXIMUM_MAG_NUM
double
fmaximum_mag_num(double x, double y)
{
return (__builtin_fmaximum_mag_num(x, y));
}
#else
double
fmaximum_mag_num(double x, double y)
{
union IEEEd2bits u[2];
bool nan_x, nan_y;
u[0].d = x;
u[1].d = y;
nan_x = isnan(x);
nan_y = isnan(y);
if (nan_x || nan_y) {
/* If both are NaN, adding returns qNaN */
if (nan_x && nan_y)
return (x + y);
/* force_except makes sure sNaN's raise exceptions */
volatile double force_except = x + y;
force_except;
if (nan_x)
return (y);
else
return (x);
}
double ax = fabs(x);
double ay = fabs(y);
if (ay > ax)
return (y);
if (ax > ay)
return (x);
/* If magnitudes are equal, we break the tie with the sign */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[0].bits.sign].d);
return (x);
}
#endif
#if (LDBL_MANT_DIG == 53)
__weak_reference(fmaximum_mag_num, fmaximum_mag_numl);
#endif
+84
View File
@@ -0,0 +1,84 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <math.h>
#include <stdbool.h>
#include "fpmath.h"
#ifdef USE_BUILTIN_FMAXIMUM_MAG_NUMF
float
fmaximum_mag_numf(float x, float y)
{
return (__builtin_fmaximum_mag_numf(x, y));
}
#else
float
fmaximum_mag_numf(float x, float y)
{
union IEEEf2bits u[2];
bool nan_x, nan_y;
u[0].f = x;
u[1].f = y;
nan_x = isnan(x);
nan_y = isnan(y);
if (nan_x || nan_y) {
/* If both are NaN, adding returns qNaN */
if (nan_x && nan_y)
return (x + y);
/* force_except makes sure sNaN's raise exceptions */
volatile float force_except = x + y;
force_except;
if (nan_x)
return (y);
else
return (x);
}
float ax = fabsf(x);
float ay = fabsf(y);
if (ay > ax)
return (y);
if (ax > ay)
return (x);
/* If magnitudes are equal, we break the tie with the sign */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[0].bits.sign].f);
return (x);
}
#endif
+77
View File
@@ -0,0 +1,77 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <math.h>
#include <stdbool.h>
#include "fpmath.h"
long double
fmaximum_mag_numl(long double x, long double y)
{
union IEEEl2bits u[2];
bool nan_x, nan_y;
u[0].e = x;
mask_nbit_l(u[0]);
u[1].e = y;
mask_nbit_l(u[1]);
nan_x = isnan(x);
nan_y = isnan(y);
if (nan_x || nan_y) {
/* If both are NaN, adding returns qNaN */
if (nan_x && nan_y)
return (x + y);
/* force_except makes sure sNaN's raise exceptions */
volatile long double force_except = x + y;
force_except;
if (nan_x)
return (y);
else
return (x);
}
long double ax = fabsl(x);
long double ay = fabsl(y);
if (ay > ax)
return (y);
if (ax > ay)
return (x);
/* If magnitudes are equal, we break the tie with the sign */
if (u[0].bits.sign != u[1].bits.sign)
return (u[0].bits.sign ? y : x);
return (x);
}
+90
View File
@@ -0,0 +1,90 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <float.h>
#include <math.h>
#include <stdbool.h>
#include "fpmath.h"
#ifdef USE_BUILTIN_FMINIMUM_MAG_NUM
double
fminimum_mag_num(double x, double y)
{
return (__builtin_fminimum_mag_num(x, y));
}
#else
double
fminimum_mag_num(double x, double y)
{
union IEEEd2bits u[2];
bool nan_x, nan_y;
u[0].d = x;
u[1].d = y;
nan_x = isnan(x);
nan_y = isnan(y);
if (nan_x || nan_y) {
/* If both are NaN, adding returns qNaN */
if (nan_x && nan_y)
return (x + y);
/* force_except makes sure sNaN's raise exceptions */
volatile double force_except = x + y;
force_except;
if (nan_x)
return (y);
else
return (x);
}
double ax = fabs(x);
double ay = fabs(y);
if (ay < ax)
return (y);
if (ax < ay)
return (x);
/* If magnitudes are equal, we break the tie with the sign */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[1].bits.sign].d);
return (x);
}
#endif
#if (LDBL_MANT_DIG == 53)
__weak_reference(fminimum_mag_num, fminimum_mag_numl);
#endif
+85
View File
@@ -0,0 +1,85 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <math.h>
#include <stdbool.h>
#include "fpmath.h"
#ifdef USE_BUILTIN_FMINIMUM_MAG_NUMF
float
fminimum_mag_numf(float x, float y)
{
return (__builtin_fminimum_mag_numf(x, y));
}
#else
float
fminimum_mag_numf(float x, float y)
{
union IEEEf2bits u[2];
bool nan_x, nan_y;
u[0].f = x;
u[1].f = y;
nan_x = isnan(x);
nan_y = isnan(y);
if (nan_x || nan_y) {
/* If both are NaN, adding returns qNaN */
if (nan_x && nan_y)
return (x + y);
/* force_except makes sure sNaN's raise exceptions */
volatile float force_except = x + y;
force_except;
if (nan_x)
return (y);
else
return (x);
}
float ax = fabsf(x);
float ay = fabsf(y);
if (ay < ax)
return (y);
if (ax < ay)
return (x);
/* If magnitudes are equal, we break the tie with the sign */
if (u[0].bits.sign != u[1].bits.sign)
return (u[u[1].bits.sign].f);
return (x);
}
#endif
+79
View File
@@ -0,0 +1,79 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
* Copyright (c) 2026 Jesús Blázquez <jesuscblazquez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <math.h>
#include <stdbool.h>
#include "fpmath.h"
long double
fminimum_mag_numl(long double x, long double y)
{
union IEEEl2bits u[2];
bool nan_x, nan_y;
u[0].e = x;
mask_nbit_l(u[0]);
u[1].e = y;
mask_nbit_l(u[1]);
nan_x = isnan(x);
nan_y = isnan(y);
if (nan_x || nan_y) {
/* If both are NaN, adding returns qNaN */
if (nan_x && nan_y)
return (x + y);
/* force_except makes sure sNaN's raise exceptions */
volatile long double force_except = x + y;
force_except;
if (nan_x)
return (y);
else
return (x);
}
long double ax = fabsl(x);
long double ay = fabsl(y);
if (ay < ax)
return (y);
if (ax < ay)
return (x);
/* If magnitudes are equal, we break the tie with the sign */
if (u[0].bits.sign != u[1].bits.sign)
return (u[1].bits.sign ? y : x);
return (x);
}
+27 -1
View File
@@ -27,7 +27,8 @@
/*
* Tests for fmaximum{,f,l}(), fminimum{,f,l}(), fmaximum_mag{,f,l},
* fminimum_mag{,f,l}, fmaximum_num{,f,l}, fminimum_num{,f,l}
* fminimum_mag{,f,l}, fmaximum_num{,f,l}, fminimum_num{,f,l},
* fmaximum_mag_num{,f,l} and fminimum_mag_num{,f,l}
*/
#include <sys/cdefs.h>
@@ -130,6 +131,30 @@ testall_num_r(long double big, long double small, int rmode) {
TEST(fminimum_numl, long double, small, big, expected_min_num, rmode);
}
static void
testall_mag_num_r(long double big, long double small, int rmode) {
long double expected_max_mag_num = isnan(big) ? small : big;
long double expected_min_mag_num = isnan(small) ? big : small;
if (fabsl(small) > fabsl(big)) {
expected_max_mag_num = small;
expected_min_mag_num = big;
}
TEST(fmaximum_mag_numf, float, big, small, expected_max_mag_num, rmode);
TEST(fmaximum_mag_numf, float, small, big, expected_max_mag_num, rmode);
TEST(fmaximum_mag_num, double, big, small, expected_max_mag_num, rmode);
TEST(fmaximum_mag_num, double, small, big, expected_max_mag_num, rmode);
TEST(fmaximum_mag_numl, long double, big, small, expected_max_mag_num, rmode);
TEST(fmaximum_mag_numl, long double, small, big, expected_max_mag_num, rmode);
TEST(fminimum_mag_numf, float, big, small, expected_min_mag_num, rmode);
TEST(fminimum_mag_numf, float, small, big, expected_min_mag_num, rmode);
TEST(fminimum_mag_num, double, big, small, expected_min_mag_num, rmode);
TEST(fminimum_mag_num, double, small, big, expected_min_mag_num, rmode);
TEST(fminimum_mag_numl, long double, big, small, expected_min_mag_num, rmode);
TEST(fminimum_mag_numl, long double, small, big, expected_min_mag_num, rmode);
}
/*
* Test all the functions: fmaximumf, fmaximum, fmaximuml, fminimumf, fminimum, fminimuml
* in all rounding modes and with the arguments in different orders.
@@ -148,6 +173,7 @@ testall(long double big, long double small)
testall_r(big, small, rmodes[i]);
testall_mag_r(big, small, rmodes[i]);
testall_num_r(big, small, rmodes[i]);
testall_mag_num_r(big, small, rmodes[i]);
}
}