1/*===-- flang/runtime/complex-reduction.c ---------------------------*- C -*-===
2 *
3 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 * See https://llvm.org/LICENSE.txt for license information.
5 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 *
7 * ===-----------------------------------------------------------------------===
8 */
9
10#include "complex-reduction.h"
11#include <float.h>
12
13struct CppComplexFloat {
14 float r, i;
15};
16struct CppComplexDouble {
17 double r, i;
18};
19struct CppComplexLongDouble {
20 long double r, i;
21};
22#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
23struct CppComplexFloat128 {
24 CFloat128Type r, i;
25};
26#endif
27
28/* Not all environments define CMPLXF, CMPLX, CMPLXL. */
29
30#ifndef CMPLXF
31#if defined(__clang_major__) && (__clang_major__ >= 12)
32#define CMPLXF __builtin_complex
33#else
34static float_Complex_t CMPLXF(float r, float i) {
35 union {
36 struct CppComplexFloat x;
37 float_Complex_t result;
38 } u;
39 u.x.r = r;
40 u.x.i = i;
41 return u.result;
42}
43#endif
44#endif
45
46#ifndef CMPLX
47#if defined(__clang_major__) && (__clang_major__ >= 12)
48#define CMPLX __builtin_complex
49#else
50static double_Complex_t CMPLX(double r, double i) {
51 union {
52 struct CppComplexDouble x;
53 double_Complex_t result;
54 } u;
55 u.x.r = r;
56 u.x.i = i;
57 return u.result;
58}
59#endif
60#endif
61
62#ifndef CMPLXL
63#if defined(__clang_major__) && (__clang_major__ >= 12)
64#define CMPLXL __builtin_complex
65#else
66static long_double_Complex_t CMPLXL(long double r, long double i) {
67 union {
68 struct CppComplexLongDouble x;
69 long_double_Complex_t result;
70 } u;
71 u.x.r = r;
72 u.x.i = i;
73 return u.result;
74}
75#endif
76#endif
77
78#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
79#ifndef CMPLXF128
80/*
81 * GCC 7.4.0 (currently minimum GCC version for llvm builds)
82 * supports __builtin_complex. For Clang, require >=12.0.
83 * Otherwise, rely on the memory layout compatibility.
84 */
85#if (defined(__clang_major__) && (__clang_major__ >= 12)) || \
86 (defined(__GNUC__) && !defined(__clang__))
87#define CMPLXF128 __builtin_complex
88#else
89static CFloat128ComplexType CMPLXF128(CFloat128Type r, CFloat128Type i) {
90 union {
91 struct CppComplexFloat128 x;
92 CFloat128ComplexType result;
93 } u;
94 u.x.r = r;
95 u.x.i = i;
96 return u.result;
97}
98#endif
99#endif
100#endif
101
102/* RTNAME(SumComplex4) calls RTNAME(CppSumComplex4) with the same arguments
103 * and converts the members of its C++ complex result to C _Complex.
104 */
105
106#define CPP_NAME(name) Cpp##name
107#define ADAPT_REDUCTION(name, cComplex, cpptype, cmplxMacro, ARGS, ARG_NAMES) \
108 struct cpptype RTNAME(CPP_NAME(name))(struct cpptype *, ARGS); \
109 cComplex RTNAME(name)(ARGS) { \
110 struct cpptype result; \
111 RTNAME(CPP_NAME(name))(&result, ARG_NAMES); \
112 return cmplxMacro(result.r, result.i); \
113 }
114
115/* TODO: COMPLEX(2 & 3) */
116
117/* SUM() */
118ADAPT_REDUCTION(SumComplex4, float_Complex_t, CppComplexFloat, CMPLXF,
119 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
120ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX,
121 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
122#if LDBL_MANT_DIG == 64
123ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble,
124 CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
125#endif
126#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
127ADAPT_REDUCTION(SumComplex16, CFloat128ComplexType, CppComplexFloat128,
128 CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
129#endif
130
131/* PRODUCT() */
132ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF,
133 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
134ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX,
135 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
136#if LDBL_MANT_DIG == 64
137ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble,
138 CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
139#endif
140#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
141ADAPT_REDUCTION(ProductComplex16, CFloat128ComplexType, CppComplexFloat128,
142 CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
143#endif
144
145/* DOT_PRODUCT() */
146ADAPT_REDUCTION(DotProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF,
147 DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
148ADAPT_REDUCTION(DotProductComplex8, double_Complex_t, CppComplexDouble, CMPLX,
149 DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
150#if LDBL_MANT_DIG == 64
151ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t,
152 CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
153#endif
154#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
155ADAPT_REDUCTION(DotProductComplex16, CFloat128ComplexType, CppComplexFloat128,
156 CMPLXF128, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
157#endif
158
159/* REDUCE() */
160#define RARGS REDUCE_ARGS(float_Complex_t)
161ADAPT_REDUCTION(ReduceComplex4, float_Complex_t, CppComplexFloat, CMPLXF, RARGS,
162 REDUCE_ARG_NAMES)
163#undef RARGS
164#define RARGS REDUCE_ARGS(double_Complex_t)
165ADAPT_REDUCTION(ReduceComplex8, double_Complex_t, CppComplexDouble, CMPLX,
166 RARGS, REDUCE_ARG_NAMES)
167#undef RARGS
168#if LDBL_MANT_DIG == 64
169#define RARGS REDUCE_ARGS(long_double_Complex_t)
170ADAPT_REDUCTION(ReduceComplex10, long_double_Complex_t, CppComplexLongDouble,
171 CMPLXL, RARGS, REDUCE_ARG_NAMES)
172#undef RARGS
173#endif
174#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
175#define RARGS REDUCE_ARGS(CFloat128ComplexType)
176ADAPT_REDUCTION(ReduceComplex16, CFloat128ComplexType, CppComplexFloat128,
177 CMPLXF128, RARGS, REDUCE_ARG_NAMES)
178#undef RARGS
179#endif
180

source code of flang/runtime/complex-reduction.c