Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libc/docs/headers/complex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Macros
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+
| <Func> | <Func_f> (float) | <Func> (double) | <Func_l> (long double) | <Func_f16> (float16) | <Func_f128> (float128) | C23 Definition Section | C23 Error Handling Section |
+===========+==================+=================+========================+======================+========================+========================+============================+
| CMPLX | | | | | | 7.3.9.3 | N/A |
| CMPLX | |check| | |check| | |check| | |check| | |check| | 7.3.9.3 | N/A |
+-----------+------------------+-----------------+------------------------+----------------------+------------------------+------------------------+----------------------------+

Functions
Expand Down
15 changes: 15 additions & 0 deletions libc/include/llvm-libc-macros/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,25 @@ add_macro_header(
fcntl-macros.h
)

add_macro_header(
cfloat128_macros
HDR
cfloat128-macros.h
)

add_macro_header(
cfloat16_macros
HDR
cfloat16-macros.h
)

add_macro_header(
complex_macros
HDR
complex-macros.h
DEPENDS
.cfloat128_macros
.cfloat16_macros
)

add_macro_header(
Expand Down
41 changes: 41 additions & 0 deletions libc/include/llvm-libc-macros/cfloat128-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===-- Detection of _Complex _Float128 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_CFLOAT128_MACROS_H
#define LLVM_LIBC_MACROS_CFLOAT128_MACROS_H

#include "float-macros.h" // LDBL_MANT_DIG

// Currently, the complex variant of C23 `_Float128` type is only defined as a
// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For
// clang, the complex variant of `__float128` is defined instead, and only on
// x86-64 targets for clang 11 or later.
//
// TODO: Update the complex variant of C23 `_Float128` type detection again when
// clang supports it.
#ifdef __clang__
#if (__clang_major__ >= 11) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__
// macro to notify the availability of __float128 type:
// https://reviews.llvm.org/D15120
#define LIBC_TYPES_HAS_CFLOAT128
#endif
#elif defined(__GNUC__)
#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \
(__GNUC__ >= 13 || (!defined(__cplusplus)))
#define LIBC_TYPES_HAS_CFLOAT128
#endif
#endif

#if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113)
#define LIBC_TYPES_HAS_CFLOAT128
#define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
#endif

#endif // LLVM_LIBC_MACROS_CFLOAT128_MACROS_H
20 changes: 20 additions & 0 deletions libc/include/llvm-libc-macros/cfloat16-macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Detection of _Complex _Float16 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_CFLOAT16_MACROS_H
#define LLVM_LIBC_MACROS_CFLOAT16_MACROS_H

#if defined(__FLT16_MANT_DIG__) && \
(!defined(__GNUC__) || __GNUC__ >= 13 || \
(defined(__clang__) && __clang_major__ >= 14)) && \
!defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
!defined(_WIN32)
#define LIBC_TYPES_HAS_CFLOAT16
#endif

#endif // LLVM_LIBC_MACROS_CFLOAT16_MACROS_H
20 changes: 20 additions & 0 deletions libc/include/llvm-libc-macros/complex-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#ifndef __LLVM_LIBC_MACROS_COMPLEX_MACROS_H
#define __LLVM_LIBC_MACROS_COMPLEX_MACROS_H

#include "cfloat128-macros.h"
#include "cfloat16-macros.h"

#ifndef __STDC_NO_COMPLEX__

#define __STDC_VERSION_COMPLEX_H__ 202311L
Expand All @@ -19,6 +22,23 @@

// TODO: Add imaginary macros once GCC or Clang support _Imaginary builtin-type.

#define CMPLX(x, y) __builtin_complex((double)(x), (double)(y))
#define CMPLXF(x, y) __builtin_complex((float)(x), (float)(y))
#define CMPLXL(x, y) __builtin_complex((long double)(x), (long double)(y))

#ifdef LIBC_TYPES_HAS_CFLOAT16
#if !defined(__clang__) || (__clang_major__ >= 22 && __clang_minor__ > 0)
#define CMPLXF16(x, y) __builtin_complex((_Float16)(x), (_Float16)(y))
#else
#define CMPLXF16(x, y) \
((complex _Float16)(__builtin_complex((float)(x), (float)(y))))
#endif
#endif // LIBC_TYPES_HAS_CFLOAT16

#ifdef LIBC_TYPES_HAS_CFLOAT128
#define CMPLXF128(x, y) __builtin_complex((float128)(x), (float128)(y))
#endif // LIBC_TYPES_HAS_CFLOAT128

#endif // __STDC_NO_COMPLEX__

#endif // __LLVM_LIBC_MACROS_COMPLEX_MACROS_H
10 changes: 8 additions & 2 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,15 @@ add_header(
HDR
cfloat128.h
DEPENDS
libc.include.llvm-libc-macros.float_macros
libc.include.llvm-libc-macros.cfloat128_macros
)
add_header(
cfloat16
HDR
cfloat16.h
DEPENDS
libc.include.llvm-libc-macros.cfloat16_macros
)
add_header(cfloat16 HDR cfloat16.h)
add_header(fsblkcnt_t HDR fsblkcnt_t.h)
add_header(fsfilcnt_t HDR fsfilcnt_t.h)
add_header(
Expand Down
34 changes: 6 additions & 28 deletions libc/include/llvm-libc-types/cfloat128.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,14 @@
#ifndef LLVM_LIBC_TYPES_CFLOAT128_H
#define LLVM_LIBC_TYPES_CFLOAT128_H

#include "../llvm-libc-macros/float-macros.h" // LDBL_MANT_DIG
#include "../llvm-libc-macros/cfloat128-macros.h"

// Currently, the complex variant of C23 `_Float128` type is only defined as a
// built-in type in GCC 7 or later, for C and in GCC 13 or later, for C++. For
// clang, the complex variant of `__float128` is defined instead, and only on
// x86-64 targets for clang 11 or later.
//
// TODO: Update the complex variant of C23 `_Float128` type detection again when
// clang supports it.
#ifdef __clang__
#if (__clang_major__ >= 11) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
// Use _Complex __float128 type. clang uses __SIZEOF_FLOAT128__ or __FLOAT128__
// macro to notify the availability of __float128 type:
// https://reviews.llvm.org/D15120
#define LIBC_TYPES_HAS_CFLOAT128
#ifdef LIBC_TYPES_HAS_CFLOAT128
#ifndef LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
typedef _Complex __float128 cfloat128;
#endif
#elif defined(__GNUC__)
#if (defined(__STDC_IEC_60559_COMPLEX__) || defined(__SIZEOF_FLOAT128__)) && \
(__GNUC__ >= 13 || (!defined(__cplusplus)))
#define LIBC_TYPES_HAS_CFLOAT128
typedef _Complex _Float128 cfloat128;
#endif
#endif

#if !defined(LIBC_TYPES_HAS_CFLOAT128) && (LDBL_MANT_DIG == 113)
#define LIBC_TYPES_HAS_CFLOAT128
#define LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
#else
typedef _Complex long double cfloat128;
#endif
#endif // LIBC_TYPES_CFLOAT128_IS_COMPLEX_LONG_DOUBLE
#endif // LIBC_TYPES_HAS_CFLOAT128

#endif // LLVM_LIBC_TYPES_CFLOAT128_H
11 changes: 4 additions & 7 deletions libc/include/llvm-libc-types/cfloat16.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
#ifndef LLVM_LIBC_TYPES_CFLOAT16_H
#define LLVM_LIBC_TYPES_CFLOAT16_H

#if defined(__FLT16_MANT_DIG__) && \
(!defined(__GNUC__) || __GNUC__ >= 13 || \
(defined(__clang__) && __clang_major__ >= 14)) && \
!defined(__arm__) && !defined(_M_ARM) && !defined(__riscv) && \
!defined(_WIN32)
#define LIBC_TYPES_HAS_CFLOAT16
#include "../llvm-libc-macros/cfloat16-macros.h"

#ifdef LIBC_TYPES_HAS_CFLOAT16
typedef _Complex _Float16 cfloat16;
#endif
#endif // LIBC_TYPES_HAS_CFLOAT16

#endif // LLVM_LIBC_TYPES_CFLOAT16_H
19 changes: 19 additions & 0 deletions libc/test/include/complex_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,22 @@ TEST(LlvmLibcComplexTest, VersionMacro) {
TEST(LlvmLibcComplexTest, IMacro) { EXPECT_CFP_EQ(1.0fi, I); }

TEST(LlvmLibcComplexTest, _Complex_IMacro) { EXPECT_CFP_EQ(1.0fi, _Complex_I); }

TEST(LlvmLibcComplexTest, CMPLXMacro) {
EXPECT_CFP_EQ(CMPLX(0, 1.0), I);
EXPECT_CFP_EQ(CMPLX(1.0, 0), 1.0);
EXPECT_CFP_EQ(CMPLXF(0, 1.0f), I);
EXPECT_CFP_EQ(CMPLXF(1.0f, 0), 1.0f);
EXPECT_CFP_EQ(CMPLXL(0, 1.0l), I);
EXPECT_CFP_EQ(CMPLXL(1.0l, 0), 1.0l);

#ifdef LIBC_TYPES_HAS_CFLOAT16
EXPECT_CFP_EQ(CMPLXF16(0, 1.0), I);
EXPECT_CFP_EQ(CMPLXF16(1.0, 0), 1.0);
#endif // LIBC_TYPES_HAS_CFLOAT16

#ifdef LIBC_TYPES_HAS_CFLOAT128
EXPECT_CFP_EQ(CMPLXF128(0, 1.0), I);
EXPECT_CFP_EQ(CMPLXF128(1.0, 0), 1.0);
#endif // LIBC_TYPES_HAS_CFLOAT128
}
Loading