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 | |
13 | struct CppComplexFloat { |
14 | float r, i; |
15 | }; |
16 | struct CppComplexDouble { |
17 | double r, i; |
18 | }; |
19 | struct CppComplexLongDouble { |
20 | long double r, i; |
21 | }; |
22 | #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 |
23 | struct 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 |
34 | static 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 |
50 | static 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 |
66 | static 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 |
89 | static 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() */ |
118 | ADAPT_REDUCTION(SumComplex4, float_Complex_t, CppComplexFloat, CMPLXF, |
119 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
120 | ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX, |
121 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
122 | #if LDBL_MANT_DIG == 64 |
123 | ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble, |
124 | CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
125 | #endif |
126 | #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 |
127 | ADAPT_REDUCTION(SumComplex16, CFloat128ComplexType, CppComplexFloat128, |
128 | CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
129 | #endif |
130 | |
131 | /* PRODUCT() */ |
132 | ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, |
133 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
134 | ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, |
135 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
136 | #if LDBL_MANT_DIG == 64 |
137 | ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble, |
138 | CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
139 | #endif |
140 | #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 |
141 | ADAPT_REDUCTION(ProductComplex16, CFloat128ComplexType, CppComplexFloat128, |
142 | CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
143 | #endif |
144 | |
145 | /* DOT_PRODUCT() */ |
146 | ADAPT_REDUCTION(DotProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, |
147 | DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) |
148 | ADAPT_REDUCTION(DotProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, |
149 | DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) |
150 | #if LDBL_MANT_DIG == 64 |
151 | ADAPT_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 |
155 | ADAPT_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) |
161 | ADAPT_REDUCTION(ReduceComplex4, float_Complex_t, CppComplexFloat, CMPLXF, RARGS, |
162 | REDUCE_ARG_NAMES) |
163 | #undef RARGS |
164 | #define RARGS REDUCE_ARGS(double_Complex_t) |
165 | ADAPT_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) |
170 | ADAPT_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) |
176 | ADAPT_REDUCTION(ReduceComplex16, CFloat128ComplexType, CppComplexFloat128, |
177 | CMPLXF128, RARGS, REDUCE_ARG_NAMES) |
178 | #undef RARGS |
179 | #endif |
180 | |