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

William Tran-Viet via libc-commits libc-commits at lists.llvm.org
Sat Nov 2 21:24:29 PDT 2024


https://github.com/smallp-o-p created https://github.com/llvm/llvm-project/pull/114694

Still a bit unsure on the base type choices for the u?int_fx_t types, would like some input on that. 

>From 5525a44c1213aa414b80a2798572b38cb6800703 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 1/9] Add fxbits functions to be generated into stdfix.h: Add
 each function to stdfix.yaml, and to entrypoints.txt for each target that
 supports stdfix. Also create files to be filled in.

---
 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/newhdrgen/yaml/stdfix.yaml             | 87 ++++++++++++++++++++-
 libc/src/stdfix/CMakeLists.txt              | 14 ++++
 libc/src/stdfix/hkbits.cpp                  |  0
 libc/src/stdfix/hkbits.h                    |  0
 libc/src/stdfix/hrbits.cpp                  | 12 +++
 libc/src/stdfix/hrbits.h                    | 11 +++
 libc/src/stdfix/kbits.cpp                   |  0
 libc/src/stdfix/kbits.h                     |  0
 libc/src/stdfix/lkbits.cpp                  |  0
 libc/src/stdfix/lkbits.h                    |  0
 libc/src/stdfix/lrbits.cpp                  |  0
 libc/src/stdfix/lrbits.h                    |  0
 libc/src/stdfix/rbits.cpp                   |  0
 libc/src/stdfix/rbits.h                     |  0
 libc/src/stdfix/uhkbits.cpp                 |  0
 libc/src/stdfix/uhkbits.h                   |  0
 libc/src/stdfix/uhrbits.cpp                 |  0
 libc/src/stdfix/uhrbits.h                   |  0
 libc/src/stdfix/ukbits.cpp                  |  0
 libc/src/stdfix/ukbits.h                    |  0
 libc/src/stdfix/ulkbits.cpp                 |  0
 libc/src/stdfix/ulkbits.h                   |  0
 libc/src/stdfix/ulrbits.cpp                 |  0
 libc/src/stdfix/ulrbits.h                   |  0
 libc/src/stdfix/urbits.cpp                  |  0
 libc/src/stdfix/urbits.h                    |  0
 30 files changed, 171 insertions(+), 1 deletion(-)
 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

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/newhdrgen/yaml/stdfix.yaml b/libc/newhdrgen/yaml/stdfix.yaml
index ca6658939e2278..72a9c7cc774eeb 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_t
 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/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
index 10d76ae31349f9..cac0e15dbdf349 100644
--- a/libc/src/stdfix/CMakeLists.txt
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -44,6 +44,20 @@ 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_entrypoint_object(
+    ${prefix}bits
+    HDRS
+      ${prefix}bits.h
+    SRCS
+      ${prefix}bits.cpp
+    COMPILE_OPTIONS
+      -O3
+    DEPENDS
+      libc.src.__support.fixed_point.fx_bits
+  )
+endforeach()
+
 add_entrypoint_object(
   uhksqrtus
   HDRS
diff --git a/libc/src/stdfix/hkbits.cpp b/libc/src/stdfix/hkbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/hkbits.h b/libc/src/stdfix/hkbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/hrbits.cpp b/libc/src/stdfix/hrbits.cpp
new file mode 100644
index 00000000000000..cd7fbb9648d5b0
--- /dev/null
+++ b/libc/src/stdfix/hrbits.cpp
@@ -0,0 +1,12 @@
+#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::bits(x);
+}
+
+}
diff --git a/libc/src/stdfix/hrbits.h b/libc/src/stdfix/hrbits.h
new file mode 100644
index 00000000000000..e66192b8ee4d2d
--- /dev/null
+++ b/libc/src/stdfix/hrbits.h
@@ -0,0 +1,11 @@
+#ifndef LLVM_LIBC_SRC_STDFIX_HRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_HRBITS_H
+    
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+short fract hrbits(int_hr_t x); 
+
+}
+#endif 
diff --git a/libc/src/stdfix/kbits.cpp b/libc/src/stdfix/kbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/kbits.h b/libc/src/stdfix/kbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/lkbits.cpp b/libc/src/stdfix/lkbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/lkbits.h b/libc/src/stdfix/lkbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/lrbits.cpp b/libc/src/stdfix/lrbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/lrbits.h b/libc/src/stdfix/lrbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/rbits.cpp b/libc/src/stdfix/rbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/rbits.h b/libc/src/stdfix/rbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/uhkbits.cpp b/libc/src/stdfix/uhkbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/uhkbits.h b/libc/src/stdfix/uhkbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/uhrbits.cpp b/libc/src/stdfix/uhrbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/uhrbits.h b/libc/src/stdfix/uhrbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/ukbits.cpp b/libc/src/stdfix/ukbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/ukbits.h b/libc/src/stdfix/ukbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/ulkbits.cpp b/libc/src/stdfix/ulkbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/ulkbits.h b/libc/src/stdfix/ulkbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/ulrbits.cpp b/libc/src/stdfix/ulrbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/ulrbits.h b/libc/src/stdfix/ulrbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/urbits.cpp b/libc/src/stdfix/urbits.cpp
new file mode 100644
index 00000000000000..e69de29bb2d1d6
diff --git a/libc/src/stdfix/urbits.h b/libc/src/stdfix/urbits.h
new file mode 100644
index 00000000000000..e69de29bb2d1d6

>From 63fe052d1ab25a20190c0821d658ee50235d2c13 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 30 Oct 2024 18:39:35 -0400
Subject: [PATCH 2/9] Add uint and int typedefs for arguments passed into
 fxbits(). Should come back to this later.

---
 libc/include/llvm-libc-macros/stdfix-macros.h | 13 +++++++++++++
 libc/newhdrgen/yaml/stdfix.yaml               |  3 +--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/libc/include/llvm-libc-macros/stdfix-macros.h b/libc/include/llvm-libc-macros/stdfix-macros.h
index 554ebe544a42ed..9be7584dbaee04 100644
--- a/libc/include/llvm-libc-macros/stdfix-macros.h
+++ b/libc/include/llvm-libc-macros/stdfix-macros.h
@@ -323,6 +323,19 @@
 #define ULACCUM_EPSILON 0x1.0p-32ULK
 #endif // ULACCUM_EPSILON
 
+typedef signed char int_hr_t;
+typedef unsigned char uint_uhr_t;
+typedef signed short int int_r_t;
+typedef unsigned short int uint_ur_t;
+typedef signed int int_lr_t;
+typedef unsigned int uint_ulr_t;
+typedef signed short int_hk_t;
+typedef unsigned short uint_uhk_t;
+typedef signed int int_k_t;
+typedef unsigned int uint_uk_t;
+typedef signed long int_lk_t;
+typedef unsigned long uint_ulk_t;
+
 #endif // LIBC_COMPILER_HAS_FIXED_POINT
 
 #endif // LLVM_LIBC_MACROS_STDFIX_MACROS_H
diff --git a/libc/newhdrgen/yaml/stdfix.yaml b/libc/newhdrgen/yaml/stdfix.yaml
index 72a9c7cc774eeb..02fb7adb1fed8c 100644
--- a/libc/newhdrgen/yaml/stdfix.yaml
+++ b/libc/newhdrgen/yaml/stdfix.yaml
@@ -1,7 +1,6 @@
 header: stdfix.h
 macros: []
-types: 
-  - type_name: stdfix_t
+types: []
 enums: []
 objects: []
 functions:

>From 072b6f27c9c01ca1035f418c8be7124463e3c6d8 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 30 Oct 2024 22:10:57 -0400
Subject: [PATCH 3/9] Implement fxbits()

---
 libc/src/__support/fixed_point/fx_bits.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 0a4c21fb6a14f7..448845103ccddb 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -163,6 +163,13 @@ template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
   return bit_and((x + round_bit), rounding_mask);
 }
 
+// u?int_fx_t --> Fixed point
+template <typename T, typename XType> LIBC_INLINE constexpr T fxbits(XType x) {
+  // Example: rbits(0x2000) where fract has 15 fractional bits, 
+  // 0x2000 --> 0010 0000 0000 0000 --> 0.010 0000 0000 0000 = 0.25  
+
+  return cpp::bit_cast<T, XType>(x); 
+}
 } // namespace fixed_point
 } // namespace LIBC_NAMESPACE_DECL
 

>From cba0fe09c918ab91929bf4310c42ea0dee9bbcbc Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 30 Oct 2024 22:11:33 -0400
Subject: [PATCH 4/9] Implement rbits and add a test fixture

---
 libc/src/stdfix/rbits.cpp           | 13 ++++++++++
 libc/src/stdfix/rbits.h             | 12 ++++++++++
 libc/test/src/stdfix/CMakeLists.txt | 17 +++++++++++++
 libc/test/src/stdfix/FxbitsTest.h   | 37 +++++++++++++++++++++++++++++
 libc/test/src/stdfix/rbits_test.cpp |  7 ++++++
 5 files changed, 86 insertions(+)
 create mode 100644 libc/test/src/stdfix/FxbitsTest.h
 create mode 100644 libc/test/src/stdfix/rbits_test.cpp

diff --git a/libc/src/stdfix/rbits.cpp b/libc/src/stdfix/rbits.cpp
index e69de29bb2d1d6..9a2fd3a2f82469 100644
--- a/libc/src/stdfix/rbits.cpp
+++ b/libc/src/stdfix/rbits.cpp
@@ -0,0 +1,13 @@
+#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::fxbits<fract, int_r_t>(x);
+}
+
+}
diff --git a/libc/src/stdfix/rbits.h b/libc/src/stdfix/rbits.h
index e69de29bb2d1d6..4ac494d7ce530b 100644
--- a/libc/src/stdfix/rbits.h
+++ b/libc/src/stdfix/rbits.h
@@ -0,0 +1,12 @@
+#ifndef LLVM_LIBC_SRC_STDFIX_HRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_HRBITS_H
+    
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+fract rbits(int_r_t x); 
+
+}
+
+#endif 
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
index 74a1fb13127cc3..d7369885335cf8 100644
--- a/libc/test/src/stdfix/CMakeLists.txt
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -59,6 +59,23 @@ 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.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..d698f140a690a5
--- /dev/null
+++ b/libc/test/src/stdfix/FxbitsTest.h
@@ -0,0 +1,37 @@
+//===-- Utility class to test fxbits -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "test/UnitTest/Test.h"
+#include "src/__support/fixed_point/fx_rep.h"
+
+template <typename T, 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 neg_half = static_cast<T>(-0.5);
+    static constexpr T one =
+        (FXRep::INTEGRAL_LEN > 0) ? static_cast<T>(1) : FXRep::MAX();
+    static constexpr T neg_one = static_cast<T>(-1);
+    static constexpr T eps = FXRep::EPS();
+
+public:
+    typedef T (*FxbitsFunc)(XType); 
+
+    void testSpecialNumbers(FxbitsFunc func) {
+        EXPECT_EQ(zero, func(0));
+        EXPECT_EQ(half, func((XType) (0b1 << (FXRep::FRACTION_LEN - 1)))); // 0.1000...b
+    }
+};
+
+
+#define LIST_FXBITS_TEST(T, XType, func)                                        \
+    using LlvmLibcFxbitsTest = FxbitsTest<T, XType>;                            \  
+    TEST_F(LlvmLibcFxbitsTest, SpecialNumbers) { testSpecialNumbers(&func); }   \ 
+    static_assert(true, "Require semicolon.")
diff --git a/libc/test/src/stdfix/rbits_test.cpp b/libc/test/src/stdfix/rbits_test.cpp
new file mode 100644
index 00000000000000..c1725b2ebeaf44
--- /dev/null
+++ b/libc/test/src/stdfix/rbits_test.cpp
@@ -0,0 +1,7 @@
+
+#include "FxbitsTest.h"
+
+#include "src/stdfix/rbits.h"
+
+LIST_FXBITS_TEST(fract, int_r_t, LIBC_NAMESPACE::rbits);
+

>From 4d7163648a4987d5208dcf24d0c05746e1fdfb75 Mon Sep 17 00:00:00 2001
From: smallp-o-p <william.tranviet at gmail.com>
Date: Thu, 31 Oct 2024 21:39:31 -0400
Subject: [PATCH 5/9] Implement fxbits

---
 libc/src/__support/fixed_point/fx_bits.h | 21 ++++++++++++++++-----
 libc/src/stdfix/hkbits.cpp               | 22 ++++++++++++++++++++++
 libc/src/stdfix/hkbits.h                 | 20 ++++++++++++++++++++
 libc/src/stdfix/hrbits.cpp               | 11 ++++++++++-
 libc/src/stdfix/hrbits.h                 | 10 +++++++++-
 libc/src/stdfix/kbits.cpp                | 21 +++++++++++++++++++++
 libc/src/stdfix/kbits.h                  | 21 +++++++++++++++++++++
 libc/src/stdfix/lkbits.cpp               | 21 +++++++++++++++++++++
 libc/src/stdfix/lkbits.h                 | 19 +++++++++++++++++++
 libc/src/stdfix/lrbits.cpp               | 21 +++++++++++++++++++++
 libc/src/stdfix/lrbits.h                 | 19 +++++++++++++++++++
 libc/src/stdfix/rbits.cpp                | 12 ++++++++++--
 libc/src/stdfix/rbits.h                  | 12 ++++++++++--
 libc/src/stdfix/uhkbits.cpp              | 21 +++++++++++++++++++++
 libc/src/stdfix/uhkbits.h                | 20 ++++++++++++++++++++
 libc/src/stdfix/uhrbits.cpp              | 21 +++++++++++++++++++++
 libc/src/stdfix/uhrbits.h                | 20 ++++++++++++++++++++
 libc/src/stdfix/ukbits.cpp               | 21 +++++++++++++++++++++
 libc/src/stdfix/ukbits.h                 | 20 ++++++++++++++++++++
 libc/src/stdfix/ulkbits.cpp              | 21 +++++++++++++++++++++
 libc/src/stdfix/ulkbits.h                | 20 ++++++++++++++++++++
 libc/src/stdfix/ulrbits.cpp              | 21 +++++++++++++++++++++
 libc/src/stdfix/ulrbits.h                | 20 ++++++++++++++++++++
 libc/src/stdfix/urbits.cpp               | 21 +++++++++++++++++++++
 libc/src/stdfix/urbits.h                 | 20 ++++++++++++++++++++
 25 files changed, 465 insertions(+), 11 deletions(-)

diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 448845103ccddb..333e46de41e425 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,12 +163,23 @@ template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
   return bit_and((x + round_bit), rounding_mask);
 }
 
-// u?int_fx_t --> Fixed point
+// (u)?int_fx_t --> Fixed point
 template <typename T, typename XType> LIBC_INLINE constexpr T fxbits(XType x) {
-  // Example: rbits(0x2000) where fract has 15 fractional bits, 
-  // 0x2000 --> 0010 0000 0000 0000 --> 0.010 0000 0000 0000 = 0.25  
+  using FXRep = FXRep<T>;
+
+  // Shift number by FX_IBITS so the bits are in the right spot.
+  // If the number is negative we need to make it positive, shift it and then
+  // renegate it to get the correct value.
+  if (cpp::is_signed_v<XType> && 
+      ((1 << (FXRep::TOTAL_LEN - 1)) & x)) {
+    x = -x;
+    x >>= FXRep::INTEGRAL_LEN;
+    x = -x;
+  } else {
+    x >>= FXRep::INTEGRAL_LEN;
+  }
 
-  return cpp::bit_cast<T, XType>(x); 
+  return cpp::bit_cast<T, XType>(x);
 }
 } // namespace fixed_point
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/hkbits.cpp b/libc/src/stdfix/hkbits.cpp
index e69de29bb2d1d6..f09e92d62ed5c1 100644
--- a/libc/src/stdfix/hkbits.cpp
+++ b/libc/src/stdfix/hkbits.cpp
@@ -0,0 +1,22 @@
+//===-- 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::fxbits<short accum, int_hk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/hkbits.h b/libc/src/stdfix/hkbits.h
index e69de29bb2d1d6..9cfff9c1ef12b8 100644
--- a/libc/src/stdfix/hkbits.h
+++ b/libc/src/stdfix/hkbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+short accum hkbits(int_hk_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/hrbits.cpp b/libc/src/stdfix/hrbits.cpp
index cd7fbb9648d5b0..67a974568b9409 100644
--- a/libc/src/stdfix/hrbits.cpp
+++ b/libc/src/stdfix/hrbits.cpp
@@ -1,4 +1,13 @@
+//===-- 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"
@@ -6,7 +15,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(short fract, hrbits, (int_hr_t x)) {
-    return fixed_point::bits(x);
+    return fixed_point::fxbits(x);
 }
 
 }
diff --git a/libc/src/stdfix/hrbits.h b/libc/src/stdfix/hrbits.h
index e66192b8ee4d2d..3499e471ced4d8 100644
--- a/libc/src/stdfix/hrbits.h
+++ b/libc/src/stdfix/hrbits.h
@@ -1,6 +1,14 @@
+//===-- 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 "src/__support/macros/config.h"
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/stdfix/kbits.cpp b/libc/src/stdfix/kbits.cpp
index e69de29bb2d1d6..e49220671ef34d 100644
--- a/libc/src/stdfix/kbits.cpp
+++ b/libc/src/stdfix/kbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<accum, int_k_t>(x);
+}
+
+}
diff --git a/libc/src/stdfix/kbits.h b/libc/src/stdfix/kbits.h
index e69de29bb2d1d6..a2d2624a6793f7 100644
--- a/libc/src/stdfix/kbits.h
+++ b/libc/src/stdfix/kbits.h
@@ -0,0 +1,21 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+accum kbits(int_k_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/lkbits.cpp b/libc/src/stdfix/lkbits.cpp
index e69de29bb2d1d6..98e00bfd5e262b 100644
--- a/libc/src/stdfix/lkbits.cpp
+++ b/libc/src/stdfix/lkbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<long accum, int_lk_t>(x);
+}
+
+}
diff --git a/libc/src/stdfix/lkbits.h b/libc/src/stdfix/lkbits.h
index e69de29bb2d1d6..01c4d50f7d6f2f 100644
--- a/libc/src/stdfix/lkbits.h
+++ b/libc/src/stdfix/lkbits.h
@@ -0,0 +1,19 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+long accum lkbits(int_lk_t x); 
+
+}
+#endif 
diff --git a/libc/src/stdfix/lrbits.cpp b/libc/src/stdfix/lrbits.cpp
index e69de29bb2d1d6..8f5cf532e99221 100644
--- a/libc/src/stdfix/lrbits.cpp
+++ b/libc/src/stdfix/lrbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<long fract, int_lr_t>(x);
+}
+
+}
diff --git a/libc/src/stdfix/lrbits.h b/libc/src/stdfix/lrbits.h
index e69de29bb2d1d6..dec00b279941dc 100644
--- a/libc/src/stdfix/lrbits.h
+++ b/libc/src/stdfix/lrbits.h
@@ -0,0 +1,19 @@
+//===-- 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_LRBITS_H
+#define LLVM_LIBC_SRC_STDFIX_LRBITS_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+long fract lrbits(int_lr_t x); 
+
+}
+#endif 
diff --git a/libc/src/stdfix/rbits.cpp b/libc/src/stdfix/rbits.cpp
index 9a2fd3a2f82469..d94eb6f0c592c9 100644
--- a/libc/src/stdfix/rbits.cpp
+++ b/libc/src/stdfix/rbits.cpp
@@ -1,3 +1,11 @@
+//===-- 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"
@@ -7,7 +15,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(fract, rbits, (int_r_t x)) {
-    return fixed_point::fxbits<fract, int_r_t>(x);
+  return fixed_point::fxbits<fract, int_r_t>(x);
 }
 
-}
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/rbits.h b/libc/src/stdfix/rbits.h
index 4ac494d7ce530b..b6b80a2369b470 100644
--- a/libc/src/stdfix/rbits.h
+++ b/libc/src/stdfix/rbits.h
@@ -1,5 +1,13 @@
-#ifndef LLVM_LIBC_SRC_STDFIX_HRBITS_H
-#define LLVM_LIBC_SRC_STDFIX_HRBITS_H
+//===-- 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 "src/__support/macros/config.h"
diff --git a/libc/src/stdfix/uhkbits.cpp b/libc/src/stdfix/uhkbits.cpp
index e69de29bb2d1d6..8e2cdbb8a19a60 100644
--- a/libc/src/stdfix/uhkbits.cpp
+++ b/libc/src/stdfix/uhkbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<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
index e69de29bb2d1d6..c2be44bd96034c 100644
--- a/libc/src/stdfix/uhkbits.h
+++ b/libc/src/stdfix/uhkbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned short accum uhkbits(uint_uhk_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/uhrbits.cpp b/libc/src/stdfix/uhrbits.cpp
index e69de29bb2d1d6..bf9226a011f768 100644
--- a/libc/src/stdfix/uhrbits.cpp
+++ b/libc/src/stdfix/uhrbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<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
index e69de29bb2d1d6..fa86bcbfe311b8 100644
--- a/libc/src/stdfix/uhrbits.h
+++ b/libc/src/stdfix/uhrbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned short fract uhrbits(uint_uhr_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/ukbits.cpp b/libc/src/stdfix/ukbits.cpp
index e69de29bb2d1d6..8e8c263f958b75 100644
--- a/libc/src/stdfix/ukbits.cpp
+++ b/libc/src/stdfix/ukbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<unsigned accum, uint_uk_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/ukbits.h b/libc/src/stdfix/ukbits.h
index e69de29bb2d1d6..2eaedd7d92a3e2 100644
--- a/libc/src/stdfix/ukbits.h
+++ b/libc/src/stdfix/ukbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned accum ukbits(uint_uk_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/ulkbits.cpp b/libc/src/stdfix/ulkbits.cpp
index e69de29bb2d1d6..654463a0a682a2 100644
--- a/libc/src/stdfix/ulkbits.cpp
+++ b/libc/src/stdfix/ulkbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<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
index e69de29bb2d1d6..a922a18c72b259 100644
--- a/libc/src/stdfix/ulkbits.h
+++ b/libc/src/stdfix/ulkbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long accum ulkbits(uint_ulk_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/ulrbits.cpp b/libc/src/stdfix/ulrbits.cpp
index e69de29bb2d1d6..ad3ebf21e6295d 100644
--- a/libc/src/stdfix/ulrbits.cpp
+++ b/libc/src/stdfix/ulrbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<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
index e69de29bb2d1d6..fc5ebe9845ae80 100644
--- a/libc/src/stdfix/ulrbits.h
+++ b/libc/src/stdfix/ulrbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned long fract ulrbits(uint_ulr_t x); 
+
+}
+
+#endif 
diff --git a/libc/src/stdfix/urbits.cpp b/libc/src/stdfix/urbits.cpp
index e69de29bb2d1d6..06f47734c4ecf7 100644
--- a/libc/src/stdfix/urbits.cpp
+++ b/libc/src/stdfix/urbits.cpp
@@ -0,0 +1,21 @@
+//===-- 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::fxbits<unsigned fract, uint_ur_t>(x);
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdfix/urbits.h b/libc/src/stdfix/urbits.h
index e69de29bb2d1d6..2fbbfb68792463 100644
--- a/libc/src/stdfix/urbits.h
+++ b/libc/src/stdfix/urbits.h
@@ -0,0 +1,20 @@
+//===-- 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 "src/__support/macros/config.h"
+namespace LIBC_NAMESPACE_DECL {
+
+unsigned fract urbits(uint_ur_t x); 
+
+}
+
+#endif 

>From aec4183a3c7205ccffa62886b761f794760be227 Mon Sep 17 00:00:00 2001
From: smallp-o-p <william.tranviet at gmail.com>
Date: Sat, 2 Nov 2024 23:22:14 -0400
Subject: [PATCH 6/9] Fix shift overflow compile error

---
 libc/src/__support/fixed_point/fx_bits.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libc/src/__support/fixed_point/fx_bits.h b/libc/src/__support/fixed_point/fx_bits.h
index 333e46de41e425..6bc4cdbfcd6ff8 100644
--- a/libc/src/__support/fixed_point/fx_bits.h
+++ b/libc/src/__support/fixed_point/fx_bits.h
@@ -166,12 +166,11 @@ template <typename T> LIBC_INLINE constexpr T round(T x, int n) {
 // (u)?int_fx_t --> Fixed point
 template <typename T, typename XType> LIBC_INLINE constexpr T fxbits(XType x) {
   using FXRep = FXRep<T>;
-
   // Shift number by FX_IBITS so the bits are in the right spot.
   // If the number is negative we need to make it positive, shift it and then
   // renegate it to get the correct value.
   if (cpp::is_signed_v<XType> && 
-      ((1 << (FXRep::TOTAL_LEN - 1)) & x)) {
+      (x >> (FXRep::TOTAL_LEN - FXRep::SIGN_LEN))) {
     x = -x;
     x >>= FXRep::INTEGRAL_LEN;
     x = -x;

>From fe66e6a26bb9bf7ee63082537b8fd550df156996 Mon Sep 17 00:00:00 2001
From: smallp-o-p <william.tranviet at gmail.com>
Date: Sat, 2 Nov 2024 23:22:36 -0400
Subject: [PATCH 7/9] Specify proper fxbits template for hrbits

---
 libc/src/stdfix/hrbits.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/stdfix/hrbits.cpp b/libc/src/stdfix/hrbits.cpp
index 67a974568b9409..ece82c9e54826a 100644
--- a/libc/src/stdfix/hrbits.cpp
+++ b/libc/src/stdfix/hrbits.cpp
@@ -15,7 +15,7 @@
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(short fract, hrbits, (int_hr_t x)) {
-    return fixed_point::fxbits(x);
+    return fixed_point::fxbits<short fract, int_hr_t>(x);
 }
 
 }

>From 46b066d857a176d9e0653a1ac9079387cee8128f Mon Sep 17 00:00:00 2001
From: smallp-o-p <william.tranviet at gmail.com>
Date: Sat, 2 Nov 2024 23:23:22 -0400
Subject: [PATCH 8/9] Add test cases for all fxbits functions

---
 libc/test/src/stdfix/FxbitsTest.h     | 7 +++++--
 libc/test/src/stdfix/hkbits_test.cpp  | 4 ++++
 libc/test/src/stdfix/hrbits_test.cpp  | 4 ++++
 libc/test/src/stdfix/kbits_test.cpp   | 4 ++++
 libc/test/src/stdfix/lkbits_test.cpp  | 5 +++++
 libc/test/src/stdfix/lrbits_test.cpp  | 4 ++++
 libc/test/src/stdfix/rbits_test.cpp   | 3 ---
 libc/test/src/stdfix/uhkbits_test.cpp | 4 ++++
 libc/test/src/stdfix/uhrbits_test.cpp | 4 ++++
 libc/test/src/stdfix/ukbits_test.cpp  | 5 +++++
 libc/test/src/stdfix/ulkbits_test.cpp | 5 +++++
 libc/test/src/stdfix/ulrbits_test.cpp | 4 ++++
 libc/test/src/stdfix/urbits_test.cpp  | 4 ++++
 13 files changed, 52 insertions(+), 5 deletions(-)
 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/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/test/src/stdfix/FxbitsTest.h b/libc/test/src/stdfix/FxbitsTest.h
index d698f140a690a5..0ee58e1293b64f 100644
--- a/libc/test/src/stdfix/FxbitsTest.h
+++ b/libc/test/src/stdfix/FxbitsTest.h
@@ -27,11 +27,14 @@ template <typename T, typename XType> class FxbitsTest : public LIBC_NAMESPACE::
     void testSpecialNumbers(FxbitsFunc func) {
         EXPECT_EQ(zero, func(0));
         EXPECT_EQ(half, func((XType) (0b1 << (FXRep::FRACTION_LEN - 1)))); // 0.1000...b
+        EXPECT_EQ(min, func((XType) 0x1));
+        EXPECT_EQ(one, func(1));
+        EXPECT_EQ(neg_one, func(-1));
     }
 };
 
 
 #define LIST_FXBITS_TEST(T, XType, func)                                        \
-    using LlvmLibcFxbitsTest = FxbitsTest<T, XType>;                            \  
-    TEST_F(LlvmLibcFxbitsTest, SpecialNumbers) { testSpecialNumbers(&func); }   \ 
+    using LlvmLibcFxbitsTest = FxbitsTest<T, XType>;                            \
+    TEST_F(LlvmLibcFxbitsTest, SpecialNumbers) { testSpecialNumbers(&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..b0cda93aa5d297
--- /dev/null
+++ b/libc/test/src/stdfix/hkbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/hkbits.h"
+
+LIST_FXBITS_TEST(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..a2807b90d88a41
--- /dev/null
+++ b/libc/test/src/stdfix/hrbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/hrbits.h"
+
+LIST_FXBITS_TEST(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..b9e75ff0fa33a9
--- /dev/null
+++ b/libc/test/src/stdfix/kbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/kbits.h"
+
+LIST_FXBITS_TEST(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..d0956e0deb9d78
--- /dev/null
+++ b/libc/test/src/stdfix/lkbits_test.cpp
@@ -0,0 +1,5 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/lkbits.h"
+
+LIST_FXBITS_TEST(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..2f7b0d6dc56100
--- /dev/null
+++ b/libc/test/src/stdfix/lrbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/lrbits.h"
+
+LIST_FXBITS_TEST(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
index c1725b2ebeaf44..7c00143697308f 100644
--- a/libc/test/src/stdfix/rbits_test.cpp
+++ b/libc/test/src/stdfix/rbits_test.cpp
@@ -1,7 +1,4 @@
-
 #include "FxbitsTest.h"
-
 #include "src/stdfix/rbits.h"
 
 LIST_FXBITS_TEST(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..bd7cb07b838bdb
--- /dev/null
+++ b/libc/test/src/stdfix/uhkbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/uhkbits.h"
+
+LIST_FXBITS_TEST(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..a866e414ceb2e9
--- /dev/null
+++ b/libc/test/src/stdfix/uhrbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/uhrbits.h"
+
+LIST_FXBITS_TEST(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..cd54ff7847b4b4
--- /dev/null
+++ b/libc/test/src/stdfix/ukbits_test.cpp
@@ -0,0 +1,5 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/ukbits.h"
+
+LIST_FXBITS_TEST(unsigned accum, uint_uk_t, LIBC_NAMESAPCE::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..90f2dce2772c50
--- /dev/null
+++ b/libc/test/src/stdfix/ulkbits_test.cpp
@@ -0,0 +1,5 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/ulkbits.h"
+
+LIST_FXBITS_TEST(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..641e58db1fb1e3
--- /dev/null
+++ b/libc/test/src/stdfix/ulrbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/ulrbits.h"
+
+LIST_FXBITS_TEST(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..4f197851a0229b
--- /dev/null
+++ b/libc/test/src/stdfix/urbits_test.cpp
@@ -0,0 +1,4 @@
+#include "FxbitsTest.h"
+#include "src/stdfix/urbits.h"
+
+LIST_FXBITS_TEST(unsigned fract, uint_ur_t, LIBC_NAMESPACE::urbits);

>From 5a3932eb2bfa45622e55d89d91a5fb19efe7ff11 Mon Sep 17 00:00:00 2001
From: smallp-o-p <william.tranviet at gmail.com>
Date: Sun, 3 Nov 2024 00:16:30 -0400
Subject: [PATCH 9/9] Update documentation

---
 libc/docs/math/stdfix.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/docs/math/stdfix.rst b/libc/docs/math/stdfix.rst
index d8dcb0cfa4c521..0751f2518bc247 100644
--- a/libc/docs/math/stdfix.rst
+++ b/libc/docs/math/stdfix.rst
@@ -71,7 +71,7 @@ The following functions are included in the ISO/IEC TR 18037:2008 standard.
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | bits\*        |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
-| \*bits        |                |             |               |            |                |             |                |             |               |            |                |             |
+| \*bits        | |check|        | |check|     | |check|       | |check|    | |check|        |  |check|    |  |check|       | |check|     |  |check|      | |check|    | |check|        | |check|     |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+
 | countls       |                |             |               |            |                |             |                |             |               |            |                |             |
 +---------------+----------------+-------------+---------------+------------+----------------+-------------+----------------+-------------+---------------+------------+----------------+-------------+



More information about the libc-commits mailing list