Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libc/config/linux/aarch64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
libc.src.math.totalorderf16
libc.src.math.totalordermagf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
libc.src.math.ufromfpxf16
Expand Down
2 changes: 2 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,8 @@ if(LIBC_TYPES_HAS_FLOAT16)
libc.src.math.rintf16
libc.src.math.roundf16
libc.src.math.roundevenf16
libc.src.math.totalorderf16
libc.src.math.totalordermagf16
libc.src.math.truncf16
libc.src.math.ufromfpf16
libc.src.math.ufromfpxf16
Expand Down
4 changes: 2 additions & 2 deletions libc/docs/c23.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ Additions:
* rsqrt*
* __STDC_IEC_60559_DFP__ functions (_Decimal32, _Decimal64, _Decimal128)
* compoundn*
* totalorder*
* totalordermag*
* totalorder* |check|
* totalordermag* |check|
* getpayload*
* setpayload*
* iscannonical
Expand Down
4 changes: 4 additions & 0 deletions libc/docs/math/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ Basic Operations
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| scalbn | |check| | |check| | |check| | | |check| | 7.12.6.19 | F.10.3.19 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| totalorder | | | | |check| | | F.10.12.1 | N/A |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| totalordermag | | | | |check| | | F.10.12.2 | N/A |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| trunc | |check| | |check| | |check| | |check| | |check| | 7.12.9.9 | F.10.6.9 |
+------------------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| ufromfp | |check| | |check| | |check| | |check| | |check| | 7.12.9.10 | F.10.6.10 |
Expand Down
4 changes: 4 additions & 0 deletions libc/spec/stdc.td
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,10 @@ def StdC : StandardSpec<"stdc"> {
FunctionSpec<"canonicalizel", RetValSpec<IntType>, [ArgSpec<LongDoubleType>, ArgSpec<LongDoubleType>]>,
GuardedFunctionSpec<"canonicalizef16", RetValSpec<IntType>, [ArgSpec<Float16Type>, ArgSpec<Float16Type>], "LIBC_TYPES_HAS_FLOAT16">,
GuardedFunctionSpec<"canonicalizef128", RetValSpec<IntType>, [ArgSpec<Float128Type>, ArgSpec<Float128Type>], "LIBC_TYPES_HAS_FLOAT128">,

GuardedFunctionSpec<"totalorderf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,

GuardedFunctionSpec<"totalordermagf16", RetValSpec<IntType>, [ArgSpec<Float16Ptr>, ArgSpec<Float16Ptr>], "LIBC_TYPES_HAS_FLOAT16">,
]
>;

Expand Down
51 changes: 51 additions & 0 deletions libc/src/__support/FPUtil/BasicOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,57 @@ LIBC_INLINE int canonicalize(T &cx, const T &x) {
return 0;
}

template <typename T>
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
totalorder(const T *x, const T *y) {
using FPBits = FPBits<T>;
FPBits xbits(*x);
FPBits ybits(*y);

if (LIBC_UNLIKELY(xbits.is_zero() && ybits.is_zero() || xbits.is_nan() ||
ybits.is_nan())) {
// totalOrder(−0, +0) is true. totalOrder(+0, -0) is false.
if (xbits.is_zero() && ybits.is_zero()) {
Sign xsign = xbits.sign();
Sign ysign = ybits.sign();
return (xsign == Sign::NEG && ysign == Sign::POS) || xsign == ysign;
}

// totalOrder(−NaN, y) is true. totalOrder(+NaN, y) is false.
if (!ybits.is_nan())
return xbits.is_neg();
// totalOrder(x, +NaN) is true. totalOrder(x, -NaN) is false.
if (!xbits.is_nan())
return ybits.is_pos();

// Negative sign orders below positive sign.
if (xbits.is_neg() && ybits.is_pos())
return true;
if (xbits.is_pos() && ybits.is_neg())
return false;

// Signaling orders below quiet for +NaN, reverse for −NaN.
if (xbits.is_quiet_nan() && ybits.is_signaling_nan())
return xbits.is_neg();
if (xbits.is_signaling_nan() && ybits.is_quiet_nan())
return ybits.is_pos();

// Otherwise, the order of NaNs is implementation-defined (IEEE 754-2019).
// We order by payload.
return xbits.get_nan_payload() <= ybits.get_nan_payload();
Copy link
Member Author

Choose a reason for hiding this comment

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

I guess this should be documented in https://libc.llvm.org/dev/undefined_behavior.html.

}

return xbits.get_val() <= ybits.get_val();
}

template <typename T>
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
totalordermag(const T *x, const T *y) {
T abs_x = abs(*x);
T abs_y = abs(*y);
return totalorder(&abs_x, &abs_y);
}

} // namespace fputil
} // namespace LIBC_NAMESPACE

Expand Down
4 changes: 4 additions & 0 deletions libc/src/__support/FPUtil/FPBits.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,10 @@ struct FPRepImpl : public FPRepSem<fp_type, RetT> {
LIBC_INLINE constexpr void set_significand(StorageType sigVal) {
bits = UP::merge(bits, sigVal, SIG_MASK);
}

LIBC_INLINE constexpr StorageType get_nan_payload() const {
return bits & (FRACTION_MASK >> 1);
}
// Unsafe function to create a floating point representation.
// It simply packs the sign, biased exponent and mantissa values without
// checking bound nor normalization.
Expand Down
4 changes: 4 additions & 0 deletions libc/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ add_math_entrypoint_object(tanhf)
add_math_entrypoint_object(tgamma)
add_math_entrypoint_object(tgammaf)

add_math_entrypoint_object(totalorderf16)

add_math_entrypoint_object(totalordermagf16)

add_math_entrypoint_object(trunc)
add_math_entrypoint_object(truncf)
add_math_entrypoint_object(truncl)
Expand Down
24 changes: 24 additions & 0 deletions libc/src/math/generic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3551,3 +3551,27 @@ add_entrypoint_object(
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
totalorderf16
SRCS
totalorderf16.cpp
HDRS
../totalorderf16.h
DEPENDS
libc.src.__support.FPUtil.basic_operations
COMPILE_OPTIONS
-O3
)

add_entrypoint_object(
totalordermagf16
SRCS
totalordermagf16.cpp
HDRS
../totalordermagf16.h
DEPENDS
libc.src.__support.FPUtil.basic_operations
COMPILE_OPTIONS
-O3
)
19 changes: 19 additions & 0 deletions libc/src/math/generic/totalorderf16.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//===-- Implementation of totalorderf16 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/totalorderf16.h"
#include "src/__support/FPUtil/BasicOperations.h"
#include "src/__support/common.h"

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, totalorderf16, (const float16 *x, const float16 *y)) {
return static_cast<int>(fputil::totalorder(x, y));
}

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

namespace LIBC_NAMESPACE {

LLVM_LIBC_FUNCTION(int, totalordermagf16,
(const float16 *x, const float16 *y)) {
return static_cast<int>(fputil::totalordermag(x, y));
}

} // namespace LIBC_NAMESPACE
20 changes: 20 additions & 0 deletions libc/src/math/totalorderf16.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for totalorderf16 -----------------*- 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_TOTALORDERF16_H
#define LLVM_LIBC_SRC_MATH_TOTALORDERF16_H

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

namespace LIBC_NAMESPACE {

int totalorderf16(const float16 *x, const float16 *y);

} // namespace LIBC_NAMESPACE

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

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

namespace LIBC_NAMESPACE {

int totalordermagf16(const float16 *x, const float16 *y);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H
6 changes: 4 additions & 2 deletions libc/test/UnitTest/FPMatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ template <typename T> struct FPTest : public Test {
LIBC_NAMESPACE::cpp::numeric_limits<StorageType>::max(); \
const T zero = FPBits::zero(Sign::POS).get_val(); \
const T neg_zero = FPBits::zero(Sign::NEG).get_val(); \
const T aNaN = FPBits::quiet_nan().get_val(); \
const T sNaN = FPBits::signaling_nan().get_val(); \
const T aNaN = FPBits::quiet_nan(Sign::POS).get_val(); \
const T neg_aNaN = FPBits::quiet_nan(Sign::NEG).get_val(); \
const T sNaN = FPBits::signaling_nan(Sign::POS).get_val(); \
const T neg_sNaN = FPBits::signaling_nan(Sign::NEG).get_val(); \
const T inf = FPBits::inf(Sign::POS).get_val(); \
const T neg_inf = FPBits::inf(Sign::NEG).get_val(); \
const T min_normal = FPBits::min_normal().get_val(); \
Expand Down
24 changes: 24 additions & 0 deletions libc/test/src/math/smoke/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3509,3 +3509,27 @@ add_fp_unittest(
libc.src.math.powf
libc.src.__support.FPUtil.fp_bits
)

add_fp_unittest(
totalorderf16_test
SUITE
libc-math-smoke-tests
SRCS
totalorderf16_test.cpp
HDRS
TotalOrderTest.h
DEPENDS
libc.src.math.totalorderf16
)

add_fp_unittest(
totalordermagf16_test
SUITE
libc-math-smoke-tests
SRCS
totalordermagf16_test.cpp
HDRS
TotalOrderMagTest.h
DEPENDS
libc.src.math.totalordermagf16
)
Loading