[libc-commits] [libc] [libc][stdfix] Implement `countlsfx` functions (PR #114318)
via libc-commits
libc-commits at lists.llvm.org
Thu Oct 31 17:18:58 PDT 2024
https://github.com/duncpro updated https://github.com/llvm/llvm-project/pull/114318
>From f71e13eb354d6a02710ceec254e8c399c60ffdbf Mon Sep 17 00:00:00 2001
From: Duncan <duncpro at icloud.com>
Date: Tue, 29 Oct 2024 22:33:41 -0400
Subject: [PATCH] [libc] [stdfix] implement `countlsfx` functions
---
libc/config/baremetal/arm/entrypoints.txt | 12 +++
libc/config/baremetal/riscv/entrypoints.txt | 12 +++
libc/config/linux/riscv/entrypoints.txt | 12 +++
libc/config/linux/x86_64/entrypoints.txt | 12 +++
libc/docs/math/stdfix.rst | 2 +-
libc/newhdrgen/yaml/stdfix.yaml | 84 +++++++++++++++++++
libc/spec/stdc_ext.td | 17 ++++
libc/src/__support/fixed_point/CMakeLists.txt | 1 +
libc/src/__support/fixed_point/fx_bits.h | 39 ++++++++-
libc/src/__support/fixed_point/fx_rep.h | 12 +++
libc/src/stdfix/CMakeLists.txt | 14 ++++
libc/src/stdfix/countlshk.cpp | 20 +++++
libc/src/stdfix/countlshk.h | 21 +++++
libc/src/stdfix/countlshr.cpp | 20 +++++
libc/src/stdfix/countlshr.h | 21 +++++
libc/src/stdfix/countlsk.cpp | 18 ++++
libc/src/stdfix/countlsk.h | 21 +++++
libc/src/stdfix/countlslk.cpp | 20 +++++
libc/src/stdfix/countlslk.h | 21 +++++
libc/src/stdfix/countlslr.cpp | 20 +++++
libc/src/stdfix/countlslr.h | 21 +++++
libc/src/stdfix/countlsr.cpp | 18 ++++
libc/src/stdfix/countlsr.h | 21 +++++
libc/src/stdfix/countlsuhk.cpp | 20 +++++
libc/src/stdfix/countlsuhk.h | 21 +++++
libc/src/stdfix/countlsuhr.cpp | 20 +++++
libc/src/stdfix/countlsuhr.h | 21 +++++
libc/src/stdfix/countlsuk.cpp | 20 +++++
libc/src/stdfix/countlsuk.h | 21 +++++
libc/src/stdfix/countlsulk.cpp | 20 +++++
libc/src/stdfix/countlsulk.h | 21 +++++
libc/src/stdfix/countlsulr.cpp | 20 +++++
libc/src/stdfix/countlsulr.h | 21 +++++
libc/src/stdfix/countlsur.cpp | 20 +++++
libc/src/stdfix/countlsur.h | 21 +++++
libc/test/src/stdfix/CMakeLists.txt | 17 ++++
libc/test/src/stdfix/CountlsTest.h | 48 +++++++++++
libc/test/src/stdfix/countlshk_test.cpp | 13 +++
libc/test/src/stdfix/countlshr_test.cpp | 13 +++
libc/test/src/stdfix/countlsk_test.cpp | 13 +++
libc/test/src/stdfix/countlslk_test.cpp | 13 +++
libc/test/src/stdfix/countlslr_test.cpp | 13 +++
libc/test/src/stdfix/countlsr_test.cpp | 13 +++
libc/test/src/stdfix/countlsuhk_test.cpp | 13 +++
libc/test/src/stdfix/countlsuhr_test.cpp | 13 +++
libc/test/src/stdfix/countlsuk_test.cpp | 13 +++
libc/test/src/stdfix/countlsulk_test.cpp | 13 +++
libc/test/src/stdfix/countlsulr_test.cpp | 13 +++
libc/test/src/stdfix/countlsur_test.cpp | 13 +++
49 files changed, 924 insertions(+), 2 deletions(-)
create mode 100644 libc/src/stdfix/countlshk.cpp
create mode 100644 libc/src/stdfix/countlshk.h
create mode 100644 libc/src/stdfix/countlshr.cpp
create mode 100644 libc/src/stdfix/countlshr.h
create mode 100644 libc/src/stdfix/countlsk.cpp
create mode 100644 libc/src/stdfix/countlsk.h
create mode 100644 libc/src/stdfix/countlslk.cpp
create mode 100644 libc/src/stdfix/countlslk.h
create mode 100644 libc/src/stdfix/countlslr.cpp
create mode 100644 libc/src/stdfix/countlslr.h
create mode 100644 libc/src/stdfix/countlsr.cpp
create mode 100644 libc/src/stdfix/countlsr.h
create mode 100644 libc/src/stdfix/countlsuhk.cpp
create mode 100644 libc/src/stdfix/countlsuhk.h
create mode 100644 libc/src/stdfix/countlsuhr.cpp
create mode 100644 libc/src/stdfix/countlsuhr.h
create mode 100644 libc/src/stdfix/countlsuk.cpp
create mode 100644 libc/src/stdfix/countlsuk.h
create mode 100644 libc/src/stdfix/countlsulk.cpp
create mode 100644 libc/src/stdfix/countlsulk.h
create mode 100644 libc/src/stdfix/countlsulr.cpp
create mode 100644 libc/src/stdfix/countlsulr.h
create mode 100644 libc/src/stdfix/countlsur.cpp
create mode 100644 libc/src/stdfix/countlsur.h
create mode 100644 libc/test/src/stdfix/CountlsTest.h
create mode 100644 libc/test/src/stdfix/countlshk_test.cpp
create mode 100644 libc/test/src/stdfix/countlshr_test.cpp
create mode 100644 libc/test/src/stdfix/countlsk_test.cpp
create mode 100644 libc/test/src/stdfix/countlslk_test.cpp
create mode 100644 libc/test/src/stdfix/countlslr_test.cpp
create mode 100644 libc/test/src/stdfix/countlsr_test.cpp
create mode 100644 libc/test/src/stdfix/countlsuhk_test.cpp
create mode 100644 libc/test/src/stdfix/countlsuhr_test.cpp
create mode 100644 libc/test/src/stdfix/countlsuk_test.cpp
create mode 100644 libc/test/src/stdfix/countlsulk_test.cpp
create mode 100644 libc/test/src/stdfix/countlsulr_test.cpp
create mode 100644 libc/test/src/stdfix/countlsur_test.cpp
diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 68030f7f1775b5..55af5413259a30 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -427,6 +427,18 @@ set(TARGET_LIBM_ENTRYPOINTS
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5894b591072ef0..baa4b27b98aee0 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -422,6 +422,18 @@ set(TARGET_LIBM_ENTRYPOINTS
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5c09edf7cfb266..cbbe9d226e05f9 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -677,6 +677,18 @@ endif()
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a2fb97d04584d5..c0bf1ce50328e5 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -780,6 +780,18 @@ endif()
if(LIBC_COMPILER_HAS_FIXED_POINT)
list(APPEND TARGET_LIBM_ENTRYPOINTS
# stdfix.h _Fract and _Accum entrypoints
+ libc.src.stdfix.countlshk
+ libc.src.stdfix.countlshr
+ libc.src.stdfix.countlsk
+ libc.src.stdfix.countlslk
+ libc.src.stdfix.countlslr
+ libc.src.stdfix.countlsr
+ libc.src.stdfix.countlsuhk
+ libc.src.stdfix.countlsuhr
+ libc.src.stdfix.countlsuk
+ libc.src.stdfix.countlsulk
+ libc.src.stdfix.countlsulr
+ libc.src.stdfix.countlsur
libc.src.stdfix.abshk
libc.src.stdfix.abshr
libc.src.stdfix.absk
diff --git a/libc/docs/math/stdfix.rst b/libc/docs/math/stdfix.rst
index d8dcb0cfa4c521..ebf19ba722c8a4 100644
--- a/libc/docs/math/stdfix.rst
+++ b/libc/docs/math/stdfix.rst
@@ -73,7 +73,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| \*bits | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
-| countls | | | | | | | | | | | | |
+| countls | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| | |check| |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
| divi | | | | | | | | | | | | |
+---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
diff --git a/libc/newhdrgen/yaml/stdfix.yaml b/libc/newhdrgen/yaml/stdfix.yaml
index ca6658939e2278..abf2e4761005de 100644
--- a/libc/newhdrgen/yaml/stdfix.yaml
+++ b/libc/newhdrgen/yaml/stdfix.yaml
@@ -4,6 +4,90 @@ types: []
enums: []
objects: []
functions:
+ - name: countlshk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: short accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlshr
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: short fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlslk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: long accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlslr
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: long fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsr
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsuhk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: unsigned short accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsuhr
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: unsigned short fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsuk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: unsigned accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsulk
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: unsigned long accum
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsulr
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: unsigned long fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
+ - name: countlsur
+ standards:
+ - stdc_ext
+ return_type: int
+ arguments:
+ - type: unsigned fract
+ guard: LIBC_COMPILER_HAS_FIXED_POINT
- name: abshk
standards:
- stdc_ext
diff --git a/libc/spec/stdc_ext.td b/libc/spec/stdc_ext.td
index 6620142146c471..26f2d526168ce7 100644
--- a/libc/spec/stdc_ext.td
+++ b/libc/spec/stdc_ext.td
@@ -24,6 +24,23 @@ def StdcExt : StandardSpec<"stdc_ext"> {
[], // types
[], // enums
[ // functions
+
+ GuardedFunctionSpec<"countlshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsr", RetValSpec<FractType>, [ArgSpec<FractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"countlshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsk", RetValSpec<AccumType>, [ArgSpec<AccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"countlsuhr", RetValSpec<UnsignedShortFractType>, [ArgSpec<UnsignedShortFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsur", RetValSpec<UnsignedFractType>, [ArgSpec<UnsignedFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsulr", RetValSpec<UnsignedLongFractType>, [ArgSpec<UnsignedLongFractType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
+ GuardedFunctionSpec<"countlsuhk", RetValSpec<UnsignedShortAccumType>, [ArgSpec<UnsignedShortAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsuk", RetValSpec<UnsignedAccumType>, [ArgSpec<UnsignedAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+ GuardedFunctionSpec<"countlsulk", RetValSpec<UnsignedLongAccumType>, [ArgSpec<UnsignedLongAccumType>, ArgSpec<IntType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
+
GuardedFunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"absr", RetValSpec<FractType>, [ArgSpec<FractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
GuardedFunctionSpec<"abslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>], "LIBC_COMPILER_HAS_FIXED_POINT">,
diff --git a/libc/src/__support/fixed_point/CMakeLists.txt b/libc/src/__support/fixed_point/CMakeLists.txt
index 3b744081765e4f..2531285d5c9cb2 100644
--- a/libc/src/__support/fixed_point/CMakeLists.txt
+++ b/libc/src/__support/fixed_point/CMakeLists.txt
@@ -20,6 +20,7 @@ add_header_library(
libc.src.__support.CPP.type_traits
libc.src.__support.CPP.bit
libc.src.__support.math_extras
+ libc.src.__support.CPP.limits
)
add_header_library(
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 0a4c21fb6a14f7..6d768ddc747d28 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -11,8 +11,9 @@
#include "include/llvm-libc-macros/stdfix-macros.h"
#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h" // numeric_limits
#include "src/__support/CPP/type_traits.h"
-#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include "src/__support/macros/config.h"
#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
#include "src/__support/math_extras.h"
@@ -66,6 +67,23 @@ template <typename T> struct FXBits {
}
}
+ // Clause 6.2.6.3 of ISO/IEC TR 18037 defines the value bits of a fixed-point
+ // type to include the integral and fraction bits but not padding nor sign
+ // bits.
+ //
+ // This function returns the value bits, right-aligned, as an unsigned integer
+ // type which is at least large enough to hold them all.
+ //
+ // Note the integral and fraction bits are contiguous. The rightmost bits in
+ // the returned value are the fraciton bits, then immediately left of those
+ // are the integral bits.
+ //
+ // Any left-padding in the return value is guaranteed to be zero.
+ LIBC_INLINE constexpr StorageType get_value_bits() {
+ constexpr StorageType VALUE_MASK = INTEGRAL_MASK | FRACTION_MASK;
+ return (value & VALUE_MASK) >> FRACTION_OFFSET;
+ }
+
LIBC_INLINE constexpr StorageType get_fraction() {
return (value & FRACTION_MASK) >> FRACTION_OFFSET;
}
@@ -142,6 +160,25 @@ template <typename T> LIBC_INLINE constexpr T abs(T x) {
}
}
+template <typename T>
+LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_fixed_point_v<T>, int>
+countls(T x) {
+ using FXRep = FXRep<T>;
+ using BitType = typename FXRep::StorageType;
+ constexpr int CONTAIN_LEN = cpp::numeric_limits<BitType>::digits;
+ constexpr int PADDING_LEN = CONTAIN_LEN - FXRep::VALUE_LEN;
+
+ if constexpr (FXRep::SIGN_LEN != 0) {
+ if (x < 0) {
+ x = -(x + FXRep::EPS());
+ }
+ }
+
+ FXBits<T> fxbits(x);
+ BitType value_bits = fxbits.get_value_bits();
+ return cpp::countl_zero(value_bits) - PADDING_LEN;
+}
+
// Round-to-nearest, tie-to-(+Inf)
template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
using FXRep = FXRep<T>;
diff --git a/libc/src/__support/fixed_point/fx_rep.h b/libc/src/__support/fixed_point/fx_rep.h
index 186938947694e5..f1321e6a629ee5 100644
--- a/libc/src/__support/fixed_point/fx_rep.h
+++ b/libc/src/__support/fixed_point/fx_rep.h
@@ -45,6 +45,7 @@ template <> struct FXRep<short fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return SFRACT_MAX; }
@@ -65,6 +66,7 @@ template <> struct FXRep<unsigned short fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return USFRACT_MAX; }
@@ -85,6 +87,7 @@ template <> struct FXRep<fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return FRACT_MAX; }
@@ -105,6 +108,7 @@ template <> struct FXRep<unsigned fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return UFRACT_MAX; }
@@ -125,6 +129,7 @@ template <> struct FXRep<long fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return LFRACT_MAX; }
@@ -145,6 +150,7 @@ template <> struct FXRep<unsigned long fract> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; }
LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MAX; }
@@ -165,6 +171,7 @@ template <> struct FXRep<short accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return SACCUM_MAX; }
@@ -185,6 +192,7 @@ template <> struct FXRep<unsigned short accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return USACCUM_MAX; }
@@ -205,6 +213,7 @@ template <> struct FXRep<accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return ACCUM_MAX; }
@@ -225,6 +234,7 @@ template <> struct FXRep<unsigned accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return UACCUM_MAX; }
@@ -245,6 +255,7 @@ template <> struct FXRep<long accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return LACCUM_MAX; }
@@ -265,6 +276,7 @@ template <> struct FXRep<unsigned long accum> {
LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT;
LIBC_INLINE_VAR static constexpr int TOTAL_LEN =
SIGN_LEN + INTEGRAL_LEN + FRACTION_LEN;
+ LIBC_INLINE_VAR static constexpr int VALUE_LEN = INTEGRAL_LEN + FRACTION_LEN;
LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; }
LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MAX; }
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 10d76ae31349f9..69e0117effb50d 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -2,6 +2,20 @@ if(NOT LIBC_COMPILER_HAS_FIXED_POINT)
return()
endif()
+foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+ add_entrypoint_object(
+ countls${suffix}
+ HDRS
+ countls${suffix}.h
+ SRCS
+ countls${suffix}.cpp
+ COMPILE_OPTIONS
+ -O3
+ DEPENDS
+ libc.src.__support.fixed_point.fx_bits
+ )
+endforeach()
+
foreach(suffix IN ITEMS hr r lr hk k lk)
add_entrypoint_object(
abs${suffix}
diff --git a/libc/src/stdfix/countlshk.cpp b/libc/src/stdfix/countlshk.cpp
new file mode 100644
index 00000000000000..d65d96312c0768
--- /dev/null
+++ b/libc/src/stdfix/countlshk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlshk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshk, (short accum x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlshk.h b/libc/src/stdfix/countlshk.h
new file mode 100644
index 00000000000000..279fb985552347
--- /dev/null
+++ b/libc/src/stdfix/countlshk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSHK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshk(short accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSHK_H
diff --git a/libc/src/stdfix/countlshr.cpp b/libc/src/stdfix/countlshr.cpp
new file mode 100644
index 00000000000000..ed3fd23e0cdf8f
--- /dev/null
+++ b/libc/src/stdfix/countlshr.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlshr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlshr, (short fract x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlshr.h b/libc/src/stdfix/countlshr.h
new file mode 100644
index 00000000000000..a2307ee0656ced
--- /dev/null
+++ b/libc/src/stdfix/countlshr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSHR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlshr(short fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSHR_H
diff --git a/libc/src/stdfix/countlsk.cpp b/libc/src/stdfix/countlsk.cpp
new file mode 100644
index 00000000000000..470f2e28539c16
--- /dev/null
+++ b/libc/src/stdfix/countlsk.cpp
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsk, (accum x)) { return fixed_point::countls(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsk.h b/libc/src/stdfix/countlsk.h
new file mode 100644
index 00000000000000..fff9bed7499c5b
--- /dev/null
+++ b/libc/src/stdfix/countlsk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsk(accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSK_H
diff --git a/libc/src/stdfix/countlslk.cpp b/libc/src/stdfix/countlslk.cpp
new file mode 100644
index 00000000000000..b3d314368e7e23
--- /dev/null
+++ b/libc/src/stdfix/countlslk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlslk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlslk, (long accum x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlslk.h b/libc/src/stdfix/countlslk.h
new file mode 100644
index 00000000000000..0d20779ef18090
--- /dev/null
+++ b/libc/src/stdfix/countlslk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSLK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSLK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlslk(long accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSLK_H
diff --git a/libc/src/stdfix/countlslr.cpp b/libc/src/stdfix/countlslr.cpp
new file mode 100644
index 00000000000000..782a50b5ace6b1
--- /dev/null
+++ b/libc/src/stdfix/countlslr.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlslr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlslr, (long fract x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlslr.h b/libc/src/stdfix/countlslr.h
new file mode 100644
index 00000000000000..28d639513215d0
--- /dev/null
+++ b/libc/src/stdfix/countlslr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSLR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSLR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlslr(long fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSLR_H
diff --git a/libc/src/stdfix/countlsr.cpp b/libc/src/stdfix/countlsr.cpp
new file mode 100644
index 00000000000000..64a2f109926284
--- /dev/null
+++ b/libc/src/stdfix/countlsr.cpp
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsr, (fract x)) { return fixed_point::countls(x); }
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsr.h b/libc/src/stdfix/countlsr.h
new file mode 100644
index 00000000000000..244ff54fabe38d
--- /dev/null
+++ b/libc/src/stdfix/countlsr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsr(fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSR_H
diff --git a/libc/src/stdfix/countlsuhk.cpp b/libc/src/stdfix/countlsuhk.cpp
new file mode 100644
index 00000000000000..53323e71410d50
--- /dev/null
+++ b/libc/src/stdfix/countlsuhk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsuhk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsuhk, (unsigned short accum x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsuhk.h b/libc/src/stdfix/countlsuhk.h
new file mode 100644
index 00000000000000..502d64a6ab91b0
--- /dev/null
+++ b/libc/src/stdfix/countlsuhk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSUHK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUHK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsuhk(unsigned short accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUHK_H
diff --git a/libc/src/stdfix/countlsuhr.cpp b/libc/src/stdfix/countlsuhr.cpp
new file mode 100644
index 00000000000000..7a5a9156a31ff7
--- /dev/null
+++ b/libc/src/stdfix/countlsuhr.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsuhr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsuhr, (unsigned short fract x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsuhr.h b/libc/src/stdfix/countlsuhr.h
new file mode 100644
index 00000000000000..5e31f18344a766
--- /dev/null
+++ b/libc/src/stdfix/countlsuhr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSUHR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUHR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsuhr(unsigned short fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUHR_H
diff --git a/libc/src/stdfix/countlsuk.cpp b/libc/src/stdfix/countlsuk.cpp
new file mode 100644
index 00000000000000..a47da60c80ddc3
--- /dev/null
+++ b/libc/src/stdfix/countlsuk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsuk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsuk, (unsigned accum x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsuk.h b/libc/src/stdfix/countlsuk.h
new file mode 100644
index 00000000000000..7e860f5473920a
--- /dev/null
+++ b/libc/src/stdfix/countlsuk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSUK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsuk(unsigned accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUK_H
diff --git a/libc/src/stdfix/countlsulk.cpp b/libc/src/stdfix/countlsulk.cpp
new file mode 100644
index 00000000000000..7ad9be229cba26
--- /dev/null
+++ b/libc/src/stdfix/countlsulk.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsulk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsulk, (unsigned long accum x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsulk.h b/libc/src/stdfix/countlsulk.h
new file mode 100644
index 00000000000000..d3bca83f7d2717
--- /dev/null
+++ b/libc/src/stdfix/countlsulk.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSULK_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSULK_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsulk(unsigned long accum x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSULK_H
diff --git a/libc/src/stdfix/countlsulr.cpp b/libc/src/stdfix/countlsulr.cpp
new file mode 100644
index 00000000000000..43605c0ab85ef1
--- /dev/null
+++ b/libc/src/stdfix/countlsulr.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsulr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsulr, (unsigned long fract x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsulr.h b/libc/src/stdfix/countlsulr.h
new file mode 100644
index 00000000000000..60fb22af869835
--- /dev/null
+++ b/libc/src/stdfix/countlsulr.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSULR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSULR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsulr(unsigned long fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSULR_H
diff --git a/libc/src/stdfix/countlsur.cpp b/libc/src/stdfix/countlsur.cpp
new file mode 100644
index 00000000000000..cf2e7c6731b664
--- /dev/null
+++ b/libc/src/stdfix/countlsur.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "countlsur.h"
+#include "src/__support/common.h"
+#include "src/__support/fixed_point/fx_bits.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, countlsur, (unsigned fract x)) {
+ return fixed_point::countls(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/countlsur.h b/libc/src/stdfix/countlsur.h
new file mode 100644
index 00000000000000..461ee1e87739c8
--- /dev/null
+++ b/libc/src/stdfix/countlsur.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_COUNTLSUR_H
+#define LLVM_LIBC_SRC_STDFIX_COUNTLSUR_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int countlsur(unsigned fract x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_COUNTLSUR_H
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index 74a1fb13127cc3..2e1b8e1f6ab628 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -4,6 +4,23 @@ endif()
add_custom_target(libc-stdfix-tests)
+foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+ add_libc_test(
+ countls${suffix}_test
+ SUITE
+ libc-stdfix-tests
+ HDRS
+ CountlsTest.h
+ SRCS
+ countls${suffix}_test.cpp
+ COMPILE_OPTIONS
+ -O3
+ DEPENDS
+ libc.src.stdfix.countls${suffix}
+ libc.src.__support.fixed_point.fx_rep
+ )
+endforeach()
+
foreach(suffix IN ITEMS hr r lr hk k lk)
add_libc_test(
abs${suffix}_test
diff --git a/libc/test/src/stdfix/CountlsTest.h b/libc/test/src/stdfix/CountlsTest.h
new file mode 100644
index 00000000000000..64eeee2bf98077
--- /dev/null
+++ b/libc/test/src/stdfix/CountlsTest.h
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 CountlsTest : 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();
+ static constexpr T eps = FXRep::EPS();
+
+public:
+ typedef int (*CountlsFunc)(T);
+
+ void testSpecialNumbers(CountlsFunc func) {
+ constexpr bool is_signed = (min != zero);
+
+ EXPECT_EQ(FXRep::INTEGRAL_LEN, func(one_half));
+ EXPECT_EQ(FXRep::INTEGRAL_LEN + 1, func(one_fourth));
+ EXPECT_EQ(FXRep::VALUE_LEN, func(zero));
+ EXPECT_EQ(FXRep::VALUE_LEN - 1, func(eps));
+ EXPECT_EQ(0, func(max));
+ // If signed, left shifting the minimum value will overflow, so countls = 0.
+ // If unsigned, the minimum value is zero, so countls is the number of value
+ // bits according to ISO/IEC TR 18037.
+ EXPECT_EQ(is_signed ? 0 : FXRep::VALUE_LEN, func(min));
+
+ if constexpr (is_signed) {
+ EXPECT_EQ(FXRep::VALUE_LEN, func(-eps));
+ }
+ }
+};
+
+#define LIST_COUNTLS_TESTS(T, func) \
+ using LlvmLibcCountlsTest = CountlsTest<T>; \
+ TEST_F(LlvmLibcCountlsTest, SpecialNumbers) { testSpecialNumbers(&func); } \
+ static_assert(true, "Require semicolon.")
diff --git a/libc/test/src/stdfix/countlshk_test.cpp b/libc/test/src/stdfix/countlshk_test.cpp
new file mode 100644
index 00000000000000..5372c8fa572310
--- /dev/null
+++ b/libc/test/src/stdfix/countlshk_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlshk.h"
+
+LIST_COUNTLS_TESTS(short accum, LIBC_NAMESPACE::countlshk);
diff --git a/libc/test/src/stdfix/countlshr_test.cpp b/libc/test/src/stdfix/countlshr_test.cpp
new file mode 100644
index 00000000000000..3cec0d9fa2f97e
--- /dev/null
+++ b/libc/test/src/stdfix/countlshr_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlshr.h"
+
+LIST_COUNTLS_TESTS(short fract, LIBC_NAMESPACE::countlshr);
diff --git a/libc/test/src/stdfix/countlsk_test.cpp b/libc/test/src/stdfix/countlsk_test.cpp
new file mode 100644
index 00000000000000..0dd3b0006f6e75
--- /dev/null
+++ b/libc/test/src/stdfix/countlsk_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsk.h"
+
+LIST_COUNTLS_TESTS(accum, LIBC_NAMESPACE::countlsk);
diff --git a/libc/test/src/stdfix/countlslk_test.cpp b/libc/test/src/stdfix/countlslk_test.cpp
new file mode 100644
index 00000000000000..d0f137bc0233dd
--- /dev/null
+++ b/libc/test/src/stdfix/countlslk_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlslk.h"
+
+LIST_COUNTLS_TESTS(long accum, LIBC_NAMESPACE::countlslk);
diff --git a/libc/test/src/stdfix/countlslr_test.cpp b/libc/test/src/stdfix/countlslr_test.cpp
new file mode 100644
index 00000000000000..94e063f41ec35f
--- /dev/null
+++ b/libc/test/src/stdfix/countlslr_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlslr.h"
+
+LIST_COUNTLS_TESTS(long fract, LIBC_NAMESPACE::countlslr);
diff --git a/libc/test/src/stdfix/countlsr_test.cpp b/libc/test/src/stdfix/countlsr_test.cpp
new file mode 100644
index 00000000000000..3fb44b312c8d6e
--- /dev/null
+++ b/libc/test/src/stdfix/countlsr_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsr.h"
+
+LIST_COUNTLS_TESTS(fract, LIBC_NAMESPACE::countlsr);
diff --git a/libc/test/src/stdfix/countlsuhk_test.cpp b/libc/test/src/stdfix/countlsuhk_test.cpp
new file mode 100644
index 00000000000000..28e38eeb05aa67
--- /dev/null
+++ b/libc/test/src/stdfix/countlsuhk_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsuhk.h"
+
+LIST_COUNTLS_TESTS(unsigned short accum, LIBC_NAMESPACE::countlsuhk);
diff --git a/libc/test/src/stdfix/countlsuhr_test.cpp b/libc/test/src/stdfix/countlsuhr_test.cpp
new file mode 100644
index 00000000000000..4647b4688ef807
--- /dev/null
+++ b/libc/test/src/stdfix/countlsuhr_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsuhr.h"
+
+LIST_COUNTLS_TESTS(unsigned short fract, LIBC_NAMESPACE::countlsuhr);
diff --git a/libc/test/src/stdfix/countlsuk_test.cpp b/libc/test/src/stdfix/countlsuk_test.cpp
new file mode 100644
index 00000000000000..f2043ecc12acc7
--- /dev/null
+++ b/libc/test/src/stdfix/countlsuk_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsuk.h"
+
+LIST_COUNTLS_TESTS(unsigned accum, LIBC_NAMESPACE::countlsuk);
diff --git a/libc/test/src/stdfix/countlsulk_test.cpp b/libc/test/src/stdfix/countlsulk_test.cpp
new file mode 100644
index 00000000000000..0158ccd4ff35cc
--- /dev/null
+++ b/libc/test/src/stdfix/countlsulk_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsulk.h"
+
+LIST_COUNTLS_TESTS(unsigned long accum, LIBC_NAMESPACE::countlsulk);
diff --git a/libc/test/src/stdfix/countlsulr_test.cpp b/libc/test/src/stdfix/countlsulr_test.cpp
new file mode 100644
index 00000000000000..181b052319e92a
--- /dev/null
+++ b/libc/test/src/stdfix/countlsulr_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsulr.h"
+
+LIST_COUNTLS_TESTS(unsigned long fract, LIBC_NAMESPACE::countlsulr);
diff --git a/libc/test/src/stdfix/countlsur_test.cpp b/libc/test/src/stdfix/countlsur_test.cpp
new file mode 100644
index 00000000000000..102f250b9b908d
--- /dev/null
+++ b/libc/test/src/stdfix/countlsur_test.cpp
@@ -0,0 +1,13 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "CountlsTest.h"
+
+#include "src/stdfix/countlsur.h"
+
+LIST_COUNTLS_TESTS(unsigned fract, LIBC_NAMESPACE::countlsur);
More information about the libc-commits
mailing list