diff options
author | lntue <35648136+lntue@users.noreply.github.com> | 2024-02-16 12:45:26 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-16 12:45:26 -0500 |
commit | f01ed3bc8884223bf3edbaad8d3685622444cbf5 (patch) | |
tree | ab5ae42f01d40f871516813c387959728e9fbeef /libc | |
parent | eb97599335be0e65de337681ce558818e57e382f (diff) | |
download | llvm-f01ed3bc8884223bf3edbaad8d3685622444cbf5.zip llvm-f01ed3bc8884223bf3edbaad8d3685622444cbf5.tar.gz llvm-f01ed3bc8884223bf3edbaad8d3685622444cbf5.tar.bz2 |
[libc][stdfix] Add round functions for fixed point types. (#81994)
Diffstat (limited to 'libc')
44 files changed, 809 insertions, 1 deletions
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 69912d3..beb7a5e 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -451,6 +451,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT) libc.src.stdfix.absr libc.src.stdfix.abslk libc.src.stdfix.abslr + libc.src.stdfix.roundhk + libc.src.stdfix.roundhr + libc.src.stdfix.roundk + libc.src.stdfix.roundr + libc.src.stdfix.roundlk + libc.src.stdfix.roundlr + libc.src.stdfix.rounduhk + libc.src.stdfix.rounduhr + libc.src.stdfix.rounduk + libc.src.stdfix.roundur + libc.src.stdfix.roundulk + libc.src.stdfix.roundulr ) endif() diff --git a/libc/docs/math/stdfix.rst b/libc/docs/math/stdfix.rst index d05e3fd..080066e 100644 --- a/libc/docs/math/stdfix.rst +++ b/libc/docs/math/stdfix.rst @@ -76,7 +76,7 @@ Fixed-point Arithmetics +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ | rdivi | | | | | | | | | | | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ -| round | | | | | | | | | | | | | +| round | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ | sqrt | | | | | | | | | | | | | +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+ diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td index dd9f06d..6620142 100644 --- a/libc/spec/stdc_ext.td +++ b/libc/spec/stdc_ext.td @@ -31,6 +31,22 @@ def StdcExt : StandardSpec<"stdc_ext"> { GuardedFunctionSpec<"abshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">, GuardedFunctionSpec<"absk", RetValSpec<AccumType>, [ArgSpec<AccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">, GuardedFunctionSpec<"abslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"roundhr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundlr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"roundhk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundlk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"rounduhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + + GuardedFunctionSpec<"rounduhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"rounduk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, + GuardedFunctionSpec<"roundulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">, ] >; diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt index 4dac9b3..c6bb9e1 100644 --- a/libc/src/__support/fixed_point/CMakeLists.txt +++ b/libc/src/__support/fixed_point/CMakeLists.txt @@ -17,4 +17,5 @@ add_header_library( libc.include.llvm-libc-macros.stdfix_macros libc.src.__support.macros.attributes libc.src.__support.macros.optimization + libc.src.__support.CPP.bit ) diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h index ad3a6fc..b26be16 100644 --- a/libc/src/__support/fixed_point/fx_bits.h +++ b/libc/src/__support/fixed_point/fx_bits.h @@ -10,6 +10,8 @@ #define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXBITS_H #include "include/llvm-libc-macros/stdfix-macros.h" +#include "src/__support/CPP/bit.h" +#include "src/__support/CPP/type_traits.h" #include "src/__support/macros/attributes.h" // LIBC_INLINE #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY @@ -19,6 +21,36 @@ namespace LIBC_NAMESPACE::fixed_point { +// Bit-wise operations are not available for fixed point types yet. +template <typename T> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T> +bit_and(T x, T y) { + using BitType = typename FXRep<T>::StorageType; + BitType x_bit = cpp::bit_cast<BitType>(x); + BitType y_bit = cpp::bit_cast<BitType>(y); + // For some reason, bit_cast cannot deduce BitType from the input. + return cpp::bit_cast<T, BitType>(x_bit & y_bit); +} + +template <typename T> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T> +bit_or(T x, T y) { + using BitType = typename FXRep<T>::StorageType; + BitType x_bit = cpp::bit_cast<BitType>(x); + BitType y_bit = cpp::bit_cast<BitType>(y); + // For some reason, bit_cast cannot deduce BitType from the input. + return cpp::bit_cast<T, BitType>(x_bit | y_bit); +} + +template <typename T> +LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, T> +bit_not(T x) { + using BitType = typename FXRep<T>::StorageType; + BitType x_bit = cpp::bit_cast<BitType>(x); + // For some reason, bit_cast cannot deduce BitType from the input. + return cpp::bit_cast<T, BitType>(~x_bit); +} + template <typename T> LIBC_INLINE constexpr T abs(T x) { using FXRep = FXRep<T>; if constexpr (FXRep::SIGN_LEN == 0) @@ -30,6 +62,27 @@ template <typename T> LIBC_INLINE constexpr T abs(T x) { } } +// Round-to-nearest, tie-to-(+Inf) +template <typename T> LIBC_INLINE constexpr T round(T x, int n) { + using FXRep = FXRep<T>; + if (LIBC_UNLIKELY(n < 0)) + n = 0; + if (LIBC_UNLIKELY(n >= FXRep::FRACTION_LEN)) + return x; + + T round_bit = FXRep::EPS() << (FXRep::FRACTION_LEN - n - 1); + // Check for overflow. + if (LIBC_UNLIKELY(FXRep::MAX() - round_bit < x)) + return FXRep::MAX(); + + T all_ones = bit_not(FXRep::ZERO()); + + int shift = FXRep::FRACTION_LEN - n; + T rounding_mask = + (shift == FXRep::TOTAL_LEN) ? FXRep::ZERO() : (all_ones << shift); + return bit_and((x + round_bit), rounding_mask); +} + } // namespace LIBC_NAMESPACE::fixed_point #endif // LIBC_COMPILER_HAS_FIXED_POINT diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt index 1eaf64b..6e2ed1b 100644 --- a/libc/src/stdfix/CMakeLists.txt +++ b/libc/src/stdfix/CMakeLists.txt @@ -16,3 +16,18 @@ foreach(suffix IN ITEMS hr r lr hk k lk) libc.src.__support.fixed_point.fx_bits ) endforeach() + +foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk) + add_entrypoint_object( + round${suffix} + HDRS + round${suffix}.h + SRCS + round${suffix}.cpp + COMPILE_OPTIONS + -O3 + -ffixed-point + DEPENDS + libc.src.__support.fixed_point.fx_bits + ) +endforeach() diff --git a/libc/src/stdfix/roundhk.cpp b/libc/src/stdfix/roundhk.cpp new file mode 100644 index 0000000..a4f459e --- /dev/null +++ b/libc/src/stdfix/roundhk.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundhk 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 "roundhk.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(short accum, roundhk, (short accum x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundhk.h b/libc/src/stdfix/roundhk.h new file mode 100644 index 0000000..9a5c874c --- /dev/null +++ b/libc/src/stdfix/roundhk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundhk -----------------------*- 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_STDFIX_ROUNDHK_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDHK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +short accum roundhk(short accum x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDHK_H diff --git a/libc/src/stdfix/roundhr.cpp b/libc/src/stdfix/roundhr.cpp new file mode 100644 index 0000000..7757d1c --- /dev/null +++ b/libc/src/stdfix/roundhr.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundhr 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 "roundhr.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(short fract, roundhr, (short fract x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundhr.h b/libc/src/stdfix/roundhr.h new file mode 100644 index 0000000..ba5a679 --- /dev/null +++ b/libc/src/stdfix/roundhr.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundhr -----------------------*- 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_STDFIX_ROUNDHR_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDHR_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +short fract roundhr(short fract x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDHR_H diff --git a/libc/src/stdfix/roundk.cpp b/libc/src/stdfix/roundk.cpp new file mode 100644 index 0000000..bf47dd9 --- /dev/null +++ b/libc/src/stdfix/roundk.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundk 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 "roundk.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(accum, roundk, (accum x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundk.h b/libc/src/stdfix/roundk.h new file mode 100644 index 0000000..e9fa6d8 --- /dev/null +++ b/libc/src/stdfix/roundk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundk ------------------------*- 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_STDFIX_ROUNDK_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +accum roundk(accum x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDK_H diff --git a/libc/src/stdfix/roundlk.cpp b/libc/src/stdfix/roundlk.cpp new file mode 100644 index 0000000..d2ffe8a --- /dev/null +++ b/libc/src/stdfix/roundlk.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundlk 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 "roundlk.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long accum, roundlk, (long accum x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundlk.h b/libc/src/stdfix/roundlk.h new file mode 100644 index 0000000..5fa0e90 --- /dev/null +++ b/libc/src/stdfix/roundlk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundlk -----------------------*- 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_STDFIX_ROUNDLK_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDLK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +long accum roundlk(long accum x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDLK_H diff --git a/libc/src/stdfix/roundlr.cpp b/libc/src/stdfix/roundlr.cpp new file mode 100644 index 0000000..cd4c911 --- /dev/null +++ b/libc/src/stdfix/roundlr.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundlr 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 "roundlr.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(long fract, roundlr, (long fract x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundlr.h b/libc/src/stdfix/roundlr.h new file mode 100644 index 0000000..c015292 --- /dev/null +++ b/libc/src/stdfix/roundlr.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundlr -----------------------*- 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_STDFIX_ROUNDLR_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDLR_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +long fract roundlr(long fract x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDLR_H diff --git a/libc/src/stdfix/roundr.cpp b/libc/src/stdfix/roundr.cpp new file mode 100644 index 0000000..2421693 --- /dev/null +++ b/libc/src/stdfix/roundr.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundr 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 "roundr.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(fract, roundr, (fract x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundr.h b/libc/src/stdfix/roundr.h new file mode 100644 index 0000000..b5b1375 --- /dev/null +++ b/libc/src/stdfix/roundr.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundr ------------------------*- 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_STDFIX_ROUNDR_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDR_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +fract roundr(fract x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDR_H diff --git a/libc/src/stdfix/rounduhk.cpp b/libc/src/stdfix/rounduhk.cpp new file mode 100644 index 0000000..2256158 --- /dev/null +++ b/libc/src/stdfix/rounduhk.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of rounduhk 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 "rounduhk.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned short accum, rounduhk, + (unsigned short accum x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/rounduhk.h b/libc/src/stdfix/rounduhk.h new file mode 100644 index 0000000..85ebf29 --- /dev/null +++ b/libc/src/stdfix/rounduhk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for rounduhk ----------------------*- 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_STDFIX_ROUNDUHK_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDUHK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned short accum rounduhk(unsigned short accum x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUHK_H diff --git a/libc/src/stdfix/rounduhr.cpp b/libc/src/stdfix/rounduhr.cpp new file mode 100644 index 0000000..e2e3435 --- /dev/null +++ b/libc/src/stdfix/rounduhr.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of rounduhr 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 "rounduhr.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned short fract, rounduhr, + (unsigned short fract x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/rounduhr.h b/libc/src/stdfix/rounduhr.h new file mode 100644 index 0000000..1be0aab --- /dev/null +++ b/libc/src/stdfix/rounduhr.h @@ -0,0 +1,20 @@ +//===-- Implementation header for rounduhr ----------------------*- 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_STDFIX_ROUNDUHR_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDUHR_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned short fract rounduhr(unsigned short fract x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUHR_H diff --git a/libc/src/stdfix/rounduk.cpp b/libc/src/stdfix/rounduk.cpp new file mode 100644 index 0000000..b9f8522 --- /dev/null +++ b/libc/src/stdfix/rounduk.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of rounduk 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 "rounduk.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned accum, rounduk, (unsigned accum x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/rounduk.h b/libc/src/stdfix/rounduk.h new file mode 100644 index 0000000..8dae895 --- /dev/null +++ b/libc/src/stdfix/rounduk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for rounduk -----------------------*- 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_STDFIX_ROUNDUK_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDUK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned accum rounduk(unsigned accum x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUK_H diff --git a/libc/src/stdfix/roundulk.cpp b/libc/src/stdfix/roundulk.cpp new file mode 100644 index 0000000..241b2c2 --- /dev/null +++ b/libc/src/stdfix/roundulk.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of roundulk 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 "roundulk.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long accum, roundulk, + (unsigned long accum x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundulk.h b/libc/src/stdfix/roundulk.h new file mode 100644 index 0000000..81dfd1d --- /dev/null +++ b/libc/src/stdfix/roundulk.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundulk ----------------------*- 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_STDFIX_ROUNDULK_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDULK_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned long accum roundulk(unsigned long accum x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDULK_H diff --git a/libc/src/stdfix/roundulr.cpp b/libc/src/stdfix/roundulr.cpp new file mode 100644 index 0000000..6c32074 --- /dev/null +++ b/libc/src/stdfix/roundulr.cpp @@ -0,0 +1,20 @@ +//===-- Implementation of roundulr 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 "roundulr.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned long fract, roundulr, + (unsigned long fract x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundulr.h b/libc/src/stdfix/roundulr.h new file mode 100644 index 0000000..002fc94 --- /dev/null +++ b/libc/src/stdfix/roundulr.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundulr ----------------------*- 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_STDFIX_ROUNDULR_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDULR_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned long fract roundulr(unsigned long fract x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDULR_H diff --git a/libc/src/stdfix/roundur.cpp b/libc/src/stdfix/roundur.cpp new file mode 100644 index 0000000..e91b7f1 --- /dev/null +++ b/libc/src/stdfix/roundur.cpp @@ -0,0 +1,19 @@ +//===-- Implementation of roundur 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 "roundur.h" +#include "src/__support/common.h" +#include "src/__support/fixed_point/fx_bits.h" + +namespace LIBC_NAMESPACE { + +LLVM_LIBC_FUNCTION(unsigned fract, roundur, (unsigned fract x, int n)) { + return fixed_point::round(x, n); +} + +} // namespace LIBC_NAMESPACE diff --git a/libc/src/stdfix/roundur.h b/libc/src/stdfix/roundur.h new file mode 100644 index 0000000..72de44b --- /dev/null +++ b/libc/src/stdfix/roundur.h @@ -0,0 +1,20 @@ +//===-- Implementation header for roundur -----------------------*- 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_STDFIX_ROUNDUR_H +#define LLVM_LIBC_SRC_STDFIX_ROUNDUR_H + +#include "include/llvm-libc-macros/stdfix-macros.h" + +namespace LIBC_NAMESPACE { + +unsigned fract roundur(unsigned fract x, int n); + +} // namespace LIBC_NAMESPACE + +#endif // LLVM_LIBC_SRC_STDFIX_ROUNDUR_H diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt index 3b2ea9e..b6e0256 100644 --- a/libc/test/src/stdfix/CMakeLists.txt +++ b/libc/test/src/stdfix/CMakeLists.txt @@ -21,3 +21,21 @@ foreach(suffix IN ITEMS hr r lr hk k lk) libc.src.__support.fixed_point.fx_bits ) endforeach() + +foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk) + add_libc_test( + round${suffix}_test + SUITE + libc-stdfix-tests + HDRS + RoundTest.h + SRCS + round${suffix}_test.cpp + COMPILE_OPTIONS + -O3 + -ffixed-point + DEPENDS + libc.src.stdfix.round${suffix} + libc.src.__support.fixed_point.fx_bits + ) +endforeach() diff --git a/libc/test/src/stdfix/RoundTest.h b/libc/test/src/stdfix/RoundTest.h new file mode 100644 index 0000000..06343ad --- /dev/null +++ b/libc/test/src/stdfix/RoundTest.h @@ -0,0 +1,65 @@ +//===-- Utility class to test fixed-point round -----------------*- 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 "test/UnitTest/Test.h" + +#include "src/__support/fixed_point/fx_rep.h" + +template <typename T> class RoundTest : public LIBC_NAMESPACE::testing::Test { + + using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<T>; + static constexpr T zero = FXRep::ZERO(); + static constexpr T min = FXRep::MIN(); + static constexpr T max = FXRep::MAX(); + static constexpr T half = static_cast<T>(0.5); + static constexpr T neg_half = static_cast<T>(-0.5); + static constexpr T one = + (FXRep::INTEGRAL_LEN > 0) ? static_cast<T>(1) : FXRep::MAX(); + static constexpr T neg_one = static_cast<T>(-1); + static constexpr T eps = FXRep::EPS(); + +public: + typedef T (*RoundFunc)(T, int); + + void testSpecialNumbers(RoundFunc func) { + EXPECT_EQ(zero, func(zero, FXRep::FRACTION_LEN - 5)); + EXPECT_EQ(max, func(min, 0)); + EXPECT_EQ(max, func(max, FXRep::FRACTION_LEN)); + + EXPECT_EQ(one, func(half, 0)); + EXPECT_EQ(half, func(half, 1)); + EXPECT_EQ(half, func(half, FXRep::FRACTION_LEN)); + EXPECT_EQ(one, func(half + eps, 0)); + EXPECT_EQ(half, func(half + eps, 1)); + EXPECT_EQ(half, func(half + eps, 2)); + EXPECT_EQ(zero, func(half - eps, 0)); + EXPECT_EQ(half, func(half - eps, 1)); + EXPECT_EQ(half, func(half - eps, 2)); + EXPECT_EQ(eps, func(eps, FXRep::FRACTION_LEN + 10)); + EXPECT_EQ(eps << 1, func(eps, FXRep::FRACTION_LEN - 1)); + EXPECT_EQ(zero, func(eps, FXRep::FRACTION_LEN - 2)); + + if constexpr (FXRep::SIGN_LEN) { + EXPECT_EQ(zero, func(neg_half, 0)); + EXPECT_EQ(neg_half, func(neg_half, 1)); + EXPECT_EQ(neg_half, func(neg_half, 3)); + EXPECT_EQ(zero, func(neg_half + eps, 0)); + EXPECT_EQ(neg_half, func(neg_half + eps, 1)); + EXPECT_EQ(neg_half, func(neg_half + eps, 2)); + EXPECT_EQ(neg_one, func(neg_half - eps, 0)); + EXPECT_EQ(neg_half, func(neg_half - eps, 1)); + EXPECT_EQ(neg_half, func(neg_half - eps, 2)); + EXPECT_EQ(-eps, func(-eps, FXRep::FRACTION_LEN + 10)); + } + } +}; + +#define LIST_ROUND_TESTS(T, func) \ + using LlvmLibcRoundTest = RoundTest<T>; \ + TEST_F(LlvmLibcRoundTest, SpecialNumbers) { testSpecialNumbers(&func); } \ + static_assert(true, "Require semicolon.") diff --git a/libc/test/src/stdfix/roundhk_test.cpp b/libc/test/src/stdfix/roundhk_test.cpp new file mode 100644 index 0000000..3cbcfb0 --- /dev/null +++ b/libc/test/src/stdfix/roundhk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundhk ---------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundhk.h" + +LIST_ROUND_TESTS(short accum, LIBC_NAMESPACE::roundhk); diff --git a/libc/test/src/stdfix/roundhr_test.cpp b/libc/test/src/stdfix/roundhr_test.cpp new file mode 100644 index 0000000..9e58fb5 --- /dev/null +++ b/libc/test/src/stdfix/roundhr_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundhr ---------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundhr.h" + +LIST_ROUND_TESTS(short fract, LIBC_NAMESPACE::roundhr); diff --git a/libc/test/src/stdfix/roundk_test.cpp b/libc/test/src/stdfix/roundk_test.cpp new file mode 100644 index 0000000..4092ce3 --- /dev/null +++ b/libc/test/src/stdfix/roundk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundk ----------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundk.h" + +LIST_ROUND_TESTS(accum, LIBC_NAMESPACE::roundk); diff --git a/libc/test/src/stdfix/roundlk_test.cpp b/libc/test/src/stdfix/roundlk_test.cpp new file mode 100644 index 0000000..c8bd1c9 --- /dev/null +++ b/libc/test/src/stdfix/roundlk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundlk ---------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundlk.h" + +LIST_ROUND_TESTS(long accum, LIBC_NAMESPACE::roundlk); diff --git a/libc/test/src/stdfix/roundlr_test.cpp b/libc/test/src/stdfix/roundlr_test.cpp new file mode 100644 index 0000000..53bfbb8 --- /dev/null +++ b/libc/test/src/stdfix/roundlr_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundlr ---------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundlr.h" + +LIST_ROUND_TESTS(long fract, LIBC_NAMESPACE::roundlr); diff --git a/libc/test/src/stdfix/roundr_test.cpp b/libc/test/src/stdfix/roundr_test.cpp new file mode 100644 index 0000000..68527f1 --- /dev/null +++ b/libc/test/src/stdfix/roundr_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundr ----------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundr.h" + +LIST_ROUND_TESTS(fract, LIBC_NAMESPACE::roundr); diff --git a/libc/test/src/stdfix/rounduhk_test.cpp b/libc/test/src/stdfix/rounduhk_test.cpp new file mode 100644 index 0000000..d03774b --- /dev/null +++ b/libc/test/src/stdfix/rounduhk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for rounduhk --------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/rounduhk.h" + +LIST_ROUND_TESTS(unsigned short accum, LIBC_NAMESPACE::rounduhk); diff --git a/libc/test/src/stdfix/rounduhr_test.cpp b/libc/test/src/stdfix/rounduhr_test.cpp new file mode 100644 index 0000000..889827c --- /dev/null +++ b/libc/test/src/stdfix/rounduhr_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for rounduhr --------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/rounduhr.h" + +LIST_ROUND_TESTS(unsigned short fract, LIBC_NAMESPACE::rounduhr); diff --git a/libc/test/src/stdfix/rounduk_test.cpp b/libc/test/src/stdfix/rounduk_test.cpp new file mode 100644 index 0000000..fbf73d5 --- /dev/null +++ b/libc/test/src/stdfix/rounduk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for rounduk ---------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/rounduk.h" + +LIST_ROUND_TESTS(unsigned accum, LIBC_NAMESPACE::rounduk); diff --git a/libc/test/src/stdfix/roundulk_test.cpp b/libc/test/src/stdfix/roundulk_test.cpp new file mode 100644 index 0000000..92db54e --- /dev/null +++ b/libc/test/src/stdfix/roundulk_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundulk --------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundulk.h" + +LIST_ROUND_TESTS(unsigned long accum, LIBC_NAMESPACE::roundulk); diff --git a/libc/test/src/stdfix/roundulr_test.cpp b/libc/test/src/stdfix/roundulr_test.cpp new file mode 100644 index 0000000..11cbb46 --- /dev/null +++ b/libc/test/src/stdfix/roundulr_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundulr --------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundulr.h" + +LIST_ROUND_TESTS(unsigned long fract, LIBC_NAMESPACE::roundulr); diff --git a/libc/test/src/stdfix/roundur_test.cpp b/libc/test/src/stdfix/roundur_test.cpp new file mode 100644 index 0000000..636f348 --- /dev/null +++ b/libc/test/src/stdfix/roundur_test.cpp @@ -0,0 +1,13 @@ +//===-- Unittests for roundur ---------------------------------------------===// +// +// 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 "RoundTest.h" + +#include "src/stdfix/roundur.h" + +LIST_ROUND_TESTS(unsigned fract, LIBC_NAMESPACE::roundur); |