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