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
12struct CppComplexFloat {
13 float r, i;
14};
15struct CppComplexDouble {
16 double r, i;
17};
18struct CppComplexLongDouble {
19 long double r, i;
20};
21#if HAS_LDBL128 || HAS_FLOAT128
22struct 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
33static 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
49static 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
65static 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
88static 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() */
117ADAPT_REDUCTION(SumComplex4, float_Complex_t, CppComplexFloat, CMPLXF,
118 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
119ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX,
120 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
121#if HAS_FLOAT80
122ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble,
123 CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
124#endif
125#if HAS_LDBL128 || HAS_FLOAT128
126ADAPT_REDUCTION(SumComplex16, CFloat128ComplexType, CppComplexFloat128,
127 CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
128#endif
129
130/* PRODUCT() */
131ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF,
132 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
133ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX,
134 REDUCTION_ARGS, REDUCTION_ARG_NAMES)
135#if HAS_FLOAT80
136ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble,
137 CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
138#endif
139#if HAS_LDBL128 || HAS_FLOAT128
140ADAPT_REDUCTION(ProductComplex16, CFloat128ComplexType, CppComplexFloat128,
141 CMPLXF128, REDUCTION_ARGS, REDUCTION_ARG_NAMES)
142#endif
143
144/* DOT_PRODUCT() */
145ADAPT_REDUCTION(DotProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF,
146 DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
147ADAPT_REDUCTION(DotProductComplex8, double_Complex_t, CppComplexDouble, CMPLX,
148 DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
149#if HAS_FLOAT80
150ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t,
151 CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
152#endif
153#if HAS_LDBL128 || HAS_FLOAT128
154ADAPT_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)
160ADAPT_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)
164ADAPT_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)
168ADAPT_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)
172ADAPT_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)
177ADAPT_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)
181ADAPT_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)
187ADAPT_REDUCTION(ReduceComplex16Ref, CFloat128ComplexType, CppComplexFloat128,
188 CMPLXF128, RARGS, REDUCE_ARG_NAMES)
189#undef RARGS
190#define RARGS REDUCE_ARGS(CFloat128ComplexType, CFloat128ComplexType_value_op)
191ADAPT_REDUCTION(ReduceComplex16Value, CFloat128ComplexType, CppComplexFloat128,
192 CMPLXF128, RARGS, REDUCE_ARG_NAMES)
193#undef RARGS
194#endif
195

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