Skip to content

Commit f01ed3b

Browse files
authored
[libc][stdfix] Add round functions for fixed point types. (#81994)
1 parent eb97599 commit f01ed3b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+815
-2
lines changed

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
451451
libc.src.stdfix.absr
452452
libc.src.stdfix.abslk
453453
libc.src.stdfix.abslr
454+
libc.src.stdfix.roundhk
455+
libc.src.stdfix.roundhr
456+
libc.src.stdfix.roundk
457+
libc.src.stdfix.roundr
458+
libc.src.stdfix.roundlk
459+
libc.src.stdfix.roundlr
460+
libc.src.stdfix.rounduhk
461+
libc.src.stdfix.rounduhr
462+
libc.src.stdfix.rounduk
463+
libc.src.stdfix.roundur
464+
libc.src.stdfix.roundulk
465+
libc.src.stdfix.roundulr
454466
)
455467
endif()
456468

libc/docs/math/stdfix.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ Fixed-point Arithmetics
7676
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
7777
| rdivi | | | | | | | | | | | | |
7878
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
79-
| round | | | | | | | | | | | | |
79+
| round | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| |
8080
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
8181
| sqrt | | | | | | | | | | | | |
8282
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+

libc/spec/stdc_ext.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ def StdcExt : StandardSpec<"stdc_ext"> {
3131
GuardedFunctionSpec<"abshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
3232
GuardedFunctionSpec<"absk", RetValSpec<AccumType>, [ArgSpec<AccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
3333
GuardedFunctionSpec<"abslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
34+
35+
GuardedFunctionSpec<"roundhr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
36+
GuardedFunctionSpec<"roundr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
37+
GuardedFunctionSpec<"roundlr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
38+
39+
GuardedFunctionSpec<"roundhk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
40+
GuardedFunctionSpec<"roundk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
41+
GuardedFunctionSpec<"roundlk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
42+
43+
GuardedFunctionSpec<"rounduhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
44+
GuardedFunctionSpec<"roundur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
45+
GuardedFunctionSpec<"roundulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
46+
47+
GuardedFunctionSpec<"rounduhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
48+
GuardedFunctionSpec<"rounduk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
49+
GuardedFunctionSpec<"roundulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
3450
]
3551
>;
3652

libc/src/__support/fixed_point/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ add_header_library(
1717
libc.include.llvm-libc-macros.stdfix_macros
1818
libc.src.__support.macros.attributes
1919
libc.src.__support.macros.optimization
20+
libc.src.__support.CPP.bit
2021
)

libc/src/__support/fixed_point/fx_bits.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
#define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXBITS_H
1111

1212
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
#include "src/__support/CPP/bit.h"
14+
#include "src/__support/CPP/type_traits.h"
1315
#include "src/__support/macros/attributes.h" // LIBC_INLINE
1416
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
1517

@@ -19,6 +21,36 @@
1921

2022
namespace LIBC_NAMESPACE::fixed_point {
2123

24+
// Bit-wise operations are not available for fixed point types yet.
25+
template <typename T>
26+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
27+
bit_and(T x, T y) {
28+
using BitType = typename FXRep<T>::StorageType;
29+
BitType x_bit = cpp::bit_cast<BitType>(x);
30+
BitType y_bit = cpp::bit_cast<BitType>(y);
31+
// For some reason, bit_cast cannot deduce BitType from the input.
32+
return cpp::bit_cast<T, BitType>(x_bit & y_bit);
33+
}
34+
35+
template <typename T>
36+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
37+
bit_or(T x, T y) {
38+
using BitType = typename FXRep<T>::StorageType;
39+
BitType x_bit = cpp::bit_cast<BitType>(x);
40+
BitType y_bit = cpp::bit_cast<BitType>(y);
41+
// For some reason, bit_cast cannot deduce BitType from the input.
42+
return cpp::bit_cast<T, BitType>(x_bit | y_bit);
43+
}
44+
45+
template <typename T>
46+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T>
47+
bit_not(T x) {
48+
using BitType = typename FXRep<T>::StorageType;
49+
BitType x_bit = cpp::bit_cast<BitType>(x);
50+
// For some reason, bit_cast cannot deduce BitType from the input.
51+
return cpp::bit_cast<T, BitType>(~x_bit);
52+
}
53+
2254
template <typename T> LIBC_INLINE constexpr T abs(T x) {
2355
using FXRep = FXRep<T>;
2456
if constexpr (FXRep::SIGN_LEN == 0)
@@ -30,6 +62,27 @@ template <typename T> LIBC_INLINE constexpr T abs(T x) {
3062
}
3163
}
3264

65+
// Round-to-nearest, tie-to-(+Inf)
66+
template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
67+
using FXRep = FXRep<T>;
68+
if (LIBC_UNLIKELY(n < 0))
69+
n = 0;
70+
if (LIBC_UNLIKELY(n >= FXRep::FRACTION_LEN))
71+
return x;
72+
73+
T round_bit = FXRep::EPS() << (FXRep::FRACTION_LEN - n - 1);
74+
// Check for overflow.
75+
if (LIBC_UNLIKELY(FXRep::MAX() - round_bit < x))
76+
return FXRep::MAX();
77+
78+
T all_ones = bit_not(FXRep::ZERO());
79+
80+
int shift = FXRep::FRACTION_LEN - n;
81+
T rounding_mask =
82+
(shift == FXRep::TOTAL_LEN) ? FXRep::ZERO() : (all_ones << shift);
83+
return bit_and((x + round_bit), rounding_mask);
84+
}
85+
3386
} // namespace LIBC_NAMESPACE::fixed_point
3487

3588
#endif // LIBC_COMPILER_HAS_FIXED_POINT

libc/src/stdfix/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,18 @@ foreach(suffix IN ITEMS hr r lr hk k lk)
1616
libc.src.__support.fixed_point.fx_bits
1717
)
1818
endforeach()
19+
20+
foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
21+
add_entrypoint_object(
22+
round${suffix}
23+
HDRS
24+
round${suffix}.h
25+
SRCS
26+
round${suffix}.cpp
27+
COMPILE_OPTIONS
28+
-O3
29+
-ffixed-point
30+
DEPENDS
31+
libc.src.__support.fixed_point.fx_bits
32+
)
33+
endforeach()

libc/src/stdfix/roundhk.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of roundhk function --------------------------------===//
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+
#include "roundhk.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/fixed_point/fx_bits.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(short accum, roundhk, (short accum x, int n)) {
16+
return fixed_point::round(x, n);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/stdfix/roundhk.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for roundhk -----------------------*- 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_STDFIX_ROUNDHK_H
10+
#define LLVM_LIBC_SRC_STDFIX_ROUNDHK_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
short accum roundhk(short accum x, int n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDFIX_ROUNDHK_H

libc/src/stdfix/roundhr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of roundhr function --------------------------------===//
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+
#include "roundhr.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/fixed_point/fx_bits.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(short fract, roundhr, (short fract x, int n)) {
16+
return fixed_point::round(x, n);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/stdfix/roundhr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for roundhr -----------------------*- 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_STDFIX_ROUNDHR_H
10+
#define LLVM_LIBC_SRC_STDFIX_ROUNDHR_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
short fract roundhr(short fract x, int n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDFIX_ROUNDHR_H

libc/src/stdfix/roundk.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of roundk function ---------------------------------===//
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+
#include "roundk.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/fixed_point/fx_bits.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(accum, roundk, (accum x, int n)) {
16+
return fixed_point::round(x, n);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/stdfix/roundk.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for roundk ------------------------*- 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_STDFIX_ROUNDK_H
10+
#define LLVM_LIBC_SRC_STDFIX_ROUNDK_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
accum roundk(accum x, int n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDFIX_ROUNDK_H

libc/src/stdfix/roundlk.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of roundlk function --------------------------------===//
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+
#include "roundlk.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/fixed_point/fx_bits.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(long accum, roundlk, (long accum x, int n)) {
16+
return fixed_point::round(x, n);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/stdfix/roundlk.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for roundlk -----------------------*- 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_STDFIX_ROUNDLK_H
10+
#define LLVM_LIBC_SRC_STDFIX_ROUNDLK_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
long accum roundlk(long accum x, int n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDFIX_ROUNDLK_H

libc/src/stdfix/roundlr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of roundlr function --------------------------------===//
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+
#include "roundlr.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/fixed_point/fx_bits.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(long fract, roundlr, (long fract x, int n)) {
16+
return fixed_point::round(x, n);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/stdfix/roundlr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for roundlr -----------------------*- 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_STDFIX_ROUNDLR_H
10+
#define LLVM_LIBC_SRC_STDFIX_ROUNDLR_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
long fract roundlr(long fract x, int n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDFIX_ROUNDLR_H

libc/src/stdfix/roundr.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//===-- Implementation of roundr function ---------------------------------===//
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+
#include "roundr.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/fixed_point/fx_bits.h"
12+
13+
namespace LIBC_NAMESPACE {
14+
15+
LLVM_LIBC_FUNCTION(fract, roundr, (fract x, int n)) {
16+
return fixed_point::round(x, n);
17+
}
18+
19+
} // namespace LIBC_NAMESPACE

libc/src/stdfix/roundr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for roundr ------------------------*- 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_STDFIX_ROUNDR_H
10+
#define LLVM_LIBC_SRC_STDFIX_ROUNDR_H
11+
12+
#include "include/llvm-libc-macros/stdfix-macros.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
fract roundr(fract x, int n);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_STDFIX_ROUNDR_H

0 commit comments

Comments
 (0)