21 changes: 21 additions & 0 deletions libc/src/math/f16mulf128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for f16mulf128 --------------------*- 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_F16MULF128_H
#define LLVM_LIBC_SRC_MATH_F16MULF128_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 f16mulf128(float128 x, float128 y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_F16MULF128_H
21 changes: 21 additions & 0 deletions libc/src/math/f16mull.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for f16mull -----------------------*- 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_F16MULL_H
#define LLVM_LIBC_SRC_MATH_F16MULL_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float16 f16mull(long double x, long double y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_F16MULL_H
21 changes: 21 additions & 0 deletions libc/src/math/fmulf128.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation header for fmulf128 ----------------------*- 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_FMULF128_H
#define LLVM_LIBC_SRC_MATH_FMULF128_H

#include "src/__support/macros/config.h"
#include "src/__support/macros/properties/types.h"

namespace LIBC_NAMESPACE_DECL {

float fmulf128(float128 x, float128 y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_FMULF128_H
20 changes: 20 additions & 0 deletions libc/src/math/fmull.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for fmull -------------------------*- 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_FMULL_H
#define LLVM_LIBC_SRC_MATH_FMULL_H

#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

float fmull(long double x, long double y);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_MATH_FMULL_H
108 changes: 103 additions & 5 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2633,11 +2633,32 @@ add_entrypoint_object(
HDRS
../fmul.h
DEPENDS
libc.src.__support.FPUtil.basic_operations
libc.src.__support.uint128
libc.src.__support.CPP.bit
libc.src.__support.FPUtil.fp_bits
libc.src.__support.FPUtil.rounding_mode
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
fmull
SRCS
fmull.cpp
HDRS
../fmull.h
DEPENDS
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
fmulf128
SRCS
fmulf128.cpp
HDRS
../fmulf128.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)
Expand Down Expand Up @@ -4200,3 +4221,80 @@ add_entrypoint_object(
libc.src.__support.macros.optimization
libc.src.__support.integer_literals
)

add_entrypoint_object(
dmull
SRCS
dmull.cpp
HDRS
../dmull.h
DEPENDS
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
dmulf128
SRCS
dmulf128.cpp
HDRS
../dmulf128.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
f16mul
SRCS
f16mul.cpp
HDRS
../f16mul.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
f16mulf
SRCS
f16mulf.cpp
HDRS
../f16mulf.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
f16mull
SRCS
f16mull.cpp
HDRS
../f16mull.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
f16mulf128
SRCS
f16mulf128.cpp
HDRS
../f16mulf128.h
DEPENDS
libc.src.__support.macros.properties.types
libc.src.__support.FPUtil.generic.mul
COMPILE_OPTIONS
-O3
)
20 changes: 20 additions & 0 deletions libc/src/math/generic/dmulf128.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of dmulf128 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/math/dmulf128.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(double, dmulf128, (float128 x, float128 y)) {
return fputil::generic::mul<double>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/dmull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of dmull 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/math/dmull.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(double, dmull, (long double x, long double y)) {
return fputil::generic::mul<double>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/f16mul.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of f16mul 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/math/f16mul.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float16, f16mul, (double x, double y)) {
return fputil::generic::mul<float16>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/f16mulf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of f16mulf 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/math/f16mulf.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float16, f16mulf, (float x, float y)) {
return fputil::generic::mul<float16>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/f16mulf128.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of f16mulf128 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/math/f16mulf128.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float16, f16mulf128, (float128 x, float128 y)) {
return fputil::generic::mul<float16>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/f16mull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of f16mull 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/math/f16mull.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float16, f16mull, (long double x, long double y)) {
return fputil::generic::mul<float16>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
115 changes: 3 additions & 112 deletions libc/src/math/generic/fmul.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//===-- Implementation of fmul function------------------------------------===//
//===-- Implementation of fmul function -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
Expand All @@ -7,123 +7,14 @@
//===----------------------------------------------------------------------===//

#include "src/math/fmul.h"
#include "src/__support/CPP/bit.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/FPUtil/FPBits.h"
#include "src/__support/FPUtil/rounding_mode.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"
#include "src/__support/uint128.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float, fmul, (double x, double y)) {
auto x_bits = fputil::FPBits<double>(x);

auto y_bits = fputil::FPBits<double>(y);

auto output_sign = (x_bits.sign() != y_bits.sign()) ? Sign::NEG : Sign::POS;

if (LIBC_UNLIKELY(x_bits.is_inf_or_nan() || y_bits.is_inf_or_nan() ||
x_bits.is_zero() || y_bits.is_zero())) {
if (x_bits.is_nan())
return static_cast<float>(x);
if (y_bits.is_nan())
return static_cast<float>(y);
if (x_bits.is_inf())
return y_bits.is_zero()
? fputil::FPBits<float>::quiet_nan().get_val()
: fputil::FPBits<float>::inf(output_sign).get_val();
if (y_bits.is_inf())
return x_bits.is_zero()
? fputil::FPBits<float>::quiet_nan().get_val()
: fputil::FPBits<float>::inf(output_sign).get_val();
// Now either x or y is zero, and the other one is finite.
return fputil::FPBits<float>::zero(output_sign).get_val();
}

uint64_t mx, my;

// Get mantissa and append the hidden bit if needed.
mx = x_bits.get_explicit_mantissa();
my = y_bits.get_explicit_mantissa();

// Get the corresponding biased exponent.
int ex = x_bits.get_explicit_exponent();
int ey = y_bits.get_explicit_exponent();

// Count the number of leading zeros of the explicit mantissas.
int nx = cpp::countl_zero(mx);
int ny = cpp::countl_zero(my);
// Shift the leading 1 bit to the most significant bit.
mx <<= nx;
my <<= ny;

// Adjust exponent accordingly: If x or y are normal, we will only need to
// shift by (exponent length + sign bit = 11 bits. If x or y are denormal, we
// will need to shift more than 11 bits.
ex -= (nx - 11);
ey -= (ny - 11);

UInt128 product = static_cast<UInt128>(mx) * static_cast<UInt128>(my);
int32_t dm1;
uint64_t highs, lows;
uint64_t g, hight, lowt;
uint32_t m;
uint32_t b;
int c;

highs = static_cast<uint64_t>(product >> 64);
c = static_cast<int>(highs >= 0x8000000000000000);
lows = static_cast<uint64_t>(product);

lowt = (lows != 0);

dm1 = ex + ey + c + fputil::FPBits<float>::EXP_BIAS;

int round_mode = fputil::quick_get_round();
if (dm1 >= 255) {
if ((round_mode == FE_TOWARDZERO) ||
(round_mode == FE_UPWARD && output_sign.is_neg()) ||
(round_mode == FE_DOWNWARD && output_sign.is_pos())) {
return fputil::FPBits<float>::max_normal(output_sign).get_val();
}
return fputil::FPBits<float>::inf().get_val();
} else if (dm1 <= 0) {

int m_shift = 40 + c - dm1;
int g_shift = m_shift - 1;
int h_shift = 64 - g_shift;
m = (m_shift >= 64) ? 0 : static_cast<uint32_t>(highs >> m_shift);

g = g_shift >= 64 ? 0 : (highs >> g_shift) & 1;
hight = h_shift >= 64 ? highs : (highs << h_shift) != 0;

dm1 = 0;
} else {
m = static_cast<uint32_t>(highs >> (39 + c));
g = (highs >> (38 + c)) & 1;
hight = (highs << (26 - c)) != 0;
}

if (round_mode == FE_TONEAREST) {
b = g && ((hight && lowt) || ((m & 1) != 0));
} else if ((output_sign.is_neg() && round_mode == FE_DOWNWARD) ||
(output_sign.is_pos() && round_mode == FE_UPWARD)) {
b = (g == 0 && (hight && lowt) == 0) ? 0 : 1;
} else {
b = 0;
}

uint32_t exp16 = (dm1 << 23);

uint32_t m2 = m & fputil::FPBits<float>::FRACTION_MASK;

uint32_t result = (exp16 + m2) + b;

auto result_bits = fputil::FPBits<float>(result);
result_bits.set_sign(output_sign);
return result_bits.get_val();
return fputil::generic::mul<float>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/fmulf128.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of fmulf128 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/math/fmulf128.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float, fmulf128, (float128 x, float128 y)) {
return fputil::generic::mul<float>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
20 changes: 20 additions & 0 deletions libc/src/math/generic/fmull.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation of fmull 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/math/fmull.h"
#include "src/__support/FPUtil/generic/mul.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(float, fmull, (long double x, long double y)) {
return fputil::generic::mul<float>(x, y);
}

} // namespace LIBC_NAMESPACE_DECL
80 changes: 79 additions & 1 deletion libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1847,10 +1847,28 @@ add_fp_unittest(
SRCS
fmul_test.cpp
HDRS
FMulTest.h
MulTest.h
DEPENDS
libc.src.math.fmul
libc.src.stdlib.rand
libc.src.stdlib.srand
)

add_fp_unittest(
fmull_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
fmull_test.cpp
HDRS
MulTest.h
DEPENDS
libc.src.math.fmull
libc.src.stdlib.rand
libc.src.stdlib.srand
)

add_fp_unittest(
asinhf_test
NEED_MPFR
Expand Down Expand Up @@ -2237,6 +2255,66 @@ add_fp_unittest(
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
dmull_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
dmull_test.cpp
HDRS
MulTest.h
DEPENDS
libc.src.math.dmull
libc.src.stdlib.rand
libc.src.stdlib.srand
)

add_fp_unittest(
f16mul_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
f16mul_test.cpp
HDRS
MulTest.h
DEPENDS
libc.src.math.f16mul
libc.src.stdlib.rand
libc.src.stdlib.srand
)

add_fp_unittest(
f16mulf_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
f16mulf_test.cpp
HDRS
MulTest.h
DEPENDS
libc.src.math.f16mulf
libc.src.stdlib.rand
libc.src.stdlib.srand
)

add_fp_unittest(
f16mull_test
NEED_MPFR
SUITE
libc-math-unittests
SRCS
f16mull_test.cpp
HDRS
MulTest.h
DEPENDS
libc.src.math.f16mull
libc.src.stdlib.rand
libc.src.stdlib.srand
)

add_subdirectory(generic)
add_subdirectory(smoke)

Expand Down
121 changes: 0 additions & 121 deletions libc/test/src/math/FMulTest.h

This file was deleted.

95 changes: 95 additions & 0 deletions libc/test/src/math/MulTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//===-- Utility class to test different flavors of float mul ----*- 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_TEST_SRC_MATH_MULTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_MULTEST_H

#include "src/stdlib/rand.h"
#include "src/stdlib/srand.h"
#include "test/UnitTest/FEnvSafeTest.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"
#include "utils/MPFRWrapper/MPFRUtils.h"

namespace mpfr = LIBC_NAMESPACE::testing::mpfr;

template <typename OutType, typename InType>
class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {

struct InConstants {
DECLARE_SPECIAL_CONSTANTS(InType)
};

using InFPBits = typename InConstants::FPBits;
using InStorageType = typename InConstants::StorageType;

static constexpr InStorageType IN_MAX_NORMAL_U =
InFPBits::max_normal().uintval();
static constexpr InStorageType IN_MIN_NORMAL_U =
InFPBits::min_normal().uintval();
static constexpr InStorageType IN_MAX_SUBNORMAL_U =
InFPBits::max_subnormal().uintval();
static constexpr InStorageType IN_MIN_SUBNORMAL_U =
InFPBits::min_subnormal().uintval();

InStorageType get_random_bit_pattern() {
InStorageType bits{0};
for (InStorageType i = 0; i < sizeof(InStorageType) / 2; ++i)
bits = (bits << 2) + static_cast<uint16_t>(LIBC_NAMESPACE::rand());
return bits;
}

public:
using MulFunc = OutType (*)(InType, InType);

void test_subnormal_range(MulFunc func) {
constexpr InStorageType COUNT = 10'001;
constexpr InStorageType STEP =
(IN_MAX_SUBNORMAL_U - IN_MIN_SUBNORMAL_U) / COUNT;
LIBC_NAMESPACE::srand(1);
for (int signs = 0; signs < 4; signs++) {
for (InStorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
InType x = InFPBits(get_random_bit_pattern()).get_val();
InType y = InFPBits(v).get_val();
if ((signs & 1) != 0)
x = -x;
if ((signs & 2) != 0)
y = -y;
mpfr::BinaryInput<InType> input{x, y};
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, func(x, y),
0.5);
}
}
}

void test_normal_range(MulFunc func) {
constexpr InStorageType COUNT = 10'001;
constexpr InStorageType STEP = (IN_MAX_NORMAL_U - IN_MIN_NORMAL_U) / COUNT;
LIBC_NAMESPACE::srand(1);
for (int signs = 0; signs < 4; signs++) {
for (InStorageType i = 0, v = 0; i <= COUNT; ++i, v += STEP) {
InType x = InFPBits(get_random_bit_pattern()).get_val();
InType y = InFPBits(v).get_val();
if ((signs & 1) != 0)
x = -x;
if ((signs & 2) != 0)
y = -y;
mpfr::BinaryInput<InType> input{x, y};
EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Mul, input, func(x, y),
0.5);
}
}
}
};

#define LIST_MUL_TESTS(OutType, InType, func) \
using LlvmLibcMulTest = MulTest<OutType, InType>; \
TEST_F(LlvmLibcMulTest, SubnormalRange) { test_subnormal_range(&func); } \
TEST_F(LlvmLibcMulTest, NormalRange) { test_normal_range(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_MULTEST_H
13 changes: 13 additions & 0 deletions libc/test/src/math/dmull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for dmull -----------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/dmull.h"

LIST_MUL_TESTS(double, long double, LIBC_NAMESPACE::dmull)
13 changes: 13 additions & 0 deletions libc/test/src/math/f16mul_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mul ----------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mul.h"

LIST_MUL_TESTS(float16, double, LIBC_NAMESPACE::f16mul)
13 changes: 13 additions & 0 deletions libc/test/src/math/f16mulf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mulf ---------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mulf.h"

LIST_MUL_TESTS(float16, float, LIBC_NAMESPACE::f16mulf)
13 changes: 13 additions & 0 deletions libc/test/src/math/f16mull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mull ---------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mull.h"

LIST_MUL_TESTS(float16, long double, LIBC_NAMESPACE::f16mull)
8 changes: 4 additions & 4 deletions libc/test/src/math/fmul_test.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//===-- Unittests for fmul-------------------------------------------------===//
//===-- Unittests for fmul ------------------------------------------------===//
//
// 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 "FMulTest.h"
#include "MulTest.h"

#include "src/math/fmul.h"

LIST_FMUL_MPFR_TESTS(float, double, LIBC_NAMESPACE::fmul)
LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
13 changes: 13 additions & 0 deletions libc/test/src/math/fmull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for fmull -----------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/fmull.h"

LIST_MUL_TESTS(float, long double, LIBC_NAMESPACE::fmull)
96 changes: 94 additions & 2 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2531,10 +2531,27 @@ add_fp_unittest(
SRCS
fmul_test.cpp
HDRS
FMulTest.h
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.fmul
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
fmull_test
SUITE
libc-math-smoke-tests
SRCS
fmull_test.cpp
HDRS
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.fmull
)

add_fp_unittest(
Expand Down Expand Up @@ -3981,3 +3998,78 @@ add_fp_unittest(
DEPENDS
libc.src.math.cbrt
)

add_fp_unittest(
dmull_test
SUITE
libc-math-smoke-tests
SRCS
dmull_test.cpp
HDRS
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.dmull
)

add_fp_unittest(
f16mul_test
SUITE
libc-math-smoke-tests
SRCS
f16mul_test.cpp
HDRS
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.f16mul
)

add_fp_unittest(
f16mulf_test
SUITE
libc-math-smoke-tests
SRCS
f16mulf_test.cpp
HDRS
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.f16mulf
)

add_fp_unittest(
f16mull_test
SUITE
libc-math-smoke-tests
SRCS
f16mull_test.cpp
HDRS
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.f16mull
)

add_fp_unittest(
f16mulf128_test
SUITE
libc-math-smoke-tests
SRCS
f16mulf128_test.cpp
HDRS
MulTest.h
DEPENDS
libc.hdr.errno_macros
libc.hdr.fenv_macros
libc.src.__support.FPUtil.basic_operations
libc.src.math.f16mulf128
)
104 changes: 0 additions & 104 deletions libc/test/src/math/smoke/FMulTest.h

This file was deleted.

171 changes: 171 additions & 0 deletions libc/test/src/math/smoke/MulTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
//===-- Utility class to test different flavors of float mul ----*- 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_TEST_SRC_MATH_SMOKE_MULTEST_H
#define LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H

#include "hdr/errno_macros.h"
#include "hdr/fenv_macros.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "test/UnitTest/FEnvSafeTest.h"
#include "test/UnitTest/FPMatcher.h"
#include "test/UnitTest/Test.h"

template <typename OutType, typename InType>
class MulTest : public LIBC_NAMESPACE::testing::FEnvSafeTest {

DECLARE_SPECIAL_CONSTANTS(OutType)

struct InConstants {
DECLARE_SPECIAL_CONSTANTS(InType)
};

using InFPBits = typename InConstants::FPBits;
using InStorageType = typename InConstants::StorageType;

InConstants in;

public:
using MulFunc = OutType (*)(InType, InType);

void test_special_numbers(MulFunc func) {
EXPECT_FP_IS_NAN(func(aNaN, aNaN));
EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(sNaN, sNaN), FE_INVALID);

InType qnan_42 = InFPBits::quiet_nan(Sign::POS, 0x42).get_val();
EXPECT_FP_EQ(InType(0x42.0p+0),
LIBC_NAMESPACE::fputil::getpayload(func(qnan_42, zero)));
EXPECT_FP_EQ(InType(0x42.0p+0),
LIBC_NAMESPACE::fputil::getpayload(func(zero, qnan_42)));

if constexpr (sizeof(OutType) < sizeof(InType)) {
InStorageType max_payload = InFPBits::FRACTION_MASK >> 1;
InType qnan_max = InFPBits::quiet_nan(Sign::POS, max_payload).get_val();
EXPECT_FP_EQ(zero,
LIBC_NAMESPACE::fputil::getpayload(func(qnan_max, zero)));
EXPECT_FP_EQ(zero,
LIBC_NAMESPACE::fputil::getpayload(func(zero, qnan_max)));
EXPECT_FP_EQ(InType(0x42.0p+0),
LIBC_NAMESPACE::fputil::getpayload(func(qnan_max, qnan_42)));
EXPECT_FP_EQ(InType(0x42.0p+0),
LIBC_NAMESPACE::fputil::getpayload(func(qnan_42, qnan_max)));
}

EXPECT_FP_EQ(inf, func(inf, InType(1.0)));
EXPECT_FP_EQ(neg_inf, func(neg_inf, InType(1.0)));
EXPECT_FP_EQ(neg_inf, func(inf, InType(-1.0)));
EXPECT_FP_EQ(inf, func(neg_inf, InType(-1.0)));

EXPECT_FP_EQ_ALL_ROUNDING(zero, func(zero, zero));
EXPECT_FP_EQ_ALL_ROUNDING(zero, func(neg_zero, neg_zero));
EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(zero, neg_zero));
EXPECT_FP_EQ_ALL_ROUNDING(neg_zero, func(neg_zero, zero));

EXPECT_FP_EQ_ALL_ROUNDING(OutType(1.0), func(1.0, 1.0));
EXPECT_FP_EQ_ALL_ROUNDING(OutType(15.0), func(3.0, 5.0));
EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-13), func(0x1.0p+1, 0x1.0p-14));
EXPECT_FP_EQ_ALL_ROUNDING(OutType(0x1.0p-10), func(0x1.0p+2, 0x1.0p-12));
}

void test_invalid_operations(MulFunc func) {
EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, zero), FE_INVALID);
EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(inf, neg_zero), FE_INVALID);
EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, zero), FE_INVALID);
EXPECT_FP_IS_NAN_WITH_EXCEPTION(func(neg_inf, neg_zero), FE_INVALID);
}

void test_range_errors(MulFunc func) {
using namespace LIBC_NAMESPACE::fputil::testing;

if (ForceRoundingMode r(RoundingMode::Nearest); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}

if (ForceRoundingMode r(RoundingMode::TowardZero); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}

if (ForceRoundingMode r(RoundingMode::Downward); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(max_normal, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_inf, func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);

EXPECT_FP_EQ_WITH_EXCEPTION(zero, func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_min_denormal,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}

if (ForceRoundingMode r(RoundingMode::Upward); r.success) {
EXPECT_FP_EQ_WITH_EXCEPTION(inf, func(max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_max_normal,
func(neg_max_normal, max_normal),
FE_OVERFLOW | FE_INEXACT);

EXPECT_FP_EQ_WITH_EXCEPTION(min_denormal,
func(in.min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
EXPECT_FP_EQ_WITH_EXCEPTION(neg_zero,
func(in.neg_min_denormal, in.min_denormal),
FE_UNDERFLOW | FE_INEXACT);
EXPECT_MATH_ERRNO(ERANGE);
}
}

void test_inexact_results(MulFunc func) {
InFPBits x_bits = InFPBits::one();
x_bits.set_mantissa(InFPBits::SIG_MASK);
InType x = x_bits.get_val();
func(x, x);
EXPECT_FP_EXCEPTION(FE_INEXACT);
}
};

#define LIST_MUL_TESTS(OutType, InType, func) \
using LlvmLibcMulTest = MulTest<OutType, InType>; \
TEST_F(LlvmLibcMulTest, SpecialNumbers) { test_special_numbers(&func); } \
TEST_F(LlvmLibcMulTest, InvalidOperations) { \
test_invalid_operations(&func); \
} \
TEST_F(LlvmLibcMulTest, RangeErrors) { test_range_errors(&func); } \
TEST_F(LlvmLibcMulTest, InexactResults) { test_inexact_results(&func); }

#endif // LLVM_LIBC_TEST_SRC_MATH_SMOKE_MULTEST_H
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/dmulf128_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for dmulf128 --------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/dmulf128.h"

LIST_MUL_TESTS(double, float128, LIBC_NAMESPACE::dmulf128)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/dmull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for dmull -----------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/dmull.h"

LIST_MUL_TESTS(double, long double, LIBC_NAMESPACE::dmull)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16mul_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mul ----------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mul.h"

LIST_MUL_TESTS(float16, double, LIBC_NAMESPACE::f16mul)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16mulf128_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mulf128 ------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mulf128.h"

LIST_MUL_TESTS(float16, float128, LIBC_NAMESPACE::f16mulf128)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16mulf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mulf ---------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mulf.h"

LIST_MUL_TESTS(float16, float, LIBC_NAMESPACE::f16mulf)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/f16mull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for f16mull ---------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/f16mull.h"

LIST_MUL_TESTS(float16, long double, LIBC_NAMESPACE::f16mull)
8 changes: 4 additions & 4 deletions libc/test/src/math/smoke/fmul_test.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//===-- Unittests for fmul-------------------------------------------------===//
//===-- Unittests for fmul ------------------------------------------------===//
//
// 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 "FMulTest.h"
#include "MulTest.h"

#include "src/math/fmul.h"

LIST_FMUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
LIST_MUL_TESTS(float, double, LIBC_NAMESPACE::fmul)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/fmulf128_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for fmulf128 --------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/fmulf128.h"

LIST_MUL_TESTS(float, float128, LIBC_NAMESPACE::fmulf128)
13 changes: 13 additions & 0 deletions libc/test/src/math/smoke/fmull_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===-- Unittests for fmull -----------------------------------------------===//
//
// 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 "MulTest.h"

#include "src/math/fmull.h"

LIST_MUL_TESTS(float, long double, LIBC_NAMESPACE::fmull)
21 changes: 15 additions & 6 deletions libc/utils/MPFRWrapper/MPFRUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ class MPFRNumber {
return result;
}

MPFRNumber fmul(const MPFRNumber &b) {
MPFRNumber mul(const MPFRNumber &b) {
MPFRNumber result(*this);
mpfr_mul(result.value, value, b.value, mpfr_rounding);
return result;
Expand Down Expand Up @@ -800,12 +800,12 @@ binary_operation_one_output(Operation op, InputType x, InputType y,
return inputX.fmod(inputY);
case Operation::Hypot:
return inputX.hypot(inputY);
case Operation::Mul:
return inputX.mul(inputY);
case Operation::Pow:
return inputX.pow(inputY);
case Operation::Sub:
return inputX.sub(inputY);
case Operation::Fmul:
return inputX.fmul(inputY);
default:
__builtin_unreachable();
}
Expand Down Expand Up @@ -1013,15 +1013,18 @@ void explain_binary_operation_one_output_error(
template void
explain_binary_operation_one_output_error(Operation, const BinaryInput<float> &,
float, double, RoundingMode);
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<double> &, float, double, RoundingMode);
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<double> &, double, double, RoundingMode);
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<long double> &, float, double, RoundingMode);
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<long double> &, double, double, RoundingMode);
template void
explain_binary_operation_one_output_error(Operation,
const BinaryInput<long double> &,
long double, double, RoundingMode);

template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<double> &, float, double, RoundingMode);
#ifdef LIBC_TYPES_HAS_FLOAT16
template void explain_binary_operation_one_output_error(
Operation, const BinaryInput<float16> &, float16, double, RoundingMode);
Expand Down Expand Up @@ -1195,6 +1198,12 @@ template bool compare_binary_operation_one_output(Operation,
const BinaryInput<double> &,
double, double, RoundingMode);
template bool
compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,
float, double, RoundingMode);
template bool
compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,
double, double, RoundingMode);
template bool
compare_binary_operation_one_output(Operation, const BinaryInput<long double> &,
long double, double, RoundingMode);

Expand Down
2 changes: 1 addition & 1 deletion libc/utils/MPFRWrapper/MPFRUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ enum class Operation : int {
Div,
Fmod,
Hypot,
Mul,
Pow,
Sub,
Fmul,
EndBinaryOperationsSingleOutput,

// Operations which take two floating point numbers of the same type as
Expand Down