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 | |
23 | /* Not all environments define CMPLXF, CMPLX, CMPLXL. */ |
24 | |
25 | #ifndef CMPLXF |
26 | #if defined(__clang_major__) && (__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 defined(__clang_major__) && (__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 defined(__clang_major__) && (__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, ARGS, ARG_NAMES) \ |
79 | struct cpptype RTNAME(CPP_NAME(name))(struct cpptype *, ARGS); \ |
80 | cComplex RTNAME(name)(ARGS) { \ |
81 | struct cpptype result; \ |
82 | RTNAME(CPP_NAME(name))(&result, 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 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
91 | ADAPT_REDUCTION(SumComplex8, double_Complex_t, CppComplexDouble, CMPLX, |
92 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
93 | #if LDBL_MANT_DIG == 64 |
94 | ADAPT_REDUCTION(SumComplex10, long_double_Complex_t, CppComplexLongDouble, |
95 | CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
96 | #elif LDBL_MANT_DIG == 113 |
97 | ADAPT_REDUCTION(SumComplex16, long_double_Complex_t, CppComplexLongDouble, |
98 | CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
99 | #endif |
100 | |
101 | /* PRODUCT() */ |
102 | ADAPT_REDUCTION(ProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, |
103 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
104 | ADAPT_REDUCTION(ProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, |
105 | REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
106 | #if LDBL_MANT_DIG == 64 |
107 | ADAPT_REDUCTION(ProductComplex10, long_double_Complex_t, CppComplexLongDouble, |
108 | CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
109 | #elif LDBL_MANT_DIG == 113 |
110 | ADAPT_REDUCTION(ProductComplex16, long_double_Complex_t, CppComplexLongDouble, |
111 | CMPLXL, REDUCTION_ARGS, REDUCTION_ARG_NAMES) |
112 | #endif |
113 | |
114 | /* DOT_PRODUCT() */ |
115 | ADAPT_REDUCTION(DotProductComplex4, float_Complex_t, CppComplexFloat, CMPLXF, |
116 | DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) |
117 | ADAPT_REDUCTION(DotProductComplex8, double_Complex_t, CppComplexDouble, CMPLX, |
118 | DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) |
119 | #if LDBL_MANT_DIG == 64 |
120 | ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t, |
121 | CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) |
122 | #elif LDBL_MANT_DIG == 113 |
123 | ADAPT_REDUCTION(DotProductComplex16, long_double_Complex_t, |
124 | CppComplexLongDouble, CMPLXL, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES) |
125 | #endif |
126 | |