Skip to content

Commit e789f8b

Browse files
[libc][math] Add Generic Comparison Operations for floating point types (#144983)
The PR implements the following generic comparison operation functions for floating point types along with unittests: - `fputil::equals` - `fputil::less_than` - `fputil::less_than_or_equals` - `fputil::greater_than` - `fputil::greater_than_or_equals` --------- Signed-off-by: krishna2803 <[email protected]> Signed-off-by: Krishna Pandey <[email protected]> Co-authored-by: OverMighty <[email protected]>
1 parent c710d46 commit e789f8b

File tree

4 files changed

+487
-0
lines changed

4 files changed

+487
-0
lines changed

libc/src/__support/FPUtil/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,17 @@ add_header_library(
209209
libc.src.__support.macros.properties.types
210210
)
211211

212+
add_header_library(
213+
comparison_operations
214+
HDRS
215+
comparison_operations.h
216+
DEPENDS
217+
.fenv_impl
218+
.fp_bits
219+
libc.src.__support.CPP.type_traits
220+
libc.src.__support.macros.config
221+
)
222+
212223
add_header_library(
213224
hypot
214225
HDRS
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
//===-- Comparison operations on floating point numbers ---------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H
10+
#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H
11+
12+
#include "FEnvImpl.h"
13+
#include "FPBits.h"
14+
#include "src/__support/CPP/type_traits.h"
15+
#include "src/__support/macros/config.h"
16+
17+
namespace LIBC_NAMESPACE_DECL {
18+
namespace fputil {
19+
20+
// All predicates are hereby implemented as per IEEE Std 754-2019
21+
// Implements compareQuietEqual predicate
22+
// Rules for comparison within the same floating point type
23+
// 1. +0 = −0
24+
// 2. (i) +inf = +inf
25+
// (ii) -inf = -inf
26+
// (iii) -inf != +inf
27+
// 3. Any comparison with NaN returns false
28+
template <typename T>
29+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> equals(T x,
30+
T y) {
31+
using FPBits = FPBits<T>;
32+
FPBits x_bits(x);
33+
FPBits y_bits(y);
34+
35+
if (x_bits.is_signaling_nan() || y_bits.is_signaling_nan())
36+
fputil::raise_except_if_required(FE_INVALID);
37+
38+
// NaN == x returns false for every x
39+
if (x_bits.is_nan() || y_bits.is_nan())
40+
return false;
41+
42+
// +/- 0 == +/- 0
43+
if (x_bits.is_zero() && y_bits.is_zero())
44+
return true;
45+
46+
return x_bits.uintval() == y_bits.uintval();
47+
}
48+
49+
// Implements compareSignalingLess predicate
50+
// Section 5.11 Rules:
51+
// 1. -inf < x (x != -inf)
52+
// 2. x < +inf (x != +inf)
53+
// 3. Any comparison with NaN return false
54+
template <typename T>
55+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool> less_than(T x,
56+
T y) {
57+
using FPBits = FPBits<T>;
58+
FPBits x_bits(x);
59+
FPBits y_bits(y);
60+
61+
// Any comparison with NaN returns false
62+
if (x_bits.is_nan() || y_bits.is_nan()) {
63+
fputil::raise_except_if_required(FE_INVALID);
64+
return false;
65+
}
66+
67+
if (x_bits.is_zero() && y_bits.is_zero())
68+
return false;
69+
70+
if (x_bits.is_neg() && y_bits.is_pos())
71+
return true;
72+
73+
if (x_bits.is_pos() && y_bits.is_neg())
74+
return false;
75+
76+
// since floating-point numbers are stored in the format: s | e | m
77+
// we can directly compare the uintval's
78+
79+
// both negative
80+
if (x_bits.is_neg())
81+
return x_bits.uintval() > y_bits.uintval();
82+
83+
// both positive
84+
return x_bits.uintval() < y_bits.uintval();
85+
}
86+
87+
// Implements compareSignalingGreater predicate
88+
// x < y => y > x
89+
template <typename T>
90+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
91+
greater_than(T x, T y) {
92+
return less_than(y, x);
93+
}
94+
95+
// Implements compareSignalingLessEqual predicate
96+
// x <= y => (x < y) || (x == y)
97+
template <typename T>
98+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
99+
less_than_or_equals(T x, T y) {
100+
return less_than(x, y) || equals(x, y);
101+
}
102+
103+
// Implements compareSignalingGreaterEqual predicate
104+
// x >= y => (x > y) || (x == y) => (y < x) || (x == y)
105+
template <typename T>
106+
LIBC_INLINE cpp::enable_if_t<cpp::is_floating_point_v<T>, bool>
107+
greater_than_or_equals(T x, T y) {
108+
return less_than(y, x) || equals(x, y);
109+
}
110+
111+
} // namespace fputil
112+
} // namespace LIBC_NAMESPACE_DECL
113+
114+
#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_COMPARISONOPERATIONS_H

libc/test/src/__support/FPUtil/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,15 @@ add_fp_unittest(
5555
DEPENDS
5656
libc.src.__support.FPUtil.bfloat16
5757
)
58+
59+
add_fp_unittest(
60+
comparison_operations_test
61+
SUITE
62+
libc-fputil-tests
63+
SRCS
64+
comparison_operations_test.cpp
65+
DEPENDS
66+
libc.src.__support.FPUtil.bfloat16
67+
libc.src.__support.FPUtil.comparison_operations
68+
libc.src.__support.macros.properties.types
69+
)

0 commit comments

Comments
 (0)