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 "flang/Common/long-double.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 
23 /* Not all environments define CMPLXF, CMPLX, CMPLXL. */
24 
25 #ifndef CMPLXF
26 #if __clang_major__ >= 12
27 #define CMPLXF __builtin_complex
28 #else
29 static float_Complex_t CMPLXF(float r, float i) {
30   union {
31     struct CppComplexFloat x;
32     float_Complex_t result;
33   } u;
34   u.x.r = r;
35   u.x.i = i;
36   return u.result;
37 }
38 #endif
39 #endif
40 
41 #ifndef CMPLX
42 #if __clang_major__ >= 12
43 #define CMPLX __builtin_complex
44 #else
45 static double_Complex_t CMPLX(double r, double i) {
46   union {
47     struct CppComplexDouble x;
48     double_Complex_t result;
49   } u;
50   u.x.r = r;
51   u.x.i = i;
52   return u.result;
53 }
54 #endif
55 #endif
56 
57 #ifndef CMPLXL
58 #if __clang_major__ >= 12
59 #define CMPLXL __builtin_complex
60 #else
61 static long_double_Complex_t CMPLXL(long double r, long double i) {
62   union {
63     struct CppComplexLongDouble x;
64     long_double_Complex_t result;
65   } u;
66   u.x.r = r;
67   u.x.i = i;
68   return u.result;
69 }
70 #endif
71 #endif
72 
73 /* RTNAME(SumComplex4) calls RTNAME(CppSumComplex4) with the same arguments
74  * and converts the members of its C++ complex result to C _Complex.
75  */
76 
77 #define CPP_NAME(name) Cpp##name
78 #define ADAPT_REDUCTION(name, cComplex, cpptype, cmplxMacro) \
79   struct cpptype RTNAME(CPP_NAME(name))(struct cpptype *, REDUCTION_ARGS); \
80   cComplex RTNAME(name)(REDUCTION_ARGS) { \
81     struct cpptype result; \
82     RTNAME(CPP_NAME(name))(&result, REDUCTION_ARG_NAMES); \
83     return cmplxMacro(result.r, result.i); \
84   }
85 
86 /* TODO: COMPLEX(2 & 3) */
87 
88 /* SUM() */
89 ADAPT_REDUCTION(SumComplex4, float_Complex_t, CppComplexFloat, CMPLXF)
90 ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX)
91 #if LONG_DOUBLE == 80
92 ADAPT_REDUCTION(
93     SumComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL)
94 #elif LONG_DOUBLE == 128
95 ADAPT_REDUCTION(
96     SumComplex16, long_double_Complex_t, CppComplexLongDouble, CMPLXL)
97 #endif
98 
99 /* PRODUCT() */
100 ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF)
101 ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX)
102 #if LONG_DOUBLE == 80
103 ADAPT_REDUCTION(
104     ProductComplex10, long_double_Complex_t, CppComplexLongDouble, CMPLXL)
105 #elif LONG_DOUBLE == 128
106 ADAPT_REDUCTION(
107     ProductComplex16, long_double_Complex_t, CppComplexLongDouble, CMPLXL)
108 #endif
109