[libc-commits] [libc] [libc][stdfix] Initial support for stdfix.h and fixed point arithmetic. (PR #81201)

via libc-commits libc-commits at lists.llvm.org
Thu Feb 8 14:33:55 PST 2024


https://github.com/lntue created https://github.com/llvm/llvm-project/pull/81201

None

>From 78ba7ab07c4c73bf51a2775d1fda2fc2f2685cf9 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Thu, 8 Feb 2024 22:32:23 +0000
Subject: [PATCH] [libc][stdfix] Initial support for stdfix.h and fixed point
 arithmetic.

---
 .../cmake/modules/CheckCompilerFeatures.cmake |   4 +-
 .../compiler_features/check_fixedpoint.cpp    |   5 +
 libc/config/linux/x86_64/entrypoints.txt      |  12 +
 libc/include/CMakeLists.txt                   |   9 +
 libc/include/llvm-libc-macros/CMakeLists.txt  |   6 +
 libc/include/llvm-libc-macros/stdfix-macros.h | 347 ++++++++++++++++++
 libc/include/llvm-libc-types/CMakeLists.txt   |   7 +
 libc/include/llvm-libc-types/stdfix_types.h   |  19 +
 libc/include/stdfix.h.def                     |  21 ++
 libc/spec/spec.td                             |  16 +
 libc/spec/stdc.td                             |  18 +
 libc/src/CMakeLists.txt                       |   1 +
 libc/src/__support/CMakeLists.txt             |   2 +
 libc/src/__support/fixedpoint/CMakeLists.txt  |  21 ++
 libc/src/__support/fixedpoint/fxbits.h        |  37 ++
 libc/src/__support/fixedpoint/fxrep.h         | 158 ++++++++
 libc/src/stdfix/CMakeLists.txt                |  17 +
 libc/src/stdfix/abshk.cpp                     |  19 +
 libc/src/stdfix/abshk.h                       |  20 +
 libc/src/stdfix/abshr.cpp                     |  19 +
 libc/src/stdfix/abshr.h                       |  20 +
 libc/src/stdfix/absk.cpp                      |  17 +
 libc/src/stdfix/absk.h                        |  20 +
 libc/src/stdfix/abslk.cpp                     |  19 +
 libc/src/stdfix/abslk.h                       |  20 +
 libc/src/stdfix/abslr.cpp                     |  19 +
 libc/src/stdfix/abslr.h                       |  20 +
 libc/src/stdfix/absr.cpp                      |  17 +
 libc/src/stdfix/absr.h                        |  20 +
 libc/test/src/stdfix/AbsTest.h                |  37 ++
 libc/test/src/stdfix/CMakeLists.txt           |  18 +
 libc/test/src/stdfix/abshk_test.cpp           |  13 +
 libc/test/src/stdfix/abshr_test.cpp           |  13 +
 libc/test/src/stdfix/absk_test.cpp            |  13 +
 libc/test/src/stdfix/abslk_test.cpp           |  13 +
 libc/test/src/stdfix/abslr_test.cpp           |  13 +
 libc/test/src/stdfix/absr_test.cpp            |  13 +
 37 files changed, 1062 insertions(+), 1 deletion(-)
 create mode 100644 libc/cmake/modules/compiler_features/check_fixedpoint.cpp
 create mode 100644 libc/include/llvm-libc-macros/stdfix-macros.h
 create mode 100644 libc/include/llvm-libc-types/stdfix_types.h
 create mode 100644 libc/include/stdfix.h.def
 create mode 100644 libc/src/__support/fixedpoint/CMakeLists.txt
 create mode 100644 libc/src/__support/fixedpoint/fxbits.h
 create mode 100644 libc/src/__support/fixedpoint/fxrep.h
 create mode 100644 libc/src/stdfix/CMakeLists.txt
 create mode 100644 libc/src/stdfix/abshk.cpp
 create mode 100644 libc/src/stdfix/abshk.h
 create mode 100644 libc/src/stdfix/abshr.cpp
 create mode 100644 libc/src/stdfix/abshr.h
 create mode 100644 libc/src/stdfix/absk.cpp
 create mode 100644 libc/src/stdfix/absk.h
 create mode 100644 libc/src/stdfix/abslk.cpp
 create mode 100644 libc/src/stdfix/abslk.h
 create mode 100644 libc/src/stdfix/abslr.cpp
 create mode 100644 libc/src/stdfix/abslr.h
 create mode 100644 libc/src/stdfix/absr.cpp
 create mode 100644 libc/src/stdfix/absr.h
 create mode 100644 libc/test/src/stdfix/AbsTest.h
 create mode 100644 libc/test/src/stdfix/CMakeLists.txt
 create mode 100644 libc/test/src/stdfix/abshk_test.cpp
 create mode 100644 libc/test/src/stdfix/abshr_test.cpp
 create mode 100644 libc/test/src/stdfix/absk_test.cpp
 create mode 100644 libc/test/src/stdfix/abslk_test.cpp
 create mode 100644 libc/test/src/stdfix/abslr_test.cpp
 create mode 100644 libc/test/src/stdfix/absr_test.cpp

diff --git a/libc/cmake/modules/CheckCompilerFeatures.cmake b/libc/cmake/modules/CheckCompilerFeatures.cmake
index 983ce86ab1b25..ed425ca90d6c7 100644
--- a/libc/cmake/modules/CheckCompilerFeatures.cmake
+++ b/libc/cmake/modules/CheckCompilerFeatures.cmake
@@ -3,7 +3,7 @@
 # ------------------------------------------------------------------------------
 
 # Initialize ALL_COMPILER_FEATURES as empty list.
-set(ALL_COMPILER_FEATURES "float128")
+set(ALL_COMPILER_FEATURES "float128" "fixedpoint")
 
 # Making sure ALL_COMPILER_FEATURES is sorted.
 list(SORT ALL_COMPILER_FEATURES)
@@ -52,6 +52,8 @@ foreach(feature IN LISTS ALL_COMPILER_FEATURES)
     list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
     if(${feature} STREQUAL "float128")
       set(LIBC_COMPILER_HAS_FLOAT128 TRUE)
+    elseif(${feature} STREQUAL "fixedpoint")
+      set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
     endif()
   endif()
 endforeach()
diff --git a/libc/cmake/modules/compiler_features/check_fixedpoint.cpp b/libc/cmake/modules/compiler_features/check_fixedpoint.cpp
new file mode 100644
index 0000000000000..f9711ff8cec0a
--- /dev/null
+++ b/libc/cmake/modules/compiler_features/check_fixedpoint.cpp
@@ -0,0 +1,5 @@
+#include "include/llvm-libc-types/stdfix_types.h"
+
+#ifndef LIBC_COMPILER_HAS_FIXED_POINT
+#error unsupported
+#endif
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index b35fc9fc6866b..5fea05df087b8 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -419,6 +419,18 @@ if(LIBC_COMPILER_HAS_FLOAT128)
   )
 endif()
 
+if(LIBC_COMPILER_HAS_FIXED_POINT)
+  list(APPEND TARGET_LIBM_ENTRYPOINTS
+    # stdfix.h N1169 _Fract and _Accum entrypoints
+    libc.src.stdfix.abshk
+    libc.src.stdfix.abshr
+    libc.src.stdfix.absk
+    libc.src.stdfix.absr
+    libc.src.stdfix.abslk
+    libc.src.stdfix.abslr
+  )
+endif()
+
 if(LLVM_LIBC_FULL_BUILD)
   list(APPEND TARGET_LIBC_ENTRYPOINTS
     # assert.h entrypoints
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 332410453b54d..be21ac1984044 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -104,6 +104,15 @@ add_gen_header(
     .llvm-libc-types.float128
 )
 
+add_gen_header(
+  stdfix
+  DEF_FILE stdfix.h.def
+  GEN_HDR stdfix.h
+  DEPENDS
+    .llvm-libc-macros.stdfix_macros
+    .llvm-libc-types.stdfix_types
+)
+
 # TODO: This should be conditional on POSIX networking being included.
 file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/arpa)
 
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index 562769a5e84ce..225885d3a9b08 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -227,3 +227,9 @@ add_macro_header(
   HDR
     inttypes-macros.h
 )
+
+add_macro_header(
+  stdfix_macros
+  HDR
+    stdfix-macros.h
+)
diff --git a/libc/include/llvm-libc-macros/stdfix-macros.h b/libc/include/llvm-libc-macros/stdfix-macros.h
new file mode 100644
index 0000000000000..0621353782936
--- /dev/null
+++ b/libc/include/llvm-libc-macros/stdfix-macros.h
@@ -0,0 +1,347 @@
+//===-- Definitions from stdfix.h -----------------------------------------===//
+//
+// 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_STDFIX_MACROS_H
+#define __LLVM_LIBC_MACROS_STDFIX_MACROS_H
+
+#ifdef __clang__
+#if (!defined(__cplusplus) || (__clang_major__ >= 18))
+// _Fract and _Accum types are avaiable
+#define LIBC_COMPILER_HAS_FIXED_POINT
+#endif // __cplusplus
+#endif // __clang__
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+
+#ifdef __SFRACT_FBIT__
+#define SFRACT_FBIT __SFRACT_FBIT__
+#else
+#define SFRACT_FBIT 7
+#endif // SFRACT_FBIT
+
+#ifdef __SFRACT_MIN__
+#define SFRACT_MIN __SFRACT_MIN__
+#else
+#define SFRACT_MIN (-0.5HR - 0.5HR)
+#endif // SFRACT_MIN
+
+#ifdef __SFRACT_MAX__
+#define SFRACT_MAX __SFRACT_MAX__
+#else
+#define SFRACT_MAX 0x1.FCp-1HR
+#endif // SFRACT_MAX
+
+#ifdef __SFRACT_EPSILON__
+#define SFRACT_EPSILON __SFRACT_EPSILON__
+#else
+#define SFRACT_EPSILON 0x1p-7HR
+#endif // SFRACT_EPSILON
+
+#ifdef __USFRACT_FBIT__
+#define USFRACT_FBIT __USFRACT_FBIT__
+#else
+#define USFRACT_FBIT 7
+#endif // USFRACT_FBIT
+
+#ifdef __USFRACT_MIN__
+#define USFRACT_MIN __USFRACT_MIN__
+#else
+#define USFRACT_MIN 0UHR
+#endif // USFRACT_MIN
+
+#ifdef __USFRACT_MAX__
+#define USFRACT_MAX __USFRACT_MAX__
+#else
+#define USFRACT_MAX 0x1.FCp-1UHR
+#endif // USFRACT_MAX
+
+#ifdef __USFRACT_EPSILON__
+#define USFRACT_EPSILON __USFRACT_EPSILON__
+#else
+#define USFRACT_EPSILON 0x1p-7UHR
+#endif // USFRACT_EPSILON
+
+#ifdef __FRACT_FBIT__
+#define FRACT_FBIT __FRACT_FBIT__
+#else
+#define FRACT_FBIT 15
+#endif // FRACT_FBIT
+
+#ifdef __FRACT_MIN__
+#define FRACT_MIN __FRACT_MIN__
+#else
+#define FRACT_MIN (-0.5R - 0.5R)
+#endif // FRACT_MIN
+
+#ifdef __FRACT_MAX__
+#define FRACT_MAX __FRACT_MAX__
+#else
+#define FRACT_MAX 0x1.FFFCp-1R
+#endif // FRACT_MAX
+
+#ifdef __FRACT_EPSILON__
+#define FRACT_EPSILON __FRACT_EPSILON__
+#else
+#define FRACT_EPSILON 0x1p-15R
+#endif // FRACT_EPSILON
+
+#ifdef __UFRACT_FBIT__
+#define UFRACT_FBIT __UFRACT_FBIT__
+#else
+#define UFRACT_FBIT 15
+#endif // UFRACT_FBIT
+
+#ifdef __UFRACT_MIN__
+#define UFRACT_MIN __UFRACT_MIN__
+#else
+#define UFRACT_MIN 0UR
+#endif // UFRACT_MIN
+
+#ifdef __UFRACT_MAX__
+#define UFRACT_MAX __UFRACT_MAX__
+#else
+#define UFRACT_MAX 0x1.FFFCp-1UR
+#endif // UFRACT_MAX
+
+#ifdef __UFRACT_EPSILON__
+#define UFRACT_EPSILON __UFRACT_EPSILON__
+#else
+#define UFRACT_EPSILON 0x1p-15UR
+#endif // UFRACT_EPSILON
+
+#ifdef __LFRACT_FBIT__
+#define LFRACT_FBIT __LFRACT_FBIT__
+#else
+#define LFRACT_FBIT 23
+#endif // LFRACT_FBIT
+
+#ifdef __LFRACT_MIN__
+#define LFRACT_MIN __LFRACT_MIN__
+#else
+#define LFRACT_MIN (-0.5LR - 0.5LR)
+#endif // LFRACT_MIN
+
+#ifdef __LFRACT_MAX__
+#define LFRACT_MAX __LFRACT_MAX__
+#else
+#define LFRACT_MAX 0x1.FFFFFCp-1LR
+#endif // LFRACT_MAX
+
+#ifdef __LFRACT_EPSILON__
+#define LFRACT_EPSILON __LFRACT_EPSILON__
+#else
+#define LFRACT_EPSILON 0x1p-23LR
+#endif // LFRACT_EPSILON
+
+#ifdef __ULFRACT_FBIT__
+#define ULFRACT_FBIT __ULFRACT_FBIT__
+#else
+#define ULFRACT_FBIT 23
+#endif // ULFRACT_FBIT
+
+#ifdef __ULFRACT_MIN__
+#define ULFRACT_MIN __ULFRACT_MIN__
+#else
+#define ULFRACT_MIN 0ULR
+#endif // ULFRACT_MIN
+
+#ifdef __ULFRACT_MAX__
+#define ULFRACT_MAX __ULFRACT_MAX__
+#else
+#define ULFRACT_MAX 0x1.FFFFFCp-1ULR
+#endif // ULFRACT_MAX
+
+#ifdef __ULFRACT_EPSILON__
+#define ULFRACT_EPSILON __ULFRACT_EPSILON__
+#else
+#define ULFRACT_EPSILON 0x1p-23ULR
+#endif // ULFRACT_EPSILON
+
+#ifdef __SACCUM_FBIT__
+#define SACCUM_FBIT __SACCUM_FBIT__
+#else
+#define SACCUM_FBIT 7
+#endif // SACCUM_FBIT
+
+#ifdef __SACCUM_IBIT__
+#define SACCUM_IBIT __SACCUM_IBIT__
+#else
+#define SACCUM_IBIT 4
+#endif // SACCUM_IBIT
+
+#ifdef __SACCUM_MIN__
+#define SACCUM_MIN __SACCUM_MIN__
+#else
+#define SACCUM_MIN (-8HK - 8HK)
+#endif // SACCUM_MIN
+
+#ifdef __SACCUM_MAX__
+#define SACCUM_MAX __SACCUM_MAX__
+#else
+#define SACCUM_MAX 0x1.FFCp+3HK
+#endif // SACCUM_MAX
+
+#ifdef __SACCUM_EPSILON__
+#define SACCUM_EPSILON __SACCUM_EPSILON__
+#else
+#define SACCUM_EPSILON 0x1p-7HK
+#endif // SACCUM_EPSILON
+
+#ifdef __USACCUM_FBIT__
+#define USACCUM_FBIT __USACCUM_FBIT__
+#else
+#define USACCUM_FBIT 7
+#endif // USACCUM_FBIT
+
+#ifdef __USACCUM_IBIT__
+#define USACCUM_IBIT __USACCUM_IBIT__
+#else
+#define USACCUM_IBIT 4
+#endif // USACCUM_IBIT
+
+#ifdef __USACCUM_MIN__
+#define USACCUM_MIN __USACCUM_MIN__
+#else
+#define USACCUM_MIN 0UHK
+#endif // USACCUM_MIN
+
+#ifdef __USACCUM_MAX__
+#define USACCUM_MAX __USACCUM_MAX__
+#else
+#define USACCUM_MAX 0x1.FFCp+3UHK
+#endif // USACCUM_MAX
+
+#ifdef __USACCUM_EPSILON__
+#define USACCUM_EPSILON __USACCUM_EPSILON__
+#else
+#define USACCUM_EPSILON 0x1p-7UHK
+#endif // USACCUM_EPSILON
+
+#ifdef __ACCUM_FBIT__
+#define ACCUM_FBIT __ACCUM_FBIT__
+#else
+#define ACCUM_FBIT 15
+#endif // ACCUM_FBIT
+
+#ifdef __ACCUM_IBIT__
+#define ACCUM_IBIT __ACCUM_IBIT__
+#else
+#define ACCUM_IBIT 4
+#endif // ACCUM_IBIT
+
+#ifdef __ACCUM_MIN__
+#define ACCUM_MIN __ACCUM_MIN__
+#else
+#define ACCUM_MIN (-8R - 8R)
+#endif // ACCUM_MIN
+
+#ifdef __ACCUM_MAX__
+#define ACCUM_MAX __ACCUM_MAX__
+#else
+#define ACCUM_MAX 0x1.FFFFCp+3K
+#endif // ACCUM_MAX
+
+#ifdef __ACCUM_EPSILON__
+#define ACCUM_EPSILON __ACCUM_EPSILON__
+#else
+#define ACCUM_EPSILON 0x1p-15K
+#endif // ACCUM_EPSILON
+
+#ifdef __UACCUM_FBIT__
+#define UACCUM_FBIT __UACCUM_FBIT__
+#else
+#define UACCUM_FBIT 15
+#endif // UACCUM_FBIT
+
+#ifdef __UACCUM_IBIT__
+#define UACCUM_IBIT __UACCUM_IBIT__
+#else
+#define UACCUM_IBIT 4
+#endif // UACCUM_IBIT
+
+#ifdef __UACCUM_MIN__
+#define UACCUM_MIN __UACCUM_MIN__
+#else
+#define UACCUM_MIN 0UK
+#endif // UACCUM_MIN
+
+#ifdef __UACCUM_MAX__
+#define UACCUM_MAX __UACCUM_MAX__
+#else
+#define UACCUM_MAX 0x1.FFFFCp+3UK
+#endif // UACCUM_MAX
+
+#ifdef __UACCUM_EPSILON__
+#define UACCUM_EPSILON __UACCUM_EPSILON__
+#else
+#define UACCUM_EPSILON 0x1p-15UK
+#endif // UACCUM_EPSILON
+
+#ifdef __LACCUM_FBIT__
+#define LACCUM_FBIT __LACCUM_FBIT__
+#else
+#define LACCUM_FBIT 23
+#endif // LACCUM_FBIT
+
+#ifdef __LACCUM_IBIT__
+#define LACCUM_IBIT __LACCUM_IBIT__
+#else
+#define LACCUM_IBIT 4
+#endif // LACCUM_IBIT
+
+#ifdef __LACCUM_MIN__
+#define LACCUM_MIN __LACCUM_MIN__
+#else
+#define LACCUM_MIN (-8LK - 8LK)
+#endif // LACCUM_MIN
+
+#ifdef __LACCUM_MAX__
+#define LACCUM_MAX __LACCUM_MAX__
+#else
+#define LACCUM_MAX 0x1.FFFFFFCp+3LK
+#endif // LACCUM_MAX
+
+#ifdef __LACCUM_EPSILON__
+#define LACCUM_EPSILON __LACCUM_EPSILON__
+#else
+#define LACCUM_EPSILON 0x1p-23LK
+#endif // LACCUM_EPSILON
+
+#ifdef __ULACCUM_FBIT__
+#define ULACCUM_FBIT __ULACCUM_FBIT__
+#else
+#define ULACCUM_FBIT 23
+#endif // ULACCUM_FBIT
+
+#ifdef __ULACCUM_IBIT__
+#define ULACCUM_IBIT __ULACCUM_IBIT__
+#else
+#define ULACCUM_IBIT 4
+#endif // ULACCUM_IBIT
+
+#ifdef __ULACCUM_MIN__
+#define ULACCUM_MIN __ULACCUM_MIN__
+#else
+#define ULACCUM_MIN 0ULK
+#endif // ULACCUM_MIN
+
+#ifdef __ULACCUM_MAX__
+#define ULACCUM_MAX __ULACCUM_MAX__
+#else
+#define ULACCUM_MAX 0x1.FFFFFFCp+3ULK
+#endif // ULACCUM_MAX
+
+#ifdef __ULACCUM_EPSILON__
+#define ULACCUM_EPSILON __ULACCUM_EPSILON__
+#else
+#define ULACCUM_EPSILON 0x1p-23ULK
+#endif // ULACCUM_EPSILON
+
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // __LLVM_LIBC_MACROS_STDFIX_MACROS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index e4f23b2a78130..0ff8e9cf95fb4 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -105,3 +105,10 @@ add_header(
   DEPENDS
     libc.include.llvm-libc-macros.float_macros
 )
+add_header(
+  stdfix_types
+  HDR
+    stdfix_types.h
+  DEPENDS
+    libc.include.llvm-libc-macros.stdfix_macros
+)
diff --git a/libc/include/llvm-libc-types/stdfix_types.h b/libc/include/llvm-libc-types/stdfix_types.h
new file mode 100644
index 0000000000000..34436d6af71c1
--- /dev/null
+++ b/libc/include/llvm-libc-types/stdfix_types.h
@@ -0,0 +1,19 @@
+//===-- Definition from stdfix.h ------------------------------------------===//
+//
+// 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_STDFIX_TYPES_H
+#define __LLVM_LIBC_MACROS_STDFIX_TYPES_H
+
+#include <include/llvm-libc-macros/stdfix-macros.h>
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+typedef _Fract fract;
+typedef _Accum accum;
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // __LLVM_LIBC_MACROS_STDFIX_TYPES_H
diff --git a/libc/include/stdfix.h.def b/libc/include/stdfix.h.def
new file mode 100644
index 0000000000000..1ffef915bfd01
--- /dev/null
+++ b/libc/include/stdfix.h.def
@@ -0,0 +1,21 @@
+//===-- C standard library header stdfix.h --------------------------------===//
+//
+// 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_STDFIX_H
+#define LLVM_LIBC_STDFIX_H
+
+#include <__llvm-libc-common.h>
+#include <llvm-libc-macros/stdfix-macros.h>
+#include <llvm-libc-types/stdfix-types.h>
+
+// From N1169 standard:
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf
+
+%%public_api()
+
+#endif // LLVM_LIBC_STDFIX_H
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 0b557c807a546..0beb90f9e7803 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -55,6 +55,22 @@ def UnsignedShortType : NamedType<"unsigned short">;
 // TODO: Add compatibility layer to use C23 type _Float128 if possible.
 def Float128Type : NamedType<"float128">;
 
+// Fixed point types
+// https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf
+def ShortFractType : NamedType<"short fract">;
+def FractType : NamedType<"fract">;
+def LongFractType : NamedType<"long fract">;
+def UnsignedShortFractType : NamedType<"unsigned short fract">;
+def UnsignedFractType : NamedType<"unsigned fract">;
+def UnsignedLongFractType : NamedType<"unsigned long fract">;
+
+def ShortAccumType : NamedType<"short accum">;
+def AccumType : NamedType<"accum">;
+def LongAccumType : NamedType<"long accum">;
+def UnsignedShortAccumType : NamedType<"unsigned short accum">;
+def UnsignedAccumType : NamedType<"unsigned accum">;
+def UnsignedLongAccumType : NamedType<"unsigned long accum">;
+
 // Common types
 def VoidPtr : PtrType<VoidType>;
 def VoidPtrPtr : PtrType<VoidPtr>;
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 97dabbc5cf07a..32b2c4b47b5e7 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -15,6 +15,8 @@ def StdC : StandardSpec<"stdc"> {
   PtrType TssTPtr = PtrType<TssTType>;
   NamedType TssDtorTType = NamedType<"tss_dtor_t">;
 
+
+
   HeaderSpec Assert = HeaderSpec<
       "assert.h",
       [
@@ -898,6 +900,22 @@ def StdC : StandardSpec<"stdc"> {
       ]
   >;
 
+  HeaderSpec StdFix = HeaderSpec<
+      "stdfix.h",
+      [],  // macros
+      [],  // types
+      [],  // enums
+      [    // functions
+        FunctionSpec<"abshr", RetValSpec<ShortFractType>, [ArgSpec<ShortFractType>]>,
+        FunctionSpec<"absr", RetValSpec<FractType>, [ArgSpec<FractType>]>,
+        FunctionSpec<"abslr", RetValSpec<LongFractType>, [ArgSpec<LongFractType>]>,
+
+        FunctionSpec<"abshk", RetValSpec<ShortAccumType>, [ArgSpec<ShortAccumType>]>,
+        FunctionSpec<"absk", RetValSpec<AccumType>, [ArgSpec<AccumType>]>,
+        FunctionSpec<"abslk", RetValSpec<LongAccumType>, [ArgSpec<LongAccumType>]>,
+      ]
+  >;
+
   HeaderSpec Limits = HeaderSpec<"limits.h">;
 
   NamedType SigAtomicT = NamedType<"sig_atomic_t">;
diff --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 5211db7bc1f99..09b16be1e2d42 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(fenv)
 add_subdirectory(inttypes)
 add_subdirectory(math)
 add_subdirectory(stdbit)
+add_subdirectory(stdfix)
 add_subdirectory(stdio)
 add_subdirectory(stdlib)
 add_subdirectory(string)
diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index bd814a080c4f8..ed32f0a032c9f 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -271,3 +271,5 @@ add_subdirectory(threads)
 add_subdirectory(File)
 
 add_subdirectory(HashTable)
+
+add_subdirectory(fixedpoint)
diff --git a/libc/src/__support/fixedpoint/CMakeLists.txt b/libc/src/__support/fixedpoint/CMakeLists.txt
new file mode 100644
index 0000000000000..0c37a53ec7638
--- /dev/null
+++ b/libc/src/__support/fixedpoint/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_header_library(
+  fx_rep
+  HDRS
+    fxrep.h
+  DEPENDS
+    libc.include.llvm-libc-macros.stdfix_macros
+    libc.include.llvm-libc-types.stdfix_types
+    libc.__support.macros.attributes
+)
+
+add_header_library(
+  fx_bits
+  HDRS
+    fxbit.h
+  DEPENDS
+    .fx_rep
+    libc.include.llvm-libc-macros.stdfix_macros
+    libc.include.llvm-libc-types.stdfix_types
+    libc.__support.macros.attributes
+    libc.__support.macros.optimization
+)
diff --git a/libc/src/__support/fixedpoint/fxbits.h b/libc/src/__support/fixedpoint/fxbits.h
new file mode 100644
index 0000000000000..093ab5a724e56
--- /dev/null
+++ b/libc/src/__support/fixedpoint/fxbits.h
@@ -0,0 +1,37 @@
+//===-- Utility class to manipulate fixed point numbers. --*- 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_FIXEDPOINT_FXREP_H
+#define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix_types.h"
+#include "src/__support/macros/attributes.h"   // LIBC_INLINE
+#include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
+
+#include "fxrep.h"
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+
+namespace LIBC_NAMESPACE::fixed_point {
+
+template <typename T> LIBC_INLINE constexpr T abs(T x) {
+  if constexpr (FXRep<T>::SIGN_LEN == 0)
+    return x;
+  else {
+    if (LIBC_UNLIKELY(x == FXRep<T>::MIN()))
+      return FXRep<T>::MAX();
+    return (x < FXRep<T>::ZERO() ? -x : x);
+  }
+}
+
+} // namespace LIBC_NAMESPACE::fixed_point
+
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
diff --git a/libc/src/__support/fixedpoint/fxrep.h b/libc/src/__support/fixedpoint/fxrep.h
new file mode 100644
index 0000000000000..1c53b6587e381
--- /dev/null
+++ b/libc/src/__support/fixedpoint/fxrep.h
@@ -0,0 +1,158 @@
+//===-- Utility class to manipulate fixed point numbers. --*- 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_FIXEDPOINT_FXREP_H
+#define LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
+
+#include "include/llvm-libc-macros/stdfix-macros.h"
+#include "include/llvm-libc-types/stdfix_types.h"
+#include "src/__support/macros/attributes.h" // LIBC_INLINE, LIBC_INLINE_VAR
+
+#ifdef LIBC_COMPILER_HAS_FIXED_POINT
+
+namespace LIBC_NAMESPACE::fixedpoint {
+
+template <typename T> FXRep;
+
+template <> FXRep<short fract> {
+  using Type = short fract;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SFRACT_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return SFRACT_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return SFRACT_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0HR; }
+  LIBC_INLINE static constexpr Type EPS() { return SFRACT_EPSILON; }
+}
+
+template <> FXRep<unsigned short fract> {
+  using Type = unsigned short fract;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USFRACT_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return USFRACT_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return USFRACT_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0UHR; }
+  LIBC_INLINE static constexpr Type EPS() { return USFRACT_EPSILON; }
+}
+
+template <> FXRep<fract> {
+  using Type = fract;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = FRACT_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return FRACT_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return FRACT_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0R; }
+  LIBC_INLINE static constexpr Type EPS() { return FRACT_EPSILON; }
+}
+
+template <> FXRep<unsigned fract> {
+  using Type = unsigned fract;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UFRACT_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return UFRACT_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return UFRACT_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0UR; }
+  LIBC_INLINE static constexpr Type EPS() { return UFRACT_EPSILON; }
+}
+
+template <> FXRep<long fract> {
+  using Type = long fract;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LFRACT_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return LFRACT_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return LFRACT_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0LR; }
+  LIBC_INLINE static constexpr Type EPS() { return LFRACT_EPSILON; }
+}
+
+template <> FXRep<unsigned long fract> {
+  using Type = unsigned long fract;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULFRACT_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return ULFRACT_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return ULFRACT_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0ULR; }
+  LIBC_INLINE static constexpr Type EPS() { return ULFRACT_EPSILON; }
+}
+
+template <> FXRep<short accum> {
+  using Type = short accum;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = SACCUM_IBIT;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = SACCUM_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return SACCUM_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return SACCUM_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0HK; }
+  LIBC_INLINE static constexpr Type EPS() { return SACCUM_EPSILON; }
+}
+
+template <> FXRep<unsigned short accum> {
+  using Type = unsigned short accum;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = USACCUM_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return USACCUM_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return USACCUM_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0UHK; }
+  LIBC_INLINE static constexpr Type EPS() { return USACCUM_EPSILON; }
+}
+
+template <> FXRep<accum> {
+  using Type = accum;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ACCUM_IBIT;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ACCUM_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return ACCUM_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return ACCUM_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0K; }
+  LIBC_INLINE static constexpr Type EPS() { return ACCUM_EPSILON; }
+}
+
+template <> FXRep<unsigned accum> {
+  using Type = unsigned accum;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = UACCUM_IBIT;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = UACCUM_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return UACCUM_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return UACCUM_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0UK; }
+  LIBC_INLINE static constexpr Type EPS() { return UACCUM_EPSILON; }
+}
+
+template <> FXRep<long accum> {
+  using Type = long accum;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 1;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = LACCUM_IBIT;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = LACCUM_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return LACCUM_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return LACCUM_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0LK; }
+  LIBC_INLINE static constexpr Type EPS() { return LACCUM_EPSILON; }
+}
+
+template <> FXRep<unsigned long accum> {
+  using Type = unsigned long accum;
+  LIBC_INLINE_VAR static constexpr int SIGN_LEN = 0;
+  LIBC_INLINE_VAR static constexpr int INTEGRAL_LEN = ULACCUM_IBIT;
+  LIBC_INLINE_VAR static constexpr int FRACTION_LEN = ULACCUM_FBIT;
+  LIBC_INLINE static constexpr Type MIN() { return ULACCUM_MIN; }
+  LIBC_INLINE static constexpr Type MAX() { return ULACCUM_MIN; }
+  LIBC_INLINE static constexpr Type ZERO() { return 0ULK; }
+  LIBC_INLINE static constexpr Type EPS() { return ULACCUM_EPSILON; }
+}
+
+} // namespace LIBC_NAMESPACE::fixedpoint
+
+#endif // LIBC_COMPILER_HAS_FIXED_POINT
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FIXEDPOINT_FXREP_H
diff --git a/libc/src/stdfix/CMakeLists.txt b/libc/src/stdfix/CMakeLists.txt
new file mode 100644
index 0000000000000..423a0f428763e
--- /dev/null
+++ b/libc/src/stdfix/CMakeLists.txt
@@ -0,0 +1,17 @@
+if(NOT LIBC_COMPILER_HAS_FIXED_POINT)
+  return()
+endif()
+
+foreach(suffix IN hr r lr hk k lk)
+  add_entrypoint_object(
+    abs${suffix}
+    HDRS
+      abs${suffix}.h
+    SRCS
+      abs${suffix}.cpp
+    COMPILE_OPTIONS
+      -O3
+    DEPENDS
+      libc.src.__support.fixedpoint.fx_bits
+  )
+endforeach()
diff --git a/libc/src/stdfix/abshk.cpp b/libc/src/stdfix/abshk.cpp
new file mode 100644
index 0000000000000..7ffc1f3b51c9f
--- /dev/null
+++ b/libc/src/stdfix/abshk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of abshk 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 "abshk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedpoint/fxbits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(short accum, abshk, (short accum x)) {
+  return fixedpoint::abs(x);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/abshk.h b/libc/src/stdfix/abshk.h
new file mode 100644
index 0000000000000..1f2d8d3faa3ec
--- /dev/null
+++ b/libc/src/stdfix/abshk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for abshk -------------------------*- 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_ABSHK_H
+#define LLVM_LIBC_SRC_STDFIX_ABSHK_H
+
+#include "include/llvm-libc-types/stdfix_types.h"
+
+namespace LIBC_NAMESPACE {
+
+short accum abshk(short accum x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSHK_H
diff --git a/libc/src/stdfix/abshr.cpp b/libc/src/stdfix/abshr.cpp
new file mode 100644
index 0000000000000..fda5fcf3d7f4c
--- /dev/null
+++ b/libc/src/stdfix/abshr.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of abshr 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 "abshr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedpoint/fxbits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(short fract, abshr, (short fract x)) {
+  return fixedpoint::abs(x);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/abshr.h b/libc/src/stdfix/abshr.h
new file mode 100644
index 0000000000000..beb61f8113162
--- /dev/null
+++ b/libc/src/stdfix/abshr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for abshr -------------------------*- 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_ABSHR_H
+#define LLVM_LIBC_SRC_STDFIX_ABSHR_H
+
+#include "include/llvm-libc-types/stdfix_types.h"
+
+namespace LIBC_NAMESPACE {
+
+short fract abshr(short fract x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSHR_H
diff --git a/libc/src/stdfix/absk.cpp b/libc/src/stdfix/absk.cpp
new file mode 100644
index 0000000000000..d42103e318fe9
--- /dev/null
+++ b/libc/src/stdfix/absk.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of absk 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 "absk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedpoint/fxbits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(accum, absk, (accum x)) { return fixedpoint::abs(x); }
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/absk.h b/libc/src/stdfix/absk.h
new file mode 100644
index 0000000000000..0e446e65413a7
--- /dev/null
+++ b/libc/src/stdfix/absk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for absk --------------------------*- 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_ABSK_H
+#define LLVM_LIBC_SRC_STDFIX_ABSK_H
+
+#include "include/llvm-libc-types/stdfix_types.h"
+
+namespace LIBC_NAMESPACE {
+
+accum absk(accum x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSK_H
diff --git a/libc/src/stdfix/abslk.cpp b/libc/src/stdfix/abslk.cpp
new file mode 100644
index 0000000000000..66a0f4a5597f2
--- /dev/null
+++ b/libc/src/stdfix/abslk.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of abslk 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 "abslk.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedpoint/fxbits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long accum, abslk, (long accum x)) {
+  return fixedpoint::abs(x);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/abslk.h b/libc/src/stdfix/abslk.h
new file mode 100644
index 0000000000000..a4b264aaae5c6
--- /dev/null
+++ b/libc/src/stdfix/abslk.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for abslk -------------------------*- 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_ABSLK_H
+#define LLVM_LIBC_SRC_STDFIX_ABSLK_H
+
+#include "include/llvm-libc-types/stdfix_types.h"
+
+namespace LIBC_NAMESPACE {
+
+long accum abslk(long accum x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSLK_H
diff --git a/libc/src/stdfix/abslr.cpp b/libc/src/stdfix/abslr.cpp
new file mode 100644
index 0000000000000..95d63577a05b2
--- /dev/null
+++ b/libc/src/stdfix/abslr.cpp
@@ -0,0 +1,19 @@
+//===-- Implementation of abslr 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 "abslr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedpoint/fxbits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(long fract, abslr, (long fract x)) {
+  return fixedpoint::abs(x);
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/abslr.h b/libc/src/stdfix/abslr.h
new file mode 100644
index 0000000000000..3c80c50928ec2
--- /dev/null
+++ b/libc/src/stdfix/abslr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for abslr -------------------------*- 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_ABSLR_H
+#define LLVM_LIBC_SRC_STDFIX_ABSLR_H
+
+#include "include/llvm-libc-types/stdfix_types.h"
+
+namespace LIBC_NAMESPACE {
+
+long fract abslr(long fract x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSLR_H
diff --git a/libc/src/stdfix/absr.cpp b/libc/src/stdfix/absr.cpp
new file mode 100644
index 0000000000000..2bd18910abbad
--- /dev/null
+++ b/libc/src/stdfix/absr.cpp
@@ -0,0 +1,17 @@
+//===-- Implementation of absr 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 "absr.h"
+#include "src/__support/common.h"
+#include "src/__support/fixedpoint/fxbits.h"
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(fract, absr, (fract x)) { return fixedpoint::abs(x); }
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/stdfix/absr.h b/libc/src/stdfix/absr.h
new file mode 100644
index 0000000000000..dbe5308d421c1
--- /dev/null
+++ b/libc/src/stdfix/absr.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for absr --------------------------*- 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_ABSR_H
+#define LLVM_LIBC_SRC_STDFIX_ABSR_H
+
+#include "include/llvm-libc-types/stdfix_types.h"
+
+namespace LIBC_NAMESPACE {
+
+fract absr(fract x);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_STDFIX_ABSR_H
diff --git a/libc/test/src/stdfix/AbsTest.h b/libc/test/src/stdfix/AbsTest.h
new file mode 100644
index 0000000000000..11d4470494b36
--- /dev/null
+++ b/libc/test/src/stdfix/AbsTest.h
@@ -0,0 +1,37 @@
+//===-- Utility class to test fixed-point abs -------------------*- 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/fixedpoint/fxrep.h"
+
+template <typename T> class AbsTest : public LIBC_NAMESPACE::testing::Test {
+
+  using FXRep = LIBC_NAMESPACE::fixedpoint::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);
+
+public:
+  typedef T (*AbsFunc)(T);
+
+  void testSpecialNumbers(AbsFunc func) {
+    EXPECT_EQ(zero, func(zero));
+    EXPECT_EQ(max, func(min));
+    EXPECT_EQ(max, func(max));
+    EXPECT_EQ(half, func(half));
+    EXPECT_EQ(half, func(neg_half));
+  }
+};
+
+#define LIST_ABS_TESTS(T, func)                                                \
+  using LlvmLibcAbsTest = AbsTest<T>;                                          \
+  TEST_F(LlvmLibcAbsTest, SpecialNumbers) { testSpecialNumbers(&func); }       \
+  static_assert(true, "Require semicolon.")
diff --git a/libc/test/src/stdfix/CMakeLists.txt b/libc/test/src/stdfix/CMakeLists.txt
new file mode 100644
index 0000000000000..68321facff3ea
--- /dev/null
+++ b/libc/test/src/stdfix/CMakeLists.txt
@@ -0,0 +1,18 @@
+if(NOT LIBC_COMPILER_HAS_FIXED_POINT)
+  return()
+endif()
+
+foreach(suffix IN hr r lr hk k lk)
+  add_libc_test(
+    abs${suffix}_test
+    HDRS
+      AbsTest.h
+    SRCS
+      abs${suffix}_test.cpp
+    COMPILE_OPTIONS
+      -O3
+    DEPENDS
+      libc.src.stdfix.abs${suffix}
+      libc.src.__support.fixedpoint.fx_bits
+  )
+endforeach()
diff --git a/libc/test/src/stdfix/abshk_test.cpp b/libc/test/src/stdfix/abshk_test.cpp
new file mode 100644
index 0000000000000..c3f58625ac58c
--- /dev/null
+++ b/libc/test/src/stdfix/abshk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for abshk -----------------------------------------------===//
+//
+// 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 "AbsTest.h"
+
+#include "src/stdfix/abshk.h"
+
+LIST_ABS_TESTS(short accum, LIBC_NAMESPACE::abshk);
diff --git a/libc/test/src/stdfix/abshr_test.cpp b/libc/test/src/stdfix/abshr_test.cpp
new file mode 100644
index 0000000000000..d7a962ea1f98d
--- /dev/null
+++ b/libc/test/src/stdfix/abshr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for abshr -----------------------------------------------===//
+//
+// 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 "AbsTest.h"
+
+#include "src/stdfix/abshr.h"
+
+LIST_ABS_TESTS(short fract, LIBC_NAMESPACE::abshr);
diff --git a/libc/test/src/stdfix/absk_test.cpp b/libc/test/src/stdfix/absk_test.cpp
new file mode 100644
index 0000000000000..729cf143a4130
--- /dev/null
+++ b/libc/test/src/stdfix/absk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for absk ------------------------------------------------===//
+//
+// 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 "AbsTest.h"
+
+#include "src/stdfix/absk.h"
+
+LIST_ABS_TESTS(accum, LIBC_NAMESPACE::absk);
diff --git a/libc/test/src/stdfix/abslk_test.cpp b/libc/test/src/stdfix/abslk_test.cpp
new file mode 100644
index 0000000000000..93ef3469a225a
--- /dev/null
+++ b/libc/test/src/stdfix/abslk_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for abslk -----------------------------------------------===//
+//
+// 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 "AbsTest.h"
+
+#include "src/stdfix/abslk.h"
+
+LIST_ABS_TESTS(long accum, LIBC_NAMESPACE::abslk);
diff --git a/libc/test/src/stdfix/abslr_test.cpp b/libc/test/src/stdfix/abslr_test.cpp
new file mode 100644
index 0000000000000..c50a558738028
--- /dev/null
+++ b/libc/test/src/stdfix/abslr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for abslr -----------------------------------------------===//
+//
+// 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 "AbsTest.h"
+
+#include "src/stdfix/abslr.h"
+
+LIST_ABS_TESTS(long fract, LIBC_NAMESPACE::abslr);
diff --git a/libc/test/src/stdfix/absr_test.cpp b/libc/test/src/stdfix/absr_test.cpp
new file mode 100644
index 0000000000000..7b81173539793
--- /dev/null
+++ b/libc/test/src/stdfix/absr_test.cpp
@@ -0,0 +1,13 @@
+//===-- Unittests for absr ------------------------------------------------===//
+//
+// 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 "AbsTest.h"
+
+#include "src/stdfix/absr.h"
+
+LIST_ABS_TESTS(fract, LIBC_NAMESPACE::absr);



More information about the libc-commits mailing list