Skip to content

Commit 3ada883

Browse files
authored
[flang][runtime] Runtime support for REDUCE() (#86214)
Supports the REDUCE() transformational intrinsic function of Fortran (see F'2023 16.9.173) in a manner similar to the existing support for SUM(), PRODUCT(), &c. There are APIs for total reductions to scalar results, and APIs for partial reductions that reduce the rank of the argument by one. This implementation requires more functions than other reductions because the various possible types of the user-supplied OPERATION= function need to be elaborated. Once the basic API in reduce.h has been approved, later patches will implement lowering. REDUCE() is primarily for completeness, not portability; only one other Fortran compiler implements this F'2018 feature today, and only some types work correctly with it.
1 parent c8b85ad commit 3ada883

File tree

12 files changed

+972
-57
lines changed

12 files changed

+972
-57
lines changed

flang/include/flang/Runtime/reduce.h

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
//===-- include/flang/Runtime/reduce.h --------------------------*- 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+
// Defines the API for implementations of the transformational intrinsic
10+
// function REDUCE(); see F'2023 16.9.173.
11+
//
12+
// Similar to the definition of the APIs for SUM(), &c., in reduction.h,
13+
// there are typed functions here like ReduceInteger4() for total reductions
14+
// to scalars and void functions like ReduceInteger4Dim() for partial
15+
// reductions to smaller arrays.
16+
17+
#ifndef FORTRAN_RUNTIME_REDUCE_H_
18+
#define FORTRAN_RUNTIME_REDUCE_H_
19+
20+
#include "flang/Common/float128.h"
21+
#include "flang/Common/uint128.h"
22+
#include "flang/Runtime/cpp-type.h"
23+
#include "flang/Runtime/entry-names.h"
24+
#include <complex>
25+
#include <cstdint>
26+
27+
namespace Fortran::runtime {
28+
29+
class Descriptor;
30+
31+
template <typename T> using ReductionOperation = T (*)(const T *, const T *);
32+
template <typename CHAR>
33+
using ReductionCharOperation = void (*)(CHAR *hiddenResult,
34+
std::size_t resultLen, const CHAR *x, const CHAR *y, std::size_t xLen,
35+
std::size_t yLen);
36+
using ReductionDerivedTypeOperation = void (*)(
37+
void *hiddenResult, const void *x, const void *y);
38+
39+
extern "C" {
40+
41+
std::int8_t RTDECL(ReduceInteger1)(const Descriptor &,
42+
ReductionOperation<std::int8_t>, const char *source, int line, int dim = 0,
43+
const Descriptor *mask = nullptr, const std::int8_t *identity = nullptr,
44+
bool ordered = true);
45+
void RTDECL(ReduceInteger1Dim)(Descriptor &result, const Descriptor &array,
46+
ReductionOperation<std::int8_t>, const char *source, int line, int dim,
47+
const Descriptor *mask = nullptr, const std::int8_t *identity = nullptr,
48+
bool ordered = true);
49+
std::int16_t RTDECL(ReduceInteger2)(const Descriptor &,
50+
ReductionOperation<std::int16_t>, const char *source, int line, int dim = 0,
51+
const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr,
52+
bool ordered = true);
53+
void RTDECL(ReduceInteger2Dim)(Descriptor &result, const Descriptor &array,
54+
ReductionOperation<std::int16_t>, const char *source, int line, int dim,
55+
const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr,
56+
bool ordered = true);
57+
std::int32_t RTDECL(ReduceInteger4)(const Descriptor &,
58+
ReductionOperation<std::int32_t>, const char *source, int line, int dim = 0,
59+
const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr,
60+
bool ordered = true);
61+
void RTDECL(ReduceInteger4Dim)(Descriptor &result, const Descriptor &array,
62+
ReductionOperation<std::int32_t>, const char *source, int line, int dim,
63+
const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr,
64+
bool ordered = true);
65+
std::int64_t RTDECL(ReduceInteger8)(const Descriptor &,
66+
ReductionOperation<std::int64_t>, const char *source, int line, int dim = 0,
67+
const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr,
68+
bool ordered = true);
69+
void RTDECL(ReduceInteger8Dim)(Descriptor &result, const Descriptor &array,
70+
ReductionOperation<std::int64_t>, const char *source, int line, int dim,
71+
const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr,
72+
bool ordered = true);
73+
#ifdef __SIZEOF_INT128__
74+
common::int128_t RTDECL(ReduceInteger16)(const Descriptor &,
75+
ReductionOperation<common::int128_t>, const char *source, int line,
76+
int dim = 0, const Descriptor *mask = nullptr,
77+
const common::int128_t *identity = nullptr, bool ordered = true);
78+
void RTDECL(ReduceInteger16Dim)(Descriptor &result, const Descriptor &array,
79+
ReductionOperation<common::int128_t>, const char *source, int line, int dim,
80+
const Descriptor *mask = nullptr,
81+
const common::int128_t *identity = nullptr, bool ordered = true);
82+
#endif
83+
84+
// REAL/COMPLEX(2 & 3) return 32-bit float results for the caller to downconvert
85+
float RTDECL(ReduceReal2)(const Descriptor &, ReductionOperation<float>,
86+
const char *source, int line, int dim = 0, const Descriptor *mask = nullptr,
87+
const float *identity = nullptr, bool ordered = true);
88+
void RTDECL(ReduceReal2Dim)(Descriptor &result, const Descriptor &array,
89+
ReductionOperation<float>, const char *source, int line, int dim,
90+
const Descriptor *mask = nullptr, const float *identity = nullptr,
91+
bool ordered = true);
92+
float RTDECL(ReduceReal3)(const Descriptor &, ReductionOperation<float>,
93+
const char *source, int line, int dim = 0, const Descriptor *mask = nullptr,
94+
const float *identity = nullptr, bool ordered = true);
95+
void RTDECL(ReduceReal3Dim)(Descriptor &result, const Descriptor &array,
96+
ReductionOperation<float>, const char *source, int line, int dim,
97+
const Descriptor *mask = nullptr, const float *identity = nullptr,
98+
bool ordered = true);
99+
float RTDECL(ReduceReal4)(const Descriptor &, ReductionOperation<float>,
100+
const char *source, int line, int dim = 0, const Descriptor *mask = nullptr,
101+
const float *identity = nullptr, bool ordered = true);
102+
void RTDECL(ReduceReal4Dim)(Descriptor &result, const Descriptor &array,
103+
ReductionOperation<float>, const char *source, int line, int dim,
104+
const Descriptor *mask = nullptr, const float *identity = nullptr,
105+
bool ordered = true);
106+
double RTDECL(ReduceReal8)(const Descriptor &, ReductionOperation<double>,
107+
const char *source, int line, int dim = 0, const Descriptor *mask = nullptr,
108+
const double *identity = nullptr, bool ordered = true);
109+
void RTDECL(ReduceReal8Dim)(Descriptor &result, const Descriptor &array,
110+
ReductionOperation<double>, const char *source, int line, int dim,
111+
const Descriptor *mask = nullptr, const double *identity = nullptr,
112+
bool ordered = true);
113+
#if LDBL_MANT_DIG == 64
114+
long double RTDECL(ReduceReal10)(const Descriptor &,
115+
ReductionOperation<long double>, const char *source, int line, int dim = 0,
116+
const Descriptor *mask = nullptr, const long double *identity = nullptr,
117+
bool ordered = true);
118+
void RTDECL(ReduceReal10Dim)(Descriptor &result, const Descriptor &array,
119+
ReductionOperation<long double>, const char *source, int line, int dim,
120+
const Descriptor *mask = nullptr, const long double *identity = nullptr,
121+
bool ordered = true);
122+
#endif
123+
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
124+
CppFloat128Type RTDECL(ReduceReal16)(const Descriptor &,
125+
ReductionOperation<CppFloat128Type>, const char *source, int line,
126+
int dim = 0, const Descriptor *mask = nullptr,
127+
const CppFloat128Type *identity = nullptr, bool ordered = true);
128+
void RTDECL(ReduceReal16Dim)(Descriptor &result, const Descriptor &array,
129+
ReductionOperation<CppFloat128Type>, const char *source, int line, int dim,
130+
const Descriptor *mask = nullptr, const CppFloat128Type *identity = nullptr,
131+
bool ordered = true);
132+
#endif
133+
134+
void RTDECL(CppReduceComplex2)(std::complex<float> &, const Descriptor &,
135+
ReductionOperation<std::complex<float>>, const char *source, int line,
136+
int dim = 0, const Descriptor *mask = nullptr,
137+
const std::complex<float> *identity = nullptr, bool ordered = true);
138+
void RTDECL(CppReduceComplex2Dim)(Descriptor &result, const Descriptor &array,
139+
ReductionOperation<std::complex<float>>, const char *source, int line,
140+
int dim, const Descriptor *mask = nullptr,
141+
const std::complex<float> *identity = nullptr, bool ordered = true);
142+
void RTDECL(CppReduceComplex3)(std::complex<float> &, const Descriptor &,
143+
ReductionOperation<std::complex<float>>, const char *source, int line,
144+
int dim = 0, const Descriptor *mask = nullptr,
145+
const std::complex<float> *identity = nullptr, bool ordered = true);
146+
void RTDECL(CppReduceComplex3Dim)(Descriptor &result, const Descriptor &array,
147+
ReductionOperation<std::complex<float>>, const char *source, int line,
148+
int dim, const Descriptor *mask = nullptr,
149+
const std::complex<float> *identity = nullptr, bool ordered = true);
150+
void RTDECL(CppReduceComplex4)(std::complex<float> &, const Descriptor &,
151+
ReductionOperation<std::complex<float>>, const char *source, int line,
152+
int dim = 0, const Descriptor *mask = nullptr,
153+
const std::complex<float> *identity = nullptr, bool ordered = true);
154+
void RTDECL(CppReduceComplex4Dim)(Descriptor &result, const Descriptor &array,
155+
ReductionOperation<std::complex<float>>, const char *source, int line,
156+
int dim, const Descriptor *mask = nullptr,
157+
const std::complex<float> *identity = nullptr, bool ordered = true);
158+
void RTDECL(CppReduceComplex8)(std::complex<double> &, const Descriptor &,
159+
ReductionOperation<std::complex<double>>, const char *source, int line,
160+
int dim = 0, const Descriptor *mask = nullptr,
161+
const std::complex<double> *identity = nullptr, bool ordered = true);
162+
void RTDECL(CppReduceComplex8Dim)(Descriptor &result, const Descriptor &array,
163+
ReductionOperation<std::complex<double>>, const char *source, int line,
164+
int dim, const Descriptor *mask = nullptr,
165+
const std::complex<double> *identity = nullptr, bool ordered = true);
166+
#if LDBL_MANT_DIG == 64
167+
void RTDECL(CppReduceComplex10)(std::complex<long double> &, const Descriptor &,
168+
ReductionOperation<std::complex<long double>>, const char *source, int line,
169+
int dim = 0, const Descriptor *mask = nullptr,
170+
const std::complex<long double> *identity = nullptr, bool ordered = true);
171+
void RTDECL(CppReduceComplex10Dim)(Descriptor &result, const Descriptor &array,
172+
ReductionOperation<std::complex<long double>>, const char *source, int line,
173+
int dim, const Descriptor *mask = nullptr,
174+
const std::complex<long double> *identity = nullptr, bool ordered = true);
175+
#endif
176+
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
177+
void RTDECL(CppReduceComplex16)(std::complex<CppFloat128Type> &,
178+
const Descriptor &, ReductionOperation<std::complex<CppFloat128Type>>,
179+
const char *source, int line, int dim = 0, const Descriptor *mask = nullptr,
180+
const std::complex<CppFloat128Type> *identity = nullptr,
181+
bool ordered = true);
182+
void RTDECL(CppReduceComplex16Dim)(Descriptor &result, const Descriptor &array,
183+
ReductionOperation<std::complex<CppFloat128Type>>, const char *source,
184+
int line, int dim, const Descriptor *mask = nullptr,
185+
const std::complex<CppFloat128Type> *identity = nullptr,
186+
bool ordered = true);
187+
#endif
188+
189+
bool RTDECL(ReduceLogical1)(const Descriptor &, ReductionOperation<std::int8_t>,
190+
const char *source, int line, int dim = 0, const Descriptor *mask = nullptr,
191+
const std::int8_t *identity = nullptr, bool ordered = true);
192+
void RTDECL(ReduceLogical1Dim)(Descriptor &result, const Descriptor &array,
193+
ReductionOperation<std::int8_t>, const char *source, int line, int dim,
194+
const Descriptor *mask = nullptr, const std::int8_t *identity = nullptr,
195+
bool ordered = true);
196+
bool RTDECL(ReduceLogical2)(const Descriptor &,
197+
ReductionOperation<std::int16_t>, const char *source, int line, int dim = 0,
198+
const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr,
199+
bool ordered = true);
200+
void RTDECL(ReduceLogical2Dim)(Descriptor &result, const Descriptor &array,
201+
ReductionOperation<std::int16_t>, const char *source, int line, int dim,
202+
const Descriptor *mask = nullptr, const std::int16_t *identity = nullptr,
203+
bool ordered = true);
204+
bool RTDECL(ReduceLogical4)(const Descriptor &,
205+
ReductionOperation<std::int32_t>, const char *source, int line, int dim = 0,
206+
const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr,
207+
bool ordered = true);
208+
void RTDECL(ReduceLogical4Dim)(Descriptor &result, const Descriptor &array,
209+
ReductionOperation<std::int32_t>, const char *source, int line, int dim,
210+
const Descriptor *mask = nullptr, const std::int32_t *identity = nullptr,
211+
bool ordered = true);
212+
bool RTDECL(ReduceLogical8)(const Descriptor &,
213+
ReductionOperation<std::int64_t>, const char *source, int line, int dim = 0,
214+
const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr,
215+
bool ordered = true);
216+
void RTDECL(ReduceLogical8Dim)(Descriptor &result, const Descriptor &array,
217+
ReductionOperation<std::int64_t>, const char *source, int line, int dim,
218+
const Descriptor *mask = nullptr, const std::int64_t *identity = nullptr,
219+
bool ordered = true);
220+
221+
void RTDECL(ReduceChar1)(char *result, const Descriptor &array,
222+
ReductionCharOperation<char>, const char *source, int line, int dim = 0,
223+
const Descriptor *mask = nullptr, const char *identity = nullptr,
224+
bool ordered = true);
225+
void RTDECL(ReduceCharacter1Dim)(Descriptor &result, const Descriptor &array,
226+
ReductionCharOperation<char>, const char *source, int line, int dim,
227+
const Descriptor *mask = nullptr, const char *identity = nullptr,
228+
bool ordered = true);
229+
void RTDECL(ReduceChar2)(char16_t *result, const Descriptor &array,
230+
ReductionCharOperation<char16_t>, const char *source, int line, int dim = 0,
231+
const Descriptor *mask = nullptr, const char16_t *identity = nullptr,
232+
bool ordered = true);
233+
void RTDECL(ReduceCharacter2Dim)(Descriptor &result, const Descriptor &array,
234+
ReductionCharOperation<char16_t>, const char *source, int line, int dim,
235+
const Descriptor *mask = nullptr, const char16_t *identity = nullptr,
236+
bool ordered = true);
237+
void RTDECL(ReduceChar4)(char32_t *result, const Descriptor &array,
238+
ReductionCharOperation<char32_t>, const char *source, int line, int dim = 0,
239+
const Descriptor *mask = nullptr, const char32_t *identity = nullptr,
240+
bool ordered = true);
241+
void RTDECL(ReduceCharacter4Dim)(Descriptor &result, const Descriptor &array,
242+
ReductionCharOperation<char32_t>, const char *source, int line, int dim,
243+
const Descriptor *mask = nullptr, const char32_t *identity = nullptr,
244+
bool ordered = true);
245+
246+
void RTDECL(ReduceDerivedType)(char *result, const Descriptor &array,
247+
ReductionDerivedTypeOperation, const char *source, int line, int dim = 0,
248+
const Descriptor *mask = nullptr, const char *identity = nullptr,
249+
bool ordered = true);
250+
void RTDECL(ReduceDerivedTypeDim)(Descriptor &result, const Descriptor &array,
251+
ReductionDerivedTypeOperation, const char *source, int line, int dim,
252+
const Descriptor *mask = nullptr, const char *identity = nullptr,
253+
bool ordered = true);
254+
255+
} // extern "C"
256+
} // namespace Fortran::runtime
257+
#endif // FORTRAN_RUNTIME_REDUCE_H_

flang/include/flang/Runtime/reduction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,11 @@ void RTDECL(CppSumComplex4)(std::complex<float> &, const Descriptor &,
8989
void RTDECL(CppSumComplex8)(std::complex<double> &, const Descriptor &,
9090
const char *source, int line, int dim = 0,
9191
const Descriptor *mask = nullptr);
92+
#if LDBL_MANT_DIG == 64
9293
void RTDECL(CppSumComplex10)(std::complex<long double> &, const Descriptor &,
9394
const char *source, int line, int dim = 0,
9495
const Descriptor *mask = nullptr);
96+
#endif
9597
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
9698
void RTDECL(CppSumComplex16)(std::complex<CppFloat128Type> &,
9799
const Descriptor &, const char *source, int line, int dim = 0,

flang/lib/Semantics/check-call.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,9 @@ static void CheckReduce(
15881588
procChars->dummyArguments.size() != 2 || !procChars->functionResult) {
15891589
messages.Say(
15901590
"OPERATION= argument of REDUCE() must be a pure function of two data arguments"_err_en_US);
1591+
} else if (procChars->attrs.test(characteristics::Procedure::Attr::BindC)) {
1592+
messages.Say(
1593+
"A BIND(C) OPERATION= argument of REDUCE() is not supported"_err_en_US);
15911594
} else if (!result || result->Rank() != 0) {
15921595
messages.Say(
15931596
"OPERATION= argument of REDUCE() must be a scalar function"_err_en_US);

flang/runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ set(sources
153153
pseudo-unit.cpp
154154
ragged.cpp
155155
random.cpp
156+
reduce.cpp
156157
reduction.cpp
157158
stat.cpp
158159
stop.cpp

flang/runtime/complex-reduction.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,25 @@ ADAPT_REDUCTION(DotProductComplex10, long_double_Complex_t,
155155
ADAPT_REDUCTION(DotProductComplex16, CFloat128ComplexType, CppComplexFloat128,
156156
CMPLXF128, DOT_PRODUCT_ARGS, DOT_PRODUCT_ARG_NAMES)
157157
#endif
158+
159+
/* REDUCE() */
160+
#define RARGS REDUCE_ARGS(float_Complex_t)
161+
ADAPT_REDUCTION(ReduceComplex4, float_Complex_t, CppComplexFloat, CMPLXF, RARGS,
162+
REDUCE_ARG_NAMES)
163+
#undef RARGS
164+
#define RARGS REDUCE_ARGS(double_Complex_t)
165+
ADAPT_REDUCTION(ReduceComplex8, double_Complex_t, CppComplexDouble, CMPLX,
166+
RARGS, REDUCE_ARG_NAMES)
167+
#undef RARGS
168+
#if LDBL_MANT_DIG == 64
169+
#define RARGS REDUCE_ARGS(long_double_Complex_t)
170+
ADAPT_REDUCTION(ReduceComplex10, long_double_Complex_t, CppComplexLongDouble,
171+
CMPLXL, RARGS, REDUCE_ARG_NAMES)
172+
#undef RARGS
173+
#endif
174+
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
175+
#define RARGS REDUCE_ARGS(CFloat128ComplexType)
176+
ADAPT_REDUCTION(ReduceComplex16, CFloat128ComplexType, CppComplexFloat128,
177+
CMPLXF128, RARGS, REDUCE_ARG_NAMES)
178+
#undef RARGS
179+
#endif

flang/runtime/complex-reduction.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,49 @@ long_double_Complex_t RTNAME(DotProductComplex10)(DOT_PRODUCT_ARGS);
6969
CFloat128ComplexType RTNAME(DotProductComplex16)(DOT_PRODUCT_ARGS);
7070
#endif
7171

72+
#define REDUCE_ARGS(T) \
73+
T##_op operation, const struct CppDescriptor *x, \
74+
const struct CppDescriptor *y, const char *source, int line, \
75+
int dim /*=0*/, const struct CppDescriptor *mask /*=NULL*/, \
76+
const T *identity /*=NULL*/, _Bool ordered /*=true*/
77+
#define REDUCE_ARG_NAMES \
78+
operation, x, y, source, line, dim, mask, identity, ordered
79+
80+
typedef float_Complex_t (*float_Complex_t_op)(
81+
const float_Complex_t *, const float_Complex_t *);
82+
typedef double_Complex_t (*double_Complex_t_op)(
83+
const double_Complex_t *, const double_Complex_t *);
84+
typedef long_double_Complex_t (*long_double_Complex_t_op)(
85+
const long_double_Complex_t *, const long_double_Complex_t *);
86+
87+
float_Complex_t RTNAME(ReduceComplex2)(REDUCE_ARGS(float_Complex_t));
88+
float_Complex_t RTNAME(ReduceComplex3)(REDUCE_ARGS(float_Complex_t));
89+
float_Complex_t RTNAME(ReduceComplex4)(REDUCE_ARGS(float_Complex_t));
90+
double_Complex_t RTNAME(ReduceComplex8)(REDUCE_ARGS(double_Complex_t));
91+
long_double_Complex_t RTNAME(ReduceComplex10)(
92+
REDUCE_ARGS(long_double_Complex_t));
93+
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
94+
typedef CFloat128ComplexType (*CFloat128ComplexType_op)(
95+
const CFloat128ComplexType *, const CFloat128ComplexType *);
96+
CFloat128ComplexType RTNAME(ReduceComplex16)(REDUCE_ARGS(CFloat128ComplexType));
97+
#endif
98+
99+
#define REDUCE_DIM_ARGS(T) \
100+
struct CppDescriptor *result, T##_op operation, \
101+
const struct CppDescriptor *x, const struct CppDescriptor *y, \
102+
const char *source, int line, int dim, \
103+
const struct CppDescriptor *mask /*=NULL*/, const T *identity /*=NULL*/, \
104+
_Bool ordered /*=true*/
105+
#define REDUCE_DIM_ARG_NAMES \
106+
result, operation, x, y, source, line, dim, mask, identity, ordered
107+
108+
void RTNAME(ReduceComplex2Dim)(REDUCE_DIM_ARGS(float_Complex_t));
109+
void RTNAME(ReduceComplex3Dim)(REDUCE_DIM_ARGS(float_Complex_t));
110+
void RTNAME(ReduceComplex4Dim)(REDUCE_DIM_ARGS(float_Complex_t));
111+
void RTNAME(ReduceComplex8Dim)(REDUCE_DIM_ARGS(double_Complex_t));
112+
void RTNAME(ReduceComplex10Dim)(REDUCE_DIM_ARGS(long_double_Complex_t));
113+
#if LDBL_MANT_DIG == 113 || HAS_FLOAT128
114+
void RTNAME(ReduceComplex16Dim)(REDUCE_DIM_ARGS(CFloat128ComplexType));
115+
#endif
116+
72117
#endif // FORTRAN_RUNTIME_COMPLEX_REDUCTION_H_

0 commit comments

Comments
 (0)