[libc-commits] [libc] [libc][stdfix] Implement fixed point fxbits functions in llvm-libc (PR #114912)

William Tran-Viet via libc-commits libc-commits at lists.llvm.org
Thu Nov 7 19:46:43 PST 2024


https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/114912

>From fdd7f3e3d3bbed4805ae63ecb7faf22a362d1786 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 30 Oct 2024 17:55:31 -0400
Subject: [PATCH] Implement fxbits

---
 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/include/CMakeLists.txt                 |  1 +
 libc/include/llvm-libc-types/CMakeLists.txt |  1 +
 libc/include/llvm-libc-types/stdfix-types.h | 17 ++++
 libc/newhdrgen/yaml/stdfix.yaml             | 87 ++++++++++++++++++++-
 libc/src/__support/fixed_point/fx_bits.h    |  6 +-
 libc/src/stdfix/CMakeLists.txt              | 13 +++
 libc/src/stdfix/hkbits.cpp                  | 19 +++++
 libc/src/stdfix/hkbits.h                    | 22 ++++++
 libc/src/stdfix/hrbits.cpp                  | 19 +++++
 libc/src/stdfix/hrbits.h                    | 22 ++++++
 libc/src/stdfix/kbits.cpp                   | 19 +++++
 libc/src/stdfix/kbits.h                     | 22 ++++++
 libc/src/stdfix/lkbits.cpp                  | 19 +++++
 libc/src/stdfix/lkbits.h                    | 22 ++++++
 libc/src/stdfix/lrbits.cpp                  | 19 +++++
 libc/src/stdfix/lrbits.h                    | 22 ++++++
 libc/src/stdfix/rbits.cpp                   | 19 +++++
 libc/src/stdfix/rbits.h                     | 22 ++++++
 libc/src/stdfix/uhkbits.cpp                 | 19 +++++
 libc/src/stdfix/uhkbits.h                   | 22 ++++++
 libc/src/stdfix/uhrbits.cpp                 | 19 +++++
 libc/src/stdfix/uhrbits.h                   | 22 ++++++
 libc/src/stdfix/ukbits.cpp                  | 19 +++++
 libc/src/stdfix/ukbits.h                    | 22 ++++++
 libc/src/stdfix/ulkbits.cpp                 | 19 +++++
 libc/src/stdfix/ulkbits.h                   | 22 ++++++
 libc/src/stdfix/ulrbits.cpp                 | 19 +++++
 libc/src/stdfix/ulrbits.h                   | 22 ++++++
 libc/src/stdfix/urbits.cpp                  | 19 +++++
 libc/src/stdfix/urbits.h                    | 22 ++++++
 libc/test/src/stdfix/CMakeLists.txt         | 18 +++++
 libc/test/src/stdfix/FxBitsTest.h           | 53 +++++++++++++
 libc/test/src/stdfix/hkbits_test.cpp        | 12 +++
 libc/test/src/stdfix/hrbits_test.cpp        | 12 +++
 libc/test/src/stdfix/kbits_test.cpp         | 12 +++
 libc/test/src/stdfix/lkbits_test.cpp        | 12 +++
 libc/test/src/stdfix/lrbits_test.cpp        | 12 +++
 libc/test/src/stdfix/rbits_test.cpp         | 12 +++
 libc/test/src/stdfix/uhkbits_test.cpp       | 13 +++
 libc/test/src/stdfix/uhrbits_test.cpp       | 13 +++
 libc/test/src/stdfix/ukbits_test.cpp        | 12 +++
 libc/test/src/stdfix/ulkbits_test.cpp       | 12 +++
 libc/test/src/stdfix/ulrbits_test.cpp       | 12 +++
 libc/test/src/stdfix/urbits_test.cpp        | 12 +++
 48 files changed, 880 insertions(+), 2 deletions(-)
 create mode 100644 libc/include/llvm-libc-types/stdfix-types.h
 create mode 100644 libc/src/stdfix/hkbits.cpp
 create mode 100644 libc/src/stdfix/hkbits.h
 create mode 100644 libc/src/stdfix/hrbits.cpp
 create mode 100644 libc/src/stdfix/hrbits.h
 create mode 100644 libc/src/stdfix/kbits.cpp
 create mode 100644 libc/src/stdfix/kbits.h
 create mode 100644 libc/src/stdfix/lkbits.cpp
 create mode 100644 libc/src/stdfix/lkbits.h
 create mode 100644 libc/src/stdfix/lrbits.cpp
 create mode 100644 libc/src/stdfix/lrbits.h
 create mode 100644 libc/src/stdfix/rbits.cpp
 create mode 100644 libc/src/stdfix/rbits.h
 create mode 100644 libc/src/stdfix/uhkbits.cpp
 create mode 100644 libc/src/stdfix/uhkbits.h
 create mode 100644 libc/src/stdfix/uhrbits.cpp
 create mode 100644 libc/src/stdfix/uhrbits.h
 create mode 100644 libc/src/stdfix/ukbits.cpp
 create mode 100644 libc/src/stdfix/ukbits.h
 create mode 100644 libc/src/stdfix/ulkbits.cpp
 create mode 100644 libc/src/stdfix/ulkbits.h
 create mode 100644 libc/src/stdfix/ulrbits.cpp
 create mode 100644 libc/src/stdfix/ulrbits.h
 create mode 100644 libc/src/stdfix/urbits.cpp
 create mode 100644 libc/src/stdfix/urbits.h
 create mode 100644 libc/test/src/stdfix/FxBitsTest.h
 create mode 100644 libc/test/src/stdfix/hkbits_test.cpp
 create mode 100644 libc/test/src/stdfix/hrbits_test.cpp
 create mode 100644 libc/test/src/stdfix/kbits_test.cpp
 create mode 100644 libc/test/src/stdfix/lkbits_test.cpp
 create mode 100644 libc/test/src/stdfix/lrbits_test.cpp
 create mode 100644 libc/test/src/stdfix/rbits_test.cpp
 create mode 100644 libc/test/src/stdfix/uhkbits_test.cpp
 create mode 100644 libc/test/src/stdfix/uhrbits_test.cpp
 create mode 100644 libc/test/src/stdfix/ukbits_test.cpp
 create mode 100644 libc/test/src/stdfix/ulkbits_test.cpp
 create mode 100644 libc/test/src/stdfix/ulrbits_test.cpp
 create mode 100644 libc/test/src/stdfix/urbits_test.cpp

diff --git a/libc/config/baremetal/arm/entrypoints.txt b/libc/config/baremetal/arm/entrypoints.txt
index 68030f7f1775b5..b85ae1119345dd 100644
--- a/libc/config/baremetal/arm/entrypoints.txt
+++ b/libc/config/baremetal/arm/entrypoints.txt
@@ -455,6 +455,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.sqrtulr
     libc.src.stdfix.uhksqrtus
     libc.src.stdfix.uksqrtui
+    libc.src.stdfix.hrbits
+    libc.src.stdfix.uhrbits
+    libc.src.stdfix.rbits
+    libc.src.stdfix.urbits
+    libc.src.stdfix.lrbits
+    libc.src.stdfix.ulrbits
+    libc.src.stdfix.hkbits
+    libc.src.stdfix.uhkbits
+    libc.src.stdfix.kbits
+    libc.src.stdfix.ukbits
+    libc.src.stdfix.lkbits
+    libc.src.stdfix.ulkbits
   )
 endif()
 
diff --git a/libc/config/baremetal/riscv/entrypoints.txt b/libc/config/baremetal/riscv/entrypoints.txt
index 5894b591072ef0..199a030ee6371e 100644
--- a/libc/config/baremetal/riscv/entrypoints.txt
+++ b/libc/config/baremetal/riscv/entrypoints.txt
@@ -450,6 +450,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.sqrtulr
     libc.src.stdfix.uhksqrtus
     libc.src.stdfix.uksqrtui
+    libc.src.stdfix.hrbits
+    libc.src.stdfix.uhrbits
+    libc.src.stdfix.rbits
+    libc.src.stdfix.urbits
+    libc.src.stdfix.lrbits
+    libc.src.stdfix.ulrbits
+    libc.src.stdfix.hkbits
+    libc.src.stdfix.uhkbits
+    libc.src.stdfix.kbits
+    libc.src.stdfix.ukbits
+    libc.src.stdfix.lkbits
+    libc.src.stdfix.ulkbits   
   )
 endif()
 
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 5c09edf7cfb266..7263f69fb08268 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -704,6 +704,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.sqrtulr
     libc.src.stdfix.uhksqrtus
     libc.src.stdfix.uksqrtui
+    libc.src.stdfix.hrbits
+    libc.src.stdfix.uhrbits
+    libc.src.stdfix.rbits
+    libc.src.stdfix.urbits
+    libc.src.stdfix.lrbits
+    libc.src.stdfix.ulrbits
+    libc.src.stdfix.hkbits
+    libc.src.stdfix.uhkbits
+    libc.src.stdfix.kbits
+    libc.src.stdfix.ukbits
+    libc.src.stdfix.lkbits
+    libc.src.stdfix.ulkbits
   )
 endif()
 
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index a2fb97d04584d5..536884779c433e 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -808,6 +808,18 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.sqrtulr
     libc.src.stdfix.uhksqrtus
     libc.src.stdfix.uksqrtui
+    libc.src.stdfix.hrbits
+    libc.src.stdfix.uhrbits
+    libc.src.stdfix.rbits
+    libc.src.stdfix.urbits
+    libc.src.stdfix.lrbits
+    libc.src.stdfix.ulrbits
+    libc.src.stdfix.hkbits
+    libc.src.stdfix.uhkbits
+    libc.src.stdfix.kbits
+    libc.src.stdfix.ukbits
+    libc.src.stdfix.lkbits
+    libc.src.stdfix.ulkbits
   )
 endif()
 
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 5deb5258d532fe..8e687c43c2e4fe 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -178,6 +178,7 @@ add_header_macro(
   stdfix.h
   DEPENDS
     .llvm-libc-macros.stdfix_macros
+    .llvm-libc-types.stdfix-types
 )
 
 # TODO: This should be conditional on POSIX networking being included.
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 836e8a507bd6f2..1dadfb1606a950 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -154,3 +154,4 @@ DEPENDS
 )
 add_header(locale_t HDR locale_t.h)
 add_header(struct_lconv HDR struct_lconv.h)
+add_header(stdfix-types HDR stdfix-types.h)
diff --git a/libc/include/llvm-libc-types/stdfix-types.h b/libc/include/llvm-libc-types/stdfix-types.h
new file mode 100644
index 00000000000000..26195948552af2
--- /dev/null
+++ b/libc/include/llvm-libc-types/stdfix-types.h
@@ -0,0 +1,17 @@
+#ifndef LLVM_LIBC_TYPES_STDFIX_TYPES_H
+#define LLVM_LIBC_TYPES_STDFIX_TYPES_H
+
+typedef signed char int_hr_t;
+typedef signed short int int_r_t;
+typedef signed int int_lr_t;
+typedef signed short int_hk_t;
+typedef signed int int_k_t;
+typedef signed long int_lk_t;
+typedef unsigned char uint_uhr_t;
+typedef unsigned short int uint_ur_t;
+typedef unsigned int uint_ulr_t;
+typedef unsigned short int uint_uhk_t;
+typedef unsigned int uint_uk_t;
+typedef unsigned long uint_ulk_t;
+
+#endif // LLVM_LIBC_TYPES_STDFIX_TYPES_H
diff --git a/libc/newhdrgen/yaml/stdfix.yaml b/libc/newhdrgen/yaml/stdfix.yaml
index ca6658939e2278..9787eaba45e4ed 100644
--- a/libc/newhdrgen/yaml/stdfix.yaml
+++ b/libc/newhdrgen/yaml/stdfix.yaml
@@ -1,6 +1,7 @@
 header: stdfix.h
 macros: []
-types: []
+types: 
+  - type_name: stdfix-types
 enums: []
 objects: []
 functions:
@@ -62,6 +63,90 @@ functions:
     arguments:
       - type: accum
     guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: hrbits
+    standards:
+      - stdc_ext
+    return_type: short fract
+    arguments:
+      - type: int_hr_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: uhrbits
+    standards:
+      - stdc_ext
+    return_type: unsigned short fract
+    arguments:
+      - type: uint_uhr_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: rbits
+    standards:
+      - stdc_ext
+    return_type: fract
+    arguments:
+      - type: int_r_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: urbits
+    standards:
+      - stdc_ext
+    return_type: unsigned fract
+    arguments:
+      - type: uint_ur_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: lrbits
+    standards:
+      - stdc_ext
+    return_type: long fract
+    arguments:
+      - type: int_lr_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: ulrbits
+    standards:
+      - stdc_ext
+    return_type: unsigned long fract
+    arguments:
+      - type: uint_ulr_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: hkbits
+    standards:
+      - stdc_ext
+    return_type: short accum
+    arguments:
+      - type: int_hk_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: uhkbits
+    standards:
+      - stdc_ext
+    return_type: unsigned short accum
+    arguments:
+      - type: uint_uhk_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: kbits
+    standards:
+      - stdc_ext
+    return_type: accum
+    arguments:
+      - type: int_k_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: ukbits
+    standards:
+      - stdc_ext
+    return_type: unsigned accum
+    arguments:
+      - type: uint_uk_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: lkbits
+    standards:
+      - stdc_ext
+    return_type: long accum
+    arguments:
+      - type: uint_ulr_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
+  - name: ulkbits
+    standards:
+      - stdc_ext
+    return_type: unsigned long accum
+    arguments:
+      - type: uint_ulk_t
+    guard: LIBC_COMPILER_HAS_FIXED_POINT
   - name: roundhk
     standards:
       - stdc_ext
diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 0a4c21fb6a14f7..913c65ea5b599b 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -12,7 +12,7 @@
 #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/attributes.h" // LIBC_INLINE
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 #include "src/__support/math_extras.h"
@@ -163,6 +163,10 @@ template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
   return bit_and((x + round_bit), rounding_mask);
 }
 
+template <typename T, typename XType> LIBC_INLINE constexpr T fx_bits(XType x) {
+  return cpp::bit_cast<T, XType>(x);
+}
+
 } // namespace fixed_point
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 10d76ae31349f9..689ddc4c26a0f9 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -37,9 +37,22 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
       round${suffix}.h
     SRCS
       round${suffix}.cpp
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
+
+foreach(prefix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+  add_entrypoint_object(
+    ${prefix}bits
+    HDRS
+      ${prefix}bits.h
+    SRCS
+      ${prefix}bits.cpp
     COMPILE_OPTIONS
       -O3
     DEPENDS
+      libc.src.__support.CPP.bit
       libc.src.__support.fixed_point.fx_bits
   )
 endforeach()
diff --git a/libc/src/stdfix/hkbits.cpp b/libc/src/stdfix/hkbits.cpp
new file mode 100644
index 00000000000000..e74530e1628cfa
--- /dev/null
+++ b/libc/src/stdfix/hkbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of hkbits 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 "hkbits.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(short accum, hkbits, (int_hk_t x)) {
+  return fixed_point::fx_bits<short accum, int_hk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/hkbits.h b/libc/src/stdfix/hkbits.h
new file mode 100644
index 00000000000000..bf1bf82f9f4458
--- /dev/null
+++ b/libc/src/stdfix/hkbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for hkbits ------------------------*- 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_HKBITS_H
+#define LLVM_LIBC_SRC_STDFIX_HKBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+short accum hkbits(int_hk_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_HKBITS_H
diff --git a/libc/src/stdfix/hrbits.cpp b/libc/src/stdfix/hrbits.cpp
new file mode 100644
index 00000000000000..0b429805416b89
--- /dev/null
+++ b/libc/src/stdfix/hrbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of hrbits 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 "hrbits.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(short fract, hrbits, (int_hr_t x)) {
+  return fixed_point::fx_bits<short fract, int_hr_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/hrbits.h b/libc/src/stdfix/hrbits.h
new file mode 100644
index 00000000000000..c6bd99a2acb195
--- /dev/null
+++ b/libc/src/stdfix/hrbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for hrbits ------------------------*- 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_HRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_HRBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+short fract hrbits(int_hr_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_HRBITS_H
diff --git a/libc/src/stdfix/kbits.cpp b/libc/src/stdfix/kbits.cpp
new file mode 100644
index 00000000000000..8a4be67899dafb
--- /dev/null
+++ b/libc/src/stdfix/kbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of kbits 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 "kbits.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(accum, kbits, (int_k_t x)) {
+  return fixed_point::fx_bits<accum, int_k_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/kbits.h b/libc/src/stdfix/kbits.h
new file mode 100644
index 00000000000000..7e709af442466a
--- /dev/null
+++ b/libc/src/stdfix/kbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for kbits -------------------------*- 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_KBITS_H
+#define LLVM_LIBC_SRC_STDFIX_KBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+accum kbits(int_k_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_KBITS_H
diff --git a/libc/src/stdfix/lkbits.cpp b/libc/src/stdfix/lkbits.cpp
new file mode 100644
index 00000000000000..828bd6d1d20c1e
--- /dev/null
+++ b/libc/src/stdfix/lkbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of lkbits 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 "lkbits.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(long accum, lkbits, (int_lk_t x)) {
+  return fixed_point::fx_bits<long accum, int_lk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/lkbits.h b/libc/src/stdfix/lkbits.h
new file mode 100644
index 00000000000000..177f121e2358e8
--- /dev/null
+++ b/libc/src/stdfix/lkbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for lkbits ------------------------*- 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_LKBITS_H
+#define LLVM_LIBC_SRC_STDFIX_LKBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+long accum lkbits(int_lk_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_LKBITS_H
diff --git a/libc/src/stdfix/lrbits.cpp b/libc/src/stdfix/lrbits.cpp
new file mode 100644
index 00000000000000..206f26cb1c7aa9
--- /dev/null
+++ b/libc/src/stdfix/lrbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of lrbits 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 "lrbits.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(long fract, lrbits, (int_lr_t x)) {
+  return fixed_point::fx_bits<long fract, int_lr_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/lrbits.h b/libc/src/stdfix/lrbits.h
new file mode 100644
index 00000000000000..087aa19779e62c
--- /dev/null
+++ b/libc/src/stdfix/lrbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for lrbits ------------------------*- 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_LRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_LRBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+long fract lrbits(int_lr_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_LRBITS_H
diff --git a/libc/src/stdfix/rbits.cpp b/libc/src/stdfix/rbits.cpp
new file mode 100644
index 00000000000000..f00634b1b83c18
--- /dev/null
+++ b/libc/src/stdfix/rbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of rbits 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 "rbits.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(fract, rbits, (int_r_t x)) {
+  return fixed_point::fx_bits<fract, int_r_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/rbits.h b/libc/src/stdfix/rbits.h
new file mode 100644
index 00000000000000..4922e1c3a2e5fa
--- /dev/null
+++ b/libc/src/stdfix/rbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for rbits -------------------------*- 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_RBITS_H
+#define LLVM_LIBC_SRC_STDFIX_RBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+fract rbits(int_r_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_RBITS_H
diff --git a/libc/src/stdfix/uhkbits.cpp b/libc/src/stdfix/uhkbits.cpp
new file mode 100644
index 00000000000000..1549dcc864f9f0
--- /dev/null
+++ b/libc/src/stdfix/uhkbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of uhkbits 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 "uhkbits.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(unsigned short accum, uhkbits, (uint_uhk_t x)) {
+  return fixed_point::fx_bits<unsigned short accum, uint_uhk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/uhkbits.h b/libc/src/stdfix/uhkbits.h
new file mode 100644
index 00000000000000..7ef15986f696ce
--- /dev/null
+++ b/libc/src/stdfix/uhkbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for uhkbits -----------------------*- 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_UHKBITS_H
+#define LLVM_LIBC_SRC_STDFIX_UHKBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned short accum uhkbits(uint_uhk_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_UHKBITS_H
diff --git a/libc/src/stdfix/uhrbits.cpp b/libc/src/stdfix/uhrbits.cpp
new file mode 100644
index 00000000000000..c73189d50dc03b
--- /dev/null
+++ b/libc/src/stdfix/uhrbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of uhrbits 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 "uhrbits.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(unsigned short fract, uhrbits, (uint_uhr_t x)) {
+  return fixed_point::fx_bits<unsigned short fract, uint_uhr_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/uhrbits.h b/libc/src/stdfix/uhrbits.h
new file mode 100644
index 00000000000000..4011a0e118c7bc
--- /dev/null
+++ b/libc/src/stdfix/uhrbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for uhrbits -----------------------*- 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_UHRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_UHRBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned short fract uhrbits(uint_uhr_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_UHRBITS_H
diff --git a/libc/src/stdfix/ukbits.cpp b/libc/src/stdfix/ukbits.cpp
new file mode 100644
index 00000000000000..d8b66c792d6c1f
--- /dev/null
+++ b/libc/src/stdfix/ukbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ukbits 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 "ukbits.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(unsigned accum, ukbits, (uint_uk_t x)) {
+  return fixed_point::fx_bits<unsigned accum, uint_uk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/ukbits.h b/libc/src/stdfix/ukbits.h
new file mode 100644
index 00000000000000..2374f48a4dbb69
--- /dev/null
+++ b/libc/src/stdfix/ukbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for ukbits ------------------------*- 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_UKBITS_H
+#define LLVM_LIBC_SRC_STDFIX_UKBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned accum ukbits(uint_uk_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_UKBITS_H
diff --git a/libc/src/stdfix/ulkbits.cpp b/libc/src/stdfix/ulkbits.cpp
new file mode 100644
index 00000000000000..2fa75dab837953
--- /dev/null
+++ b/libc/src/stdfix/ulkbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ulkbits 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 "ulkbits.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(unsigned long accum, ulkbits, (uint_ulk_t x)) {
+  return fixed_point::fx_bits<unsigned long accum, uint_ulk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/ulkbits.h b/libc/src/stdfix/ulkbits.h
new file mode 100644
index 00000000000000..955c96c6a49577
--- /dev/null
+++ b/libc/src/stdfix/ulkbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for ulkbits -----------------------*- 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_ULKBITS_H
+#define LLVM_LIBC_SRC_STDFIX_ULKBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long accum ulkbits(uint_ulk_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_ULKBITS_H
diff --git a/libc/src/stdfix/ulrbits.cpp b/libc/src/stdfix/ulrbits.cpp
new file mode 100644
index 00000000000000..5814c650f204a7
--- /dev/null
+++ b/libc/src/stdfix/ulrbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of ulrbits 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 "ulrbits.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(unsigned long fract, ulrbits, (uint_ulr_t x)) {
+  return fixed_point::fx_bits<unsigned long fract, uint_ulr_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/ulrbits.h b/libc/src/stdfix/ulrbits.h
new file mode 100644
index 00000000000000..7ae49ba212b720
--- /dev/null
+++ b/libc/src/stdfix/ulrbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for ulrbits -----------------------*- 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_ULRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_ULRBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long fract ulrbits(uint_ulr_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_ULRBITS_H
diff --git a/libc/src/stdfix/urbits.cpp b/libc/src/stdfix/urbits.cpp
new file mode 100644
index 00000000000000..b29aafb3982fde
--- /dev/null
+++ b/libc/src/stdfix/urbits.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of urbits 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 "urbits.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(unsigned fract, urbits, (uint_ur_t x)) {
+  return fixed_point::fx_bits<unsigned fract, uint_ur_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/urbits.h b/libc/src/stdfix/urbits.h
new file mode 100644
index 00000000000000..8fc0881cf645b9
--- /dev/null
+++ b/libc/src/stdfix/urbits.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for urbits ------------------------*- 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_URBITS_H
+#define LLVM_LIBC_SRC_STDFIX_URBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned fract urbits(uint_ur_t x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STDFIX_URBITS_H
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index 74a1fb13127cc3..db9d7d46d8b88d 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -59,6 +59,24 @@ foreach(suffix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
   )
 endforeach()
 
+foreach(prefix IN ITEMS hr r lr hk k lk uhr ur ulr uhk uk ulk)
+  add_libc_test(
+    ${prefix}bits_test
+    SUITE
+      libc-stdfix-tests
+    HDRS
+      FxBitsTest.h
+    SRCS
+      ${prefix}bits_test.cpp
+    COMPILE_OPTIONS
+      -O3
+    DEPENDS
+      libc.src.stdfix.${prefix}bits
+      libc.src.__support.CPP.bit
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
+
 add_libc_test(
   uhksqrtus_test
   SUITE
diff --git a/libc/test/src/stdfix/FxBitsTest.h b/libc/test/src/stdfix/FxBitsTest.h
new file mode 100644
index 00000000000000..b2c70de1d9fcb4
--- /dev/null
+++ b/libc/test/src/stdfix/FxBitsTest.h
@@ -0,0 +1,53 @@
+//===-- Utility class to test int to fixed point conversions ----*- 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 "include/llvm-libc-types/stdfix-types.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/fixed_point/fx_bits.h"
+template <typename T, typename XType>
+class FxBitsTest : 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 quarter = static_cast<T>(0.25);
+  static constexpr T one =
+      (FXRep::INTEGRAL_LEN > 0) ? static_cast<T>(1) : FXRep::MAX();
+  static constexpr T eps = FXRep::EPS();
+  constexpr XType get_one_or_saturated_fraction() {
+    if (FXRep::INTEGRAL_LEN > 0) {
+      return (XType)((XType)0x1 << FXRep::FRACTION_LEN);
+    } else {
+      return (
+          XType)LIBC_NAMESPACE::mask_trailing_ones<typename FXRep::StorageType,
+                                                   FXRep::FRACTION_LEN>();
+    }
+  }
+
+public:
+  typedef T (*FxBitsFunc)(XType);
+
+  void test_special_numbers(FxBitsFunc func) {
+    EXPECT_EQ(zero, func(0));
+    EXPECT_EQ(eps, func(0x1));
+    EXPECT_EQ(half, func((XType)0x1 << (FXRep::FRACTION_LEN - 1)));
+    // Occupy the bit to the left of the fixed point for Accum types
+    // Saturate fraction portion for Fract types
+    EXPECT_EQ(one, func(get_one_or_saturated_fraction()));
+  }
+};
+
+#define LIST_FXBITS_TEST(Name, T, XType, func)                                 \
+  using LlvmLibc##Name##BitsTest = FxBitsTest<T, XType>;                       \
+  TEST_F(LlvmLibc##Name##BitsTest, SpecialNumbers) {                           \
+    test_special_numbers(&func);                                               \
+  }                                                                            \
+  static_assert(true, "Require semicolon.")
diff --git a/libc/test/src/stdfix/hkbits_test.cpp b/libc/test/src/stdfix/hkbits_test.cpp
new file mode 100644
index 00000000000000..c4b55e13502b55
--- /dev/null
+++ b/libc/test/src/stdfix/hkbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for hkbits ----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/hkbits.h"
+
+LIST_FXBITS_TEST(hk, short accum, int_hk_t, LIBC_NAMESPACE::hkbits);
diff --git a/libc/test/src/stdfix/hrbits_test.cpp b/libc/test/src/stdfix/hrbits_test.cpp
new file mode 100644
index 00000000000000..d47456a8b1d6ed
--- /dev/null
+++ b/libc/test/src/stdfix/hrbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for hrbits ----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/hrbits.h"
+
+LIST_FXBITS_TEST(hr, short fract, int_hr_t, LIBC_NAMESPACE::hrbits);
diff --git a/libc/test/src/stdfix/kbits_test.cpp b/libc/test/src/stdfix/kbits_test.cpp
new file mode 100644
index 00000000000000..f646e13badc8f2
--- /dev/null
+++ b/libc/test/src/stdfix/kbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for kbits -----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/kbits.h"
+
+LIST_FXBITS_TEST(k, accum, int_k_t, LIBC_NAMESPACE::kbits);
diff --git a/libc/test/src/stdfix/lkbits_test.cpp b/libc/test/src/stdfix/lkbits_test.cpp
new file mode 100644
index 00000000000000..f8fd3a69a2b739
--- /dev/null
+++ b/libc/test/src/stdfix/lkbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for lkbits ----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/lkbits.h"
+
+LIST_FXBITS_TEST(lk, long accum, int_lk_t, LIBC_NAMESPACE::lkbits);
diff --git a/libc/test/src/stdfix/lrbits_test.cpp b/libc/test/src/stdfix/lrbits_test.cpp
new file mode 100644
index 00000000000000..881a8c980642bf
--- /dev/null
+++ b/libc/test/src/stdfix/lrbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for lrbits ----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/lrbits.h"
+
+LIST_FXBITS_TEST(lr, long fract, int_lr_t, LIBC_NAMESPACE::lrbits);
diff --git a/libc/test/src/stdfix/rbits_test.cpp b/libc/test/src/stdfix/rbits_test.cpp
new file mode 100644
index 00000000000000..12c95a5816a2e2
--- /dev/null
+++ b/libc/test/src/stdfix/rbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for rbits -----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/rbits.h"
+
+LIST_FXBITS_TEST(r, fract, int_r_t, LIBC_NAMESPACE::rbits);
diff --git a/libc/test/src/stdfix/uhkbits_test.cpp b/libc/test/src/stdfix/uhkbits_test.cpp
new file mode 100644
index 00000000000000..b57e23b1cffd64
--- /dev/null
+++ b/libc/test/src/stdfix/uhkbits_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for uhkbits ---------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/uhkbits.h"
+
+LIST_FXBITS_TEST(uhk, unsigned short accum, uint_uhk_t,
+                 LIBC_NAMESPACE::uhkbits);
diff --git a/libc/test/src/stdfix/uhrbits_test.cpp b/libc/test/src/stdfix/uhrbits_test.cpp
new file mode 100644
index 00000000000000..1a9d2c6cecca20
--- /dev/null
+++ b/libc/test/src/stdfix/uhrbits_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for uhrbits ---------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/uhrbits.h"
+
+LIST_FXBITS_TEST(uhr, unsigned short fract, uint_uhr_t,
+                 LIBC_NAMESPACE::uhrbits);
diff --git a/libc/test/src/stdfix/ukbits_test.cpp b/libc/test/src/stdfix/ukbits_test.cpp
new file mode 100644
index 00000000000000..bad707f49474b8
--- /dev/null
+++ b/libc/test/src/stdfix/ukbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for ukbits ----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/ukbits.h"
+
+LIST_FXBITS_TEST(uk, unsigned accum, uint_uk_t, LIBC_NAMESPACE::ukbits);
diff --git a/libc/test/src/stdfix/ulkbits_test.cpp b/libc/test/src/stdfix/ulkbits_test.cpp
new file mode 100644
index 00000000000000..3ee54be4c4f003
--- /dev/null
+++ b/libc/test/src/stdfix/ulkbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for ulkbits ---------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/ulkbits.h"
+
+LIST_FXBITS_TEST(ulk, unsigned long accum, uint_ulk_t, LIBC_NAMESPACE::ulkbits);
diff --git a/libc/test/src/stdfix/ulrbits_test.cpp b/libc/test/src/stdfix/ulrbits_test.cpp
new file mode 100644
index 00000000000000..a248deb6e5aad3
--- /dev/null
+++ b/libc/test/src/stdfix/ulrbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for ulrbits ---------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/ulrbits.h"
+
+LIST_FXBITS_TEST(ulr, unsigned long fract, uint_ulr_t, LIBC_NAMESPACE::ulrbits);
diff --git a/libc/test/src/stdfix/urbits_test.cpp b/libc/test/src/stdfix/urbits_test.cpp
new file mode 100644
index 00000000000000..285b0170a3bf38
--- /dev/null
+++ b/libc/test/src/stdfix/urbits_test.cpp
@@ -0,0 +1,12 @@
+//===-- Unittests for urbits ----------------------------------------------===//
+//
+// 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 "FxBitsTest.h"
+#include "src/stdfix/urbits.h"
+
+LIST_FXBITS_TEST(ur, unsigned fract, uint_ur_t, LIBC_NAMESPACE::urbits);



More information about the libc-commits mailing list