Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 02 May 2026 14:56:15 +0000
From:      Robert Clausecker <fuz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Cc:        =?utf-8?Q?Jes=C3=BAs?= =?utf-8?Q?Bl=C3=A1zqu?=ez <jesuscblazquez@gmail.com>
Subject:   git: f62d826a6f5b - main - lib/msun: fmaximum_mag_num family. Tests and man page
Message-ID:  <69f6108f.472a8.610d749f@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by fuz:

URL: https://cgit.FreeBSD.org/src/commit/?id=f62d826a6f5b9022b0cedfe22a698998ad9cb7f4

commit f62d826a6f5b9022b0cedfe22a698998ad9cb7f4
Author:     Jesús Blázquez <jesuscblazquez@gmail.com>
AuthorDate: 2026-04-21 17:17:00 +0000
Commit:     Robert Clausecker <fuz@FreeBSD.org>
CommitDate: 2026-05-02 14:50:13 +0000

    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
---
 lib/msun/Makefile                       |  18 ++++--
 lib/msun/Symbol.map                     |  18 ++++--
 lib/msun/man/fmaximum_mag.3             |   2 +-
 lib/msun/man/fmaximum_mag_num.3         | 109 ++++++++++++++++++++++++++++++++
 lib/msun/src/math.h                     |  18 ++++--
 lib/msun/src/s_fmaximum_mag_num.c       |  88 ++++++++++++++++++++++++++
 lib/msun/src/s_fmaximum_mag_numf.c      |  84 ++++++++++++++++++++++++
 lib/msun/src/s_fmaximum_mag_numl.c      |  77 ++++++++++++++++++++++
 lib/msun/src/s_fminimum_mag_num.c       |  90 ++++++++++++++++++++++++++
 lib/msun/src/s_fminimum_mag_numf.c      |  85 +++++++++++++++++++++++++
 lib/msun/src/s_fminimum_mag_numl.c      |  79 +++++++++++++++++++++++
 lib/msun/tests/fmaximum_fminimum_test.c |  28 +++++++-
 12 files changed, 677 insertions(+), 19 deletions(-)

diff --git a/lib/msun/Makefile b/lib/msun/Makefile
index d61f4e9a1659..a9b07babc0a6 100644
--- a/lib/msun/Makefile
+++ b/lib/msun/Makefile
@@ -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
diff --git a/lib/msun/Symbol.map b/lib/msun/Symbol.map
index 35addfcee3d5..00222c960f80 100644
--- a/lib/msun/Symbol.map
+++ b/lib/msun/Symbol.map
@@ -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;
 };
diff --git a/lib/msun/man/fmaximum_mag.3 b/lib/msun/man/fmaximum_mag.3
index f5e4c39f96ef..004f9d51daa2 100644
--- a/lib/msun/man/fmaximum_mag.3
+++ b/lib/msun/man/fmaximum_mag.3
@@ -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
diff --git a/lib/msun/man/fmaximum_mag_num.3 b/lib/msun/man/fmaximum_mag_num.3
new file mode 100644
index 000000000000..525822bcde27
--- /dev/null
+++ b/lib/msun/man/fmaximum_mag_num.3
@@ -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 ..\"
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
index 853984953a91..9894401160d4 100644
--- a/lib/msun/src/math.h
+++ b/lib/msun/src/math.h
@@ -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);
diff --git a/lib/msun/src/s_fmaximum_mag_num.c b/lib/msun/src/s_fmaximum_mag_num.c
new file mode 100644
index 000000000000..fbb8ffbfc250
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_mag_num.c
@@ -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
diff --git a/lib/msun/src/s_fmaximum_mag_numf.c b/lib/msun/src/s_fmaximum_mag_numf.c
new file mode 100644
index 000000000000..18232ed5aba8
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_mag_numf.c
@@ -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
+
diff --git a/lib/msun/src/s_fmaximum_mag_numl.c b/lib/msun/src/s_fmaximum_mag_numl.c
new file mode 100644
index 000000000000..eceee8059b03
--- /dev/null
+++ b/lib/msun/src/s_fmaximum_mag_numl.c
@@ -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);
+}
diff --git a/lib/msun/src/s_fminimum_mag_num.c b/lib/msun/src/s_fminimum_mag_num.c
new file mode 100644
index 000000000000..b5f62837f1b4
--- /dev/null
+++ b/lib/msun/src/s_fminimum_mag_num.c
@@ -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
+
+
diff --git a/lib/msun/src/s_fminimum_mag_numf.c b/lib/msun/src/s_fminimum_mag_numf.c
new file mode 100644
index 000000000000..b8cb31f2315a
--- /dev/null
+++ b/lib/msun/src/s_fminimum_mag_numf.c
@@ -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
+
+
diff --git a/lib/msun/src/s_fminimum_mag_numl.c b/lib/msun/src/s_fminimum_mag_numl.c
new file mode 100644
index 000000000000..1d001e84b618
--- /dev/null
+++ b/lib/msun/src/s_fminimum_mag_numl.c
@@ -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);
+}
+
+
diff --git a/lib/msun/tests/fmaximum_fminimum_test.c b/lib/msun/tests/fmaximum_fminimum_test.c
index 4c8ec9a5b0e0..0d97c4be8d8c 100644
--- a/lib/msun/tests/fmaximum_fminimum_test.c
+++ b/lib/msun/tests/fmaximum_fminimum_test.c
@@ -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]);
 	}
 }
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f6108f.472a8.610d749f>