[libc-commits] [libc] [libc][math][c++23] Add bfloat16 support in LLVM libc (PR #144463)

Krishna Pandey via libc-commits libc-commits at lists.llvm.org
Sun Jul 6 00:05:23 PDT 2025


https://github.com/krishna2803 updated https://github.com/llvm/llvm-project/pull/144463

>From 3bd7c349abb7df4caad3f6343dbaa8a1e109e452 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sun, 27 Apr 2025 11:35:15 +0530
Subject: [PATCH 01/28] [libc][stdfix] Fix typo `ulk` -> `lk` in riscv
 entrypoints

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/config/linux/riscv/entrypoints.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 09957995ba976..f2f895117e35a 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -779,7 +779,7 @@ if(LIBC_COMPILER_HAS_FIXED_POINT)
     libc.src.stdfix.idivr
     libc.src.stdfix.idivlr
     libc.src.stdfix.idivk
-    libc.src.stdfix.idivulk
+    libc.src.stdfix.idivlk
     libc.src.stdfix.idivur
     libc.src.stdfix.idivulr
     libc.src.stdfix.idivuk

>From 369756cb3ca4a51c4e66a3e99a07d5ada7391049 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Mon, 2 Jun 2025 11:35:05 +0530
Subject: [PATCH 02/28] feat: add bfloat16 struct

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt | 13 +++++++
 libc/src/__support/FPUtil/bfloat16.h     | 47 ++++++++++++++++++++++++
 2 files changed, 60 insertions(+)
 create mode 100644 libc/src/__support/FPUtil/bfloat16.h

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index bfe0170f09fd9..219fdaf516b25 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -257,4 +257,17 @@ add_header_library(
     libc.src.__support.macros.properties.types
 )
 
+add_header_library(
+  bfloat16
+  HDRS
+    bfloat16.h
+  DEPENDS
+    .fenv_impl
+    .fp_bits
+    .rounding_mode
+    libc.src.__support.CPP.bit
+    libc.hdr.fenv_macros
+    libc.src.__support.CPP.type_traits
+)
+
 add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
new file mode 100644
index 0000000000000..3a3913a744b23
--- /dev/null
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -0,0 +1,47 @@
+//===-- Utilities for bfloat16 data type. -----------------------*- 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___SUPPORT_FPUTIL_BFLOAT16_H
+#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
+
+#include "FEnvImpl.h"
+#include "FPBits.h"
+#include "hdr/fenv_macros.h"
+#include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/type_traits.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace fputil {
+
+struct BFloat16 {
+  uint16_t bits;
+
+  constexpr BFloat16() = default;
+
+  constexpr BFloat16(float x) {
+    FPBits x_bits(x);
+
+    // TODO: correct rounding for all modes
+    // currently it is RTNE
+    uint32_t val = x_bits.get_val();
+    bits = static_cast<uint16_t>(val >> 16);
+  }
+
+  constexpr float as_float() const {
+    uint32_t val = static_cast<uint32_t>(bits) << 16U;
+    return cpp::bit_cast<float>(val);
+  }
+}
+
+} // namespace fputil
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H

>From 817cdfa528765d939a4d19abbb95ae21c2f9de94 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Wed, 4 Jun 2025 04:20:10 +0530
Subject: [PATCH 03/28] add: FPType::BFloat16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 .../llvm-libc-macros/bfloat16-macros.h        | 21 +++++++++++++++++++
 libc/src/__support/FPUtil/FPBits.h            | 13 ++++++++++++
 libc/src/__support/FPUtil/bfloat16.h          |  4 +---
 libc/src/__support/macros/properties/types.h  | 13 +++++++++---
 4 files changed, 45 insertions(+), 6 deletions(-)
 create mode 100644 libc/include/llvm-libc-macros/bfloat16-macros.h

diff --git a/libc/include/llvm-libc-macros/bfloat16-macros.h b/libc/include/llvm-libc-macros/bfloat16-macros.h
new file mode 100644
index 0000000000000..5b52f73efbadb
--- /dev/null
+++ b/libc/include/llvm-libc-macros/bfloat16-macros.h
@@ -0,0 +1,21 @@
+//===-- Detection of __bf16 compiler builtin type -------------------------===//
+//
+// 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_MACROS_BFLOAT16_MACROS_H
+#define LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
+
+#if ((defined(__clang__) && __clang_major__ > 17) ||                           \
+     (defined(__GNUC__) && __GNUC__ > 13)) &&                                  \
+    !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) &&              \
+    !defined(_WIN32)
+
+#define LIBC_TYPES_HAS_BFLOAT16
+
+#endif // LIBC_TYPES_HAS_BFLOAT16
+
+#endif // LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 4fa3bc30ecd12..5d30d459b6a8a 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -38,6 +38,7 @@ enum class FPType {
   IEEE754_Binary64,
   IEEE754_Binary128,
   X86_Binary80,
+  BFloat16
 };
 
 // The classes hierarchy is as follows:
@@ -138,6 +139,14 @@ template <> struct FPLayout<FPType::X86_Binary80> {
   LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN - 1;
 };
 
+template <> struct FPLayout<FPType::BFloat16> {
+  using StorageType = uint16_t;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int EXP_LEN = 8;
+  LIBC_INLINE_VAR static constexpr int SIG_LEN = 7;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SIG_LEN;
+};
+
 // FPStorage derives useful constants from the FPLayout above.
 template <FPType fp_type> struct FPStorage : public FPLayout<fp_type> {
   using UP = FPLayout<fp_type>;
@@ -800,6 +809,10 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
 #if defined(LIBC_TYPES_HAS_FLOAT128)
   else if constexpr (cpp::is_same_v<UnqualT, float128>)
     return FPType::IEEE754_Binary128;
+#endif
+#if defined(LIBC_TYPES_HAS_BFLOAT16)
+  else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
+    return FPType::BFloat16;
 #endif
   else
     static_assert(cpp::always_false<UnqualT>, "Unsupported type");
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 3a3913a744b23..87d5a593b6899 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -29,10 +29,8 @@ struct BFloat16 {
   constexpr BFloat16(float x) {
     FPBits x_bits(x);
 
-    // TODO: correct rounding for all modes
-    // currently it is RTNE
     uint32_t val = x_bits.get_val();
-    bits = static_cast<uint16_t>(val >> 16);
+    bits = fputil::cast<BFloat16>(x);
   }
 
   constexpr float as_float() const {
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 6293b9d4d292a..edef8fe5499a3 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -10,9 +10,10 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
 #define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
 
-#include "hdr/float_macros.h"                      // LDBL_MANT_DIG
-#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16
-#include "include/llvm-libc-types/float128.h"        // float128
+#include "hdr/float_macros.h"                         // LDBL_MANT_DIG
+#include "include/llvm-libc-macros/bfloat16-macros.h" // LIBC_TYPES_HAS_BFLOAT16
+#include "include/llvm-libc-macros/float16-macros.h"  // LIBC_TYPES_HAS_FLOAT16
+#include "include/llvm-libc-types/float128.h"         // float128
 #include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
 #include "src/__support/macros/properties/cpu_features.h"
@@ -58,4 +59,10 @@ using float16 = _Float16;
 // LIBC_TYPES_HAS_FLOAT128 and 'float128' type are provided by
 // "include/llvm-libc-types/float128.h"
 
+// -- bfloat16 support ---------------------------------------------------------
+#ifdef LIBC_TYPES_HAS_BFLOAT16
+using bfloat16 = __bf16; // TODO: verify this
+#endif // LIBC_TYPES_HAS_BFLOAT16
+
+
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H

>From 39511a457d53a8096e42cd96248c4b4ad96ca03b Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Thu, 5 Jun 2025 05:02:18 +0530
Subject: [PATCH 04/28] chore: remove compiler version checks and add bfloat16
 to is_floating_type

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/include/llvm-libc-macros/bfloat16-macros.h      | 12 +++++++-----
 .../__support/CPP/type_traits/is_floating_point.h    |  4 ++++
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/libc/include/llvm-libc-macros/bfloat16-macros.h b/libc/include/llvm-libc-macros/bfloat16-macros.h
index 5b52f73efbadb..466432b990a32 100644
--- a/libc/include/llvm-libc-macros/bfloat16-macros.h
+++ b/libc/include/llvm-libc-macros/bfloat16-macros.h
@@ -9,13 +9,15 @@
 #ifndef LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
 #define LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
 
-#if ((defined(__clang__) && __clang_major__ > 17) ||                           \
-     (defined(__GNUC__) && __GNUC__ > 13)) &&                                  \
-    !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) &&              \
-    !defined(_WIN32)
+// #if ((defined(__clang__) && __clang_major__ > 17) ||                        \
+//      (defined(__GNUC__) && __GNUC__ > 13)) &&                               \
+//     !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) &&           \
+//     !defined(_WIN32)
 
 #define LIBC_TYPES_HAS_BFLOAT16
 
-#endif // LIBC_TYPES_HAS_BFLOAT16
+struct BFloat16;
+
+// #endif // LIBC_TYPES_HAS_BFLOAT16
 
 #endif // LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index 11ffbfabe60b6..2954b3061d186 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -35,6 +35,10 @@ template <typename T> struct is_floating_point {
 #ifdef LIBC_TYPES_HAS_FLOAT128
                               ,
                               float128
+#endif
+#ifdef LIBC_TYPES_HAS_BFLOAT16
+                              ,
+                              bfloat16
 #endif
                               >();
 };

>From 265896dc1fb31b5c8ab33b6e3cb732d2b0bbdeb8 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Thu, 5 Jun 2025 07:07:19 +0530
Subject: [PATCH 05/28] feat: update MPCommon.h for bfloat16 type and change
 __bf16 to our own type

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/macros/properties/types.h |  4 +++-
 libc/utils/MPFRWrapper/MPCommon.h            | 14 ++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index edef8fe5499a3..ac215243c0402 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -61,7 +61,9 @@ using float16 = _Float16;
 
 // -- bfloat16 support ---------------------------------------------------------
 #ifdef LIBC_TYPES_HAS_BFLOAT16
-using bfloat16 = __bf16; // TODO: verify this
+
+using bfloat16 = BFloat16;
+
 #endif // LIBC_TYPES_HAS_BFLOAT16
 
 
diff --git a/libc/utils/MPFRWrapper/MPCommon.h b/libc/utils/MPFRWrapper/MPCommon.h
index 99cb7ec66a2ca..f0e72872e2e0f 100644
--- a/libc/utils/MPFRWrapper/MPCommon.h
+++ b/libc/utils/MPFRWrapper/MPCommon.h
@@ -13,6 +13,7 @@
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
 #include "test/UnitTest/RoundingModeUtils.h"
 
 #include <stdint.h>
@@ -134,6 +135,19 @@ class MPFRNumber {
     mpfr_set_d(value, x, mpfr_rounding);
   }
 
+#ifdef LIBC_TYPES_HAS_BFLOAT16
+  template <typename XType,
+            cpp::enable_if_t<cpp::is_same_v<bfloat16, XType>, int> = 0>
+  explicit MPFRNumber(XType x,
+                      unsigned int precision = 8,
+                      RoundingMode rounding = RoundingMode::Nearest)
+      : mpfr_precision(precision),
+        mpfr_rounding(get_mpfr_rounding_mode(rounding)) {
+    mpfr_init2(value, mpfr_precision);
+    mpfr_set_flt(value, x.as_float(), mpfr_rounding);
+  }
+#endif
+
   template <typename XType,
             cpp::enable_if_t<cpp::is_same_v<long double, XType>, int> = 0>
   explicit MPFRNumber(XType x,

>From 0038a8aba32362a522b33c984da958a933469a16 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 6 Jun 2025 12:35:20 +0530
Subject: [PATCH 06/28] feat: create a dummy struct for bfloat16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt |  7 ++++-
 libc/src/__support/FPUtil/bfloat16.h     | 37 +++++++++++++++---------
 2 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 219fdaf516b25..30a375ddb0666 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -264,10 +264,15 @@ add_header_library(
   DEPENDS
     .fenv_impl
     .fp_bits
+    .cast
     .rounding_mode
-    libc.src.__support.CPP.bit
+    libc.hdr.errno_macros
     libc.hdr.fenv_macros
     libc.src.__support.CPP.type_traits
+    libc.src.__support.CPP.bit
+    libc.src.__support.big_int
+    libc.src.__support.macros.optimization
+    libc.src.__support.macros.properties.types
 )
 
 add_subdirectory(generic)
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 87d5a593b6899..b0a5cb38f71e8 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -1,4 +1,4 @@
-//===-- Utilities for bfloat16 data type. -----------------------*- C++ -*-===//
+//===-- Definition of bfloat16 data type. -----------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -11,35 +11,44 @@
 
 #include "FEnvImpl.h"
 #include "FPBits.h"
+#include "hdr/errno_macros.h"
 #include "hdr/fenv_macros.h"
-#include "src/__support/CPP/bit.h"
+#include "multiply_add.h"
+#include "rounding_mode.h"
 #include "src/__support/CPP/type_traits.h"
+#include "src/__support/FPUtil/cast.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h" // bfloat16
 
 #include <stddef.h>
 #include <stdint.h>
 
 namespace LIBC_NAMESPACE_DECL {
-namespace fputil {
-
 struct BFloat16 {
   uint16_t bits;
 
-  constexpr BFloat16() = default;
+  constexpr BFloat16() : bits(0) {}
 
-  constexpr BFloat16(float x) {
-    FPBits x_bits(x);
+  explicit BFloat16(float x = 0.0f) {
+    if (x == 0.0f) {
+      bits = 0;
+    } else {
+      bits = 1;
+    }
+  }
 
-    uint32_t val = x_bits.get_val();
-    bits = fputil::cast<BFloat16>(x);
+  constexpr bool operator==(const BFloat16 other) const {
+    return bits == other.bits;
   }
 
-  constexpr float as_float() const {
-    uint32_t val = static_cast<uint32_t>(bits) << 16U;
-    return cpp::bit_cast<float>(val);
+  float as_float() const {
+    uint32_t x_bits = static_cast<uint32_t>(bits) << 16U;
+    return cpp::bit_cast<float>(x_bits);
   }
-}
+};
+
+using bfloat16 = BFloat16;
 
-} // namespace fputil
 } // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H

>From 4086984d2f80d6ca11120bb9ae30d7baa58ba014 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 6 Jun 2025 12:50:34 +0530
Subject: [PATCH 07/28] feat: add BFloat16 checks in compiler features

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/cmake/modules/CheckCompilerFeatures.cmake          | 3 +++
 libc/cmake/modules/compiler_features/check_bfloat16.cpp | 5 +++++
 2 files changed, 8 insertions(+)
 create mode 100644 libc/cmake/modules/compiler_features/check_bfloat16.cpp

diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index a5ea66a5935b7..6db69bd5c4895 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -15,6 +15,7 @@ set(
     "fixed_point"
     "cfloat16"
     "cfloat128"
+    "bfloat16"
 )
 
 # Making sure ALL_COMPILER_FEATURES is sorted.
@@ -116,6 +117,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
       set(LIBC_TYPES_HAS_CFLOAT16 TRUE)
     elseif(${feature} STREQUAL "cfloat128")
       set(LIBC_TYPES_HAS_CFLOAT128 TRUE)
+    elseif(${feature} STREQUAL "bfloat16")
+      set(LIBC_TYPES_HAS_BFLOAT16 TRUE)
     elseif(${feature} STREQUAL "builtin_ceil_floor_rint_trunc")
       set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC TRUE)
     elseif(${feature} STREQUAL "builtin_fmax_fmin")
diff --git a/libc/cmake/modules/compiler_features/check_bfloat16.cpp b/libc/cmake/modules/compiler_features/check_bfloat16.cpp
new file mode 100644
index 0000000000000..1fcb73b01eb9c
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_bfloat16.cpp
@@ -0,0 +1,5 @@
+#include "src/__support/macros/properties/types.h"
+
+#ifndef LIBC_TYPES_HAS_BFLOAT16
+#error unsupported
+#endif

>From af0bda3487626e70bb673cdccaa57deb914bac0a Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Mon, 9 Jun 2025 13:12:17 +0530
Subject: [PATCH 08/28] feat: add dummy bfloat16 -> float conversion function

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/math/fbfloat16.h            | 22 ++++++++++++++++++++++
 libc/src/math/generic/CMakeLists.txt | 14 ++++++++++++++
 libc/src/math/generic/fbfloat16.cpp  | 25 +++++++++++++++++++++++++
 3 files changed, 61 insertions(+)
 create mode 100644 libc/src/math/fbfloat16.h
 create mode 100644 libc/src/math/generic/fbfloat16.cpp

diff --git a/libc/src/math/fbfloat16.h b/libc/src/math/fbfloat16.h
new file mode 100644
index 0000000000000..5b1b04b24a563
--- /dev/null
+++ b/libc/src/math/fbfloat16.h
@@ -0,0 +1,22 @@
+//===-- Implementation header for fbfloat16 ---------------------*- 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_MATH_FBFLOAT16_H
+#define LLVM_LIBC_SRC_MATH_FBFLOAT16_H
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+float fbfloat16(bfloat16 x);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_MATH_FBFLOAT16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index e5d1f9075bcb1..bfd057ac57937 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -5066,6 +5066,20 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.generic.mul
 )
 
+# Bfloat16 Functions
+
+add_entrypoint_object(
+  fbfloat16
+  SRCS
+    fbfloat16.cpp
+  HDRS
+    ../fbfloat16.h
+  DEPENDS
+    libc.src.__support.macros.config
+    libc.src.__support.macros.properties.types
+    libc.src.__support.FPUtil.bfloat16
+)
+
 add_header_library(
   expxf16
   HDRS
diff --git a/libc/src/math/generic/fbfloat16.cpp b/libc/src/math/generic/fbfloat16.cpp
new file mode 100644
index 0000000000000..d42a486354e64
--- /dev/null
+++ b/libc/src/math/generic/fbfloat16.cpp
@@ -0,0 +1,25 @@
+//===-- Implementation of fbfloat16 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 "src/math/fbfloat16.h"
+
+#include "src/__support/FPUtil/bfloat16.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/types.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(float, fbfloat16, (LIBC_NAMESPACE::bfloat16 x)) {
+  if (x.bits == 0)
+    return 0.0f;
+  else
+    return 1.0f;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

>From 67786f3875818ebcfb8b42ff9348b9e6c186747c Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Mon, 9 Jun 2025 13:15:49 +0530
Subject: [PATCH 09/28] chore: add entrypoints for fbfloat16 function

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/config/linux/x86_64/entrypoints.txt | 7 +++++++
 libc/src/math/CMakeLists.txt             | 3 +++
 2 files changed, 10 insertions(+)

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 9f447dd0d35d2..2af2066671d01 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -855,6 +855,13 @@ if(LIBC_TYPES_HAS_FLOAT128)
   )
 endif()
 
+if(LIBC_TYPES_HAS_BFLOAT16)
+  list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # Bfloat16 Entrypoints
+    libc.src.math.fbfloat16
+  )
+endif()
+
 if(LIBC_COMPILER_HAS_FIXED_POINT)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # stdfix.h _Fract and _Accum entrypoints
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 055e76468a461..0aa0fa7ab700a 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -554,3 +554,6 @@ add_math_entrypoint_object(ufromfpxf)
 add_math_entrypoint_object(ufromfpxl)
 add_math_entrypoint_object(ufromfpxf16)
 add_math_entrypoint_object(ufromfpxf128)
+
+# BFloat16 functions
+add_math_entrypoint_object(fbfloat16)

>From 485592ae79ccb3e7097177b9fca7833302ab71bc Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Mon, 9 Jun 2025 18:32:40 +0530
Subject: [PATCH 10/28] chore: add dummy tests for fbfloat16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/smoke/CMakeLists.txt     | 13 ++++++++++++
 libc/test/src/math/smoke/fbfloat16_test.cpp | 23 +++++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 libc/test/src/math/smoke/fbfloat16_test.cpp

diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 55edffb4f5bdf..6823f1dc44428 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5307,3 +5307,16 @@ add_fp_unittest(
     libc.src.__support.macros.properties.os
     libc.src.__support.macros.properties.types
 )
+
+# Bfloat16 Smoke Tests
+
+add_fp_unittest(
+  fbfloat16_test
+  SUITE
+    libc-math-smoke-tests
+  SRCS
+    fbfloat16_test.cpp
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.math.fbfloat16
+)
diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
new file mode 100644
index 0000000000000..8f52fe36aae61
--- /dev/null
+++ b/libc/test/src/math/smoke/fbfloat16_test.cpp
@@ -0,0 +1,23 @@
+//===-- Unittests for fbfloat16 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 "src/math/fbfloat16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+// TODO: change this to bfloat16
+using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<float>;
+
+TEST_F(LlvmLibcFBfloat16Test, SpecialNumbers) {
+  ASSERT_EQ(1, 2);
+  // TODO: implement this!
+  // x = some bfloat number
+  // float y = x as float (using our ctor?)
+  // float z = mfpr(x) as float
+  // check y == z
+}

>From f3ef6e0ab8fbd22f3e7c734ff2f2bc3e94c6a21a Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Mon, 9 Jun 2025 18:40:58 +0530
Subject: [PATCH 11/28] chore: update fbfloat16 dummy smoke tests

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/smoke/fbfloat16_test.cpp | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
index 8f52fe36aae61..a63a7e05a8ba5 100644
--- a/libc/test/src/math/smoke/fbfloat16_test.cpp
+++ b/libc/test/src/math/smoke/fbfloat16_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/math/fbfloat16.h"
+
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
@@ -14,7 +15,14 @@
 using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<float>;
 
 TEST_F(LlvmLibcFBfloat16Test, SpecialNumbers) {
-  ASSERT_EQ(1, 2);
+
+  LIBC_NAMESPACE::bfloat16 x{0.0f};
+  ASSERT_EQ(0, static_cast<int>(x.bits));
+
+
+  LIBC_NAMESPACE::bfloat16 y{1.0f};
+  ASSERT_EQ(1, static_cast<int>(y.bits));
+
   // TODO: implement this!
   // x = some bfloat number
   // float y = x as float (using our ctor?)

>From 548417c560c22b99fa20c71bb274efd9d9268f0d Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Wed, 11 Jun 2025 20:20:44 +0530
Subject: [PATCH 12/28] fix: circular dependencies

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 .../llvm-libc-macros/bfloat16-macros.h        | 23 -------------------
 libc/src/__support/FPUtil/bfloat16.h          |  2 --
 libc/src/__support/FPUtil/cast.h              |  8 +++++--
 libc/src/__support/macros/properties/types.h  | 16 +++++++++++--
 libc/src/math/generic/fbfloat16.cpp           |  2 +-
 libc/test/src/math/smoke/CMakeLists.txt       |  1 -
 libc/test/src/math/smoke/fbfloat16_test.cpp   |  9 ++++----
 7 files changed, 26 insertions(+), 35 deletions(-)
 delete mode 100644 libc/include/llvm-libc-macros/bfloat16-macros.h

diff --git a/libc/include/llvm-libc-macros/bfloat16-macros.h b/libc/include/llvm-libc-macros/bfloat16-macros.h
deleted file mode 100644
index 466432b990a32..0000000000000
--- a/libc/include/llvm-libc-macros/bfloat16-macros.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//===-- Detection of __bf16 compiler builtin type -------------------------===//
-//
-// 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_MACROS_BFLOAT16_MACROS_H
-#define LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
-
-// #if ((defined(__clang__) && __clang_major__ > 17) ||                        \
-//      (defined(__GNUC__) && __GNUC__ > 13)) &&                               \
-//     !defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) &&           \
-//     !defined(_WIN32)
-
-#define LIBC_TYPES_HAS_BFLOAT16
-
-struct BFloat16;
-
-// #endif // LIBC_TYPES_HAS_BFLOAT16
-
-#endif // LLVM_LIBC_MACROS_BFLOAT16_MACROS_H
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index b0a5cb38f71e8..9640314ca5987 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -47,8 +47,6 @@ struct BFloat16 {
   }
 };
 
-using bfloat16 = BFloat16;
-
 } // namespace LIBC_NAMESPACE_DECL
 
 #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 7578bb42b18f1..9204bf0040f60 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -26,9 +26,13 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
                                            cpp::is_floating_point_v<InType>,
                                        OutType>
 cast(InType x) {
-#if defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION)
+#if (defined(LIBC_TYPES_HAS_FLOAT16) &&                                        \
+     !defined(__LIBC_USE_FLOAT16_CONVERSION)) ||                               \
+    defined(LIBC_TYPES_HAS_BFLOAT16)
   if constexpr (cpp::is_same_v<OutType, float16> ||
-                cpp::is_same_v<InType, float16>) {
+                cpp::is_same_v<InType, float16> ||
+                cpp::is_same_v<OutType, bfloat16> ||
+                cpp::is_same_v<InType, bfloat16>) {
     using InFPBits = FPBits<InType>;
     using InStorageType = typename InFPBits::StorageType;
     using OutFPBits = FPBits<OutType>;
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index ac215243c0402..ca4a6099747d1 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -11,7 +11,6 @@
 #define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
 
 #include "hdr/float_macros.h"                         // LDBL_MANT_DIG
-#include "include/llvm-libc-macros/bfloat16-macros.h" // LIBC_TYPES_HAS_BFLOAT16
 #include "include/llvm-libc-macros/float16-macros.h"  // LIBC_TYPES_HAS_FLOAT16
 #include "include/llvm-libc-types/float128.h"         // float128
 #include "src/__support/macros/properties/architectures.h"
@@ -19,6 +18,8 @@
 #include "src/__support/macros/properties/cpu_features.h"
 #include "src/__support/macros/properties/os.h"
 
+#include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
+
 #include <stdint.h> // UINT64_MAX, __SIZEOF_INT128__
 
 // 'long double' properties.
@@ -60,9 +61,20 @@ using float16 = _Float16;
 // "include/llvm-libc-types/float128.h"
 
 // -- bfloat16 support ---------------------------------------------------------
+
+// since we have our own generic type, we don't need to check against any
+// compiler versions
+// TODO: verify this
+#define LIBC_TYPES_HAS_BFLOAT16
+
+
 #ifdef LIBC_TYPES_HAS_BFLOAT16
 
-using bfloat16 = BFloat16;
+namespace LIBC_NAMESPACE_DECL {
+    struct BFloat16;
+}
+
+using bfloat16 = LIBC_NAMESPACE::BFloat16;
 
 #endif // LIBC_TYPES_HAS_BFLOAT16
 
diff --git a/libc/src/math/generic/fbfloat16.cpp b/libc/src/math/generic/fbfloat16.cpp
index d42a486354e64..1ef183668a51a 100644
--- a/libc/src/math/generic/fbfloat16.cpp
+++ b/libc/src/math/generic/fbfloat16.cpp
@@ -15,7 +15,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-LLVM_LIBC_FUNCTION(float, fbfloat16, (LIBC_NAMESPACE::bfloat16 x)) {
+LLVM_LIBC_FUNCTION(float, fbfloat16, (bfloat16 x)) {
   if (x.bits == 0)
     return 0.0f;
   else
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 6823f1dc44428..fc9cbbf4e9df0 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5317,6 +5317,5 @@ add_fp_unittest(
   SRCS
     fbfloat16_test.cpp
   DEPENDS
-    libc.src.errno.errno
     libc.src.math.fbfloat16
 )
diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
index a63a7e05a8ba5..2a7a2ea4fddf9 100644
--- a/libc/test/src/math/smoke/fbfloat16_test.cpp
+++ b/libc/test/src/math/smoke/fbfloat16_test.cpp
@@ -6,21 +6,22 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "src/math/fbfloat16.h"
+#include "src/__support/FPUtil/bfloat16.h"
 
+#include "src/math/fbfloat16.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
 // TODO: change this to bfloat16
-using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<float>;
+using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
 
 TEST_F(LlvmLibcFBfloat16Test, SpecialNumbers) {
 
-  LIBC_NAMESPACE::bfloat16 x{0.0f};
+  bfloat16 x{0.0f};
   ASSERT_EQ(0, static_cast<int>(x.bits));
 
 
-  LIBC_NAMESPACE::bfloat16 y{1.0f};
+  bfloat16 y{1.0f};
   ASSERT_EQ(1, static_cast<int>(y.bits));
 
   // TODO: implement this!

>From 95b10485557664c70c102ca812e8975969485bb3 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Mon, 9 Jun 2025 21:10:18 +0530
Subject: [PATCH 13/28] refactor: remove `LIBC_TYPES_HAS_BFLOAT16` dependency
 from sources and headers

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 .../modules/compiler_features/check_bfloat16.cpp      |  6 +-----
 .../src/__support/CPP/type_traits/is_floating_point.h |  6 +-----
 libc/src/__support/FPUtil/FPBits.h                    |  2 --
 libc/src/__support/macros/properties/types.h          | 11 -----------
 libc/test/src/math/smoke/fbfloat16_test.cpp           |  1 -
 libc/utils/MPFRWrapper/MPCommon.h                     |  2 --
 6 files changed, 2 insertions(+), 26 deletions(-)

diff --git a/libc/cmake/modules/compiler_features/check_bfloat16.cpp b/libc/cmake/modules/compiler_features/check_bfloat16.cpp
index 1fcb73b01eb9c..fac0b901ac594 100644
--- a/libc/cmake/modules/compiler_features/check_bfloat16.cpp
+++ b/libc/cmake/modules/compiler_features/check_bfloat16.cpp
@@ -1,5 +1 @@
-#include "src/__support/macros/properties/types.h"
-
-#ifndef LIBC_TYPES_HAS_BFLOAT16
-#error unsupported
-#endif
+// intentionally left empty for CheckCompilerFeatures to work.
diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index 2954b3061d186..cd2d6bea1db6d 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -36,11 +36,7 @@ template <typename T> struct is_floating_point {
                               ,
                               float128
 #endif
-#ifdef LIBC_TYPES_HAS_BFLOAT16
-                              ,
-                              bfloat16
-#endif
-                              >();
+                              , bfloat16>();
 };
 template <typename T>
 LIBC_INLINE_VAR constexpr bool is_floating_point_v =
diff --git a/libc/src/__support/FPUtil/FPBits.h b/libc/src/__support/FPUtil/FPBits.h
index 5d30d459b6a8a..9e21136558a03 100644
--- a/libc/src/__support/FPUtil/FPBits.h
+++ b/libc/src/__support/FPUtil/FPBits.h
@@ -810,10 +810,8 @@ template <typename T> LIBC_INLINE static constexpr FPType get_fp_type() {
   else if constexpr (cpp::is_same_v<UnqualT, float128>)
     return FPType::IEEE754_Binary128;
 #endif
-#if defined(LIBC_TYPES_HAS_BFLOAT16)
   else if constexpr (cpp::is_same_v<UnqualT, bfloat16>)
     return FPType::BFloat16;
-#endif
   else
     static_assert(cpp::always_false<UnqualT>, "Unsupported type");
 }
diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index ca4a6099747d1..729086295e83f 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -62,21 +62,10 @@ using float16 = _Float16;
 
 // -- bfloat16 support ---------------------------------------------------------
 
-// since we have our own generic type, we don't need to check against any
-// compiler versions
-// TODO: verify this
-#define LIBC_TYPES_HAS_BFLOAT16
-
-
-#ifdef LIBC_TYPES_HAS_BFLOAT16
-
 namespace LIBC_NAMESPACE_DECL {
     struct BFloat16;
 }
 
 using bfloat16 = LIBC_NAMESPACE::BFloat16;
 
-#endif // LIBC_TYPES_HAS_BFLOAT16
-
-
 #endif // LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
index 2a7a2ea4fddf9..723922746eae2 100644
--- a/libc/test/src/math/smoke/fbfloat16_test.cpp
+++ b/libc/test/src/math/smoke/fbfloat16_test.cpp
@@ -12,7 +12,6 @@
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-// TODO: change this to bfloat16
 using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
 
 TEST_F(LlvmLibcFBfloat16Test, SpecialNumbers) {
diff --git a/libc/utils/MPFRWrapper/MPCommon.h b/libc/utils/MPFRWrapper/MPCommon.h
index f0e72872e2e0f..c2de650f20806 100644
--- a/libc/utils/MPFRWrapper/MPCommon.h
+++ b/libc/utils/MPFRWrapper/MPCommon.h
@@ -135,7 +135,6 @@ class MPFRNumber {
     mpfr_set_d(value, x, mpfr_rounding);
   }
 
-#ifdef LIBC_TYPES_HAS_BFLOAT16
   template <typename XType,
             cpp::enable_if_t<cpp::is_same_v<bfloat16, XType>, int> = 0>
   explicit MPFRNumber(XType x,
@@ -146,7 +145,6 @@ class MPFRNumber {
     mpfr_init2(value, mpfr_precision);
     mpfr_set_flt(value, x.as_float(), mpfr_rounding);
   }
-#endif
 
   template <typename XType,
             cpp::enable_if_t<cpp::is_same_v<long double, XType>, int> = 0>

>From f14ff95dc6fac0c0e34264b14e1de7835dd1cede Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Thu, 12 Jun 2025 21:07:07 +0530
Subject: [PATCH 14/28] refactor: fputil::cast for bfloat16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 .../CPP/type_traits/is_floating_point.h         |  3 ++-
 libc/src/__support/FPUtil/cast.h                | 17 +++++++++--------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/libc/src/__support/CPP/type_traits/is_floating_point.h b/libc/src/__support/CPP/type_traits/is_floating_point.h
index cd2d6bea1db6d..9dc77ad7ee0ea 100644
--- a/libc/src/__support/CPP/type_traits/is_floating_point.h
+++ b/libc/src/__support/CPP/type_traits/is_floating_point.h
@@ -36,7 +36,8 @@ template <typename T> struct is_floating_point {
                               ,
                               float128
 #endif
-                              , bfloat16>();
+                              ,
+                              bfloat16>();
 };
 template <typename T>
 LIBC_INLINE_VAR constexpr bool is_floating_point_v =
diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 9204bf0040f60..0831ee3396322 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -26,13 +26,15 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
                                            cpp::is_floating_point_v<InType>,
                                        OutType>
 cast(InType x) {
-#if (defined(LIBC_TYPES_HAS_FLOAT16) &&                                        \
-     !defined(__LIBC_USE_FLOAT16_CONVERSION)) ||                               \
-    defined(LIBC_TYPES_HAS_BFLOAT16)
-  if constexpr (cpp::is_same_v<OutType, float16> ||
-                cpp::is_same_v<InType, float16> ||
-                cpp::is_same_v<OutType, bfloat16> ||
-                cpp::is_same_v<InType, bfloat16>) {
+
+  // bfloat16 is always defined (for now)
+  if constexpr (cpp::is_same_v<OutType, bfloat16> ||
+                cpp::is_same_v<InType, bfloat16>
+#if (defined(LIBC_TYPES_HAS_FLOAT16) && !defined(__LIBC_USE_FLOAT16_CONVERSION))
+                || cpp::is_same_v<InType, float16> ||
+                cpp::is_same_v<InType, float16>
+#endif
+  ) {
     using InFPBits = FPBits<InType>;
     using InStorageType = typename InFPBits::StorageType;
     using OutFPBits = FPBits<OutType>;
@@ -62,7 +64,6 @@ cast(InType x) {
     DyadicFloat<cpp::bit_ceil(MAX_FRACTION_LEN)> xd(x);
     return xd.template as<OutType, /*ShouldSignalExceptions=*/true>();
   }
-#endif
 
   return static_cast<OutType>(x);
 }

>From 9ef7cc1d6e880b8d5b838bcc95a6f8c27aac1887 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Thu, 12 Jun 2025 22:15:44 +0530
Subject: [PATCH 15/28] feat: complete arbitrary float to bfloat conversion

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/bfloat16.h     | 19 +++++++++----------
 libc/src/__support/FPUtil/dyadic_float.h |  6 +++++-
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 9640314ca5987..f0507a8709dc8 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -27,21 +27,20 @@ namespace LIBC_NAMESPACE_DECL {
 struct BFloat16 {
   uint16_t bits;
 
-  constexpr BFloat16() : bits(0) {}
-
-  explicit BFloat16(float x = 0.0f) {
-    if (x == 0.0f) {
-      bits = 0;
-    } else {
-      bits = 1;
-    }
-  }
+  BFloat16() = default;
+
+  constexpr explicit BFloat16(uint16_t bits) : bits(bits) {}
+
+  // fputil::cast<bfloat16>(T) only works for T = floating point type
+  // TODO: integer to bfloat16 conversion
+  template <typename T>
+  constexpr explicit BFloat16(T x) : bits(fputil::cast<bfloat16>(x).bits) {}
 
   constexpr bool operator==(const BFloat16 other) const {
     return bits == other.bits;
   }
 
-  float as_float() const {
+  constexpr float as_float() const {
     uint32_t x_bits = static_cast<uint32_t>(bits) << 16U;
     return cpp::bit_cast<float>(x_bits);
   }
diff --git a/libc/src/__support/FPUtil/dyadic_float.h b/libc/src/__support/FPUtil/dyadic_float.h
index 6c3e1520e5aff..9ceda5ce9476d 100644
--- a/libc/src/__support/FPUtil/dyadic_float.h
+++ b/libc/src/__support/FPUtil/dyadic_float.h
@@ -415,7 +415,11 @@ template <size_t Bits> struct DyadicFloat {
     if constexpr (cpp::is_same_v<T, float16>)
       return generic_as<T, ShouldSignalExceptions>();
 #endif
-    return fast_as<T, ShouldSignalExceptions>();
+    if constexpr (cpp::is_same_v<T, bfloat16>) {
+      return generic_as<T, ShouldSignalExceptions>();
+    } else {
+      return fast_as<T, ShouldSignalExceptions>();
+    }
   }
 
   template <typename T,

>From 0058b85c45824b5e746b2a688ed2cf5846e34080 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Thu, 12 Jun 2025 22:34:15 +0530
Subject: [PATCH 16/28] chore: complete smoke tests for fbfloat16 function

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/smoke/fbfloat16_test.cpp | 25 ++++++++++-----------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
index 723922746eae2..06624fbfd33d0 100644
--- a/libc/test/src/math/smoke/fbfloat16_test.cpp
+++ b/libc/test/src/math/smoke/fbfloat16_test.cpp
@@ -15,17 +15,16 @@
 using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
 
 TEST_F(LlvmLibcFBfloat16Test, SpecialNumbers) {
-
-  bfloat16 x{0.0f};
-  ASSERT_EQ(0, static_cast<int>(x.bits));
-
-
-  bfloat16 y{1.0f};
-  ASSERT_EQ(1, static_cast<int>(y.bits));
-
-  // TODO: implement this!
-  // x = some bfloat number
-  // float y = x as float (using our ctor?)
-  // float z = mfpr(x) as float
-  // check y == z
+  constexpr float SPECIAL_FLOATS[] = {
+    0.0f, 1.0f, 2.0f, 4.5f, -1.0f, -0.5f, 3.140625f
+  };
+
+  constexpr uint16_t SPECIAL_BFLOAT16_BITS[] = {
+    0, 0x3f80U, 0x4000U, 0x4090U, 0xbf80U, 0xbf00, 0x4049U
+  };
+
+  for (int i=0; i<7; i++) {
+    bfloat16 x{SPECIAL_FLOATS[i]};
+    ASSERT_EQ(SPECIAL_BFLOAT16_BITS[i], x.bits);
+  }
 }

>From 77d38974819149d7fe4a9895ed6169c86b2c8702 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 13 Jun 2025 05:09:24 +0530
Subject: [PATCH 17/28] refactor: rename fbfloat16 smoke test suite, refactor
 bfloat16 specialization for MPFRNumber

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/smoke/fbfloat16_test.cpp |  4 ++--
 libc/utils/MPFRWrapper/MPCommon.h           | 23 +++++++++++----------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
index 06624fbfd33d0..c4f0892e4772e 100644
--- a/libc/test/src/math/smoke/fbfloat16_test.cpp
+++ b/libc/test/src/math/smoke/fbfloat16_test.cpp
@@ -12,9 +12,9 @@
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-using LlvmLibcFBfloat16Test = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+using LlvmLibcFBfloat16SmokeTest = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
 
-TEST_F(LlvmLibcFBfloat16Test, SpecialNumbers) {
+TEST_F(LlvmLibcFBfloat16SmokeTest, SpecialNumbers) {
   constexpr float SPECIAL_FLOATS[] = {
     0.0f, 1.0f, 2.0f, 4.5f, -1.0f, -0.5f, 3.140625f
   };
diff --git a/libc/utils/MPFRWrapper/MPCommon.h b/libc/utils/MPFRWrapper/MPCommon.h
index c2de650f20806..a577d4013f717 100644
--- a/libc/utils/MPFRWrapper/MPCommon.h
+++ b/libc/utils/MPFRWrapper/MPCommon.h
@@ -135,17 +135,6 @@ class MPFRNumber {
     mpfr_set_d(value, x, mpfr_rounding);
   }
 
-  template <typename XType,
-            cpp::enable_if_t<cpp::is_same_v<bfloat16, XType>, int> = 0>
-  explicit MPFRNumber(XType x,
-                      unsigned int precision = 8,
-                      RoundingMode rounding = RoundingMode::Nearest)
-      : mpfr_precision(precision),
-        mpfr_rounding(get_mpfr_rounding_mode(rounding)) {
-    mpfr_init2(value, mpfr_precision);
-    mpfr_set_flt(value, x.as_float(), mpfr_rounding);
-  }
-
   template <typename XType,
             cpp::enable_if_t<cpp::is_same_v<long double, XType>, int> = 0>
   explicit MPFRNumber(XType x,
@@ -181,6 +170,18 @@ class MPFRNumber {
     mpfr_set_sj(value, x, mpfr_rounding);
   }
 
+  // BFloat16
+  template <typename XType,
+            cpp::enable_if_t<cpp::is_same_v<bfloat16, XType>, int> = 0>
+  explicit MPFRNumber(XType x, unsigned int precision = 8,
+                      RoundingMode rounding = RoundingMode::Nearest)
+      : mpfr_precision(precision),
+        mpfr_rounding(get_mpfr_rounding_mode(rounding)) {
+    mpfr_init2(value, mpfr_precision);
+    // BFloat16::as_float() requires no rounding
+    mpfr_set_flt(value, x.as_float(), mpfr_rounding);
+  }
+
   MPFRNumber(const MPFRNumber &other);
   MPFRNumber(const MPFRNumber &other, unsigned int precision);
   MPFRNumber(const mpfr_t x, unsigned int precision, RoundingMode rounding);

>From 3a1493e7c586e159baa7ff42b60728734a33d2ab Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 13 Jun 2025 05:09:53 +0530
Subject: [PATCH 18/28] feat: add exhaustive tests for fbfloat16

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/math/exhaustive/CMakeLists.txt  | 15 +++++++
 .../src/math/exhaustive/fbfloat16_test.cpp    | 45 +++++++++++++++++++
 2 files changed, 60 insertions(+)
 create mode 100644 libc/test/src/math/exhaustive/fbfloat16_test.cpp

diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 551f449c9c8db..feff53aad7dff 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -535,3 +535,18 @@ add_fp_unittest(
   LINK_LIBRARIES
     -lpthread
 )
+
+# Bfloat16 Exhaustive Tests
+
+add_fp_unittest(
+  fbfloat16_test
+  NO_RUN_POSTBUILD
+  NEED_MPFR
+  SUITE
+    libc_math_exhaustive_tests
+  SRCS
+    fbfloat16_test.cpp
+  DEPENDS
+    .exhaustive_test
+    libc.src.math.fbfloat16
+)
diff --git a/libc/test/src/math/exhaustive/fbfloat16_test.cpp b/libc/test/src/math/exhaustive/fbfloat16_test.cpp
new file mode 100644
index 0000000000000..bb5e6f9854a54
--- /dev/null
+++ b/libc/test/src/math/exhaustive/fbfloat16_test.cpp
@@ -0,0 +1,45 @@
+//===-- Exhaustive tests for fbfloat16 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 "src/__support/FPUtil/bfloat16.h"
+
+#include "utils/MPFRWrapper/MPCommon.h"
+
+#include "src/math/fbfloat16.h"
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcFBfloat16ExhaustiveTest =
+    LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80;
+
+
+using MPFRNumber = LIBC_NAMESPACE::testing::mpfr::MPFRNumber;
+
+TEST_F(LlvmLibcFBfloat16ExhaustiveTest, PositiveRange) {
+  for (uint16_t bits = POS_START; bits <= POS_STOP; bits++) {
+    bfloat16 bf16_num{bits};
+    MPFRNumber mpfr_num{bf16_num};
+    ASSERT_FP_EQ(mpfr_num.as<float>(), bf16_num.as_float());
+  }
+}
+
+TEST_F(LlvmLibcFBfloat16ExhaustiveTest, NegativeRange) {
+  for (uint16_t bits = NEG_START; bits <= NEG_STOP; bits++) {
+    bfloat16 bf16_num{bits};
+    MPFRNumber mpfr_num{bf16_num};
+    ASSERT_FP_EQ(mpfr_num.as<float>(), bf16_num.as_float());
+  }
+}

>From 32a5efd4a494e069a8ca04148cb94381da035a6d Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Fri, 13 Jun 2025 05:48:19 +0530
Subject: [PATCH 19/28] chore: update bfloat16 ctor to support conversion from
 non-floats

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/bfloat16.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index f0507a8709dc8..03a7ef35b3450 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -31,10 +31,14 @@ struct BFloat16 {
 
   constexpr explicit BFloat16(uint16_t bits) : bits(bits) {}
 
-  // fputil::cast<bfloat16>(T) only works for T = floating point type
-  // TODO: integer to bfloat16 conversion
-  template <typename T>
-  constexpr explicit BFloat16(T x) : bits(fputil::cast<bfloat16>(x).bits) {}
+  // TODO: verify this if correct for integers and similar types.
+  template <typename T> constexpr explicit BFloat16(T value) {
+    if constexpr (cpp::is_floating_point_v<T>) {
+      bits = fputil::cast<bfloat16>(value).bits;
+    } else {
+      bits = fputil::cast<bfloat16>(static_cast<float>(value)).bits;
+    }
+  }
 
   constexpr bool operator==(const BFloat16 other) const {
     return bits == other.bits;

>From 394f420f2404fa4552896809291bf6f82b0dc025 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 14 Jun 2025 06:42:41 +0530
Subject: [PATCH 20/28] refactor: bfloat16.h dependencies

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/CMakeLists.txt | 12 +++---------
 libc/src/__support/FPUtil/bfloat16.h     | 18 ++++++------------
 2 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index 30a375ddb0666..55a6ddee5d7e0 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -262,16 +262,10 @@ add_header_library(
   HDRS
     bfloat16.h
   DEPENDS
-    .fenv_impl
-    .fp_bits
-    .cast
-    .rounding_mode
-    libc.hdr.errno_macros
-    libc.hdr.fenv_macros
-    libc.src.__support.CPP.type_traits
     libc.src.__support.CPP.bit
-    libc.src.__support.big_int
-    libc.src.__support.macros.optimization
+    libc.src.__support.CPP.type_traits
+    .cast
+    libc.src.__support.macros.config
     libc.src.__support.macros.properties.types
 )
 
diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 03a7ef35b3450..d83d8595e9dbe 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -9,19 +9,13 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
 #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_BFLOAT16_H
 
-#include "FEnvImpl.h"
-#include "FPBits.h"
-#include "hdr/errno_macros.h"
-#include "hdr/fenv_macros.h"
-#include "multiply_add.h"
-#include "rounding_mode.h"
-#include "src/__support/CPP/type_traits.h"
-#include "src/__support/FPUtil/cast.h"
-#include "src/__support/macros/config.h"
+#include "src/__support/CPP/bit.h"                 // cpp::bit_cast
+#include "src/__support/CPP/type_traits.h"         // cpp::is_floating_point_v
+#include "src/__support/FPUtil/cast.h"             // fputil::cast
+#include "src/__support/macros/config.h"           // LIBC_NAMESPACE_DECL
 #include "src/__support/macros/properties/types.h" // bfloat16
 
-#include <stddef.h>
-#include <stdint.h>
+#include <stdint.h> // uint16_t
 
 namespace LIBC_NAMESPACE_DECL {
 struct BFloat16 {
@@ -48,7 +42,7 @@ struct BFloat16 {
     uint32_t x_bits = static_cast<uint32_t>(bits) << 16U;
     return cpp::bit_cast<float>(x_bits);
   }
-};
+}; // struct BFloat16
 
 } // namespace LIBC_NAMESPACE_DECL
 

>From f137dcf6a37bbb6b2d337110a5b4f4e740c9e4bd Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Sat, 14 Jun 2025 07:15:12 +0530
Subject: [PATCH 21/28] chore: remove fbfloat16 dummy function

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/config/linux/x86_64/entrypoints.txt      |  1 -
 libc/src/math/CMakeLists.txt                  |  3 --
 libc/src/math/fbfloat16.h                     | 22 ---------
 libc/src/math/generic/CMakeLists.txt          | 14 ------
 libc/src/math/generic/fbfloat16.cpp           | 25 -----------
 libc/test/src/math/exhaustive/CMakeLists.txt  | 15 -------
 .../src/math/exhaustive/fbfloat16_test.cpp    | 45 -------------------
 libc/test/src/math/smoke/CMakeLists.txt       | 12 -----
 libc/test/src/math/smoke/fbfloat16_test.cpp   | 30 -------------
 9 files changed, 167 deletions(-)
 delete mode 100644 libc/src/math/fbfloat16.h
 delete mode 100644 libc/src/math/generic/fbfloat16.cpp
 delete mode 100644 libc/test/src/math/exhaustive/fbfloat16_test.cpp
 delete mode 100644 libc/test/src/math/smoke/fbfloat16_test.cpp

diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 2af2066671d01..00044b1631f8c 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -858,7 +858,6 @@ endif()
 if(LIBC_TYPES_HAS_BFLOAT16)
   list(APPEND TARGET_LIBM_ENTRYPOINTS
     # Bfloat16 Entrypoints
-    libc.src.math.fbfloat16
   )
 endif()
 
diff --git a/libc/src/math/CMakeLists.txt b/libc/src/math/CMakeLists.txt
index 0aa0fa7ab700a..055e76468a461 100644
--- a/libc/src/math/CMakeLists.txt
+++ b/libc/src/math/CMakeLists.txt
@@ -554,6 +554,3 @@ add_math_entrypoint_object(ufromfpxf)
 add_math_entrypoint_object(ufromfpxl)
 add_math_entrypoint_object(ufromfpxf16)
 add_math_entrypoint_object(ufromfpxf128)
-
-# BFloat16 functions
-add_math_entrypoint_object(fbfloat16)
diff --git a/libc/src/math/fbfloat16.h b/libc/src/math/fbfloat16.h
deleted file mode 100644
index 5b1b04b24a563..0000000000000
--- a/libc/src/math/fbfloat16.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- Implementation header for fbfloat16 ---------------------*- 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_MATH_FBFLOAT16_H
-#define LLVM_LIBC_SRC_MATH_FBFLOAT16_H
-
-#include "src/__support/FPUtil/bfloat16.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/properties/types.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-float fbfloat16(bfloat16 x);
-
-} // namespace LIBC_NAMESPACE_DECL
-
-#endif // LLVM_LIBC_SRC_MATH_FBFLOAT16_H
diff --git a/libc/src/math/generic/CMakeLists.txt b/libc/src/math/generic/CMakeLists.txt
index bfd057ac57937..e5d1f9075bcb1 100644
--- a/libc/src/math/generic/CMakeLists.txt
+++ b/libc/src/math/generic/CMakeLists.txt
@@ -5066,20 +5066,6 @@ add_entrypoint_object(
     libc.src.__support.FPUtil.generic.mul
 )
 
-# Bfloat16 Functions
-
-add_entrypoint_object(
-  fbfloat16
-  SRCS
-    fbfloat16.cpp
-  HDRS
-    ../fbfloat16.h
-  DEPENDS
-    libc.src.__support.macros.config
-    libc.src.__support.macros.properties.types
-    libc.src.__support.FPUtil.bfloat16
-)
-
 add_header_library(
   expxf16
   HDRS
diff --git a/libc/src/math/generic/fbfloat16.cpp b/libc/src/math/generic/fbfloat16.cpp
deleted file mode 100644
index 1ef183668a51a..0000000000000
--- a/libc/src/math/generic/fbfloat16.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===-- Implementation of fbfloat16 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 "src/math/fbfloat16.h"
-
-#include "src/__support/FPUtil/bfloat16.h"
-#include "src/__support/common.h"
-#include "src/__support/macros/config.h"
-#include "src/__support/macros/properties/types.h"
-
-namespace LIBC_NAMESPACE_DECL {
-
-LLVM_LIBC_FUNCTION(float, fbfloat16, (bfloat16 x)) {
-  if (x.bits == 0)
-    return 0.0f;
-  else
-    return 1.0f;
-}
-
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index feff53aad7dff..551f449c9c8db 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -535,18 +535,3 @@ add_fp_unittest(
   LINK_LIBRARIES
     -lpthread
 )
-
-# Bfloat16 Exhaustive Tests
-
-add_fp_unittest(
-  fbfloat16_test
-  NO_RUN_POSTBUILD
-  NEED_MPFR
-  SUITE
-    libc_math_exhaustive_tests
-  SRCS
-    fbfloat16_test.cpp
-  DEPENDS
-    .exhaustive_test
-    libc.src.math.fbfloat16
-)
diff --git a/libc/test/src/math/exhaustive/fbfloat16_test.cpp b/libc/test/src/math/exhaustive/fbfloat16_test.cpp
deleted file mode 100644
index bb5e6f9854a54..0000000000000
--- a/libc/test/src/math/exhaustive/fbfloat16_test.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===-- Exhaustive tests for fbfloat16 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 "src/__support/FPUtil/bfloat16.h"
-
-#include "utils/MPFRWrapper/MPCommon.h"
-
-#include "src/math/fbfloat16.h"
-#include "test/UnitTest/FPMatcher.h"
-#include "test/UnitTest/Test.h"
-
-using LlvmLibcFBfloat16ExhaustiveTest =
-    LIBC_NAMESPACE::testing::FPTest<bfloat16>;
-
-// range: [0, inf]
-static constexpr uint16_t POS_START = 0x0000U;
-static constexpr uint16_t POS_STOP = 0x7f80U;
-
-// range: [-0, -inf]
-static constexpr uint16_t NEG_START = 0x8000U;
-static constexpr uint16_t NEG_STOP = 0xff80;
-
-
-using MPFRNumber = LIBC_NAMESPACE::testing::mpfr::MPFRNumber;
-
-TEST_F(LlvmLibcFBfloat16ExhaustiveTest, PositiveRange) {
-  for (uint16_t bits = POS_START; bits <= POS_STOP; bits++) {
-    bfloat16 bf16_num{bits};
-    MPFRNumber mpfr_num{bf16_num};
-    ASSERT_FP_EQ(mpfr_num.as<float>(), bf16_num.as_float());
-  }
-}
-
-TEST_F(LlvmLibcFBfloat16ExhaustiveTest, NegativeRange) {
-  for (uint16_t bits = NEG_START; bits <= NEG_STOP; bits++) {
-    bfloat16 bf16_num{bits};
-    MPFRNumber mpfr_num{bf16_num};
-    ASSERT_FP_EQ(mpfr_num.as<float>(), bf16_num.as_float());
-  }
-}
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index fc9cbbf4e9df0..55edffb4f5bdf 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -5307,15 +5307,3 @@ add_fp_unittest(
     libc.src.__support.macros.properties.os
     libc.src.__support.macros.properties.types
 )
-
-# Bfloat16 Smoke Tests
-
-add_fp_unittest(
-  fbfloat16_test
-  SUITE
-    libc-math-smoke-tests
-  SRCS
-    fbfloat16_test.cpp
-  DEPENDS
-    libc.src.math.fbfloat16
-)
diff --git a/libc/test/src/math/smoke/fbfloat16_test.cpp b/libc/test/src/math/smoke/fbfloat16_test.cpp
deleted file mode 100644
index c4f0892e4772e..0000000000000
--- a/libc/test/src/math/smoke/fbfloat16_test.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===-- Unittests for fbfloat16 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 "src/__support/FPUtil/bfloat16.h"
-
-#include "src/math/fbfloat16.h"
-#include "test/UnitTest/FPMatcher.h"
-#include "test/UnitTest/Test.h"
-
-using LlvmLibcFBfloat16SmokeTest = LIBC_NAMESPACE::testing::FPTest<bfloat16>;
-
-TEST_F(LlvmLibcFBfloat16SmokeTest, SpecialNumbers) {
-  constexpr float SPECIAL_FLOATS[] = {
-    0.0f, 1.0f, 2.0f, 4.5f, -1.0f, -0.5f, 3.140625f
-  };
-
-  constexpr uint16_t SPECIAL_BFLOAT16_BITS[] = {
-    0, 0x3f80U, 0x4000U, 0x4090U, 0xbf80U, 0xbf00, 0x4049U
-  };
-
-  for (int i=0; i<7; i++) {
-    bfloat16 x{SPECIAL_FLOATS[i]};
-    ASSERT_EQ(SPECIAL_BFLOAT16_BITS[i], x.bits);
-  }
-}

>From 1ce3c78a44de3946a5076c324a03fd8508cf518b Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Tue, 17 Jun 2025 08:52:20 +0530
Subject: [PATCH 22/28] style: clang-format

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/macros/properties/types.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/macros/properties/types.h b/libc/src/__support/macros/properties/types.h
index 729086295e83f..d5b7775200e4e 100644
--- a/libc/src/__support/macros/properties/types.h
+++ b/libc/src/__support/macros/properties/types.h
@@ -10,9 +10,9 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
 #define LLVM_LIBC_SRC___SUPPORT_MACROS_PROPERTIES_TYPES_H
 
-#include "hdr/float_macros.h"                         // LDBL_MANT_DIG
-#include "include/llvm-libc-macros/float16-macros.h"  // LIBC_TYPES_HAS_FLOAT16
-#include "include/llvm-libc-types/float128.h"         // float128
+#include "hdr/float_macros.h"                        // LDBL_MANT_DIG
+#include "include/llvm-libc-macros/float16-macros.h" // LIBC_TYPES_HAS_FLOAT16
+#include "include/llvm-libc-types/float128.h"        // float128
 #include "src/__support/macros/properties/architectures.h"
 #include "src/__support/macros/properties/compiler.h"
 #include "src/__support/macros/properties/cpu_features.h"
@@ -63,7 +63,7 @@ using float16 = _Float16;
 // -- bfloat16 support ---------------------------------------------------------
 
 namespace LIBC_NAMESPACE_DECL {
-    struct BFloat16;
+struct BFloat16;
 }
 
 using bfloat16 = LIBC_NAMESPACE::BFloat16;

>From 0bef082ab39894bc9aa6e21e5401fa733b3c8666 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Tue, 17 Jun 2025 10:05:03 +0530
Subject: [PATCH 23/28] feat: implement unittests for bfloat16 conversions

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/test/src/__support/FPUtil/CMakeLists.txt | 11 ++++
 .../src/__support/FPUtil/bfloat16_test.cpp    | 63 +++++++++++++++++++
 libc/utils/MPFRWrapper/CMakeLists.txt         |  1 +
 libc/utils/MPFRWrapper/MPCommon.cpp           |  6 ++
 4 files changed, 81 insertions(+)
 create mode 100644 libc/test/src/__support/FPUtil/bfloat16_test.cpp

diff --git a/libc/test/src/__support/FPUtil/CMakeLists.txt b/libc/test/src/__support/FPUtil/CMakeLists.txt
index 1e64e9ba425a5..dfd90057b6ebf 100644
--- a/libc/test/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/test/src/__support/FPUtil/CMakeLists.txt
@@ -38,3 +38,14 @@ add_fp_unittest(
   DEPENDS
     libc.src.__support.FPUtil.rounding_mode
 )
+
+add_fp_unittest(
+  bfloat16_test
+  NEED_MPFR
+  SUITE
+    libc-fputil-tests
+  SRCS
+    bfloat16_test.cpp
+  DEPENDS
+    libc.src.__support.FPUtil.bfloat16
+)
diff --git a/libc/test/src/__support/FPUtil/bfloat16_test.cpp b/libc/test/src/__support/FPUtil/bfloat16_test.cpp
new file mode 100644
index 0000000000000..3bfabf3fdd3db
--- /dev/null
+++ b/libc/test/src/__support/FPUtil/bfloat16_test.cpp
@@ -0,0 +1,63 @@
+//===-- Unit tests for bfloat16 type --------------------------------------===//
+//
+// 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 "src/__support/FPUtil/bfloat16.h"
+
+#include "utils/MPFRWrapper/MPCommon.h"
+
+#include "test/UnitTest/FPMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcBfloat16ExhaustiveTest =
+    LIBC_NAMESPACE::testing::FPTest<bfloat16>;
+
+// range: [0, inf]
+static constexpr uint16_t POS_START = 0x0000U;
+static constexpr uint16_t POS_STOP = 0x7f80U;
+
+// range: [-0, -inf]
+static constexpr uint16_t NEG_START = 0x8000U;
+static constexpr uint16_t NEG_STOP = 0xff80;
+
+
+using MPFRNumber = LIBC_NAMESPACE::testing::mpfr::MPFRNumber;
+
+// TODO: better naming?
+TEST_F(LlvmLibcBfloat16ExhaustiveTest, PositiveRange) {
+  for (uint16_t bits = POS_START; bits <= POS_STOP; bits++) {
+    bfloat16 bf16_num{bits};
+    MPFRNumber mpfr_num{bf16_num};
+    
+    // bfloat16 to float
+    float mpfr_float = mpfr_num.as<float>();
+    ASSERT_FP_EQ(mpfr_float, bf16_num.as_float());
+
+    // float to bfloat16
+    bfloat16 bf16_from_float{mpfr_float};
+    MPFRNumber mpfr_num_2{mpfr_float};
+    bfloat16 mpfr_bfloat = mpfr_num_2.as<bfloat16>();
+    ASSERT_FP_EQ(mpfr_bfloat, bf16_from_float);
+  }
+}
+
+TEST_F(LlvmLibcBfloat16ExhaustiveTest, NegativeRange) {
+  for (uint16_t bits = NEG_START; bits <= NEG_STOP; bits++) {
+    bfloat16 bf16_num{bits};
+    MPFRNumber mpfr_num{bf16_num};
+    
+    // bfloat16 to float
+    float mpfr_float = mpfr_num.as<float>();
+    ASSERT_FP_EQ(mpfr_float, bf16_num.as_float());
+
+    // float to bfloat16
+    bfloat16 bf16_from_float{mpfr_float};
+    MPFRNumber mpfr_num_2{mpfr_float};
+    bfloat16 mpfr_bfloat = mpfr_num_2.as<bfloat16>();
+    ASSERT_FP_EQ(mpfr_bfloat, bf16_from_float);
+  }
+}
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index 9ff7fa109ff97..ccc26642aaf69 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -42,6 +42,7 @@ if(LIBC_TESTS_CAN_USE_MPFR)
     libc.src.__support.CPP.stringstream
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.fpbits_str
+    libc.src.__support.FPUtil.bfloat16
     LibcTest.unit
   )
   if(EXISTS ${LLVM_LIBC_MPFR_INSTALL_PATH})
diff --git a/libc/utils/MPFRWrapper/MPCommon.cpp b/libc/utils/MPFRWrapper/MPCommon.cpp
index ccd4d2d01a4e2..9d2dd2e37f6fb 100644
--- a/libc/utils/MPFRWrapper/MPCommon.cpp
+++ b/libc/utils/MPFRWrapper/MPCommon.cpp
@@ -13,6 +13,8 @@
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/types.h"
 
+#include "src/__support/FPUtil/bfloat16.h"
+
 namespace LIBC_NAMESPACE_DECL {
 namespace testing {
 namespace mpfr {
@@ -566,6 +568,10 @@ template <> float16 MPFRNumber::as<float16>() const {
 }
 #endif
 
+template <> bfloat16 MPFRNumber::as<bfloat16>() const {
+  return fputil::cast<bfloat16>(mpfr_get_flt(value, mpfr_rounding));
+}
+
 #ifdef LIBC_TYPES_FLOAT128_IS_NOT_LONG_DOUBLE
 template <> float128 MPFRNumber::as<float128>() const {
   return mpfr_get_float128(value, mpfr_rounding);

>From d5b22c279e2612998f3197939f93ad75a131e079 Mon Sep 17 00:00:00 2001
From: krishna2803 <kpandey81930 at gmail.com>
Date: Wed, 18 Jun 2025 04:02:49 +0530
Subject: [PATCH 24/28] chore: prevent casting to same type in fputil::cast

Signed-off-by: krishna2803 <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/cast.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libc/src/__support/FPUtil/cast.h b/libc/src/__support/FPUtil/cast.h
index 0831ee3396322..2ba6560db29bb 100644
--- a/libc/src/__support/FPUtil/cast.h
+++ b/libc/src/__support/FPUtil/cast.h
@@ -27,6 +27,11 @@ LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_floating_point_v<OutType> &&
                                        OutType>
 cast(InType x) {
 
+  // no need to cast to the same type
+  if constexpr (cpp::is_same_v<InType, OutType>) {
+    return x;
+  }
+
   // bfloat16 is always defined (for now)
   if constexpr (cpp::is_same_v<OutType, bfloat16> ||
                 cpp::is_same_v<InType, bfloat16>

>From 78af99a7dc833b420e5da071b425ffc2a50594f2 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 5 Jul 2025 15:15:56 +0530
Subject: [PATCH 25/28] remove: operator overload for equals from bfloat16 type

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/bfloat16.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index d83d8595e9dbe..39999e8e1e207 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -34,10 +34,6 @@ struct BFloat16 {
     }
   }
 
-  constexpr bool operator==(const BFloat16 other) const {
-    return bits == other.bits;
-  }
-
   constexpr float as_float() const {
     uint32_t x_bits = static_cast<uint32_t>(bits) << 16U;
     return cpp::bit_cast<float>(x_bits);

>From 11097876da838429e5568b3b0d02bc9d819caa68 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sat, 5 Jul 2025 15:16:38 +0530
Subject: [PATCH 26/28] feat: add exhaustive tests for float to bfloat16
 conversion

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/test/src/math/exhaustive/CMakeLists.txt  | 18 +++++
 .../src/math/exhaustive/bfloat16_test.cpp     | 70 +++++++++++++++++++
 2 files changed, 88 insertions(+)
 create mode 100644 libc/test/src/math/exhaustive/bfloat16_test.cpp

diff --git a/libc/test/src/math/exhaustive/CMakeLists.txt b/libc/test/src/math/exhaustive/CMakeLists.txt
index 551f449c9c8db..5939b21b9cb66 100644
--- a/libc/test/src/math/exhaustive/CMakeLists.txt
+++ b/libc/test/src/math/exhaustive/CMakeLists.txt
@@ -535,3 +535,21 @@ add_fp_unittest(
   LINK_LIBRARIES
     -lpthread
 )
+
+
+add_fp_unittest(
+  bfloat16_test
+  NO_RUN_POSTBUILD
+  NEED_MPFR
+  SUITE
+  libc_math_exhaustive_tests
+  SRCS
+  bfloat16_test.cpp
+  DEPENDS
+  .exhaustive_test
+  libc.src.__support.FPUtil.bfloat16
+  libc.src.__support.FPUtil.fp_bits
+  LINK_LIBRARIES
+  -lpthread
+)
+
diff --git a/libc/test/src/math/exhaustive/bfloat16_test.cpp b/libc/test/src/math/exhaustive/bfloat16_test.cpp
new file mode 100644
index 0000000000000..f90167fd82195
--- /dev/null
+++ b/libc/test/src/math/exhaustive/bfloat16_test.cpp
@@ -0,0 +1,70 @@
+//===-- Exhaustive tests for float32 -> bfloat16 conversion ---------------===//
+//
+// 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 "exhaustive_test.h"
+#include "src/__support/FPUtil/bfloat16.h"
+#include "utils/MPFRWrapper/MPCommon.h"
+#include "utils/MPFRWrapper/MPFRUtils.h"
+
+namespace mpfr = LIBC_NAMESPACE::testing::mpfr;
+using MPFRNumber = LIBC_NAMESPACE::testing::mpfr::MPFRNumber;
+
+template <typename InType>
+struct Bfloat16ConversionChecker
+    : public virtual LIBC_NAMESPACE::testing::Test {
+  using FloatType = InType;
+  using FPBits = LIBC_NAMESPACE::fputil::FPBits<FloatType>;
+  using StorageType = typename FPBits::StorageType;
+
+  // Check in a range, return the number of failures.
+  // Slightly modified version of UnaryOpChecker.
+  uint64_t check(StorageType start, StorageType stop,
+                 mpfr::RoundingMode rounding) {
+    mpfr::ForceRoundingMode r(rounding);
+    if (!r.success)
+      return (stop > start);
+    StorageType bits = start;
+    uint64_t failed = 0;
+    do {
+      FPBits x_bits(bits);
+      FloatType x = x_bits.get_val();
+
+      const bfloat16 libc_bfloat{x};
+      const bfloat16 mpfr_bfloat = MPFRNumber(x).as<bfloat16>();
+
+      const bool correct =
+          LIBC_NAMESPACE::testing::getMatcher<
+              LIBC_NAMESPACE::testing::TestCond::EQ>(mpfr_bfloat)
+              .match(libc_bfloat);
+
+      failed += (!correct);
+    } while (bits++ < stop);
+    return failed;
+  }
+};
+
+template <typename FloatType>
+using LlvmLibcBfloat16ExhaustiveTest =
+    LlvmLibcExhaustiveMathTest<Bfloat16ConversionChecker<FloatType>>;
+using LlvmLibcBfloat16FromFloatTest = LlvmLibcBfloat16ExhaustiveTest<float>;
+
+// Positive Range: [0, Inf];
+constexpr uint32_t POS_START = 0x0000'0000U;
+constexpr uint32_t POS_STOP = 0x7f80'0000U;
+
+// Negative Range: [-Inf, 0];
+constexpr uint32_t NEG_START = 0xb000'0000U;
+constexpr uint32_t NEG_STOP = 0xff80'0000U;
+
+TEST_F(LlvmLibcBfloat16FromFloatTest, PostiveRange) {
+  test_full_range_all_roundings(POS_START, POS_STOP);
+}
+
+TEST_F(LlvmLibcBfloat16FromFloatTest, NegativeRange) {
+  test_full_range_all_roundings(NEG_START, NEG_STOP);
+}

>From 5e882aa7d707b1b5b4c978a4aebcc2320360d029 Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sun, 6 Jul 2025 12:33:03 +0530
Subject: [PATCH 27/28] feat[WIP]: implement integer to bfloat16 ctor

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 libc/src/__support/FPUtil/bfloat16.h | 35 +++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/FPUtil/bfloat16.h b/libc/src/__support/FPUtil/bfloat16.h
index 39999e8e1e207..fa24adf5c5ffc 100644
--- a/libc/src/__support/FPUtil/bfloat16.h
+++ b/libc/src/__support/FPUtil/bfloat16.h
@@ -25,10 +25,43 @@ struct BFloat16 {
 
   constexpr explicit BFloat16(uint16_t bits) : bits(bits) {}
 
-  // TODO: verify this if correct for integers and similar types.
   template <typename T> constexpr explicit BFloat16(T value) {
     if constexpr (cpp::is_floating_point_v<T>) {
       bits = fputil::cast<bfloat16>(value).bits;
+    } else if constexpr (cpp::is_integral_v<T>) {
+      //  TODO: verify this
+      Sign sign = Sign::POS;
+
+      if constexpr (cpp::is_signed_v<T>) {
+        if (value < 0) {
+          sign = Sign::NEG;
+          value = -value;
+        }
+      }
+      cpp::make_unsigned_t<T> uvalue = value;
+
+      int msb = cpp::bit_width(uvalue) - 1;
+      int biased_exponent = msb + 127;
+
+      if (biased_exponent > 255) {
+        bits = fputil::FPBits<bfloat16>::inf(sign).get_val().bits;
+        return;
+      }
+
+      // TODO: currently, this is just truncation. need to handle rounding.
+      if (msb >= 7) {
+        uvalue >>= (msb - 7);
+      } else {
+        uvalue <<= (7 - msb);
+      }
+
+      const auto exp = static_cast<uint16_t>(biased_exponent << 7U);
+      const uint16_t mant = static_cast<uint16_t>(uvalue) & 0x7F;
+
+      bits = exp | mant;
+      if (sign.is_neg()) {
+        bits |= (1U << 15);
+      }
     } else {
       bits = fputil::cast<bfloat16>(static_cast<float>(value)).bits;
     }

>From ab1eb04d52edea21301ee3958996c7e677c81b0c Mon Sep 17 00:00:00 2001
From: Krishna Pandey <kpandey81930 at gmail.com>
Date: Sun, 6 Jul 2025 12:34:14 +0530
Subject: [PATCH 28/28] feat[WIP]: implement dummy tests for integer to
 bfloat16 ctor

Signed-off-by: Krishna Pandey <kpandey81930 at gmail.com>
---
 .../src/__support/FPUtil/bfloat16_test.cpp    | 25 ++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/libc/test/src/__support/FPUtil/bfloat16_test.cpp b/libc/test/src/__support/FPUtil/bfloat16_test.cpp
index 3bfabf3fdd3db..96e8f83a36817 100644
--- a/libc/test/src/__support/FPUtil/bfloat16_test.cpp
+++ b/libc/test/src/__support/FPUtil/bfloat16_test.cpp
@@ -24,7 +24,6 @@ static constexpr uint16_t POS_STOP = 0x7f80U;
 static constexpr uint16_t NEG_START = 0x8000U;
 static constexpr uint16_t NEG_STOP = 0xff80;
 
-
 using MPFRNumber = LIBC_NAMESPACE::testing::mpfr::MPFRNumber;
 
 // TODO: better naming?
@@ -32,7 +31,7 @@ TEST_F(LlvmLibcBfloat16ExhaustiveTest, PositiveRange) {
   for (uint16_t bits = POS_START; bits <= POS_STOP; bits++) {
     bfloat16 bf16_num{bits};
     MPFRNumber mpfr_num{bf16_num};
-    
+
     // bfloat16 to float
     float mpfr_float = mpfr_num.as<float>();
     ASSERT_FP_EQ(mpfr_float, bf16_num.as_float());
@@ -43,13 +42,23 @@ TEST_F(LlvmLibcBfloat16ExhaustiveTest, PositiveRange) {
     bfloat16 mpfr_bfloat = mpfr_num_2.as<bfloat16>();
     ASSERT_FP_EQ(mpfr_bfloat, bf16_from_float);
   }
+
+  auto test_for_int = [&](const int x) {
+    const auto y = static_cast<float>(x);
+    EXPECT_FP_EQ(bfloat16{y}, bfloat16{x});
+  };
+
+  test_for_int(2);
+  test_for_int(17);
+  test_for_int(21);
+  test_for_int(16320);
 }
 
 TEST_F(LlvmLibcBfloat16ExhaustiveTest, NegativeRange) {
   for (uint16_t bits = NEG_START; bits <= NEG_STOP; bits++) {
     bfloat16 bf16_num{bits};
     MPFRNumber mpfr_num{bf16_num};
-    
+
     // bfloat16 to float
     float mpfr_float = mpfr_num.as<float>();
     ASSERT_FP_EQ(mpfr_float, bf16_num.as_float());
@@ -60,4 +69,14 @@ TEST_F(LlvmLibcBfloat16ExhaustiveTest, NegativeRange) {
     bfloat16 mpfr_bfloat = mpfr_num_2.as<bfloat16>();
     ASSERT_FP_EQ(mpfr_bfloat, bf16_from_float);
   }
+
+  auto test_for_int = [&](const int x) {
+    const auto y = static_cast<float>(x);
+    EXPECT_FP_EQ(bfloat16{y}, bfloat16{x});
+  };
+
+  test_for_int(-2);
+  test_for_int(-17);
+  test_for_int(-21);
+  test_for_int(-16320);
 }



More information about the libc-commits mailing list