Skip to content

[libc][math][c23] add c23 floating point fmaximum and fminimum functions. #86016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from Mar 25, 2024
24 changes: 24 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,30 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmin
libc.src.math.fminf
libc.src.math.fminl
libc.src.math.fmaximum
libc.src.math.fmaximumf
libc.src.math.fmaximuml
libc.src.math.fmaximum_num
libc.src.math.fmaximum_numf
libc.src.math.fmaximum_numl
libc.src.math.fmaximum_mag
libc.src.math.fmaximum_magf
libc.src.math.fmaximum_magl
libc.src.math.fmaximum_mag_num
libc.src.math.fmaximum_mag_numf
libc.src.math.fmaximum_mag_numl
libc.src.math.fminimum
libc.src.math.fminimumf
libc.src.math.fminimuml
libc.src.math.fminimum_num
libc.src.math.fminimum_numf
libc.src.math.fminimum_numl
libc.src.math.fminimum_mag
libc.src.math.fminimum_magf
libc.src.math.fminimum_magl
libc.src.math.fminimum_mag_num
libc.src.math.fminimum_mag_numf
libc.src.math.fminimum_mag_numl
libc.src.math.fmod
libc.src.math.fmodf
libc.src.math.fmodl
Expand Down
24 changes: 24 additions & 0 deletions libc/config/linux/arm/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,30 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmin
libc.src.math.fminf
libc.src.math.fminl
libc.src.math.fmaximum
libc.src.math.fmaximumf
libc.src.math.fmaximuml
libc.src.math.fmaximum_num
libc.src.math.fmaximum_numf
libc.src.math.fmaximum_numl
libc.src.math.fmaximum_mag
libc.src.math.fmaximum_magf
libc.src.math.fmaximum_magl
libc.src.math.fmaximum_mag_num
libc.src.math.fmaximum_mag_numf
libc.src.math.fmaximum_mag_numl
libc.src.math.fminimum
libc.src.math.fminimumf
libc.src.math.fminimuml
libc.src.math.fminimum_num
libc.src.math.fminimum_numf
libc.src.math.fminimum_numl
libc.src.math.fminimum_mag
libc.src.math.fminimum_magf
libc.src.math.fminimum_magl
libc.src.math.fminimum_mag_num
libc.src.math.fminimum_mag_numf
libc.src.math.fminimum_mag_numl
libc.src.math.fmod
libc.src.math.fmodf
libc.src.math.frexp
Expand Down
24 changes: 24 additions & 0 deletions libc/config/linux/riscv/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,30 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmax
libc.src.math.fmaxf
libc.src.math.fmaxl
libc.src.math.fmaximum
libc.src.math.fmaximumf
libc.src.math.fmaximuml
libc.src.math.fmaximum_num
libc.src.math.fmaximum_numf
libc.src.math.fmaximum_numl
libc.src.math.fmaximum_mag
libc.src.math.fmaximum_magf
libc.src.math.fmaximum_magl
libc.src.math.fmaximum_mag_num
libc.src.math.fmaximum_mag_numf
libc.src.math.fmaximum_mag_numl
libc.src.math.fminimum
libc.src.math.fminimumf
libc.src.math.fminimuml
libc.src.math.fminimum_num
libc.src.math.fminimum_numf
libc.src.math.fminimum_numl
libc.src.math.fminimum_mag
libc.src.math.fminimum_magf
libc.src.math.fminimum_magl
libc.src.math.fminimum_mag_num
libc.src.math.fminimum_mag_numf
libc.src.math.fminimum_mag_numl
libc.src.math.fmod
libc.src.math.fmodf
libc.src.math.fmodl
Expand Down
24 changes: 24 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,30 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmax
libc.src.math.fmaxf
libc.src.math.fmaxl
libc.src.math.fmaximum
libc.src.math.fmaximumf
libc.src.math.fmaximuml
libc.src.math.fmaximum_num
libc.src.math.fmaximum_numf
libc.src.math.fmaximum_numl
libc.src.math.fmaximum_mag
libc.src.math.fmaximum_magf
libc.src.math.fmaximum_magl
libc.src.math.fmaximum_mag_num
libc.src.math.fmaximum_mag_numf
libc.src.math.fmaximum_mag_numl
libc.src.math.fminimum
libc.src.math.fminimumf
libc.src.math.fminimuml
libc.src.math.fminimum_num
libc.src.math.fminimum_numf
libc.src.math.fminimum_numl
libc.src.math.fminimum_mag
libc.src.math.fminimum_magf
libc.src.math.fminimum_magl
libc.src.math.fminimum_mag_num
libc.src.math.fminimum_mag_numf
libc.src.math.fminimum_mag_numl
libc.src.math.fmod
libc.src.math.fmodf
libc.src.math.fmodl
Expand Down
26 changes: 25 additions & 1 deletion libc/config/windows/entrypoints.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(TARGET_LIBC_ENTRYPOINTS
fset(TARGET_LIBC_ENTRYPOINTS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may have had a typo adding an f here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix this.

# ctype.h entrypoints
libc.src.ctype.isalnum
libc.src.ctype.isalpha
Expand Down Expand Up @@ -153,6 +153,30 @@ set(TARGET_LIBM_ENTRYPOINTS
libc.src.math.fmax
libc.src.math.fmaxf
libc.src.math.fmaxl
libc.src.math.fmaximum
libc.src.math.fmaximumf
libc.src.math.fmaximuml
libc.src.math.fmaximum_num
libc.src.math.fmaximum_numf
libc.src.math.fmaximum_numl
libc.src.math.fmaximum_mag
libc.src.math.fmaximum_magf
libc.src.math.fmaximum_magl
libc.src.math.fmaximum_mag_num
libc.src.math.fmaximum_mag_numf
libc.src.math.fmaximum_mag_numl
libc.src.math.fminimum
libc.src.math.fminimumf
libc.src.math.fminimuml
libc.src.math.fminimum_num
libc.src.math.fminimum_numf
libc.src.math.fminimum_numl
libc.src.math.fminimum_mag
libc.src.math.fminimum_magf
libc.src.math.fminimum_magl
libc.src.math.fminimum_mag_num
libc.src.math.fminimum_mag_numf
libc.src.math.fminimum_mag_numl
libc.src.math.fmod
libc.src.math.fmodf
libc.src.math.fmodl
Expand Down
40 changes: 40 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,46 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"fmaxf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmaxl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fmaxf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fmaximum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaximumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmaximuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fmaximumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fmaximum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaximum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fmaximum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fmaximum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaximum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmaximum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fmaximum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fmaximum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaximum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmaximum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fmaximum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fminimum", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fminimumf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fminimuml", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fminimumf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fminimum_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fminimum_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fmaximum_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fminimum_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fminimum_mag", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fminimum_magf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fminimum_magl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fminimum_magf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fminimum_mag_num", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fminimum_mag_numf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>]>,
FunctionSpec<"fminimum_mag_numl", RetValSpec<LongDoubleType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"fminimum_mag_numf128", RetValSpec<Float128Type>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

FunctionSpec<"fma", RetValSpec<DoubleType>, [ArgSpec<DoubleType>, ArgSpec<DoubleType>, ArgSpec<DoubleType>]>,
FunctionSpec<"fmaf", RetValSpec<FloatType>, [ArgSpec<FloatType>, ArgSpec<FloatType>, ArgSpec<FloatType>]>,
Expand Down
124 changes: 124 additions & 0 deletions libc/src/__support/FPUtil/BasicOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,130 @@ LIBC_INLINE T fmax(T x, T y) {
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fmaximum(T x, T y) {
FPBits<T> bitx(x), bity(y);

if (bitx.is_nan()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You don't need else here, since you always return if the condition is true.

This could be

if(foo)
    return foo;
if(bar)
    return bar;
...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will fix it. thanks

return x;
} else if (bity.is_nan()) {
Copy link
Member

@nickdesaulniers nickdesaulniers Mar 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the form:

if (bitx. ...)
  return ...
if (bity. ...)
  return
if (bitx.sign ...)
  return
return x > y ? x : y;

Here and below. When the body of the if statement returns, there's no need for the else.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok I will fix it. is it ok after I make my changes to do

$ git add
$ git commit --amend
$ git push --force

So I can keep it at two commits?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok for you to keep multiple commits, don't need to --amend.

return y;
} else if (bitx.sign() != bity.sign()) {
// To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and
// y has different signs and both are not NaNs, we return the number
// with positive sign.
return (bitx.is_neg() ? y : x);
} else {
return (x > y ? x : y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fminimum(T x, T y) {
const FPBits<T> bitx(x), bity(y);

if (bitx.is_nan()) {
return x;
} else if (bity.is_nan()) {
return y;
} else if (bitx.sign() != bity.sign()) {
// To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and
// y has different signs and both are not NaNs, we return the number
// with negative sign.
return (bitx.is_neg()) ? x : y;
} else {
return (x < y ? x : y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fmaximum_num(T x, T y) {
FPBits<T> bitx(x), bity(y);

if (bitx.is_nan()) {
return y;
} else if (bity.is_nan()) {
return x;
} else if (bitx.sign() != bity.sign()) {
// To make sure that fmax(+0, -0) == +0 == fmax(-0, +0), whenever x and
// y has different signs and both are not NaNs, we return the number
// with positive sign.
return (bitx.is_neg() ? y : x);
} else {
return (x > y ? x : y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fminimum_num(T x, T y) {
const FPBits<T> bitx(x), bity(y);

if (bitx.is_nan()) {
return y;
} else if (bity.is_nan()) {
return x;
} else if (bitx.sign() != bity.sign()) {
// To make sure that fmin(+0, -0) == -0 == fmin(-0, +0), whenever x and
// y has different signs and both are not NaNs, we return the number
// with negative sign.
return (bitx.is_neg()) ? x : y;
} else {
return (x < y ? x : y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fmaximum_mag(T x, T y) {
FPBits<T> bitx(x), bity(y);

if (abs(x) > abs(y)) {
return x;
} else if (abs(y) > abs(x)) {
return y;
} else {
return fmaximum(x, y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fminimum_mag(T x, T y) {
FPBits<T> bitx(x), bity(y);

if (abs(x) < abs(y)) {
return x;
} else if (abs(y) < abs(x)) {
return y;
} else {
return fminimum(x, y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fmaximum_mag_num(T x, T y) {
FPBits<T> bitx(x), bity(y);

if (abs(x) > abs(y)) {
return x;
} else if (abs(y) > abs(x)) {
return y;
} else {
return fmaximum_num(x, y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fminimum_mag_num(T x, T y) {
FPBits<T> bitx(x), bity(y);

if (abs(x) < abs(y)) {
return x;
} else if (abs(y) < abs(x)) {
return y;
} else {
return fminimum_num(x, y);
}
}

template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
LIBC_INLINE T fdim(T x, T y) {
FPBits<T> bitx(x), bity(y);
Expand Down
40 changes: 40 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,46 @@ add_math_entrypoint_object(fminf)
add_math_entrypoint_object(fminl)
add_math_entrypoint_object(fminf128)

add_math_entrypoint_object(fmaximum)
add_math_entrypoint_object(fmaximumf)
add_math_entrypoint_object(fmaximuml)
add_math_entrypoint_object(fmaximumf128)

add_math_entrypoint_object(fmaximum_num)
add_math_entrypoint_object(fmaximum_numf)
add_math_entrypoint_object(fmaximum_numl)
add_math_entrypoint_object(fmaximum_numf128)

add_math_entrypoint_object(fmaximum_mag)
add_math_entrypoint_object(fmaximum_magf)
add_math_entrypoint_object(fmaximum_magl)
add_math_entrypoint_object(fmaximum_magf128)

add_math_entrypoint_object(fmaximum_mag_num)
add_math_entrypoint_object(fmaximum_mag_numf)
add_math_entrypoint_object(fmaximum_mag_numl)
add_math_entrypoint_object(fmaximum_mag_numf128)

add_math_entrypoint_object(fminimum)
add_math_entrypoint_object(fminimumf)
add_math_entrypoint_object(fminimuml)
add_math_entrypoint_object(fminimumf128)

add_math_entrypoint_object(fminimum_num)
add_math_entrypoint_object(fminimum_numf)
add_math_entrypoint_object(fminimum_numl)
add_math_entrypoint_object(fminimum_numf128)

add_math_entrypoint_object(fminimum_mag)
add_math_entrypoint_object(fminimum_magf)
add_math_entrypoint_object(fminimum_magl)
add_math_entrypoint_object(fminimum_magf128)

add_math_entrypoint_object(fminimum_mag_num)
add_math_entrypoint_object(fminimum_mag_numf)
add_math_entrypoint_object(fminimum_mag_numl)
add_math_entrypoint_object(fminimum_mag_numf128)

add_math_entrypoint_object(fmod)
add_math_entrypoint_object(fmodf)
add_math_entrypoint_object(fmodl)
Expand Down
Loading