diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -28,6 +28,8 @@ libc.src.math.floor libc.src.math.floorf libc.src.math.floorl + libc.src.math.fmin + libc.src.math.fminf libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -163,6 +163,8 @@ "floor", "floorf", "floorl", + "fmin", + "fminf", "frexp", "frexpf", "frexpl", diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -61,6 +61,8 @@ libc.src.math.floor libc.src.math.floorf libc.src.math.floorl + libc.src.math.fmin + libc.src.math.fminf libc.src.math.frexp libc.src.math.frexpf libc.src.math.frexpl diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td --- a/libc/spec/stdc.td +++ b/libc/spec/stdc.td @@ -205,6 +205,9 @@ FunctionSpec<"floorf", RetValSpec, [ArgSpec]>, FunctionSpec<"floorl", RetValSpec, [ArgSpec]>, + FunctionSpec<"fmin", RetValSpec, [ArgSpec]>, + FunctionSpec<"fminf", RetValSpec, [ArgSpec]>, + FunctionSpec<"frexp", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"frexpf", RetValSpec, [ArgSpec, ArgSpec]>, FunctionSpec<"frexpl", RetValSpec, [ArgSpec, ArgSpec]>, diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt --- a/libc/src/math/CMakeLists.txt +++ b/libc/src/math/CMakeLists.txt @@ -413,3 +413,26 @@ COMPILE_OPTIONS -O2 ) +add_entrypoint_object( + fmin + SRCS + fmin.cpp + HDRS + fmin.h + DEPENDS + libc.utils.FPUtil.fputil + COMPILE_OPTIONS + -O2 +) + +add_entrypoint_object( + fminf + SRCS + fminf.cpp + HDRS + fminf.h + DEPENDS + libc.utils.FPUtil.fputil + COMPILE_OPTIONS + -O2 +) diff --git a/libc/src/math/fmin.h b/libc/src/math/fmin.h new file mode 100644 --- /dev/null +++ b/libc/src/math/fmin.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fmin --------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_FMIN_H +#define LLVM_LIBC_SRC_MATH_FMIN_H + +namespace __llvm_libc { + +double fmin(double x, double y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_MATH_FMIN_H diff --git a/libc/src/math/fmin.cpp b/libc/src/math/fmin.cpp new file mode 100644 --- /dev/null +++ b/libc/src/math/fmin.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of fmin function -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/common.h" +#include "utils/FPUtil/ComparisonFunctions.h" + +namespace __llvm_libc { + +double LLVM_LIBC_ENTRYPOINT(fmin)(double x, double y) { + return fputil::fmin(x, y); +} + +} // namespace __llvm_libc diff --git a/libc/src/math/fminf.h b/libc/src/math/fminf.h new file mode 100644 --- /dev/null +++ b/libc/src/math/fminf.h @@ -0,0 +1,18 @@ +//===-- Implementation header for fminf -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_MATH_FMINF_H +#define LLVM_LIBC_SRC_MATH_FMINF_H + +namespace __llvm_libc { + +float fminf(float x, float y); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_MATH_FMINF_H diff --git a/libc/src/math/fminf.cpp b/libc/src/math/fminf.cpp new file mode 100644 --- /dev/null +++ b/libc/src/math/fminf.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of fminf function ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/__support/common.h" +#include "utils/FPUtil/ComparisonFunctions.h" + +namespace __llvm_libc { + +float LLVM_LIBC_ENTRYPOINT(fminf)(float x, float y) { + return fputil::fmin(x, y); +} + +} // namespace __llvm_libc diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt --- a/libc/test/src/math/CMakeLists.txt +++ b/libc/test/src/math/CMakeLists.txt @@ -437,3 +437,27 @@ libc.src.math.modfl libc.utils.FPUtil.fputil ) + +add_math_unittest( + fminf_test + SUITE + libc_math_unittests + SRCS + fminf_test.cpp + DEPENDS + libc.include.math + libc.src.math.fminf + libc.utils.FPUtil.fputil +) + +add_math_unittest( + fmin_test + SUITE + libc_math_unittests + SRCS + fmin_test.cpp + DEPENDS + libc.include.math + libc.src.math.fmin + libc.utils.FPUtil.fputil +) diff --git a/libc/test/src/math/fmin_test.cpp b/libc/test/src/math/fmin_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/math/fmin_test.cpp @@ -0,0 +1,55 @@ +//===-- Unittests for fmin -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#include "include/math.h" +#include "src/math/fmin.h" +#include "utils/FPUtil/BitPatterns.h" +#include "utils/FPUtil/FloatOperations.h" +#include "utils/FPUtil/FloatProperties.h" +#include "utils/UnitTest/Test.h" + +using __llvm_libc::fputil::valueAsBits; +using __llvm_libc::fputil::valueFromBits; + +using BitPatterns = __llvm_libc::fputil::BitPatterns; +using Properties = __llvm_libc::fputil::FloatProperties; +using BitTypes = Properties::BitsType; + +#define SPECIAL_NUMBERS_SIZE 6 + +TEST(FminTest, SpecialNumbers) { + BitTypes orderedValues[SPECIAL_NUMBERS_SIZE] = { + BitPatterns::negInf, + Properties::signMask | BitTypes{12345}, + BitPatterns::negZero, + BitPatterns::zero, + BitTypes{12345}, + BitPatterns::inf + }; + + for (int i = 0; i < SPECIAL_NUMBERS_SIZE; ++i) { + for (int j = 0; j < SPECIAL_NUMBERS_SIZE; ++j) { + EXPECT_EQ( + orderedValues[(i < j ? i : j)], + valueAsBits(__llvm_libc::fmin(valueFromBits(orderedValues[i]), + valueFromBits(orderedValues[j]))) + ); + } + } + + EXPECT_EQ( + BitPatterns::inf, + valueAsBits(__llvm_libc::fmin(valueFromBits(BitPatterns::aQuietNaN), + valueFromBits(BitPatterns::inf)))); + + EXPECT_EQ( + BitPatterns::aSignallingNaN, + valueAsBits(__llvm_libc::fmin(valueFromBits(BitPatterns::aQuietNaN), + valueFromBits(BitPatterns::aSignallingNaN)))); + +} diff --git a/libc/test/src/math/fminf_test.cpp b/libc/test/src/math/fminf_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/math/fminf_test.cpp @@ -0,0 +1,56 @@ +//===-- Unittests for fminf -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "include/math.h" +#include "src/math/fminf.h" +#include "utils/FPUtil/BitPatterns.h" +#include "utils/FPUtil/FloatOperations.h" +#include "utils/FPUtil/FloatProperties.h" +#include "utils/UnitTest/Test.h" + +using __llvm_libc::fputil::valueAsBits; +using __llvm_libc::fputil::valueFromBits; + +using BitPatterns = __llvm_libc::fputil::BitPatterns; +using Properties = __llvm_libc::fputil::FloatProperties; +using BitTypes = Properties::BitsType; + +#define SPECIAL_NUMBERS_SIZE 6 + +TEST(FminfTest, SpecialNumbers) { + + BitTypes orderedValues[SPECIAL_NUMBERS_SIZE] = { + BitPatterns::negInf, + Properties::signMask | BitTypes{123456789}, + BitPatterns::negZero, + BitPatterns::zero, + BitTypes{123456789}, + BitPatterns::inf + }; + + for (int i = 0; i < SPECIAL_NUMBERS_SIZE; ++i) { + for (int j = 0; j < SPECIAL_NUMBERS_SIZE; ++j) { + EXPECT_EQ( + orderedValues[(i < j ? i : j)], + valueAsBits(__llvm_libc::fminf(valueFromBits(orderedValues[i]), + valueFromBits(orderedValues[j]))) + ); + } + } + + EXPECT_EQ( + BitPatterns::inf, + valueAsBits(__llvm_libc::fminf(valueFromBits(BitPatterns::aQuietNaN), + valueFromBits(BitPatterns::inf)))); + + EXPECT_EQ( + BitPatterns::aSignallingNaN, + valueAsBits(__llvm_libc::fminf(valueFromBits(BitPatterns::aQuietNaN), + valueFromBits(BitPatterns::aSignallingNaN)))); + +} diff --git a/libc/utils/FPUtil/CMakeLists.txt b/libc/utils/FPUtil/CMakeLists.txt --- a/libc/utils/FPUtil/CMakeLists.txt +++ b/libc/utils/FPUtil/CMakeLists.txt @@ -12,6 +12,7 @@ FloatOperations.h FloatProperties.h FPBits.h + ComparisonFunctions.h ManipulationFunctions.h DEPENDS libc.utils.CPP.standalone_cpp diff --git a/libc/utils/FPUtil/ComparisonFunctions.h b/libc/utils/FPUtil/ComparisonFunctions.h new file mode 100644 --- /dev/null +++ b/libc/utils/FPUtil/ComparisonFunctions.h @@ -0,0 +1,42 @@ +//===-- Floating-point manipulation functions -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "FPBits.h" +#include "FloatProperties.h" +#include "FloatOperations.h" + +#include "utils/CPP/TypeTraits.h" + +#ifndef LLVM_LIBC_UTILS_FPUTIL_COMPARISON_FUNCTIONS_H +#define LLVM_LIBC_UTILS_FPUTIL_COMPARISON_FUNCTIONS_H + +namespace __llvm_libc { +namespace fputil { + +template ::Value, int> = 0> +static inline T fmin(T x, T y) { + FPBits bit_x(x), bit_y(y); + + if (bit_x.isNaN()) { + return y; + } else if (bit_y.isNaN()) { + return x; + } else if (bit_x.sign != bit_y.sign) { + return (bit_x.sign ? x : y); + } else if (absBits(x) < absBits(y)) { + return bit_x.sign ? y : x; + } else { + return bit_x.sign ? x : y; + } +} + +} // namespace fputil +} // namespace __llvm_libc + +#endif // LLVM_LIBC_UTILS_FPUTIL_COMPARISON_FUNCTIONS_H