xref: /llvm-project/flang/runtime/complex-reduction.c (revision fc51c7f0cc1abf1679100d71d103fe5d943f580b)
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 HAS_LDBL128 || 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 HAS_LDBL128 || 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 HAS_FLOAT80
123 ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble,
124     CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
125 #endif
126 #if HAS_LDBL128 || 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 HAS_FLOAT80
137 ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble,
138     CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
139 #endif
140 #if HAS_LDBL128 || 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 HAS_FLOAT80
151 ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t,
152     CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
153 #endif
154 #if HAS_LDBL128 || 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, float_Complex_t_ref_op)
161 ADAPT_REDUCTION(ReduceComplex4Ref, float_Complex_t, CppComplexFloat, CMPLXF,
162     RARGS, REDUCE_ARG_NAMES)
163 #undef RARGS
164 #define RARGS REDUCE_ARGS(float_Complex_t, float_Complex_t_value_op)
165 ADAPT_REDUCTION(ReduceComplex4Value, float_Complex_t, CppComplexFloat, CMPLXF,
166     RARGS, REDUCE_ARG_NAMES)
167 #undef RARGS
168 #define RARGS REDUCE_ARGS(double_Complex_t, double_Complex_t_ref_op)
169 ADAPT_REDUCTION(ReduceComplex8Ref, double_Complex_t, CppComplexDouble, CMPLX,
170     RARGS, REDUCE_ARG_NAMES)
171 #undef RARGS
172 #define RARGS REDUCE_ARGS(double_Complex_t, double_Complex_t_value_op)
173 ADAPT_REDUCTION(ReduceComplex8Value, double_Complex_t, CppComplexDouble, CMPLX,
174     RARGS, REDUCE_ARG_NAMES)
175 #undef RARGS
176 #if HAS_FLOAT80
177 #define RARGS REDUCE_ARGS(long_double_Complex_t, long_double_Complex_t_ref_op)
178 ADAPT_REDUCTION(ReduceComplex10Ref, long_double_Complex_t, CppComplexLongDouble,
179     CMPLXL, RARGS, REDUCE_ARG_NAMES)
180 #undef RARGS
181 #define RARGS REDUCE_ARGS(long_double_Complex_t, long_double_Complex_t_value_op)
182 ADAPT_REDUCTION(ReduceComplex10Value, long_double_Complex_t,
183     CppComplexLongDouble, CMPLXL, RARGS, REDUCE_ARG_NAMES)
184 #undef RARGS
185 #endif
186 #if HAS_LDBL128 || HAS_FLOAT128
187 #define RARGS REDUCE_ARGS(CFloat128ComplexType, CFloat128ComplexType_ref_op)
188 ADAPT_REDUCTION(ReduceComplex16Ref, CFloat128ComplexType, CppComplexFloat128,
189     CMPLXF128, RARGS, REDUCE_ARG_NAMES)
190 #undef RARGS
191 #define RARGS REDUCE_ARGS(CFloat128ComplexType, CFloat128ComplexType_value_op)
192 ADAPT_REDUCTION(ReduceComplex16Value, CFloat128ComplexType, CppComplexFloat128,
193     CMPLXF128, RARGS, REDUCE_ARG_NAMES)
194 #undef RARGS
195 #endif
196