[libc][stdfix] Implement idivfx functions in LLVM libc (#133005)

This PR implements the following 8 functions along with the tests.

```c++
int idivr(fract, fract);
long int idivlr(long fract, long fract);
int idivk(accum, accum);
long int idivlk(long accum, long accum);

unsigned int idivur(unsigned fract, unsigned fract);
unsigned long int idivulr(unsigned long fract, unsigned long fract);
unsigned int idivuk(unsigned accum, unsigned accum);
unsigned long int idivulk(unsigned long accum, unsigned long accum);
```

ref: https://www.iso.org/standard/51126.html

Fixes #129125

---------

Signed-off-by: krishna2803 <kpandey81930@gmail.com>
This commit is contained in:
Krishna Pandey
2025-04-25 17:28:16 +05:30
committed by GitHub
parent 2dc6e98169
commit 5ff277462d
36 changed files with 703 additions and 1 deletions

View File

@@ -820,6 +820,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
libc.src.stdfix.idivr
libc.src.stdfix.idivlr
libc.src.stdfix.idivk
libc.src.stdfix.idivlk
libc.src.stdfix.idivur
libc.src.stdfix.idivulr
libc.src.stdfix.idivuk
libc.src.stdfix.idivulk
)
endif()

View File

@@ -820,6 +820,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
libc.src.stdfix.idivr
libc.src.stdfix.idivlr
libc.src.stdfix.idivk
libc.src.stdfix.idivlk
libc.src.stdfix.idivur
libc.src.stdfix.idivulr
libc.src.stdfix.idivuk
libc.src.stdfix.idivulk
)
endif()

View File

@@ -775,6 +775,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
libc.src.stdfix.idivr
libc.src.stdfix.idivlr
libc.src.stdfix.idivk
libc.src.stdfix.idivulk
libc.src.stdfix.idivur
libc.src.stdfix.idivulr
libc.src.stdfix.idivuk
libc.src.stdfix.idivulk
)
endif()

View File

@@ -920,6 +920,14 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
libc.src.stdfix.countlsuhk
libc.src.stdfix.countlsuk
libc.src.stdfix.countlsulk
libc.src.stdfix.idivr
libc.src.stdfix.idivlr
libc.src.stdfix.idivk
libc.src.stdfix.idivlk
libc.src.stdfix.idivur
libc.src.stdfix.idivulr
libc.src.stdfix.idivuk
libc.src.stdfix.idivulk
)
endif()

View File

@@ -77,7 +77,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| divi\* | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| idiv\* | | | | | | | | | | | | |
| idiv\* | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| muli | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+

View File

@@ -238,6 +238,70 @@ functions:
arguments:
- type: unsigned long accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivr
standards:
- stdc_ext
return_type: int
arguments:
- type: fract
- type: fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivlr
standards:
- stdc_ext
return_type: long int
arguments:
- type: long fract
- type: long fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivk
standards:
- stdc_ext
return_type: int
arguments:
- type: accum
- type: accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivlk
standards:
- stdc_ext
return_type: long int
arguments:
- type: long accum
- type: long accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivur
standards:
- stdc_ext
return_type: unsigned int
arguments:
- type: unsigned fract
- type: unsigned fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivulr
standards:
- stdc_ext
return_type: unsigned long int
arguments:
- type: unsigned long fract
- type: unsigned long fract
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivuk
standards:
- stdc_ext
return_type: unsigned int
arguments:
- type: unsigned accum
- type: unsigned accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: idivulk
standards:
- stdc_ext
return_type: unsigned long int
arguments:
- type: unsigned long accum
- type: unsigned long accum
guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: roundhk
standards:
- stdc_ext

View File

@@ -16,6 +16,7 @@ add_header_library(
.fx_rep
libc.include.llvm-libc-macros.stdfix_macros
libc.src.__support.macros.attributes
libc.src.__support.macros.null_check
libc.src.__support.macros.optimization
libc.src.__support.CPP.type_traits
libc.src.__support.CPP.bit

View File

@@ -15,6 +15,7 @@
#include "src/__support/CPP/type_traits.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
#include "src/__support/macros/null_check.h" // LIBC_CRASH_ON_VALUE
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/math_extras.h"
@@ -201,6 +202,28 @@ bitsfx(T f) {
return cpp::bit_cast<XType, T>(f);
}
// divide the two fixed-point types and return an integer result
template <typename T, typename XType>
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, XType>
idiv(T x, T y) {
using FXBits = FXBits<T>;
using FXRep = FXRep<T>;
using CompType = typename FXRep::CompType;
// If the value of the second operand of the / operator is zero, the
// behavior is undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
LIBC_CRASH_ON_VALUE(y, FXRep::ZERO());
CompType x_comp = static_cast<CompType>(FXBits(x).get_bits());
CompType y_comp = static_cast<CompType>(FXBits(y).get_bits());
// If an integer result of one of these functions overflows, the behavior is
// undefined. Ref: ISO/IEC TR 18037:2008(E) p.g. 16
CompType result = x_comp / y_comp;
return static_cast<XType>(result);
}
} // namespace fixed_point
} // namespace LIBC_NAMESPACE_DECL

View File

@@ -19,10 +19,19 @@
if (LIBC_UNLIKELY((ptr) == nullptr)) \
__builtin_trap(); \
} while (0)
#define LIBC_CRASH_ON_VALUE(var, value) \
do { \
if (LIBC_UNLIKELY((var) == (value))) \
__builtin_trap(); \
} while (0)
#else
#define LIBC_CRASH_ON_NULLPTR(ptr) \
do { \
} while (0)
#define LIBC_CRASH_ON_VALUE(var, value) \
do { \
} while (0)
#endif
#endif // LLVM_LIBC_SRC___SUPPORT_MACROS_NULL_CHECK_H

View File

@@ -75,6 +75,20 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
)
endforeach()
foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
add_entrypoint_object(
idiv${suffix}
HDRS
idiv${suffix}.h
SRCS
idiv${suffix}.cpp
COMPILE_OPTIONS
${libc_opt_high_flag}
DEPENDS
libc.src.__support.fixed_point.fx_bits
)
endforeach()
add_entrypoint_object(
uhksqrtus
HDRS

21
libc/src/stdfix/idivk.cpp Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation of idivk 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 "idivk.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // accum
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, idivk, (accum x, accum y)) {
return fixed_point::idiv<accum, int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivk.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivk ------------------------*- 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_IDIVK_H
#define LLVM_LIBC_SRC_STDFIX_IDIVK_H
#include "include/llvm-libc-macros/stdfix-macros.h" // accum
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
int idivk(accum x, accum y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVK_H

View File

@@ -0,0 +1,21 @@
//===-- Implementation of idivlk 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 "idivlk.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(long int, idivlk, (long accum x, long accum y)) {
return fixed_point::idiv<long accum, long int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivlk.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivlk -----------------------*- 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_IDIVLK_H
#define LLVM_LIBC_SRC_STDFIX_IDIVLK_H
#include "include/llvm-libc-macros/stdfix-macros.h" // long accum
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
long int idivlk(long accum x, long accum y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVLK_H

View File

@@ -0,0 +1,21 @@
//===-- Implementation of idivlr 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 "idivlr.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(long int, idivlr, (long fract x, long fract y)) {
return fixed_point::idiv<long fract, long int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivlr.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivlr -----------------------*- 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_IDIVLR_H
#define LLVM_LIBC_SRC_STDFIX_IDIVLR_H
#include "include/llvm-libc-macros/stdfix-macros.h" // long fract
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
long int idivlr(long fract x, long fract y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVLR_H

21
libc/src/stdfix/idivr.cpp Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation of idivr 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 "idivr.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // fract
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, idivr, (fract x, fract y)) {
return fixed_point::idiv<fract, int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivr.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivr ------------------------*- 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_IDIVR_H
#define LLVM_LIBC_SRC_STDFIX_IDIVR_H
#include "include/llvm-libc-macros/stdfix-macros.h" // fract
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
int idivr(fract x, fract y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVR_H

View File

@@ -0,0 +1,21 @@
//===-- Implementation of idivuk 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 "idivuk.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned accum
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(unsigned int, idivuk, (unsigned accum x, unsigned accum y)) {
return fixed_point::idiv<unsigned accum, unsigned int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivuk.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivuk ------------------------*- 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_IDIVUK_H
#define LLVM_LIBC_SRC_STDFIX_IDIVUK_H
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned accum
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
unsigned int idivuk(unsigned accum x, unsigned accum y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVUK_H

View File

@@ -0,0 +1,22 @@
//===-- Implementation of idivulk 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 "idivulk.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long accum
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(unsigned long int, idivulk,
(unsigned long accum x, unsigned long accum y)) {
return fixed_point::idiv<unsigned long accum, unsigned long int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivulk.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivlk -----------------------*- 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_IDIVULK_H
#define LLVM_LIBC_SRC_STDFIX_IDIVULK_H
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long accum
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
unsigned long int idivulk(unsigned long accum x, unsigned long accum y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVULK_H

View File

@@ -0,0 +1,22 @@
//===-- Implementation of idivulr 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 "idivulr.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long fract
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(unsigned long int, idivulr,
(unsigned long fract x, unsigned long fract y)) {
return fixed_point::idiv<unsigned long fract, unsigned long int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivulr.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivulr ----------------------*- 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_IDIVULR_H
#define LLVM_LIBC_SRC_STDFIX_IDIVULR_H
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned long fract
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
unsigned long int idivulr(unsigned long fract x, unsigned long fract y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVULR_H

View File

@@ -0,0 +1,21 @@
//===-- Implementation of idivur 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 "idivur.h"
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned fract
#include "src/__support/common.h" // LLVM_LIBC_FUNCTION
#include "src/__support/fixed_point/fx_bits.h" // fixed_point
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(unsigned int, idivur, (unsigned fract x, unsigned fract y)) {
return fixed_point::idiv<unsigned fract, unsigned int>(x, y);
}
} // namespace LIBC_NAMESPACE_DECL

21
libc/src/stdfix/idivur.h Normal file
View File

@@ -0,0 +1,21 @@
//===-- Implementation header for idivur -----------------------*- 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_IDIVUR_H
#define LLVM_LIBC_SRC_STDFIX_IDIVUR_H
#include "include/llvm-libc-macros/stdfix-macros.h" // unsigned fract
#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
namespace LIBC_NAMESPACE_DECL {
unsigned int idivur(unsigned fract x, unsigned fract y);
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC_STDFIX_IDIVUR_H

View File

@@ -104,6 +104,22 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
)
endforeach()
foreach(suffix IN ITEMS r lr k lk ur ulr uk ulk)
add_libc_test(
idiv${suffix}_test
SUITE
libc-stdfix-tests
HDRS
IdivTest.h
SRCS
idiv${suffix}_test.cpp
DEPENDS
libc.src.stdfix.idiv${suffix}
libc.src.__support.fixed_point.fx_bits
libc.hdr.signal_macros
)
endforeach()
add_libc_test(
uhksqrtus_test
SUITE

View File

@@ -0,0 +1,91 @@
//===-- Utility class to test idivfx functions ------------------*- 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"
#include "src/__support/macros/sanitizer.h"
#include "hdr/signal_macros.h"
template <typename T, typename XType>
class IdivTest : public LIBC_NAMESPACE::testing::Test {
using FXRep = LIBC_NAMESPACE::fixed_point::FXRep<T>;
static constexpr T zero = FXRep::ZERO();
static constexpr T max = FXRep::MAX();
static constexpr T min = FXRep::MIN();
static constexpr T one_half = FXRep::ONE_HALF();
static constexpr T one_fourth = FXRep::ONE_FOURTH();
public:
typedef XType (*IdivFunc)(T, T);
void testSpecialNumbers(IdivFunc func) {
constexpr bool is_signed = (FXRep::SIGN_LEN > 0);
constexpr bool has_integral = (FXRep::INTEGRAL_LEN > 0);
EXPECT_EQ(func(one_half, one_fourth), static_cast<XType>(2));
EXPECT_EQ(func(one_half, one_half), static_cast<XType>(1));
EXPECT_EQ(func(one_fourth, one_half), static_cast<XType>(0));
EXPECT_EQ(func(0.75, 0.25), static_cast<XType>(3));
EXPECT_EQ(func(0.625, 0.125), static_cast<XType>(5));
if constexpr (is_signed) {
EXPECT_EQ(func(min, one_half), static_cast<XType>(min) * 2);
} else {
EXPECT_EQ(func(min, one_half), static_cast<XType>(0));
}
if constexpr (has_integral && min <= 7 && max >= 5) {
EXPECT_EQ(func(6.9, 4.2), static_cast<XType>(1));
EXPECT_EQ(func(4.2, 6.9), static_cast<XType>(0));
EXPECT_EQ(func(4.5, 2.2), static_cast<XType>(2));
EXPECT_EQ(func(2.2, 1.1), static_cast<XType>(2));
EXPECT_EQ(func(2.25, 1.0), static_cast<XType>(2));
EXPECT_EQ(func(2.25, 3.0), static_cast<XType>(0));
if constexpr (is_signed) {
EXPECT_EQ(func(4.2, -6.9), static_cast<XType>(0));
EXPECT_EQ(func(-6.9, 4.2), static_cast<XType>(-1));
EXPECT_EQ(func(-2.5, 1.25), static_cast<XType>(-2));
EXPECT_EQ(func(-2.25, 1.0), static_cast<XType>(-2));
EXPECT_EQ(func(2.25, -3.0), static_cast<XType>(0));
}
}
}
void testInvalidNumbers(IdivFunc func) {
constexpr bool has_integral = (FXRep::INTEGRAL_LEN > 0);
EXPECT_DEATH([func] { func(0.5, 0.0); }, WITH_SIGNAL(SIGILL));
if constexpr (has_integral) {
EXPECT_DEATH([func] { func(2.5, 0.0); }, WITH_SIGNAL(SIGSEGV));
}
}
};
#if defined(LIBC_ADD_NULL_CHECKS) && !defined(LIBC_HAS_SANITIZER)
#define LIST_IDIV_TESTS(Name, T, XTYpe, func) \
using LlvmLibcIdiv##Name##Test = IdivTest<T, XType>; \
TEST_F(LlvmLibcIdiv##Name##Test, InvalidNumbers) { \
testInvalidNumbers(&func); \
} \
TEST_F(LlvmLibcIdiv##Name##Test, SpecialNumbers) { \
testSpecialNumbers(&func); \
} \
static_assert(true, "Require semicolon.")
#else
#define LIST_IDIV_TESTS(Name, T, XType, func) \
using LlvmLibcIdiv##Name##Test = IdivTest<T, XType>; \
TEST_F(LlvmLibcIdiv##Name##Test, SpecialNumbers) { \
testSpecialNumbers(&func); \
} \
static_assert(true, "Require semicolon.")
#endif // LIBC_HAS_ADDRESS_SANITIZER

View File

@@ -0,0 +1,14 @@
//===-- Unittests for idivk -----------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // accum
#include "src/stdfix/idivk.h"
LIST_IDIV_TESTS(k, accum, int, LIBC_NAMESPACE::idivk);

View File

@@ -0,0 +1,14 @@
//===-- Unittests for idivlk ----------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // long accum
#include "src/stdfix/idivlk.h"
LIST_IDIV_TESTS(lk, long accum, long int, LIBC_NAMESPACE::idivlk);

View File

@@ -0,0 +1,14 @@
//===-- Unittests for idivlr ----------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // long fract
#include "src/stdfix/idivlr.h"
LIST_IDIV_TESTS(lr, long fract, long int, LIBC_NAMESPACE::idivlr);

View File

@@ -0,0 +1,14 @@
//===-- Unittests for idivr -----------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // fract
#include "src/stdfix/idivr.h"
LIST_IDIV_TESTS(r, fract, int, LIBC_NAMESPACE::idivr);

View File

@@ -0,0 +1,14 @@
//===-- Unittests for idivuk ----------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // unsigned accum
#include "src/stdfix/idivuk.h"
LIST_IDIV_TESTS(uk, unsigned accum, unsigned int, LIBC_NAMESPACE::idivuk);

View File

@@ -0,0 +1,15 @@
//===-- Unittests for idivulk ---------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // unsigned long accum
#include "src/stdfix/idivulk.h"
LIST_IDIV_TESTS(ulk, unsigned long accum, unsigned long int,
LIBC_NAMESPACE::idivulk);

View File

@@ -0,0 +1,15 @@
//===-- Unittests for idivulr ---------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // unsigned long fract
#include "src/stdfix/idivulr.h"
LIST_IDIV_TESTS(ulr, unsigned long fract, unsigned long int,
LIBC_NAMESPACE::idivulr);

View File

@@ -0,0 +1,14 @@
//===-- Unittests for idivur ----------------------------------------------===//
//
// 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 "IdivTest.h"
#include "llvm-libc-macros/stdfix-macros.h" // unsigned fract
#include "src/stdfix/idivur.h"
LIST_IDIV_TESTS(ur, unsigned fract, unsigned int, LIBC_NAMESPACE::idivur);